Skip to content

Instantly share code, notes, and snippets.

@ekimekim
Created September 7, 2020 21:56
Show Gist options
  • Save ekimekim/61c329c94f84701c63cb66dc09ce8e8e to your computer and use it in GitHub Desktop.
Save ekimekim/61c329c94f84701c63cb66dc09ce8e8e to your computer and use it in GitHub Desktop.
import itertools as it
import argh
def get_tries(codes, permute, start, offset, hardcodes):
"""
codes is list of codes
permute is a permutation of (0, 1, 2) where the value at index i
is the index (MSD first) of the digit in the counting number to be used in that position.
eg. (0, 1, 2) is identity, (2, 0, 1) is rotated right once.
Counting numbers start from START and are tried in order:
START, START + OFFSET, START + 2, START + OFFSET + 2, etc.
Offset must be odd.
Hardcodes is how many of the longest codes to ignore.
"""
not_found = codes.copy()
tries = 0
for i in range(500):
for o in (0, offset):
tries += 1
n = str((start + o + 2 * i) % 1000)
n = '0' * (3 - len(n)) + n # left pad with 0
code = ''.join(n[permute[p]] for p in range(3))
if code in not_found:
not_found.remove(code)
if len(not_found) <= hardcodes:
break
# propogate break
else: continue
break
else:
assert False, "Did not find codes: {}".format(not_found)
return tries, not_found
def main(codes, report=1000, hardcodes=20, target=''):
codes = set(open(codes).read().strip().split())
if target:
permutes, start, offset = target.split(',')
permutes = [map(int, permutes)]
starts = [int(start)]
offsets = [int(offset)]
else:
permutes = it.permutations(range(3))
starts = range(1000)
offsets = range(1, 1000, 2)
options = list(it.product(permutes, starts, offsets))
results = []
for i, (permute, start, offset) in enumerate(options):
if i % report == 0:
print "Done {}/{} ({:.2f}%)".format(i, len(options), 100. * i / len(options))
tries, to_hardcode = get_tries(codes, permute, start, offset, hardcodes)
results.append((permute, start, offset, tries, to_hardcode))
print "Finding best..."
permute, start, offset, tries, to_hardcode = min(results, key=lambda (p, s, o, t, h): (t, o, s))
per_rev = [permute.index(i) for i in range(3)]
example = list(to_hardcode)[0]
print per_rev, example, ''.join(example[per_rev[i]] for i in range(3))
to_hardcode = sorted((
''.join(code[per_rev[i]] for i in range(3))
for code in to_hardcode
), reverse=True)
swiz_digits = ''.join(
str(3-i) for i in permute
)
print "{} tries: digits {}, start {}, offset {}, hardcode: {}".format(
tries, swiz_digits, start, offset, ",".join(to_hardcode),
)
print "As code:"
for code in to_hardcode:
print "COPY {} M".format(code)
print
print "ADDI X {} M".format(start)
print "ADDI X 2 X"
print "ADDI X {} M".format(start + offset - 2)
if __name__ == '__main__':
argh.dispatch_command(main)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment