-
Notifications
You must be signed in to change notification settings - Fork 0
/
day21.py
71 lines (60 loc) · 2.68 KB
/
day21.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
68
69
70
71
import re
FIRST_PASSWORD = 'abcdefgh'
SECOND_PASSWORD = 'fbgdceah'
PASSWORD_LENGTH = len(FIRST_PASSWORD)
INSTRUCTIONS = list(open('day21.txt'))
def rotation_amount(i):
return (1 + i + (1 if i >= 4 else 0)) % PASSWORD_LENGTH
rotation_inverse = {(i + rotation_amount(i)) % PASSWORD_LENGTH: i for i in range(PASSWORD_LENGTH)}
REVERSED_INSTRUCTIONS = []
for line in INSTRUCTIONS:
if line.startswith('rotate based'):
REVERSED_INSTRUCTIONS.append('invert ' + line)
elif line.startswith('rotate left'):
REVERSED_INSTRUCTIONS.append(line.replace('left', 'right'))
elif line.startswith('rotate right'):
REVERSED_INSTRUCTIONS.append(line.replace('right', 'left'))
elif line.startswith('move'):
i, j = re.findall(r'\d+', line)
REVERSED_INSTRUCTIONS.append(f'move position {j} to position {i}')
# swaps and reverse are their own inverses
else:
REVERSED_INSTRUCTIONS.append(line)
REVERSED_INSTRUCTIONS.reverse()
def scramble(password, instructions):
password = list(password)
for line in instructions:
if line.startswith('swap position'):
i, j = map(int, re.findall(r'\d+', line))
password[i], password[j] = password[j], password[i]
elif line.startswith('swap letter'):
a, b = re.findall(r'letter ([a-z])', line)
i, j = password.index(a), password.index(b)
password[i], password[j] = password[j], password[i]
elif line.startswith('move'):
i, j = map(int, re.findall(r'\d+', line))
letter = password.pop(i)
password.insert(j, letter)
elif line.startswith('reverse'):
i, j = map(int, re.findall(r'\d+', line))
password = password[:i] + password[i:j+1][::-1] + password[j+1:]
elif line.startswith('rotate based'):
letter = line[-2]
index = password.index(letter)
rotation = rotation_amount(index)
password = password[-rotation:] + password[:-rotation]
elif line.startswith('invert rotate'):
letter = line[-2]
index = password.index(letter)
want_index = rotation_inverse[index]
rotation = index - want_index
password = password[rotation:] + password[:rotation]
elif line.startswith('rotate'):
_, direction, amount, _ = line.split()
rotation = int(amount) % PASSWORD_LENGTH
if direction == 'right':
rotation *= -1
password = password[rotation:] + password[:rotation]
return ''.join(password)
print('part 1:', scramble(FIRST_PASSWORD, INSTRUCTIONS))
print('part 2:', scramble(SECOND_PASSWORD, REVERSED_INSTRUCTIONS))