4
\$\begingroup\$

Here is my first attempt to solve Jumble puzzle:

import argparse
from itertools import permutations


parser = argparse.ArgumentParser(description='Solver for Jumble')
parser.add_argument('jumbledwords', nargs='+',
                    help='One or more jumbled words')
argv = parser.parse_args()

# http://www-01.sil.org/linguistics/wordlists/english/wordlist/wordsEn.txt
words = [line.rstrip() for line in open('wordsEn.txt')]
for jumbledword in argv.jumbledwords:
    perms = set([''.join(p) for p in permutations(jumbledword)])
    legalwords = [word for word in perms if word in words]
    # print(len(perms))
    print(jumbledword, legalwords)

Any suggestions for improvement?

\$\endgroup\$
4
\$\begingroup\$

Close what you open

words = [line.rstrip() for line in open('wordsEn.txt')]

Here you opened a file but you did not close it! In fact I suggest to use with that will handle closing automagically.

with open('wordsEn.txt') as f:
    words = [line.rstrip() for line in f.read()]

Let the user change the file

You should let the user input as an optional arg his own filename, I may have my own wordlist that is not called exactly: 'wordsEn.txt', the dafault file should be None (You read directly from the webpage).

set built-in operations

If you change the below line to be:

words = set([line.rstrip() for line in f.read().splitlines()])

You can then use set intersection:

legalwords = perms & words

To enhance both clarity and performance.

Allowing long words

The complexity of finding all the permutations of a word is O(N!): for a mere 20 characters word that means 2.432 * 10**18 combinations, I suggest comparing the sorted words for better efficiency if you need to run the script with long words.

\$\endgroup\$
  • \$\begingroup\$ Thanks for your valuable inputs. FYI, 'wordsEn.txt' is already sorted and I think using list will maintain the order. \$\endgroup\$ – inyoot May 22 '15 at 16:52
  • \$\begingroup\$ You are right that set intersection is better performance than list. I do not understand what you mean by sorted words because there are no order in set. Could you expound more? I will post the revised code as a new answer. \$\endgroup\$ – inyoot May 22 '15 at 23:54
  • \$\begingroup\$ @inyoot I mean an unsorted collection of sorted words. \$\endgroup\$ – Caridorc May 23 '15 at 11:04
  • \$\begingroup\$ could you give example, @Caridorc ? \$\endgroup\$ – inyoot May 23 '15 at 13:37
0
\$\begingroup\$

Here is my revised code. I fixed the unclosed file problem. I use set intersection instead of list.

import argparse
from itertools import permutations


parser = argparse.ArgumentParser(description='Solver for Jumble')
parser.add_argument('jumbledwords', nargs='+',
                    help='One or more jumbled words')
argv = parser.parse_args()

# http://www-01.sil.org/linguistics/wordlists/english/wordlist/wordsEn.txt
with open('wordsEn.txt') as f:
    words = {line.rstrip() for line in f}

for jumbledword in argv.jumbledwords:
    perms = set([''.join(p) for p in permutations(jumbledword)])
    legal_words = perms & words
    # print(len(perms))
    print(jumbledword, legal_words)

There is significant performance improvement by using set intersection instead of 'list'.

(list)$ time python jumble_puzzle.py nabando enegativ
nabando ['abandon']
enegativ ['negative']

real    1m5.735s
user    1m5.556s
sys     0m0.060s

(set)$ time python jumble_puzzle.py nabando enegativ
nabando {'abandon'}
enegativ {'negative'}

real    0m0.170s
user    0m0.153s
sys     0m0.016s
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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