diff --git a/2015/d02.py b/2015/d02.py index c1d96d7..2403dee 100755 --- a/2015/d02.py +++ b/2015/d02.py @@ -2,6 +2,7 @@ """Advent of Code: Day 02.""" import itertools +import math from lib import aoc @@ -33,5 +34,5 @@ def part2(self, puzzle_input: InputType) -> int: total = 0 for dims in puzzle_input: perimeters = [a + b for a, b in itertools.combinations(dims, 2)] - total += min(perimeters) * 2 + self.mult(dims) + total += min(perimeters) * 2 + math.prod(dims) return total diff --git a/2015/d20.py b/2015/d20.py index 109262e..a10697f 100755 --- a/2015/d20.py +++ b/2015/d20.py @@ -75,7 +75,7 @@ def part1_nope_a(self, puzzle_input: InputType) -> int: pfactors = prime_factors(i) factors = set(pfactors) for l in range(2, len(pfactors)): - factors.update(self.mult(c) for c in itertools.combinations(pfactors, l)) + factors.update(math.prod(c) for c in itertools.combinations(pfactors, l)) amount = sum(factors) + 1 + i if amount >= target: diff --git a/2015/d24.py b/2015/d24.py index a13f982..5cb2191 100755 --- a/2015/d24.py +++ b/2015/d24.py @@ -2,6 +2,7 @@ """Advent of Code, Day 24: It Hangs in the Balance. Balance numbers into groups with contraints.""" import itertools +import math from lib import aoc @@ -26,7 +27,7 @@ def balance(self, packages: list[int], groups: int) -> int: for package_count in range(1, len(packages)): for group in itertools.combinations(packages, package_count): if sum(group) == group_size: - candidates.append(self.mult(group)) + candidates.append(math.prod(group)) if candidates: break return min(candidates) diff --git a/2019/d08.py b/2019/d08.py index 53831ba..6db1a34 100755 --- a/2019/d08.py +++ b/2019/d08.py @@ -5,6 +5,7 @@ """ import collections +import math import more_itertools from lib import aoc @@ -44,4 +45,4 @@ def part2(self, puzzle_input: str) -> int: # Displays the actual solution. # print('\n'.join(out)) # Meaningless number to use in the solutions file. - return self.mult(sum(True for i in row if i != ' ') for row in out) + return math.prod(sum(True for i in row if i != ' ') for row in out) diff --git a/2020/d16.py b/2020/d16.py index ddbd513..41cb691 100755 --- a/2020/d16.py +++ b/2020/d16.py @@ -1,6 +1,7 @@ #!/usr/bin/env python """Train tickets.""" +import math from lib import aoc # Fudge the second sample to include departure rows @@ -133,4 +134,4 @@ def part2(self, data) -> int: candidates.remove(column) # Multiply all the fields that start with "departure". - return self.mult(v for k, v in completed_ticket.items() if k.startswith('departure')) + return math.prod(v for k, v in completed_ticket.items() if k.startswith('departure')) diff --git a/2020/d20.py b/2020/d20.py index 513b709..a75c14f 100755 --- a/2020/d20.py +++ b/2020/d20.py @@ -4,6 +4,7 @@ from lib import aoc import collections import enum +import math from typing import Dict, List, Tuple import data @@ -290,7 +291,7 @@ def part1(self, blocks: List[str]) -> int: # Four corners. Top left, top right, bottom left, bottom right. line = list(range(4)) corners = zip(line, line[1:] + line[:1]) - return self.mult( + return math.prod( self.find_corner(tiles, corner) for corner in corners ) diff --git a/2021/d09.py b/2021/d09.py index d2e873d..b613980 100755 --- a/2021/d09.py +++ b/2021/d09.py @@ -1,6 +1,7 @@ #!/bin/python """Advent of Code: Day 09.""" +import math from lib import aoc SAMPLE = ["""\ @@ -46,4 +47,4 @@ def part2(self, puzzle_input: aoc.Map) -> int: basins = aoc.partition_regions(unexplored, predicate=lambda a, b: True) basin_sizes = (len(basin) for basin in basins) - return aoc.Helpers.mult(sorted(basin_sizes, reverse=True)[:3]) + return math.prod(sorted(basin_sizes, reverse=True)[:3]) diff --git a/2022/d08.py b/2022/d08.py index 844d7bb..0d23a3d 100755 --- a/2022/d08.py +++ b/2022/d08.py @@ -1,6 +1,7 @@ #!/bin/python """Advent of Code, Day 8: Treetop Tree House. Compute tree visibility.""" +import math from lib import aoc SAMPLE = [ @@ -73,6 +74,6 @@ def part2(self, puzzle_input: aoc.Map) -> int: break cur += direction visible.append(num) - scores.append(self.mult(visible)) + scores.append(math.prod(visible)) return max(scores) diff --git a/2022/d11.py b/2022/d11.py index eee7f8b..83bcf69 100755 --- a/2022/d11.py +++ b/2022/d11.py @@ -96,7 +96,7 @@ def solver(self, monkeys: list[Monkey], part_one: bool) -> int: monkeys[next_monkey].items.append(item) monkey.items = [] inspected = sorted(monkey.inspected for monkey in monkeys) - return self.mult(inspected[-2:]) + return math.prod(inspected[-2:]) def input_parser(self, puzzle_input: str) -> InputType: """Parse the input data.""" diff --git a/2022/d13.py b/2022/d13.py index 05c112e..5333553 100755 --- a/2022/d13.py +++ b/2022/d13.py @@ -3,6 +3,7 @@ import functools import json +import math from typing import Any from lib import aoc @@ -35,7 +36,7 @@ InputType = list[list[Any]] # cmp for integers. -int_cmp = aoc.Helpers.cmp +int_cmp = aoc.cmp def cmp(first: Any, second: Any) -> int: @@ -87,4 +88,4 @@ def part2(self, puzzle_input: InputType) -> int: for pair in pairs: vals.extend(pair) vals.sort(key=functools.cmp_to_key(cmp)) - return self.mult(vals.index(divider) + 1 for divider in dividers) + return math.prod(vals.index(divider) + 1 for divider in dividers) diff --git a/2022/d19.py b/2022/d19.py index 526f818..dc9e2d2 100755 --- a/2022/d19.py +++ b/2022/d19.py @@ -1,6 +1,7 @@ #!/bin/python """Advent of Code, Day 19: Not Enough Minerals.""" +import math import re from lib import aoc @@ -140,7 +141,7 @@ def part1(self, puzzle_input: InputType) -> int: return sum(idx * score for idx, score in enumerate(scores, start=1)) def part2(self, puzzle_input: InputType) -> int: - return self.mult(self.simulator(puzzle_input[:3], 32)) + return math.prod(self.simulator(puzzle_input[:3], 32)) def input_parser(self, puzzle_input: str) -> InputType: """Parse the input data.""" diff --git a/pylib/aoc.py b/pylib/aoc.py index d4fd1a6..4aab000 100644 --- a/pylib/aoc.py +++ b/pylib/aoc.py @@ -359,7 +359,7 @@ def render(points: set[complex], off: str = COLOR_EMPTY, on: str = COLOR_SOLID) return "\n".join(rows) -def sign(number: int) -> int: +def sign(number: float) -> int: """Return the "sign" of a number, i.e. 1 or -1.""" if number > 0: return 1 @@ -368,6 +368,16 @@ def sign(number: int) -> int: return 0 +def cmp(a: float, b: float) -> int: + """Compare two numbers like Perl <=>. + + Binary "<=>" returns -1, 0, or 1 depending on whether the left argument + is numerically less than, equal to, or greater than the right argument. + """ + return sign(a - b) + + + def reading_order(data: Sequence[complex]) -> list[complex]: return sorted(data, key=lambda x: (x.imag, x.real)) @@ -433,27 +443,6 @@ class Helpers: _primes = [2, 3, 5] _gcd: dict[tuple[int, int], int] = {} - @staticmethod - def cmp(a: float, b: float) -> int: - """Compare two numbers like Perl <=>. - - Binary "<=>" returns -1, 0, or 1 depending on whether the left argument - is numerically less than, equal to, or greater than the right argument. - """ - if a < b: - return -1 - if a > b: - return +1 - return 0 - - @staticmethod - def mult(nums: Iterable[int]) -> int: - """Product of all values. Like sum() but with multiplication.""" - p = 1 - for n in nums: - p *= n - return p - @staticmethod def sum_map(lines: List[str], func: Callable[[str], int]) -> int: """sum_map(lines, func)"""