This repository has been archived by the owner on May 28, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path21_scrambled_letters_and_hash.py
98 lines (79 loc) · 3.04 KB
/
21_scrambled_letters_and_hash.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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
##############################################
# --- Day 21: Scrambled Letters and Hash --- #
##############################################
import AOCUtils
def scramble(password, steps):
password = list(password)
for step in steps:
step = step.split()
if step[0] == "move":
a, b = int(step[2]), int(step[5])
c = password[a]
if b > a:
password[a:b] = password[a+1:b+1]
else:
password[b+1:a+1] = password[b:a]
password[b] = c
elif step[0] == "reverse":
a, b = int(step[2]), int(step[4])
password[a:b+1] = reversed(password[a:b+1])
elif step[0] == "rotate":
if step[1] == "based":
c = password.index(step[-1])
n = c + 1 + int(c >= 4)
else:
n = int(step[2])
if step[1] == "left": n *= -1
n %= len(password)
password = password[-n:] + password[:-n] # Rotate right
elif step[0] == "swap":
if step[1] == "letter":
a, b = password.index(step[2]), password.index(step[5])
elif step[1] == "position":
a, b = int(step[2]), int(step[5])
password[a], password[b] = password[b], password[a]
return "".join(password)
def unscramble(password, steps):
password = list(password)
for step in reversed(steps):
step = step.split()
if step[0] == "move":
b, a = int(step[2]), int(step[5])
c = password[a]
if b > a:
password[a:b] = password[a+1:b+1]
else:
password[b+1:a+1] = password[b:a]
password[b] = c
elif step[0] == "reverse":
a, b = int(step[2]), int(step[4])
password[a:b+1] = reversed(password[a:b+1])
elif step[0] == "rotate":
if step[1] == "based":
c = step[-1]
# Rotate 1 left until c is at position i
# At the 4th rotation, rotate twice
i = 0
while True:
n = 1 + int(i == 4)
password = password[n:] + password[:n] # Rotate left
if password[i] == c:
break
i += 1
else:
n = int(step[2])
if step[1] == "left": n *= -1
n %= len(password)
password = password[n:] + password[:n] # Rotate left
elif step[0] == "swap":
if step[1] == "letter":
a, b = password.index(step[2]), password.index(step[5])
elif step[1] == "position":
a, b = int(step[2]), int(step[5])
password[a], password[b] = password[b], password[a]
return "".join(password)
##############################################
steps = AOCUtils.loadInput(21)
print("Part 1: {}".format(scramble("abcdefgh", steps)))
print("Part 2: {}".format(unscramble("fbgdceah", steps)))
AOCUtils.printTimeTaken()