By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
425,719 Members | 1,046 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 425,719 IT Pros & Developers. It's quick & easy.

Help with word unscrambler code for newbie?

P: 27
Hi, I'm new to Python and need some help with this program. I'm trying to take 10 jumbled words at a time and have the program unscramble them and then print them out like: word1,word2,word3, etc.
So far the code will unscramble more than one word at once but it will print the answer several times if there is more than 1 of the same letter in the word and it will print them in a column. Example is inwdwo and garnama (window anagram). It will print them like this:
window
window
anagram
anagram
anagram.
I read that a set can help this but I'm not sure where to put that or how to get the %s,%s,%s type of print out. Any help?
Expand|Select|Wrap|Line Numbers
  1.  
  2. import string
  3. def anagrams(s):
  4.     if s == "":
  5.         return [s]
  6.     else:
  7.         ans = []
  8.         for an in anagrams(s[1:]):
  9.             for pos in range(len(an)+1):
  10.                 ans.append(an[:pos]+s[0]+an[pos:])
  11.         return ans
  12.  
  13. def dictionary(wordlist):
  14.     dict = {}
  15.     infile = open(wordlist, "r")
  16.     for line in infile:
  17.         word = line.split("\n")[0]
  18.         dict[word] = 1
  19.     infile.close()
  20.     return dict
  21.  
  22. def main():
  23.     anagram = raw_input("Please enter words: ")
  24.     wordLst = anagram.split(None)
  25.     diction = dictionary("wordlist.txt")
  26.     for word in wordLst:
  27.         anaLst = anagrams(word)
  28.             for ana in anaLst:
  29.             if diction.has_key(ana):
  30.                 diction[ana] = word
  31.                 print " ", ana  
  32.  
  33. main()
  34.  
Jan 30 '07 #1
Share this Question
Share on Google+
12 Replies


bvdet
Expert Mod 2.5K+
P: 2,851
You were very close. This seems to work:
Expand|Select|Wrap|Line Numbers
  1. # inwdwo garnama (window anagram)
  2.  
  3. import string
  4. def anagrams(s):
  5.     if s == "":
  6.         return [s]
  7.     else:
  8.         ans = []
  9.         for an in anagrams(s[1:]):
  10.             for pos in range(len(an)+1):
  11.                 ans.append(an[:pos]+s[0]+an[pos:])
  12.         return ans
  13.  
  14. def dictionary(wordlist):
  15.     dict = {}
  16.     infile = open(wordlist, "r")
  17.     for line in infile:
  18.         word = line.split("\n")[0]
  19.         dict[word] = 1
  20.     infile.close()
  21.     return dict
  22.  
  23. def main(fn, s):
  24.     # anagram = raw_input("Please enter words: ")
  25.     anagram = s
  26.     wordLst = anagram.split(None)
  27.     diction = dictionary(fn)
  28.     outStr = ""
  29.     for word in wordLst:
  30.         anaLst = anagrams(word)
  31.         for ana in anaLst:
  32.             if diction.has_key(ana):
  33.                 diction[ana] = word
  34.                 outStr += '%s ' % (ana)
  35.                 break
  36.     print outStr
  37.  
  38. import os
  39.  
  40. fn = (os.path.join('H:\\', 'TEMP', 'temsys', 'anagrams.txt'))
  41.  
  42. s = 'inwdwo garnama'
  43. main(fn, s)
>>> window anagram
>>>
There were multiple occurrences of 'window' and 'anagram' returned by anagrams(), and 'break' took care of that. Ideally anagrams() should only return one of each possible combination.
Jan 30 '07 #2

bvdet
Expert Mod 2.5K+
P: 2,851
If you are in Python 2.4 and above, this will eliminate duplicates from the list:
Expand|Select|Wrap|Line Numbers
  1. def anagrams(s):
  2.     if s == "":
  3.         return [s]
  4.     else:
  5.         ans = []
  6.         for an in anagrams(s[1:]):
  7.             for pos in range(len(an)+1):
  8.                 ans.append(an[:pos]+s[0]+an[pos:])
  9.         return set(ans)
  10.  
Or:
Expand|Select|Wrap|Line Numbers
  1. def anagrams(s):
  2.     if s == "":
  3.         return [s]
  4.     else:
  5.         ans = set()
  6.         for an in anagrams(s[1:]):
  7.             for pos in range(len(an)+1):
  8.                 ans.add(an[:pos]+s[0]+an[pos:])
  9.         return ans
Python 2.3:
Expand|Select|Wrap|Line Numbers
  1. def anagrams(s):
  2.     if s == "":
  3.         return [s]
  4.     else:
  5.         ans = []
  6.         for an in anagrams(s[1:]):
  7.             for pos in range(len(an)+1):
  8.                 ans.append(an[:pos]+s[0]+an[pos:])
  9.                 [i]u={}
  10.         for i in ans:
  11.             u=1
  12.         return u.keys()
Jan 30 '07 #3

P: 27
Thank you, Bvdet for the replies! I'm using 2.5. I tried your suggestions and this part worked for the repeating words part:
Expand|Select|Wrap|Line Numbers
  1. else:
  2.         ans = set()
  3.         for an in anagrams(s[1:]):
  4.             for pos in range(len(an)+1):
  5.                 ans.add(an[:pos]+s[0]+an[pos:])
  6.         return ans
  7.  
Jan 30 '07 #4

bvdet
Expert Mod 2.5K+
P: 2,851
Thank you, Bvdet for the replies! I'm using 2.5. I tried your suggestions and this part worked for the repeating words part:
Expand|Select|Wrap|Line Numbers
  1. else:
  2.         ans = set()
  3.         for an in anagrams(s[1:]):
  4.             for pos in range(len(an)+1):
  5.                 ans.add(an[:pos]+s[0]+an[pos:])
  6.         return ans
  7.  
You are welcome!
Jan 30 '07 #5

P: 27
What would you suggest for these next issues? The code now works to unscramble 10 words at a time, taken from a specific wordlist but there are only 30 sec.s to complete it. The scrambled words appear in a column but need solved in single line, seperated by comas.
Scrambled:
irsitp
aiigabl
ttgrae
pmohnat
relkil
ciusrt
aegnor
nceahc
gishof
jme1sa
Solution:spirit,abigail,target,phantom,killer,curt is,orange,chance,gofish,james1
I can't copy and paste the scrambled words in a column because it will only take the 1st word in that format. Is there a way to have the code accept the words like that? Maybe I should have an empty *.txt file, copy and paste to it, then have the code point to it to unscramble? Or, would something like TkInter be helpful?
Jan 30 '07 #6

P: 27
Well, I did the "Hello, World" in TkInter and after looking over the documentation for it, I think I'd be getting in way over my head at this point! I'll stick to the basics for now :)
Jan 30 '07 #7

bvdet
Expert Mod 2.5K+
P: 2,851
Expand|Select|Wrap|Line Numbers
  1. fn1 = 'your_file.txt'
  2. sLst = []
  3. f = open(fn1, 'r')
  4. for line in f:
  5.     sLst.append(line.strip())
  6. f.close()
  7.  
  8. s = " ".join(sLst)
  9. print s
  10. main(fn, s)
Yields:
>>> irsitp aiigabl ttgrae pmohnat relkil ciusrt aegnor nceahc gishof jme1sa
spirit abigail target phantom killer curtis orange chance gofish james1

This may not be the best way, but it works. :)
Jan 30 '07 #8

P: 27
bvdet, for some reason when I tried that it doesn't work for me so I've come up with this:
Expand|Select|Wrap|Line Numbers
  1. def main():
  2.     anagram = raw_input("Please enter words: ")
  3.     wordLst = anagram.split(None)
  4.     diction = dictionary("wordlist.txt")
  5.     for word in wordLst:
  6.         anaLst = anagrams(word)
  7.         for ana in anaLst:
  8.             if diction.has_key(ana):
  9.                 diction[ana] = word
  10.                 Solution = ana+','
  11.                 solutionWrite = open('solution.txt','w')
  12.                 solutionWrite.write(Solution)
  13. main()
  14.  
  15.  
This is printing to solution.txt with a comma behind the word BUT it's only printing one unscrambled word. If I enter:irispt
I can open the text file and see:
spirit,
Great. Now I try: irispt ubasc1 bbu1ab
and it writes:
bubba1,
It's only writing the last unscrambled word.
Feb 1 '07 #9

P: 27
Here's the whole code so far:
Expand|Select|Wrap|Line Numbers
  1. import string
  2. def anagrams(s):
  3.     if s == "":
  4.         return [s]
  5.     else:
  6.         ans = set()
  7.         for an in anagrams(s[1:]):
  8.             for pos in range(len(an)+1):
  9.                 ans.add(an[:pos]+s[0]+an[pos:])
  10.         return ans
  11.  
  12. def dictionary(wordlist):
  13.     dict = {}
  14.     infile = open(wordlist, "r")
  15.     for line in infile:
  16.         word = line.split("\n")[0]
  17.         dict[word] = 1
  18.     infile.close()
  19.     return dict
  20.  
  21. def main():
  22.     anagram = raw_input("Please enter words: ")
  23.     wordLst = anagram.split(None)
  24.     diction = dictionary("wordlist.txt")
  25.     for word in wordLst:
  26.         anaLst = anagrams(word)
  27.         for ana in anaLst:
  28.             if diction.has_key(ana):
  29.                 diction[ana] = word
  30.                 Solution = ana+','
  31.                 solutionWrite = open('solution.txt','w')
  32.                 solutionWrite.write(Solution)
  33. main()
  34.  
Feb 1 '07 #10

bvdet
Expert Mod 2.5K+
P: 2,851
I changed a few things but have not tested it. The solution string is initialized before the loop. The solution text is concatenated to it in the loop. The complete solution string is written to file after the iterations are complete. The slice '[:-2]' trims off the trailing comma and space. It is good practice to close each file that you open. I personally like to use single letters such as 'f' for file in file operations. It's easier to read when there are fewer letters and a descriptive name is not necessary.

Check out Guido's Python style guide for some useful tips. http://www.python.org/doc/essays/styleguide/
Expand|Select|Wrap|Line Numbers
  1. def main():
  2.     anagram = raw_input("Please enter words: ")
  3.     wordLst = anagram.split(None)
  4.     diction = dictionary("wordlist.txt")
  5.     solution = ""
  6.     for word in wordLst:
  7.         anaLst = anagrams(word)
  8.         for ana in anaLst:
  9.             if diction.has_key(ana):
  10.                 diction[ana] = word
  11.                 solution += '%s, ' % (ana)
  12.     f = open('solution.txt','w')
  13.     f.write(solution[:-2])
  14.     f.close()
  15. main()
  16.  
Feb 1 '07 #11

P: 27
I changed a few things but have not tested it. The solution string is initialized before the loop. The solution text is concatenated to it in the loop. The complete solution string is written to file after the iterations are complete. The slice '[:-2]' trims off the trailing comma and space. It is good practice to close each file that you open. I personally like to use single letters such as 'f' for file in file operations. It's easier to read when there are fewer letters and a descriptive name is not necessary.

Check out Guido's Python style guide for some useful tips. http://www.python.org/doc/essays/styleguide/
Expand|Select|Wrap|Line Numbers
  1. def main():
  2.     anagram = raw_input("Please enter words: ")
  3.     wordLst = anagram.split(None)
  4.     diction = dictionary("wordlist.txt")
  5.     solution = ""
  6.     for word in wordLst:
  7.         anaLst = anagrams(word)
  8.         for ana in anaLst:
  9.             if diction.has_key(ana):
  10.                 diction[ana] = word
  11.                 solution += '%s, ' % (ana)
  12.     f = open('solution.txt','w')
  13.     f.write(solution[:-2])
  14.     f.close()
  15. main()
  16.  
bvdet, you are my hero! This works! Thanks again for your time and knowledge!
Now I'll finish it off by adding #comments before moving on to another project. Also, thanks for the link and for helping me 'clean-up' the code by keeping it simpler.
Feb 1 '07 #12

bvdet
Expert Mod 2.5K+
P: 2,851
bvdet, you are my hero! This works! Thanks again for your time and knowledge!
Now I'll finish it off by adding #comments before moving on to another project. Also, thanks for the link and for helping me 'clean-up' the code by keeping it simpler.
My pleasure. This was an interesting problem. Your positive comments make it worth the effort!
Feb 1 '07 #13

Post your reply

Sign in to post your reply or Sign up for a free account.