Sign up ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

This is my solution to the codercharts problem http://codercharts.com/puzzle/word-swap but if keeps failing when I submit the solution because of the cpu_excess_time. Please suggest possible optimisations for this problem, I believe my solution is correct but not optimal.

#!/usr/bin/python

def swap_words(first_word,second_word,word_dict):
    wd = word_dict
    #if the first word is equal to second , 
    # we have got the target word
    if first_word == second_word:
        return [first_word]
    for word in word_dict:
        if len(word) == len(first_word) and \
           sum([x != y for x,y in zip(list(first_word),list(word))]) == 1:
            wd.remove(word)
            ret = swap_words(word,second_word,wd)
            if ret != False:
                ret.append(first_word)
                return ret
    return False

if __name__ == '__main__':
    import sys
    filename = sys.argv[1]
    first_word = sys.argv[2]
    second_word = sys.argv[3]
    text = open(filename).read()
    word_dict = text.split('\n')
    word_list = swap_words(first_word,second_word,word_dict)
    for word in reversed(word_list):
        print word
share|improve this question

2 Answers 2

Simple optimizations:

By reading the whole file into text, then splitting the text into a word list, you will need enough memory to hold two copies of the file, which might be huge. Look into line-by-line input methods.

Many strings, after a quick check, don't need to be seen ever again.

The off-by-one-letter test does not ALWAYS need to process every letter in the words.

You never actually have to find the target word in the word list to know you have a solution (you know it's in there from the problem description). Some simpler solutions don't even need to consult the word list.

Deeper optimizations:

If you had a way to test which "next" words were more likely to lead to a solution, you might be able to defer other alternatives to explore those first, for a faster average solution time.

It MIGHT make more sense to solve the problem working backwards or both ways at once.

It MIGHT be worthwhile to keep stats on different words you find and/or to place words that seem like they might be useful later in some kind of separate structure.

share|improve this answer

"Make it right then make it fast".

I'm afraid your algorithm is not correct. It fails to trace AA -> BB within this simple dict :

AA
AB
AC
BB

Now, let :

s = words size 
N = dict size
n = numbers of s-sized words in dict

It may take s! tries (at worst) to find the good path.
So your approach, once backtracking issue fixed, would be roughly O(s! * s * (N + n*s)).
If, instead, you check whether new candidates (created by putting 1 letter from target word) belong to dict, complexity melts down to O(s! * s) (approximating hash look-up complexity to constant time).

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.