-
Notifications
You must be signed in to change notification settings - Fork 0
/
formula_solve.py
63 lines (55 loc) · 2.34 KB
/
formula_solve.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# --------------
# User Instructions
#
# Modify the function compile_formula so that the function
# it returns, f, does not allow numbers where the first digit
# is zero. So if the formula contained YOU, f would return
# False anytime that Y was 0
import re
import itertools
import string
import operator
def compile_formula(formula, verbose=False):
"""Compile formula into a function. Also return letters found, as a str,
in same order as parms of function. The first digit of a multi-digit
number can't be 0. So if YOU is a word in the formula, and the function
is called with Y eqal to 0, the function should return False."""
# modify the code in this function.
letters = ''.join(set(re.findall('[A-Z]', formula)))
parms = ', '.join(letters)
tokens = map(compile_word, re.split('([A-Z]+)', formula))
leading_letters = set(re.findall(r'\b([A-Z])[A-Z]', formula))
body = ''.join('%s != 0 and ' % l for l in leading_letters)
body += ''.join(tokens)
f = 'lambda %s: %s' % (parms, body)
if verbose: print f
return eval(f), letters
def compile_word(word):
"""Compile a word of uppercase letters as numeric digits.
E.g., compile_word('YOU') => '(1*U+10*O+100*Y)'
Non-uppercase words uncahanged: compile_word('+') => '+'"""
if word.isupper():
terms = [('%s*%s' % (10**i, d))
for (i, d) in enumerate(word[::-1])]
return '(' + '+'.join(terms) + ')'
else:
return word
def faster_solve(formula):
"""Given a formula like 'ODD + ODD == EVEN', fill in digits to solve it.
Input formula is a string; output is a digit-filled-in string or None.
This version precompiles the formula; only one eval per formula."""
f, letters = compile_formula(formula, True)
for digits in itertools.permutations((1,2,3,4,5,6,7,8,9,0), len(letters)):
try:
if f(*digits) is True:
table = string.maketrans(letters, ''.join(map(str, digits)))
return formula.translate(table)
except ArithmeticError:
pass
return None
def test():
assert faster_solve('A + B == BA') == None # should NOT return '1 + 0 == 01'
assert faster_solve('YOU == ME**2') == ('289 == 17**2' or '576 == 24**2' or '841 == 29**2')
assert faster_solve('X / X == X') == '1 / 1 == 1'
return 'tests pass'
print test()