12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667 |
- #!/usr/bin/python3
-
- """Solution for day 21 of Advent of Code 2016.
-
- Each operation has an entry in the ops dictionary, which mangles arguments and does pre-processing before handing off
- to one of the main methods to perform the actual transformation.
-
- For part two, the reverse_ops dictionary maps most operations to a reverse of their original. The only exception is
- 'rotate based on position', which is just brute-forced by rotating the letters and seeing if the forward instruction
- puts them back to the expected positions.
- """
-
-
- from functools import reduce
-
- ops = {
- 'swap position': lambda l, a: swap_positions(l, int(a[0]), int(a[3])),
- 'swap letter': lambda l, a: swap_letter(l, a[0], a[3]),
- 'rotate left': lambda l, a: rotate(l, -int(a[0])),
- 'rotate right': lambda l, a: rotate(l, int(a[0])),
- 'rotate based': lambda l, a: rotate(l, 1 + l.index(a[4]) + (1 if l.index(a[4]) > 3 else 0)),
- 'reverse positions': lambda l, a: reverse(l, int(a[0]), int(a[2])),
- 'move position': lambda l, a: move(l, int(a[0]), int(a[3])),
- }
-
- reverse_ops = {
- 'swap position': lambda l, a: swap_positions(l, int(a[3]), int(a[0])),
- 'swap letter': ops['swap letter'],
- 'rotate left': ops['rotate right'],
- 'rotate right': ops['rotate left'],
- 'rotate based': lambda l, a: reverse_rotation(l, a),
- 'reverse positions': ops['reverse positions'],
- 'move position': lambda l, a: move(l, int(a[3]), int(a[0])),
- }
-
-
- def swap_positions(letters, x, y):
- letters[x], letters[y] = letters[y], letters[x]
- return letters
-
-
- def swap_letter(letters, a, b):
- return [a if l == b else b if l == a else l for l in letters]
-
-
- def rotate(letters, num):
- num %= len(letters)
- return letters[-num:] + letters[:-num]
-
-
- def reverse(letters, start, end):
- return letters[:start] + letters[start:end+1][::-1] + letters[end+1:]
-
-
- def move(letters, start, end):
- letters.insert(end, letters.pop(start))
- return letters
-
-
- def reverse_rotation(l, a):
- return [rotate(l, i) for i in range(len(l)) if ops['rotate based'](rotate(l, i), a) == l][0]
-
-
- with open('data/21.txt', 'r') as file:
- instr = list(map(lambda x: [' '.join(x.split(' ')[0:2])] + x.strip().split(' ')[2:], file.readlines()))
- print('Part one: %s' % ''.join(reduce(lambda l, o: ops[o[0]](l, o[1:]), instr, list('abcdefgh'))))
- print('Part two: %s' % ''.join(reduce(lambda l, o: reverse_ops[o[0]](l, o[1:]), instr[::-1], list('fbgdceah'))))
|