Project Euler 98 – Investigating words and anagrams that are square numbers

by Rob on January 20, 2012

in Code Samples,Project Euler

http://projecteuler.net/problem=98

A very hacky solution, I admit, but I got it to work.

#euler 98

import time
import math

t0 = time.time()

f = open('words.txt', 'r')

for line in f:
    a = line.split(',')

maxLength = 0
for i in range(len(a)):
    a[i] = a[i].strip('"')
    if len(a[i]) > maxLength:
        maxLength = len(a[i])

print "longest word has ", maxLength, "characters"

def isAnagram(a, b):
    if len(a) !=  len(b):
        return False
    length = len(a)
    for i in range(length):
        if a[i] not in b:
            return False
        else:
            b = b.replace(a[i], '', 1)
    return True

ana = []
biggestLength = 0
for i in range(len(a)):
    j = i + 1
    while j < len(a):
        if isAnagram(a[i], a[j]):
            ana.append((a[i],a[j]))
            print a[i], a[j]
            if len(a[i]) > biggestLength:
                biggestLength = len(a[i])
        j += 1

print "longest anagram is ", biggestLength, "characters"

anaNum = {}  # dictionary with key as length of anagram, and value as list of anagram tuples
sNum = {}  # dictionary for square list
for i in range(1, biggestLength+1):
    anaNum[i] = []
    sNum[i] = []

for tup in ana:
    lenTup = len(tup[0])
    anaNum[lenTup].append(tup)

#let's generate squares
squares = []
counter = 1
temp = counter * counter
while len(str(temp)) <= biggestLength:
    squares.append(temp)
    counter += 1
    temp = counter * counter

for i in squares:
    lsquares = len(str(i))
    sNum[lsquares].append(i)

def translate(n):  # takes a tuple, converts to '1234' format
    sA = str(n[0])
    sB = str(n[1])
    length = len(sA)
    outputA = ['x' for i in range(length)]
    outputB = outputA[:]
    index = 0
    counter = 1
    while index < length:
        if outputA[index] == 'x':
            temp = sA[index]
            for j in range(index, length):
                if sA[j] == temp:
                    outputA[j] = counter
            counter += 1
        index += 1
    for a in range(length):
        temp = sA[a]
        replace = outputA[a]
        for b in range(length):
            if sB[b] == temp:
                outputB[b] = replace
    return (outputA, outputB)

testAnaLength = 5  # this counter sets the length of the word anagram to check

mapp = []
wordList = anaNum[testAnaLength]
for wtuples in wordList:
    mt = translate(wtuples)  # this is the mapping tuple
    mapp.append(mt)

def concat(n):
    return ''.join([str(x) for x in n])

uniques = []
dummy1 = [x for x in range(testAnaLength)]
dummy2 = concat(dummy1)  #use this dummy variable as placeholder for translate function

for i in mapp:
    if not i[0] in uniques:
        uniques.append(i[0])
print uniques

searchSpace = {}
for abc in uniques:
    searchSpace[tuple(abc)] = []

for i in sNum[testAnaLength]:
    temp = translate((i, dummy2))
    if temp[0] in uniques:
        searchSpace[tuple(temp[0])].append(i)

def transform(n, mapping):  #takes a number and transforms it using map (same length)
    temp1 = str(n)
    temp2 = mapping[0]
    temp3 = mapping[1]
    if len(temp1) != len(temp2):
        raise ValueError
    output = ['x' for a in range(len(temp1))]
    for i in range(len(temp2)):
        index = temp2[i]
        ivalue = temp1[index-1]
        for j in range(len(temp3)):
            if index == temp3[j]:
                output[j] = ivalue
    return concat(output)

answer = 0
for q in range(len(mapp)):
    for i in searchSpace[tuple(mapp[q][0])]:
        temp = transform(i, mapp[q])
        if int(temp) in searchSpace[tuple(mapp[q][0])]:
            print i, temp
            if max([i, temp]) > answer:
                answer = max([i, temp])

print "For an anagram of length ", testAnaLength, "the largest square number is ", answer

t1 = time.time()
total = t1 - t0
print "time taken in seconds was: ", total

Leave a Comment

Previous post:

Next post: