from time import clock
from random import randint
class mathagram(object):
def __init__(self, first, second, third,
fourth=None, fifth=None, sixth=None,
seventh=None, eighth=None, ninth=None):
self.level = 0
self.unused_nums = range(1, 10)
self.input = [first, second, third, fourth, fifth, sixth, seventh, eighth, ninth]
if self.input.count(None) == 6:
self.level = 1
elif self.input.count(None) == 3:
self.level = 2
else:
self.level = 3
self.unused_nums *= self.level
#remove used numbers
for opt in self.input:
if not opt is None:
for char_ in opt:
try:
if int(char_) in self.unused_nums:
self.unused_nums.remove(int(char_))
except ValueError:
pass
self.unused_nums.sort() # sorted for shits and giggles
def guess(self):
abc = []
if self.level >= 1:
a, b, c = list(self.input[0:3])
abc.extend([a, b, c])
if self.level >= 2:
d, e, f = list(self.input[3:6])
abc.extend([d, e, f,])
if self.level == 3:
g, h, i = list(self.input[6:9])
abc.extend([g, h, i])
# basically replaces 'x' with a random unused number
for idx,currStr in enumerate(abc):
if currStr != None:
currStr = list(currStr)
for idx_, int_ in enumerate(currStr):
if int_ == 'x':
guess = randint(0, (len(self.unused_nums)-1))
replace = self.unused_nums[guess]
currStr[idx_] = str(replace)
self.unused_nums.remove(replace)
attempt = int(''.join(currStr))
abc[idx] = attempt
if self.level == 1:
if (abc[0] + abc[1]) == abc[2]:
print "{} + {} = {}".format(*abc[0:3])
return True
else:
return False
elif self.level == 2:
if (abc[0] + abc[1] + abc[2] + abc[3]) == (abc[4] + abc[5]):
print "{} + {} + {} + {} = {} + {}".format(*abc[0:6])
return True
else:
return False
elif self.level == 3:
if (abc[0] + abc[1] + abc[2] + abc[3] + abc[4]) == (abc[5] + abc[6] + abc[7] + abc[8]):
print "{} + {} + {} + {} + {} = {} + {} + {} + {}".format(*abc[0:10])
return True
else:
return False
# end of class
# running the class to make the calculations and print pretty things
programStart = clock()
tests = [('1xx', 'xxx', '468'),
('xxx', 'x81', '9x4'),
('xxx', '5x1', '86x'),
('xxx', '39x', 'x75'),
('xxx', 'xxx', '5x3', '123', 'xxx', '795'),
('xxx', 'xxx', '23x', '571', 'xxx', 'x82'),
('xxx', 'xxx', 'xx7', '212', 'xxx', '889'),
('xxx', 'xxx', '1x6', '142', 'xxx', '533'),
('xxx', 'xxx', 'xxx', 'x29', '821', 'xxx', 'xxx', '8xx', '867'),
('xxx', 'xxx', 'xxx', '4x1', '689', 'xxx', 'xxx', 'x5x', '957'),
('xxx', 'xxx', 'xxx', '64x', '581', 'xxx', 'xxx', 'xx2', '623'),
('xxx', 'xxx', 'xxx', 'x81', '759', 'xxx', 'xxx', '8xx', '462'),
('xxx', 'xxx', 'xxx', '6x3', '299', 'xxx', 'xxx', 'x8x', '423'),
('xxx', 'xxx', 'xxx', '58x', '561', 'xxx', 'xxx', 'xx7', '993'),
# the one below takes 5-30 minutes to solve
#('xxx', 'xxx', 'xxx', 'xxx', 'xxx', '987', '944', '921', '8x5'),
('987', '978', '111', '222', '33x', 'xxx', 'xxx', 'xxx', 'xxx')
]
# main guessing occurs here. Make a new object each time. Not sure if safe.
for equation in tests:
solved = False
c = 0
loopStart = clock()
while solved == False:
m = mathagram(*equation) # <== I learned something new!
solved = m.guess()
c += 1
else:
loopElapsed = (clock() - loopStart)
print "{} attempts in {} seconds.".format(c, round(loopElapsed, 3))
#finalize and beautify
programElapsed = (clock() - programStart)
if programElapsed > 60:
pMinutes = programElapsed // 60
pSeconds = programElapsed % 60
print "All mathagrams calculated in {}:{} minuetes.".format(pMinutes, round(pSeconds, 3))
else:
print "All mathagrams calculated in {} seconds.".format(round(programElapsed, 3))
ZnJvbSB0aW1lIGltcG9ydCBjbG9jawpmcm9tIHJhbmRvbSBpbXBvcnQgcmFuZGludAoKY2xhc3MgbWF0aGFncmFtKG9iamVjdCk6CgkKCWRlZiBfX2luaXRfXyhzZWxmLCBmaXJzdCwgc2Vjb25kLCB0aGlyZCwgCgkgICAgICAgICAgICAgICAgICAgICBmb3VydGg9Tm9uZSwgZmlmdGg9Tm9uZSwgc2l4dGg9Tm9uZSwKCQkJCQkJIHNldmVudGg9Tm9uZSwgZWlnaHRoPU5vbmUsIG5pbnRoPU5vbmUpOgoJCXNlbGYubGV2ZWwgPSAwCQkJCSAKCQlzZWxmLnVudXNlZF9udW1zID0gcmFuZ2UoMSwgMTApCgkJc2VsZi5pbnB1dCA9IFtmaXJzdCwgc2Vjb25kLCB0aGlyZCwgZm91cnRoLCBmaWZ0aCwgc2l4dGgsIHNldmVudGgsIGVpZ2h0aCwgbmludGhdCgkJaWYgc2VsZi5pbnB1dC5jb3VudChOb25lKSA9PSA2OgoJCQlzZWxmLmxldmVsID0gMQoJCWVsaWYgc2VsZi5pbnB1dC5jb3VudChOb25lKSA9PSAzOgoJCQlzZWxmLmxldmVsID0gMgoJCWVsc2U6CgkJCXNlbGYubGV2ZWwgPSAzCgkJc2VsZi51bnVzZWRfbnVtcyAqPSBzZWxmLmxldmVsCQkJCQkKCQkjcmVtb3ZlIHVzZWQgbnVtYmVycwkJCQkJCgkJZm9yIG9wdCBpbiBzZWxmLmlucHV0OgoJCQlpZiBub3Qgb3B0IGlzIE5vbmU6CgkJCQlmb3IgY2hhcl8gaW4gb3B0OgoJCQkJCXRyeToKCQkJCQkJaWYgaW50KGNoYXJfKSBpbiBzZWxmLnVudXNlZF9udW1zOgoJCQkJCQkJc2VsZi51bnVzZWRfbnVtcy5yZW1vdmUoaW50KGNoYXJfKSkKCQkJCQlleGNlcHQgVmFsdWVFcnJvcjoKCQkJCQkJcGFzcwoJCXNlbGYudW51c2VkX251bXMuc29ydCgpICMgc29ydGVkIGZvciBzaGl0cyBhbmQgZ2lnZ2xlcwoJCQkKCWRlZiBndWVzcyhzZWxmKToKCQlhYmMgID0gW10KCQlpZiBzZWxmLmxldmVsID49IDE6CgkJCWEsIGIsIGMgPSBsaXN0KHNlbGYuaW5wdXRbMDozXSkKCQkJYWJjLmV4dGVuZChbYSwgYiwgY10pCgkJaWYgc2VsZi5sZXZlbCA+PSAyOgoJCQlkLCBlLCBmID0gbGlzdChzZWxmLmlucHV0WzM6Nl0pCgkJCWFiYy5leHRlbmQoW2QsIGUsIGYsXSkKCQlpZiBzZWxmLmxldmVsID09IDM6CgkJCWcsIGgsIGkgPSBsaXN0KHNlbGYuaW5wdXRbNjo5XSkKCQkJYWJjLmV4dGVuZChbZywgaCwgaV0pCgkJIyBiYXNpY2FsbHkgcmVwbGFjZXMgJ3gnIHdpdGggYSByYW5kb20gdW51c2VkIG51bWJlcgoJCWZvciBpZHgsY3VyclN0ciBpbiBlbnVtZXJhdGUoYWJjKToKCQkJaWYgY3VyclN0ciAhPSBOb25lOgoJCQkJY3VyclN0ciA9IGxpc3QoY3VyclN0cikKCQkJCWZvciBpZHhfLCBpbnRfIGluIGVudW1lcmF0ZShjdXJyU3RyKToKCQkJCQlpZiBpbnRfID09ICd4JzoKCQkJCQkJZ3Vlc3MgPSByYW5kaW50KDAsIChsZW4oc2VsZi51bnVzZWRfbnVtcyktMSkpCgkJCQkJCXJlcGxhY2UgPSBzZWxmLnVudXNlZF9udW1zW2d1ZXNzXQoJCQkJCQljdXJyU3RyW2lkeF9dID0gc3RyKHJlcGxhY2UpCgkJCQkJCXNlbGYudW51c2VkX251bXMucmVtb3ZlKHJlcGxhY2UpCgkJCQlhdHRlbXB0ID0gaW50KCcnLmpvaW4oY3VyclN0cikpCgkJCQlhYmNbaWR4XSA9IGF0dGVtcHQKCQkKCQlpZiBzZWxmLmxldmVsID09IDE6CgkJCWlmIChhYmNbMF0gKyBhYmNbMV0pID09IGFiY1syXToKCQkJCXByaW50ICJ7fSArIHt9ID0ge30iLmZvcm1hdCgqYWJjWzA6M10pCgkJCQlyZXR1cm4gVHJ1ZQoJCQllbHNlOgoJCQkJcmV0dXJuIEZhbHNlCgkJZWxpZiBzZWxmLmxldmVsID09IDI6CgkJCWlmIChhYmNbMF0gKyBhYmNbMV0gKyBhYmNbMl0gKyBhYmNbM10pID09IChhYmNbNF0gKyBhYmNbNV0pOgoJCQkJcHJpbnQgInt9ICsge30gKyB7fSArIHt9ID0ge30gKyB7fSIuZm9ybWF0KCphYmNbMDo2XSkKCQkJCXJldHVybiBUcnVlCgkJCWVsc2U6CgkJCQlyZXR1cm4gRmFsc2UKCQllbGlmIHNlbGYubGV2ZWwgPT0gMzoKCQkJaWYgKGFiY1swXSArIGFiY1sxXSArIGFiY1syXSArIGFiY1szXSArIGFiY1s0XSkgPT0gKGFiY1s1XSArIGFiY1s2XSArIGFiY1s3XSArIGFiY1s4XSk6CgkJCQlwcmludCAie30gKyB7fSArIHt9ICsge30gKyB7fSA9IHt9ICsge30gKyB7fSArIHt9Ii5mb3JtYXQoKmFiY1swOjEwXSkKCQkJCXJldHVybiBUcnVlCgkJCWVsc2U6CgkJCQlyZXR1cm4gRmFsc2UKIyBlbmQgb2YgY2xhc3MKIyBydW5uaW5nIHRoZSBjbGFzcyB0byBtYWtlIHRoZSBjYWxjdWxhdGlvbnMgYW5kIHByaW50IHByZXR0eSB0aGluZ3MKcHJvZ3JhbVN0YXJ0ID0gY2xvY2soKQp0ZXN0cyA9IFsoJzF4eCcsICd4eHgnLCAnNDY4JyksCgkJICAoJ3h4eCcsICd4ODEnLCAnOXg0JyksCgkJICAoJ3h4eCcsICc1eDEnLCAnODZ4JyksCgkJICAoJ3h4eCcsICczOXgnLCAneDc1JyksCgkJICAoJ3h4eCcsICd4eHgnLCAnNXgzJywgJzEyMycsICd4eHgnLCAnNzk1JyksCgkJICAoJ3h4eCcsICd4eHgnLCAnMjN4JywgJzU3MScsICd4eHgnLCAneDgyJyksCgkJICAoJ3h4eCcsICd4eHgnLCAneHg3JywgJzIxMicsICd4eHgnLCAnODg5JyksCgkJICAoJ3h4eCcsICd4eHgnLCAnMXg2JywgJzE0MicsICd4eHgnLCAnNTMzJyksCgkJICAoJ3h4eCcsICd4eHgnLCAneHh4JywgJ3gyOScsICc4MjEnLCAneHh4JywgJ3h4eCcsICc4eHgnLCAnODY3JyksCgkJICAoJ3h4eCcsICd4eHgnLCAneHh4JywgJzR4MScsICc2ODknLCAneHh4JywgJ3h4eCcsICd4NXgnLCAnOTU3JyksCgkJICAoJ3h4eCcsICd4eHgnLCAneHh4JywgJzY0eCcsICc1ODEnLCAneHh4JywgJ3h4eCcsICd4eDInLCAnNjIzJyksCgkJICAoJ3h4eCcsICd4eHgnLCAneHh4JywgJ3g4MScsICc3NTknLCAneHh4JywgJ3h4eCcsICc4eHgnLCAnNDYyJyksCgkJICAoJ3h4eCcsICd4eHgnLCAneHh4JywgJzZ4MycsICcyOTknLCAneHh4JywgJ3h4eCcsICd4OHgnLCAnNDIzJyksCgkJICAoJ3h4eCcsICd4eHgnLCAneHh4JywgJzU4eCcsICc1NjEnLCAneHh4JywgJ3h4eCcsICd4eDcnLCAnOTkzJyksCgkJICAjIHRoZSBvbmUgYmVsb3cgdGFrZXMgNS0zMCBtaW51dGVzIHRvIHNvbHZlCgkJICAjKCd4eHgnLCAneHh4JywgJ3h4eCcsICd4eHgnLCAneHh4JywgJzk4NycsICc5NDQnLCAnOTIxJywgJzh4NScpLAoJCSAgKCc5ODcnLCAnOTc4JywgJzExMScsICcyMjInLCAnMzN4JywgJ3h4eCcsICd4eHgnLCAneHh4JywgJ3h4eCcpCgkJICBdCiMgbWFpbiBndWVzc2luZyBvY2N1cnMgaGVyZS4gTWFrZSBhIG5ldyBvYmplY3QgZWFjaCB0aW1lLiBOb3Qgc3VyZSBpZiBzYWZlLgkJICAKZm9yIGVxdWF0aW9uIGluIHRlc3RzOgoJc29sdmVkID0gRmFsc2UKCWMgPSAwCglsb29wU3RhcnQgPSBjbG9jaygpCgl3aGlsZSBzb2x2ZWQgPT0gRmFsc2U6CgkJbSA9IG1hdGhhZ3JhbSgqZXF1YXRpb24pICMgPD09IEkgbGVhcm5lZCBzb21ldGhpbmcgbmV3IQoJCXNvbHZlZCA9IG0uZ3Vlc3MoKQoJCWMgKz0gMQoJZWxzZToKCQlsb29wRWxhcHNlZCA9IChjbG9jaygpIC0gbG9vcFN0YXJ0KQoJCXByaW50ICJ7fSBhdHRlbXB0cyBpbiB7fSBzZWNvbmRzLiIuZm9ybWF0KGMsIHJvdW5kKGxvb3BFbGFwc2VkLCAzKSkKI2ZpbmFsaXplIGFuZCBiZWF1dGlmeQpwcm9ncmFtRWxhcHNlZCA9IChjbG9jaygpIC0gcHJvZ3JhbVN0YXJ0KQppZiBwcm9ncmFtRWxhcHNlZCA+IDYwOgoJcE1pbnV0ZXMgPSBwcm9ncmFtRWxhcHNlZCAvLyA2MAoJcFNlY29uZHMgPSBwcm9ncmFtRWxhcHNlZCAlIDYwCglwcmludCAiQWxsIG1hdGhhZ3JhbXMgY2FsY3VsYXRlZCBpbiB7fTp7fSBtaW51ZXRlcy4iLmZvcm1hdChwTWludXRlcywgcm91bmQocFNlY29uZHMsIDMpKQplbHNlOgoJcHJpbnQgIkFsbCBtYXRoYWdyYW1zIGNhbGN1bGF0ZWQgaW4ge30gc2Vjb25kcy4iLmZvcm1hdChyb3VuZChwcm9ncmFtRWxhcHNlZCwgMykpCg==