Help with word unscrambler code for newbie?

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • defience
    New Member
    • Jan 2007
    • 27

    #1

    Help with word unscrambler code for newbie?

    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,wor d3, 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?
    Code:
    import string
    def anagrams(s):
        if s == "":
            return [s]
        else:
            ans = []
            for an in anagrams(s[1:]):
                for pos in range(len(an)+1):
                    ans.append(an[:pos]+s[0]+an[pos:])
            return ans
        
    def dictionary(wordlist):
        dict = {}
        infile = open(wordlist, "r")
        for line in infile:
            word = line.split("\n")[0]
            dict[word] = 1
        infile.close()
        return dict
    
    def main():
        anagram = raw_input("Please enter words: ")
        wordLst = anagram.split(None)
        diction = dictionary("wordlist.txt")
        for word in wordLst:
            anaLst = anagrams(word)
                for ana in anaLst:
                if diction.has_key(ana):
                    diction[ana] = word
                    print " ", ana  
    
    main()
  • bvdet
    Recognized Expert Specialist
    • Oct 2006
    • 2851

    #2
    You were very close. This seems to work:
    Code:
    # inwdwo garnama (window anagram)
    
    import string
    def anagrams(s):
        if s == "":
            return [s]
        else:
            ans = []
            for an in anagrams(s[1:]):
                for pos in range(len(an)+1):
                    ans.append(an[:pos]+s[0]+an[pos:])
            return ans
        
    def dictionary(wordlist):
        dict = {}
        infile = open(wordlist, "r")
        for line in infile:
            word = line.split("\n")[0]
            dict[word] = 1
        infile.close()
        return dict
    
    def main(fn, s):
        # anagram = raw_input("Please enter words: ")
        anagram = s
        wordLst = anagram.split(None)
        diction = dictionary(fn)
        [U][I][B]outStr = ""[/B][/I][/U]
        for word in wordLst:
            anaLst = anagrams(word)
            for ana in anaLst:
                if diction.has_key(ana):
                    diction[ana] = word
                    [I][B]outStr += '%s ' % (ana)
                    break
        print outStr[/B][/I]
    
    import os
    
    fn = (os.path.join('H:\\', 'TEMP', 'temsys', 'anagrams.txt'))
    
    s = 'inwdwo garnama'
    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.

    Comment

    • bvdet
      Recognized Expert Specialist
      • Oct 2006
      • 2851

      #3
      If you are in Python 2.4 and above, this will eliminate duplicates from the list:
      Code:
      def anagrams(s):
          if s == "":
              return [s]
          else:
              ans = []
              for an in anagrams(s[1:]):
                  for pos in range(len(an)+1):
                      ans.append(an[:pos]+s[0]+an[pos:])
              [I][B]return set(ans)[/B][/I]
      Or:
      Code:
      def anagrams(s):
          if s == "":
              return [s]
          else:
              [I][B]ans = set()[/B][/I]
              for an in anagrams(s[1:]):
                  for pos in range(len(an)+1):
                      [I][B]ans.add(an[:pos]+s[0]+an[pos:])[/B][/I]
              return ans
      Python 2.3:
      Code:
      def anagrams(s):
          if s == "":
              return [s]
          else:
              ans = []
              for an in anagrams(s[1:]):
                  for pos in range(len(an)+1):
                      ans.append(an[:pos]+s[0]+an[pos:])
                      [B][I]u={}
              for i in ans:
                  u[i]=1
              return u.keys()[/I][/B]

      Comment

      • defience
        New Member
        • Jan 2007
        • 27

        #4
        Thank you, Bvdet for the replies! I'm using 2.5. I tried your suggestions and this part worked for the repeating words part:
        Code:
        else:
                ans = [B]set()[/B]
                for an in anagrams(s[1:]):
                    for pos in range(len(an)+1):
                        ans.[B]add[/B](an[:pos]+s[0]+an[pos:])
                return ans

        Comment

        • bvdet
          Recognized Expert Specialist
          • Oct 2006
          • 2851

          #5
          Originally posted by defience
          Thank you, Bvdet for the replies! I'm using 2.5. I tried your suggestions and this part worked for the repeating words part:
          Code:
          else:
                  ans = [B]set()[/B]
                  for an in anagrams(s[1:]):
                      for pos in range(len(an)+1):
                          ans.[B]add[/B](an[:pos]+s[0]+an[pos:])
                  return ans
          You are welcome!

          Comment

          • defience
            New Member
            • Jan 2007
            • 27

            #6
            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 ,curtis,orange, chance,gofish,j ames1
            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?

            Comment

            • defience
              New Member
              • Jan 2007
              • 27

              #7
              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 :)

              Comment

              • bvdet
                Recognized Expert Specialist
                • Oct 2006
                • 2851

                #8
                Code:
                fn1 = 'your_file.txt'
                sLst = []
                f = open(fn1, 'r')
                for line in f:
                    sLst.append(line.strip())
                f.close()
                
                s = " ".join(sLst)
                print s
                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. :)

                Comment

                • defience
                  New Member
                  • Jan 2007
                  • 27

                  #9
                  bvdet, for some reason when I tried that it doesn't work for me so I've come up with this:
                  Code:
                  def main():
                      anagram = raw_input("Please enter words: ")
                      wordLst = anagram.split(None)
                      diction = dictionary("wordlist.txt")
                      for word in wordLst:
                          anaLst = anagrams(word)
                          for ana in anaLst:
                              if diction.has_key(ana):
                                  diction[ana] = word
                                  [B]Solution = ana+','
                                  solutionWrite = open('solution.txt','w')
                                  solutionWrite.write(Solution)[/B]
                  main()
                  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.

                  Comment

                  • defience
                    New Member
                    • Jan 2007
                    • 27

                    #10
                    Here's the whole code so far:
                    Code:
                    import string
                    def anagrams(s):
                        if s == "":
                            return [s]
                        else:
                            ans = set()
                            for an in anagrams(s[1:]):
                                for pos in range(len(an)+1):
                                    ans.add(an[:pos]+s[0]+an[pos:])
                            return ans
                        
                    def dictionary(wordlist):
                        dict = {}
                        infile = open(wordlist, "r")
                        for line in infile:
                            word = line.split("\n")[0]
                            dict[word] = 1
                        infile.close()
                        return dict
                    
                    def main():
                        anagram = raw_input("Please enter words: ")
                        wordLst = anagram.split(None)
                        diction = dictionary("wordlist.txt")
                        for word in wordLst:
                            anaLst = anagrams(word)
                            for ana in anaLst:
                                if diction.has_key(ana):
                                    diction[ana] = word
                                    Solution = ana+','
                                    solutionWrite = open('solution.txt','w')
                                    solutionWrite.write(Solution)
                    main()

                    Comment

                    • bvdet
                      Recognized Expert Specialist
                      • Oct 2006
                      • 2851

                      #11
                      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/
                      Code:
                      def main():
                          anagram = raw_input("Please enter words: ")
                          wordLst = anagram.split(None)
                          diction = dictionary("wordlist.txt")
                          solution = ""
                          for word in wordLst:
                              anaLst = anagrams(word)
                              for ana in anaLst:
                                  if diction.has_key(ana):
                                      diction[ana] = word
                                      solution += '%s, ' % (ana)
                          f = open('solution.txt','w')
                          f.write(solution[:-2])
                          f.close()
                      main()

                      Comment

                      • defience
                        New Member
                        • Jan 2007
                        • 27

                        #12
                        Originally posted by bvdet
                        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/
                        Code:
                        def main():
                            anagram = raw_input("Please enter words: ")
                            wordLst = anagram.split(None)
                            diction = dictionary("wordlist.txt")
                            solution = ""
                            for word in wordLst:
                                anaLst = anagrams(word)
                                for ana in anaLst:
                                    if diction.has_key(ana):
                                        diction[ana] = word
                                        solution += '%s, ' % (ana)
                            f = open('solution.txt','w')
                            f.write(solution[:-2])
                            f.close()
                        main()
                        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.

                        Comment

                        • bvdet
                          Recognized Expert Specialist
                          • Oct 2006
                          • 2851

                          #13
                          Originally posted by defience
                          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!

                          Comment

                          Working...