advent24-llm / day09 /solution_jerpint.py
jerpint's picture
Add solution files
a4da721
def load_data(file):
with open(file) as f:
return f.read().strip("\n")
def generate_blocks(disk_map):
blocks = []
for idx, i in enumerate(disk_map):
if idx % 2:
blocks.extend( ["."]*int(i))
else:
blocks.extend( [str(idx // 2)] *int(i))
return blocks
def get_next_valid_block_from_end(end: int, blocks):
for j in range(end, -1, -1):
if blocks[j] != ".":
return j
def compact_blocks(blocks):
# blocks = list(blocks)
end = get_next_valid_block_from_end(len(blocks) - 1, blocks)
for idx, block in enumerate(blocks):
if end == idx:
break
if block == ".":
blocks[idx] = blocks[end]
blocks[end] = "."
end = get_next_valid_block_from_end(end, blocks)
# print("".join(blocks))
return blocks
def compute_checksum(blocks):
checksum = 0
for idx, num in enumerate(blocks):
if num == ".":
return checksum
checksum += idx*int(num)
return checksum
disk_map = load_data("input.txt")
blocks = generate_blocks(disk_map)
compact_blocks = compact_blocks(blocks)
print(compute_checksum(compact_blocks))
## Part two
def generate_blocks(disk_map):
blocks = []
for idx, i in enumerate(disk_map):
if idx % 2:
if int(i) > 0:
blocks.append( ["."]*int(i))
else:
blocks.append( [str(idx // 2)] *int(i))
return blocks
def get_free_space_map(blocks):
free_space_map = []
pos = 0
for idx, block in enumerate(blocks):
if block[0] == ".":
free_space_map.append((idx, len(block)))
pos += len(block)
return free_space_map
def get_next_valid_block_from_end(blocks):
for idx, block in enumerate(blocks[::-1]):
if block[0] != ".":
block_idx = len(blocks) - idx - 1
return block, block_idx
def pprint(blocks):
print("".join(["".join(b) for b in blocks]))
def move_block_at_fileid(blocks, file_id: int):
free_space_map = get_free_space_map(blocks)
# block = blocks[block_idx]
for idx, block in enumerate(blocks):
if block[0] != "." and block[0] == str(file_id):
block_idx = idx
break
K = len(block)
for free_block_idx, free_len in free_space_map:
if free_len > K and free_block_idx < block_idx:
# First condition means we have more space than needed
# Second condition ensures we Only move forward in queue, not backwards
blocks[free_block_idx] = ["."] * (free_len - len(block)) # Remaining free memory after insert
blocks.insert(free_block_idx, block) # Insert at index
blocks[block_idx + 1] = ["."] * K # Overwrite at end (+1 because we added a new index)
return True
elif free_len == K and free_block_idx < block_idx:
# First condition means we have just enough space
# Second condition ensures we Only move forward in queue, not backwards
blocks[free_block_idx] = block
blocks[block_idx] = ["."] * K
return True
return False
def compute_checksum(blocks):
blocks_ext = [b for block in blocks for b in block]
checksum = 0
for idx, num in enumerate(blocks_ext):
if num == ".":
continue
checksum += idx*int(num)
return checksum
def get_max_file_id(blocks):
for block in blocks[::-1]:
if block[0] != ".":
max_file_id = int(block[0])
return max_file_id
disk_map = load_data("input.txt")
blocks = generate_blocks(disk_map)
max_file_id = get_max_file_id(blocks)
# pprint(blocks)
for file_id in range(max_file_id, -1, -1):
# Progress-bar
# if file_id % 1000 == 0:
# print(file_id)
moved = move_block_at_fileid(blocks, file_id)
# if moved:
# pprint(blocks)
print(compute_checksum(blocks))