Last active
December 15, 2015 20:58
-
-
Save jbalboni/5322150 to your computer and use it in GitHub Desktop.
Python solution for generating a string that contains all possible N digit combinations and is as short as possible. The problem was described as Batman needing the combinations to open a lock and escape, hence the numerous cheesy Batman references. Default number of digits is 4.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import math | |
import sys | |
class BatSequenceGenerator(): | |
"""Class to generate a key sequence Batman can use to escape""" | |
def __init__(self, digits=4): | |
self.digits = digits | |
#char sequence | |
self.bat_sequence = [] | |
#Batman thought Bat Hash sounded cooler than Bat Dict | |
self.bat_hash = {} | |
#Add the new combinations covered, based on how much was added to the sequence | |
def update_bat_hash(self, str_size): | |
if str_size < 0: | |
for str_len in xrange(1, abs(str_size) + 1): | |
self.bat_hash["".join(self.bat_sequence[-(str_len + self.digits):-str_len])] = 1 | |
else: | |
for str_len in xrange(1, abs(str_size) + 1): | |
self.bat_hash["".join(self.bat_sequence[str_len:str_len + self.digits])] = 1 | |
#The important, Batman-saving method | |
def generate_bat_sequence(self): | |
self.bat_sequence = [] | |
self.bat_hash = {} | |
#loop through all possible combinations | |
bat_combos = xrange(int(math.pow(10, self.digits))) | |
for combo in bat_combos: | |
bat_combo = "%04d" % combo | |
#there's no need to add the combination to our string if it's in the hash | |
if bat_combo not in self.bat_hash: | |
#just getting started | |
if len(self.bat_sequence) == 0: | |
self.bat_sequence.extend(list(bat_combo)) | |
self.bat_hash[bat_combo] = 1 | |
else: | |
added = False | |
#we want to add as few digits as possible, so see if there's a matching substring | |
#at either end of the sequence and then add the non-matching digits | |
for str_size in reversed(xrange(1, self.digits)): | |
if list(bat_combo[:str_size]) == self.bat_sequence[-str_size:]: | |
added = True | |
self.bat_sequence.extend(list(bat_combo[-(self.digits - str_size):])) | |
self.update_bat_hash(-self.digits - str_size) | |
break | |
elif list(bat_combo[-str_size:]) == self.bat_sequence[:str_size]: | |
added = True | |
self.bat_sequence = list(bat_combo[:self.digits - str_size]) + self.bat_sequence | |
self.update_bat_hash(self.digits - str_size) | |
break | |
#No substring, just append the combo to the sequence | |
if not added: | |
self.bat_sequence.extend(list(bat_combo)) | |
self.update_bat_hash(-self.digits) | |
return self.bat_sequence | |
#Batman wanted some assurance you didn't screw this up | |
def bat_tester(self, sequence): | |
for combo in xrange(int(math.pow(10, self.digits))): | |
bat_combo = "%04d" % combo | |
if bat_combo not in sequence: | |
print "Batman DIED because you missed %s! HOW COULD YOU!?" % bat_combo | |
return | |
print "Batman ESCAPED! You must be very proud." | |
if __name__ == '__main__': | |
if len(sys.argv) > 1 and sys.argv[1].lower() == "--quiet": | |
sequencer = BatSequenceGenerator() | |
output = sequencer.generate_bat_sequence() | |
print "".join(output) | |
else: | |
print "Welcome to the Save Batman Key Sequence Generator Thingy" | |
print "How many digits is the combination?" | |
input = raw_input() | |
try: | |
input_digits = int(input) | |
except ValueError: | |
print "I'm sorry, Batman doesn't know that number and assumes you meant 4." | |
input_digits = 4 | |
print "Finding sequence for Batman..." | |
sequencer = BatSequenceGenerator(input_digits) | |
output = sequencer.generate_bat_sequence() | |
print "".join(output) | |
print "You gave Batman a %d digit combination. Batman is not looking forward to this." % len(output) | |
print "Batman is using your combination to escape..." | |
sequencer.bat_tester("".join(output)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment