# Archive for November, 2009

## Python: Anagram solver

Finding the solutions to an anagram can be enjoyable and used as a sign of mental agility, with examples from long running television series (countdown) to online gambling skill games. It also makes an interesting tutorial for learning some simple python skills.

We start off by writing a function to check if a given word is an anagram of another word. This will be used to check a list of dictionary words against a given word in order to find its anagrams. The function accepts two string inputs, the word we are testing (word), and the given anagram to check it against (chkword).

The function loops over every letter in the word and if it is not present in chkword then we know that it cannot be an anagram of the chkword. Otherwise it is valid and that letter is removed from the chkword so that each letter may only be used once. For example checking “netting” with “testing” would fail on the second n.

def anagramchk(word,chkword): for letter in word: if letter in chkword: chkword=chkword.replace(letter, '', 1) else: return 0 return 1

Now we need to get the anagram from the user. The following using raw_input to read what the user types in the console and assign it to a variable, with the optional argument used to print text so the user knows they need to do something.

wordin=raw_input('Enter anagram:\n')

We can now join both these together and loop over our dictionary file. We strip each line to remove any extra space and gumph at the end of the lines. If the length of a line is less than 4 then it is ignored,this can be changed to whatever minimum you like, so if you want it to be the same length as the input you could replace it with len(line)==len(wordin). We then use the function already written earlier to check if the word is a valid anagram and print the word if it is. Then we finish by closing the file.

f=open('english.txt', 'r') for line in f: line=line.strip() if len(line)>=4: if anagramchk(line,wordin): print line f.close()

Hopefully this has been helpful to someone. As ever if you have any suggestions or improvements then please leave a comment. Below is the complete version of the code

def anagramchk(word,chkword): for letter in word: if letter in chkword: chkword=chkword.replace(letter, '', 1) else: return 0 return 1 wordin=raw_input('Enter anagram:') f=open('english.txt', 'r') for line in f: line=line.strip() if len(line)>=4: if anagramchk(line,wordin): print line f.close()

The dictionary file I used was one I found in /usr/share/dict/british-english (most linux distro’s should have this or similar) it can also be found here

## Python: Factors of a number

Project Euler often requires the factors of a number to be found, here is the function I have written for that purpose.

def factors(n): fact=[1,n] check=2 rootn=sqrt(n) while check<rootn: if n%check==0: fact.append(check) fact.append(n/check) check+=1 if rootn==check: fact.append(check) fact.sort() return fact

As always any help in speeding up my function would be appreciated. I think it could be improved using a sieve method or by checking if its divisible by 2 first then using check+=2 starting at 3 to improve the speed of the loop by a factor of 2.

Below is a the commented version to help explain what’s going on if it’s not clear.

def factors(n): # 1 and n are automatically factors of n fact=[1,n] # starting at 2 as we have already dealt with 1 check=2 # calculate the square root of n and use this as the # limit when checking if a number is divisible as # factors above sqrt(n) will already be calculated as # the inverse of a lower factor IE. finding factors of # 100 only need go up to 10 (sqrt(100)=10) as factors # such as 25 can be found when 5 is found to be a # factor 100/5=25 rootn=sqrt(n) while check<rootn: if n%check==0: fact.append(check) fact.append(n/check) check+=1 # this line checks the sqrt of the number to see if # it is a factor putting it here prevents it appearing # twice in the above while loop and putting it outside # the loop should save some time. if rootn==check: fact.append(check) # return an array of factors sorted into numerial order. fact.sort() return fact