""" Advent of Code 2021 - Day 07 Run with: python puzzles/day07.py inputs/day07.txt """ import pathlib import sys from statistics import median from typing import List, Tuple class AlignCrabSubs: positions: List[int] def __init__(self, positions: List[int]) -> None: self.positions = positions def calc_fuel(self, pricey: bool = False) -> int: if not pricey: return self.calc_fuel_simple(median(self.positions)) fuel = None for position in range(len(set(self.positions)) + 1): price = self.calc_fuel_pricey(position) if fuel is None or fuel > price: fuel = price return fuel def calc_fuel_simple(self, target: int) -> int: return int(sum(abs(num - target) for num in self.positions)) def calc_fuel_pricey(self, target: int) -> int: # This is slow and needs reworking fuel = 0 for num in self.positions: num_range = abs(num - target) + 1 fuel += sum(range(num_range)) return int(fuel) def part1(inputs: List[int]) -> int: subs = AlignCrabSubs(inputs) return subs.calc_fuel() def part2(inputs: List[int]) -> int: subs = AlignCrabSubs(inputs) return subs.calc_fuel(pricey=True) def parse(inputs: str) -> List[int]: """Parse the input string""" return [int(value) for value in inputs.split(",")] def solve(path: str) -> Tuple[int, int]: """Solve the puzzle""" puzzle_input = parse(pathlib.Path(path).read_text().strip()) part1_result = part1(puzzle_input) part2_result = part2(puzzle_input) return part1_result, part2_result def main() -> None: for path in sys.argv[1:]: print(f"Input File: {path}") part1_result, part2_result = solve(path) print(f"Part 1 Result: {part1_result}") print(f"Part 2 Result: {part2_result}") if __name__ == "__main__": main()