Spaces:
Running
Running
def parse_input(s): | |
# Convert the input string into alternating lengths of files and spaces | |
lengths = [int(c) for c in s] | |
# Convert to blocks representation | |
blocks = [] | |
file_id = 0 | |
pos = 0 | |
for i, length in enumerate(lengths): | |
if i % 2 == 0: # File | |
blocks.extend([file_id] * length) | |
file_id += 1 | |
else: # Space | |
blocks.extend([-1] * length) # -1 represents free space | |
return blocks | |
def calculate_checksum(blocks): | |
checksum = 0 | |
for pos, block in enumerate(blocks): | |
if block != -1: # Skip free space | |
checksum += pos * block | |
return checksum | |
def compact_blocks_part1(blocks): | |
result = blocks.copy() | |
while True: | |
# Find rightmost file block | |
right = len(result) - 1 | |
while right >= 0 and result[right] == -1: | |
right -= 1 | |
if right < 0: | |
break | |
# Find leftmost free space | |
left = 0 | |
while left < len(result) and result[left] != -1: | |
left += 1 | |
if left >= right: | |
break | |
# Move one block | |
result[left] = result[right] | |
result[right] = -1 | |
return result | |
def compact_blocks_part2(blocks): | |
result = blocks.copy() | |
# Get unique file IDs in descending order | |
file_ids = sorted(set(x for x in result if x != -1), reverse=True) | |
for file_id in file_ids: | |
# Find all blocks of this file | |
file_blocks = [] | |
start = None | |
for i, block in enumerate(result): | |
if block == file_id: | |
if start is None: | |
start = i | |
file_blocks.append(block) | |
elif start is not None and block != file_id: | |
break | |
if not file_blocks: | |
continue | |
# Remove the file from its current position | |
for i in range(start, start + len(file_blocks)): | |
result[i] = -1 | |
# Find leftmost position where file can fit | |
pos = 0 | |
while pos < len(result): | |
if all(result[i] == -1 for i in range(pos, pos + len(file_blocks)) if i < len(result)): | |
# Place file here | |
for i in range(len(file_blocks)): | |
result[pos + i] = file_id | |
break | |
pos += 1 | |
return result | |
# Read input | |
with open("input.txt", "r") as f: | |
input_data = f.read().strip() | |
# Part 1 | |
blocks = parse_input(input_data) | |
compacted = compact_blocks_part1(blocks) | |
checksum = calculate_checksum(compacted) | |
print(str(checksum)) | |
# Part 2 | |
blocks = parse_input(input_data) | |
compacted = compact_blocks_part2(blocks) | |
checksum = calculate_checksum(compacted) | |
print(str(checksum)) |