This repository has been archived by the owner on Jan 2, 2023. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
21.py
67 lines (46 loc) · 2.44 KB
/
21.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#!/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'))))