89 lines
2.3 KiB
Python
89 lines
2.3 KiB
Python
|
|
||
|
def get_words():
|
||
|
with open("../txt/e098.txt", "r") as f:
|
||
|
words = list(map(lambda w: w.strip().lower(), f.readlines()))
|
||
|
words.sort(key=len, reverse=True)
|
||
|
return words
|
||
|
|
||
|
|
||
|
def get_pair_subsets(xs):
|
||
|
""" Returns all subsets of size two. """
|
||
|
r = [(xs[i], xs[j])
|
||
|
for i in range(len(xs))
|
||
|
for j in range(i + 1, len(xs))]
|
||
|
return r
|
||
|
|
||
|
|
||
|
def find_anagrams(xs):
|
||
|
anagrams = {}
|
||
|
for x in xs:
|
||
|
x_tuple = tuple(sorted(x))
|
||
|
try:
|
||
|
anagrams[x_tuple].append(x)
|
||
|
except KeyError:
|
||
|
anagrams[x_tuple] = [x]
|
||
|
anagrams = [a for a in anagrams.values() if len(a) > 1]
|
||
|
return anagrams
|
||
|
|
||
|
|
||
|
def find_anagram_pairs(xs):
|
||
|
anagrams = find_anagrams(xs)
|
||
|
r = [pair
|
||
|
for anagram in anagrams
|
||
|
for pair in get_pair_subsets(anagram)]
|
||
|
return r
|
||
|
|
||
|
|
||
|
def words_match_numbers(words, numbers):
|
||
|
letters_a, letters_b = words
|
||
|
digits_a, digits_b = numbers
|
||
|
|
||
|
digit_to_letter = {}
|
||
|
for l, d in zip(letters_a, digits_a):
|
||
|
if d in digit_to_letter and digit_to_letter[d] != l:
|
||
|
# Each digit can only be assigned to one letter
|
||
|
return False
|
||
|
digit_to_letter[d] = l
|
||
|
|
||
|
|
||
|
letter_to_digit = {l: d for l, d in zip(letters_a, digits_a)}
|
||
|
for l, d in zip(letters_b, digits_b):
|
||
|
if letter_to_digit[l] != d:
|
||
|
return False
|
||
|
return True
|
||
|
|
||
|
|
||
|
def find_pairs(words, squares):
|
||
|
pairs = []
|
||
|
anagram_pairs = find_anagram_pairs(words)
|
||
|
square_pairs = find_anagram_pairs(squares)
|
||
|
for word_pair in anagram_pairs:
|
||
|
for number_pair in square_pairs:
|
||
|
if words_match_numbers(word_pair, number_pair):
|
||
|
# pairs.append([word_pair, number_pair])
|
||
|
pairs.append(number_pair)
|
||
|
return pairs
|
||
|
|
||
|
|
||
|
def euler_098():
|
||
|
squares = [str(i * i) for i in range(200000)]
|
||
|
words = get_words()
|
||
|
|
||
|
largest_number = 0
|
||
|
for i in range(3, 9):
|
||
|
words_i = list(filter(lambda w: len(w) == i, words))
|
||
|
squares_i = list(filter(lambda w: len(w) == i, squares))
|
||
|
pairs = find_pairs(words_i, squares_i)
|
||
|
for pair in pairs:
|
||
|
n = max(map(int, pair))
|
||
|
if n > largest_number:
|
||
|
largest_number = n
|
||
|
return largest_number
|
||
|
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
solution = euler_098()
|
||
|
print("e098.py: " + str(solution))
|
||
|
assert(solution == 18769)
|
||
|
|