solve Day05 Part2 in Python

This commit is contained in:
wieerwill 2023-12-06 19:08:52 +01:00
parent 39280b7906
commit 53818e5bd2
2 changed files with 57 additions and 57 deletions

View File

@ -1,61 +1,67 @@
import os
import gc
from itertools import groupby
def free_up_memory():
"""Explicitly frees up memory."""
gc.collect()
def parse_ranges(line):
"""Parses a line containing seed ranges."""
numbers = list(map(int, line.split()))
return [(numbers[i], numbers[i + 1]) for i in range(0, len(numbers), 2)]
def parse_input(file_path):
"""Parses the input file into seeds and categories."""
with open(file_path) as file:
lines = file.read().splitlines()
def map_single_seed_through_category(seed, category_map):
"""Maps a single seed through a category based on the mapping."""
print(f"map seed {seed} in category map")
for source_start, (dest_start, range_length) in category_map.items():
if source_start <= seed < source_start + range_length:
return dest_start + (seed - source_start)
return seed
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_category(file, ranges):
"""Processes seed ranges through a single category based on the file lines."""
category_map = {}
for i, line in file:
line = line.strip()
if not line or ':' in line: # End of the current category map
break
dest_start, source_start, range_length = map(int, line.split())
category_map[source_start] = (dest_start, range_length)
print(f"parsed line {i} in file")
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:]]
# Process each seed through the category map
mapped_seeds = set()
for start, length in ranges:
print(f"process range {start} with length {length}")
for i in range(length):
seed = start + i
mapped_seed = map_single_seed_through_category(seed, category_map)
mapped_seeds.add(mapped_seed)
return mapped_seeds
def process_file(file_path):
"""Processes the file to find the lowest location number for the seed ranges."""
try:
with open(file_path, 'r') as file:
ranges = parse_ranges(file.readline().split(':')[1])
while True:
line = file.readline()
if not line: # End of file
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
if ':' in line: # Start of a new category map
ranges = {(seed, 1) for seed in process_category(file, ranges)}
else:
sources.append((start, end))
lowest_location = min(ranges)[0]
seeds_numbers = sources
return seeds_numbers
return lowest_location
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.")
@ -66,21 +72,16 @@ def test():
"""Run tests using the test.txt file."""
print("Starting test")
expected_result = 46 # Updated expected result for the new puzzle
result = process_file('../test.txt')
assert result == expected_result, f"Test failed, expected 46 but got {result}"
print(f"Test passed: {result}")
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:
# Run tests first
test()
free_up_memory() # Free memory after testing
# Process actual input
print("Starting input.txt")
result = process_file("../input.txt")
print(f"Total result from input.txt: {result}")
find_lowest_location("../input.txt")
free_up_memory()
except Exception as e:

View File

@ -1,6 +1,5 @@
# Advent of Code 2023
# 🎄 Advent of Code 2023 🎄
## Overview
Welcome to my repository where I share my solutions for the [Advent of Code 2023](https://adventofcode.com/2023). Advent of Code is an annual online event where participants solve a series of programming puzzles released daily from December 1st until December 25th. Each puzzle is a fun and unique challenge designed to test problem-solving skills.
## Structure
@ -16,13 +15,13 @@ Within each folder, you'll find:
- `README.md`: A brief description of the day's problem.
- Source code files: My solution for the day's puzzle, typically in Python or Rust
- `input.txt`: The input data provided for the puzzle.
- `input.txt`: The input data provided for the puzzle. (add those yourself as we don't provide those for legal reasons)
- Additional resources or notes if applicable.
## My Approach
For Advent of Code 2023, I've decided to primarily use Python due to its readability and the extensive libraries available, which make it an excellent choice for solving diverse and complex problems quickly. In each solution, I focus not only on solving the problem but also on writing clean, efficient, and well-documented code.
## Progress
## 📈 Progress
Here I'll track my progress throughout the event.
I aim to complete each day's puzzle on the same day, but as with any challenge, there might be some delays.
@ -32,7 +31,7 @@ I aim to complete each day's puzzle on the same day, but as with any challenge,
| 02 | ✅ | ✅ | [Day02 README](/Day02/README.md) |
| 03 | ✅ | ✅ | [Day03 README](/Day03/README.md) |
| 04 | ✅ | ✅ | [Day04 README](/Day04/README.md) |
| 05 | ✅ | | [Day05 README](/Day05/README.md) |
| 05 | ✅ | | [Day05 README](/Day05/README.md) |
| 06 | ❓ | ❓ | [Day06 README](/Day06/README.md) |
| 07 | ❓ | ❓ | [Day07 README](/Day07/README.md) |
| 08 | ❓ | ❓ | [Day08 README](/Day08/README.md) |