Advertisement
Guest User

Untitled

a guest
Dec 9th, 2024
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.08 KB | None | 0 0
  1. """AoC 9, 2024."""
  2.  
  3. # Standard library imports
  4. import pathlib
  5. import sys
  6.  
  7.  
  8. def part1(data):
  9. """Solve part 1."""
  10. disk = data[0]
  11. left_pointer = 0
  12. right_pointer = len(disk) - 1
  13.  
  14. while(left_pointer < right_pointer):
  15. # do stuff
  16. while disk[left_pointer] != "." and left_pointer < right_pointer:
  17. left_pointer = left_pointer + 1
  18.  
  19. while disk[right_pointer] == "." and left_pointer < right_pointer:
  20. right_pointer = right_pointer - 1
  21.  
  22. # we should be in a state of swapping now
  23. disk[left_pointer], disk[right_pointer] = disk[right_pointer], disk[left_pointer]
  24.  
  25. left_pointer = left_pointer + 1
  26. right_pointer = right_pointer - 1
  27.  
  28. total = 0
  29. # calculate the filesystem checksum
  30. for i, digit in enumerate(disk):
  31. if digit == ".":
  32. break
  33.  
  34. total = total + (i * int(digit))
  35.  
  36. return total
  37.  
  38.  
  39. def parse_data(puzzle_input):
  40. """Parse input."""
  41. compressed_disk = list(puzzle_input)
  42. disk = []
  43. id = 0
  44. for i, digit in enumerate(compressed_disk):
  45. is_file = i % 2 == 0
  46. if is_file:
  47. for _ in range(int(digit)):
  48. disk.append(str(id))
  49.  
  50. id = id + 1
  51. else:
  52. for _ in range(int(digit)):
  53. disk.append(".")
  54.  
  55. return disk, id
  56.  
  57.  
  58. def part2(data):
  59. """Solve part 2."""
  60. # print("\nStarting the disk compaction process...")
  61.  
  62. disk = list(data[0]) # Ensure the disk is mutable
  63. max_id = data[1]
  64. print(f"Initial disk state: {''.join(disk)}")
  65.  
  66. # Loop over file IDs in descending order
  67. for current_id in range(max_id - 1, -1, -1):
  68. current_id_str = str(current_id)
  69. print(f"\nProcessing file ID: {current_id_str}")
  70.  
  71. # Find all file blocks and free space blocks
  72. file_blocks = find_contiguous_blocks(disk, current_id_str)
  73. free_blocks = find_contiguous_blocks(disk, ".")
  74.  
  75. # Debug output: show the identified blocks
  76. print(f"File blocks for ID {current_id_str}: {file_blocks}")
  77. print(f"Free space blocks: {free_blocks}")
  78.  
  79. # We need to attempt moving the files one by one
  80. for file_start, file_end in file_blocks:
  81. file_size = file_end - file_start + 1
  82. print(f"File block found from {file_start} to {file_end} (size {file_size})")
  83.  
  84. # Find leftmost free block that can fit the file
  85. for free_start, free_end in free_blocks:
  86. free_size = free_end - free_start + 1
  87. print(f"Checking free block from {free_start} to {free_end} (size {free_size})")
  88.  
  89. if free_size >= file_size:
  90. print(f"Found enough free space for file ID {current_id_str} in block from {free_start} to {free_end}")
  91.  
  92. if free_start > file_start and free_end > file_end:
  93. print(f"Skipping free block starting at {free_start} because it starts after the file block at {file_start}")
  94. continue
  95.  
  96. # Move file to free space, from left to right
  97. for i in range(file_size):
  98. disk[free_start + i] = current_id_str
  99. disk[file_start + i] = "."
  100.  
  101. print(f"Moved file ID {current_id_str} to position {free_start}")
  102.  
  103. # Update free space after file movement
  104. free_blocks = find_contiguous_blocks(disk, ".")
  105. print(f"Updated free blocks after move: {free_blocks}")
  106.  
  107. # Stop moving this file, since it's already moved
  108. break # Move to the next file block
  109.  
  110. # Visualize the disk after processing each file ID
  111. print(f"Disk state after processing file ID {current_id_str}: {''.join(disk)}")
  112.  
  113. print("\nFinal disk state:", ''.join(disk))
  114. total = 0
  115. for i, digit in enumerate(disk):
  116. if digit == ".":
  117. continue
  118. total = total + (i * int(digit))
  119. return total
  120.  
  121. def find_contiguous_blocks(disk, char):
  122. """Find all contiguous blocks of a given character in the disk."""
  123. blocks = []
  124. start = None
  125. for i, c in enumerate(disk):
  126. if c == char:
  127. if start is None:
  128. start = i
  129. else:
  130. if start is not None:
  131. blocks.append((start, i - 1))
  132. start = None
  133. if start is not None:
  134. blocks.append((start, len(disk) - 1))
  135. return blocks
  136.  
  137.  
  138.  
  139. def solve(puzzle_input):
  140. """Solve the puzzle for the given input."""
  141. data = parse_data(puzzle_input)
  142. yield part1(data)
  143. yield part2(data)
  144.  
  145.  
  146. if __name__ == "__main__":
  147. for path in sys.argv[1:]:
  148. print(f"\n{path}:")
  149. solutions = solve(puzzle_input=pathlib.Path(path).read_text().rstrip())
  150. print("\n".join(str(solution) for solution in solutions))
  151.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement