2017-12-16 - Permutation Promenade
(original .ipynb)
puzzle_input_str = open("puzzle_input/day16.txt").read()
def init_programs(limit):
curr = ord("a")
programs = []
while curr <= ord(limit):
programs.append(chr(curr))
curr += 1
return programs
def spin(programs, x):
new_programs = []
while x > 0:
new_programs.insert(0, programs.pop())
x -= 1
return new_programs + programs
def exchange(programs, a, b):
new_programs = [c for c in programs]
a_val = new_programs[a]
b_val = new_programs[b]
new_programs[a] = b_val
new_programs[b] = a_val
return new_programs
def partner(programs, a, b):
return exchange(programs, programs.index(a), programs.index(b))
def read_int(sequence, pos):
ints = []
while pos < len(sequence) and sequence[pos].isdigit():
ints.append(sequence[pos])
pos += 1
return int("".join(ints)), pos
def dance(programs, sequences):
n = 0
while n < len(sequences):
sequence = [c for c in sequences[n]]
command = sequence[0]
pos = 1
if command == "s":
x, pos = read_int(sequence, pos)
programs = spin(programs, x)
elif command == "x":
a, pos = read_int(sequence, pos)
pos += 1 # should be a "/"
b, pos = read_int(sequence, pos)
programs = exchange(programs, a, b)
elif command == "p":
a = sequence[pos]
b = sequence[pos+2]
programs = partner(programs, a, b)
pos += 3
else:
raise Exception(f"unknown command: {command}")
n += 1
return programs
def part_one(input_str, limit="p"):
programs = init_programs(limit)
sequences = input_str.split(",")
return "".join(dance(programs, sequences))
assert "baedc" == part_one("s1,x3/4,pe/b", "e")
print("part one:", part_one(puzzle_input_str))
part one: ebjpfdgmihonackl
# gonna assume we hit a pattern, and just need to find how frequently it repeats
def part_two(input_str, limit="p"):
programs = init_programs(limit)
sequences = input_str.split(",")
iterations = 0
seen = set([input_str])
pattern_at_iteration = {0:input_str}
max_iterations = 1_000_000_000
while iterations < max_iterations: # we hopefully won't hit this
programs = dance(programs, sequences)
pattern = "".join(programs)
if pattern in seen:
return pattern_at_iteration[max_iterations % iterations]
iterations += 1
seen.add(pattern)
pattern_at_iteration[iterations] = pattern
print("part two:", part_two(puzzle_input_str))
part two: abocefghijklmndp