-
Notifications
You must be signed in to change notification settings - Fork 0
/
15b.py
executable file
·144 lines (108 loc) · 5.69 KB
/
15b.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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#!/usr/bin/python3
# python3 -m doctest -v 15b.py
'''
--- Part Two ---
You convince the reindeer to bring you the page; the page confirms that your HASH algorithm is working.
The book goes on to describe a series of 256 boxes numbered 0 through 255. The boxes are arranged in a line starting from the point where light enters the facility. The boxes have holes that allow light to pass from one box to the next all the way down the line.
+-----+ +-----+ +-----+
Light | Box | | Box | ... | Box |
----------------------------------------->
| 0 | | 1 | ... | 255 |
+-----+ +-----+ +-----+
Inside each box, there are several lens slots that will keep a lens correctly positioned to focus light passing through the box. The side of each box has a panel that opens to allow you to insert or remove lenses as necessary.
Along the wall running parallel to the boxes is a large library containing lenses organized by focal length ranging from 1 through 9. The reindeer also brings you a small handheld label printer.
The book goes on to explain how to perform each step in the initialization sequence, a process it calls the Holiday ASCII String Helper Manual Arrangement Procedure, or HASHMAP for short.
Each step begins with a sequence of letters that indicate the label of the lens on which the step operates. The result of running the HASH algorithm on the label indicates the correct box for that step.
The label will be immediately followed by a character that indicates the operation to perform: either an equals sign (=) or a dash (-).
If the operation character is a dash (-), go to the relevant box and remove the lens with the given label if it is present in the box. Then, move any remaining lenses as far forward in the box as they can go without changing their order, filling any space made by removing the indicated lens. (If no lens in that box has the given label, nothing happens.)
If the operation character is an equals sign (=), it will be followed by a number indicating the focal length of the lens that needs to go into the relevant box; be sure to use the label maker to mark the lens with the label given in the beginning of the step so you can find it later. There are two possible situations:
If there is already a lens in the box with the same label, replace the old lens with the new lens: remove the old lens and put the new lens in its place, not moving any other lenses in the box.
If there is not already a lens in the box with the same label, add the lens to the box immediately behind any lenses already in the box. Don't move any of the other lenses when you do this. If there aren't any lenses in the box, the new lens goes all the way to the front of the box.
Here is the contents of every box after each step in the example initialization sequence above:
After "rn=1":
Box 0: [rn 1]
After "cm-":
Box 0: [rn 1]
After "qp=3":
Box 0: [rn 1]
Box 1: [qp 3]
After "cm=2":
Box 0: [rn 1] [cm 2]
Box 1: [qp 3]
After "qp-":
Box 0: [rn 1] [cm 2]
After "pc=4":
Box 0: [rn 1] [cm 2]
Box 3: [pc 4]
After "ot=9":
Box 0: [rn 1] [cm 2]
Box 3: [pc 4] [ot 9]
After "ab=5":
Box 0: [rn 1] [cm 2]
Box 3: [pc 4] [ot 9] [ab 5]
After "pc-":
Box 0: [rn 1] [cm 2]
Box 3: [ot 9] [ab 5]
After "pc=6":
Box 0: [rn 1] [cm 2]
Box 3: [ot 9] [ab 5] [pc 6]
After "ot=7":
Box 0: [rn 1] [cm 2]
Box 3: [ot 7] [ab 5] [pc 6]
All 256 boxes are always present; only the boxes that contain any lenses are shown here. Within each box, lenses are listed from front to back; each lens is shown as its label and focal length in square brackets.
To confirm that all of the lenses are installed correctly, add up the focusing power of all of the lenses. The focusing power of a single lens is the result of multiplying together:
One plus the box number of the lens in question.
The slot number of the lens within the box: 1 for the first lens, 2 for the second lens, and so on.
The focal length of the lens.
At the end of the above example, the focusing power of each lens is as follows:
rn: 1 (box 0) * 1 (first slot) * 1 (focal length) = 1
cm: 1 (box 0) * 2 (second slot) * 2 (focal length) = 4
ot: 4 (box 3) * 1 (first slot) * 7 (focal length) = 28
ab: 4 (box 3) * 2 (second slot) * 5 (focal length) = 40
pc: 4 (box 3) * 3 (third slot) * 6 (focal length) = 72
So, the above example ends up with a total focusing power of 145.
With the help of an over-enthusiastic reindeer in a hard hat, follow the initialization sequence. What is the focusing power of the resulting lens configuration?
'''
with open('input/15.txt', 'r') as f:
# with open('input/15-small.txt', 'r') as f:
# with open('input/15-small-2.txt', 'r') as f:
lines = f.readlines()
lines = [l.rstrip() for l in lines]
lines = [l for l in lines if l]
def hash2(i):
h = 0
for ch in i:
n = ord(ch)
h = ((h + n) * 17) % 256
return h
inc = lines[0].split(',')
box = [list() for i in range(256)]
for i in inc:
ix_op = i.find('=')
if ix_op < 0:
# -
ix_op = i.find('-')
label = i[:ix_op]
ix_box = hash2(label)
new_content = [p for p in box[ix_box] if p[0] != label]
box[ix_box] = new_content
else: # =
label = i[:ix_op]
ix_box = hash2(label)
s = i[ix_op + 1:]
lens = int(s)
found = False
for id_slot in range(len(box[ix_box])):
lbl, _ = box[ix_box][id_slot]
if lbl == label:
box[ix_box][id_slot] = (label, lens)
found = True
if not found:
box[ix_box].append((label, lens))
total = 0
for id_box, b in enumerate(box):
if len(b) > 0:
for id_slot, pair in enumerate(b):
label, lens = pair
total += (id_box + 1) * (id_slot + 1) * lens
print(f'total={total}')