commit 40bb7b6585266071b48ebabc71a17c23b33b02c5 Author: Markus Birth Date: Tue Dec 1 01:00:18 2015 +0100 Initial commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..f65c706 --- /dev/null +++ b/README.md @@ -0,0 +1,34 @@ +Acrostic Solver +=============== + +Get a dictionary file (text file with one word per line) from [here](http://www.puzzlers.org/dokuwiki/doku.php?id=solving:wordlists:about:start) +and change the `WORDLIST` variable accordingly. + + +`SQUARE` holds the square - without spaces or anything else. Just all letters one after another. + + +At the bottom, the `letters` variable holds all available letters from the `SQUARE` and their amounts. + +To start a search, run: + +``` +result = try_solve(letters.copy()) +print(result) +``` + +If it doesn't find anything, try a different wordlist or specify a limit to which you want to search to: + +``` +result = try_solve(letters.copy(), max_level=4) +print(result) +``` + +If you already have the first and second words, use this: + +``` +rem_first = check_valid("BEACON", letters.copy()) # get remaining letters after first word +rem_second = check_valid("NROBE", rem_first.copy()) # get remaining letters after second word (NOTE: Since the letter "E" is used up already, we specify NROBE.) +result = try_solve(rem_second.copy(), ["BEACON", "ENROBE"]) # solve remaining +print(result) +``` diff --git a/solve.py b/solve.py new file mode 100755 index 0000000..7e80d27 --- /dev/null +++ b/solve.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python3 +# (c)2015 Markus Birth +# -*- coding: utf-8 -*- + +import math + +WORDLIST="web2.txt" + +#SQUARE="NRONACNELEGOOESLEIEECIDEAIRBBTBODETS" +#SQUARE="DUAEAYURIZESAEIRLPESPESRSSESSAPPSEED" +#SQUARE="ERRSERYTORLTERYRERSLEEOSE" +#SQUARE="NNREDCTEMAROACRAMEEIAIMTONCTETERESEC" +#SQUARE="NEREILGEDENALRLELRIGNAATREONALETUGTE" +#SQUARE="FNADIHALNARTANUUGIANFALNSCGNTATRICTS" +SQUARE="RRCOLALAALETSTEIIRSATSTRRECCAEOSEHRE" +word_len = math.sqrt(len(SQUARE)) + +print("Word length: %i" % word_len) + + +def count_letters(pool): + letters = {} + + for i in range(len(pool)): + letter = pool[i] + if not letter in letters: + letters[letter] = 1 + else: + letters[letter] += 1 + + return letters + +letters = count_letters(SQUARE) +print(repr(letters)) + +for l in letters: + if letters[l]%2 == 1: + print("Diag candidate: %s" % l) + +candidates = [] + +f = open("web2.txt", "r") +for line in f: + line = line.strip().upper() + # check word length + if len(line) != word_len: + continue + # check word letters + cand_letters = count_letters(line) + for l in cand_letters: + if not l in letters: + break + # If a letter occurs twice in a word, we need at least 3 to build it across and down. (1=>1, 2=>3, 3=>5, etc.) + if cand_letters[l]*2-1 > letters[l]: + break + else: + candidates.append(line) + +f.close() + +#for c in candidates: +# print(c) + +print("%i candidates." % len(candidates)) +#print(candidates) + +def check_valid(word, letters): + for i in range(len(word)): + l = word[i] + if not l in letters: + return False + if letters[l]>1: + letters[l] -= 1 + else: + del letters[l] + if i == 0: + continue + if not l in letters: + return False + if letters[l]>1: + letters[l] -= 1 + else: + del letters[l] + return letters + +def try_solve(letters, words = [], max_level = 99): + level = len(words) + if level == max_level: + return ["---ABORTED---"] + start_letters = "" + for i in range(len(words)): + start_letters += words[i][level] +# if level == max_level -1: +# print("Prefix: %s, letters: %s" % (start_letters, repr(letters))) + next_matches = [] + for w in candidates: + if w[:level] != start_letters: + continue + rem_letters = check_valid(w[level:], letters.copy()) + if type(rem_letters) is dict: +# next_matches.append(w) + if len(rem_letters)>0: + more = try_solve(rem_letters.copy(), words + [w], max_level) + if more: + next_matches.append((w, more)) + else: + next_matches.append(w) + return next_matches + +#rem_first = check_valid("BEACON", letters.copy()) +#rem_second = check_valid("NROBE", rem_first.copy()) +#print(rem_second) +#result = try_solve(rem_second.copy(), ["BEACON", "ENROBE"]) + +result = try_solve(letters.copy(), max_level=5) +print(result) \ No newline at end of file