Created
September 7, 2020 21:56
-
-
Save ekimekim/61c329c94f84701c63cb66dc09ce8e8e to your computer and use it in GitHub Desktop.
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 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 "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