92 lines
3.1 KiB
Python
92 lines
3.1 KiB
Python
import os
|
|
import gc
|
|
from itertools import groupby
|
|
|
|
def free_up_memory():
|
|
"""Explicitly frees up memory."""
|
|
gc.collect()
|
|
|
|
def parse_input(file_path):
|
|
"""Parses the input file into seeds and categories."""
|
|
with open(file_path) as file:
|
|
lines = file.read().splitlines()
|
|
|
|
groups = [tuple(group) for not_empty, group in groupby(lines, bool) if not_empty]
|
|
seeds, *categories = groups
|
|
seeds_ranges = tuple(map(int, seeds[0].split()[1:]))
|
|
seeds_numbers = [
|
|
(seeds_ranges[i], seeds_ranges[i] + seeds_ranges[i + 1])
|
|
for i in range(0, len(seeds_ranges), 2)
|
|
]
|
|
return seeds_numbers, categories
|
|
|
|
def process_categories(seeds_numbers, categories):
|
|
"""Processes the seed ranges through all categories."""
|
|
for category in categories:
|
|
ranges = [tuple(map(int, numbers.split())) for numbers in category[1:]]
|
|
|
|
sources = []
|
|
while seeds_numbers:
|
|
start, end = seeds_numbers.pop()
|
|
for destination, source, length in ranges:
|
|
overlap_start = max(start, source)
|
|
overlap_end = min(end, source + length)
|
|
if overlap_start < overlap_end:
|
|
sources.append(
|
|
(
|
|
overlap_start - source + destination,
|
|
overlap_end - source + destination,
|
|
)
|
|
)
|
|
if overlap_start > start:
|
|
seeds_numbers.append((start, overlap_start))
|
|
if end > overlap_end:
|
|
seeds_numbers.append((overlap_end, end))
|
|
break
|
|
else:
|
|
sources.append((start, end))
|
|
|
|
seeds_numbers = sources
|
|
return seeds_numbers
|
|
|
|
def find_lowest_location(file_path, is_test=False, expected_result=None):
|
|
"""Finds the lowest location number from the input file."""
|
|
try:
|
|
seeds_numbers, categories = parse_input(file_path)
|
|
seeds_numbers = process_categories(seeds_numbers, categories)
|
|
lowest_location = min(seeds_numbers)[0]
|
|
|
|
if is_test:
|
|
assert lowest_location == expected_result, f"Test failed, expected {expected_result} but got {lowest_location}"
|
|
print("Test passed.")
|
|
else:
|
|
print(f"Lowest location from {file_path}: {lowest_location}")
|
|
return lowest_location
|
|
|
|
except FileNotFoundError:
|
|
print(f"Error: File '{file_path}' not found.")
|
|
except Exception as e:
|
|
print(f"An error occurred processing '{file_path}': {e}")
|
|
|
|
def test():
|
|
"""Run tests using the test.txt file."""
|
|
print("Starting test")
|
|
expected_result = 46 # Updated expected result for the new puzzle
|
|
find_lowest_location('../test.txt', is_test=True, expected_result=expected_result)
|
|
|
|
def main():
|
|
"""Main function to process the input file and display results."""
|
|
try:
|
|
test()
|
|
free_up_memory() # Free memory after testing
|
|
|
|
print("Starting input.txt")
|
|
find_lowest_location("../input.txt")
|
|
free_up_memory()
|
|
|
|
except Exception as e:
|
|
print(f"An error occurred: {e}")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|