-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday_9.py
101 lines (73 loc) · 2.53 KB
/
day_9.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
from utils import read_input
def map_fn(line):
# Filesystem is the state of disk
filesystem = {}
file_lengths = {}
file_start_indices = {}
empty_space_lengths = []
file_id = 0
fs_pointer = 0
for idx, value in enumerate(line):
value = int(value)
# Is file
if idx % 2 == 0:
file_start_indices[file_id] = fs_pointer
file_lengths[file_id] = value
for _ in range(value):
filesystem[fs_pointer] = file_id
fs_pointer += 1
file_id += 1
# Is empty space
else:
empty_space_lengths.append((fs_pointer, value))
fs_pointer += value
return filesystem, (file_lengths, empty_space_lengths, file_start_indices)
def part_1():
fs, _ = read_input(9, map_fn)[0]
max_idx = max(fs)
for i in range(max_idx + 1):
if fs.get(i) is not None:
# It's a file in a correct spot, do nothing
continue
while fs.get(max_idx) is None:
# Find the right-most file index
max_idx -= 1
if i >= max_idx:
# Don't move files to the right
break
# Move from end to the current empty spot
fs[i] = fs[max_idx]
# Delete old file block pointer
del fs[max_idx]
max_idx -= 1
checksum = sum(index * file_id for index, file_id in fs.items())
print(f"Part 1: {checksum}")
assert checksum == 6288707484810
def find_empty_slot(empty_spaces, length):
for index, (fs_index, empty_length) in enumerate(empty_spaces):
if empty_length >= length:
return (index, (fs_index))
return None
def part_2():
fs, (file_lengths, empty_lengths, file_start_indices) = read_input(9, map_fn)[0]
for file_id in reversed(file_lengths):
length = file_lengths[file_id]
empty_slot = find_empty_slot(empty_lengths, length)
if empty_slot is None:
continue
empty_lengths_idx, empty_fs_idx = empty_slot
start_idx = file_start_indices[file_id]
if empty_fs_idx > start_idx:
continue
for k in range(length):
fs[empty_fs_idx + k] = fs[start_idx + k]
del fs[start_idx + k]
empty_lengths[empty_lengths_idx] = (
empty_fs_idx + length,
empty_lengths[empty_lengths_idx][1] - length,
)
checksum = sum(index * file_id for index, file_id in fs.items())
print(f"Part 2: {checksum}")
assert checksum == 6311837662089
part_1()
part_2()