|
1 | 1 | #!/bin/python |
2 | 2 | """Advent of Code, Day 6: Trash Compactor.""" |
3 | | -from __future__ import annotations |
4 | | - |
5 | | -import collections |
6 | | -import functools |
7 | | -import itertools |
8 | | -import logging |
9 | | -import math |
10 | | -import re |
11 | | - |
12 | 3 | from lib import aoc |
13 | 4 |
|
14 | | -SAMPLE = [ |
15 | | - """\ |
| 5 | +SAMPLE = """\ |
16 | 6 | 123 328 51 64 |
17 | 7 | 45 64 387 23 |
18 | 8 | 6 98 215 314 |
19 | | -* + * +""", # 2 |
20 | | -] |
21 | | - |
22 | | -LineType = int |
23 | | -InputType = list[LineType] |
24 | | -log = logging.info |
| 9 | +* + * +""" |
25 | 10 |
|
26 | 11 |
|
27 | 12 | class Day06(aoc.Challenge): |
28 | 13 | """Day 6: Trash Compactor.""" |
29 | 14 |
|
30 | | - DEBUG = True |
31 | | - # Default is True. On live solve, submit one tests pass. |
32 | | - # SUBMIT = {1: False, 2: False} |
33 | | - |
34 | 15 | TESTS = [ |
35 | | - aoc.TestCase(part=1, inputs=SAMPLE[0], want=4277556), |
36 | | - aoc.TestCase(part=2, inputs=SAMPLE[0], want=3263827), |
37 | | - # aoc.TestCase(part=2, inputs=SAMPLE[0], want=aoc.TEST_SKIP), |
| 16 | + aoc.TestCase(part=1, inputs=SAMPLE, want=4277556), |
| 17 | + aoc.TestCase(part=2, inputs=SAMPLE, want=3263827), |
38 | 18 | ] |
39 | | - |
40 | | - # INPUT_PARSER = aoc.parse_ints |
41 | 19 | INPUT_PARSER = aoc.parse_one_str |
42 | | - # INPUT_PARSER = aoc.parse_one_str_per_line |
43 | | - # INPUT_PARSER = aoc.parse_multi_str_per_line |
44 | | - # INPUT_PARSER = aoc.parse_one_int |
45 | | - # INPUT_PARSER = aoc.parse_one_int_per_line |
46 | | - # INPUT_PARSER = aoc.parse_ints_one_line |
47 | | - # INPUT_PARSER = aoc.parse_ints_per_line |
48 | | - # INPUT_PARSER = aoc.parse_re_group_str(r"(a) .* (b) .* (c)") |
49 | | - # INPUT_PARSER = aoc.parse_re_findall_str(r"(a|b|c)") |
50 | | - # INPUT_PARSER = aoc.parse_multi_mixed_per_line |
51 | | - # INPUT_PARSER = aoc.parse_re_group_mixed(r"(foo) .* (\d+)") |
52 | | - # INPUT_PARSER = aoc.parse_re_findall_mixed(r"\d+|foo|bar") |
53 | | - # INPUT_PARSER = aoc.ParseBlocks([aoc.parse_one_str_per_line, aoc.parse_re_findall_int(r"\d+")]) |
54 | | - # INPUT_PARSER = aoc.ParseOneWord(aoc.Board.from_int_block) |
55 | | - # INPUT_PARSER = aoc.CoordinatesParser(chars=None, origin_top_left=True) |
56 | | - # --- |
57 | | - # (width, height), start, garden, rocks = puzzle_input |
58 | | - # max_x, max_y = width - 1, height - 1 |
59 | | - |
60 | | - def part1(self, puzzle_input: InputType) -> int: |
61 | | - puzzle_input = aoc.parse_multi_str_per_line.parse(puzzle_input) |
62 | | - numbers = [ |
63 | | - [int(i) for i in line] |
64 | | - for line in puzzle_input[:-1] |
65 | | - ] |
66 | | - numbers = list(zip(*numbers)) |
67 | | - total = 0 |
68 | | - for nums, op in zip(numbers, puzzle_input[-1]): |
69 | | - if op == "+": |
70 | | - total += sum(nums) |
71 | | - else: |
72 | | - total += math.prod(nums) |
73 | | - return total |
74 | 20 |
|
75 | | - def part2(self, puzzle_input: InputType) -> int: |
| 21 | + def part1(self, puzzle_input: str) -> int: |
| 22 | + """Return the answer for the math homework.""" |
| 23 | + *lines, operators = [line.split() for line in puzzle_input.splitlines()] |
| 24 | + numbers = [[int(i) for i in line] for line in lines] |
| 25 | + transposed = zip(*numbers) |
| 26 | + return sum( |
| 27 | + aoc.LIST_OPS[op](nums) |
| 28 | + for nums, op in zip(transposed, operators) |
| 29 | + ) |
| 30 | + |
| 31 | + def part2(self, puzzle_input: str) -> int: |
| 32 | + """Return the answer for the math homework.""" |
76 | 33 | *nums, ops = puzzle_input.splitlines() |
77 | | - starts = [idx for idx, char in enumerate(ops) if char != " "] |
78 | | - ends = [i - 1 for i in starts[1:]] + [max(len(i) for i in nums)] |
| 34 | + longest_line = max(len(i) for i in puzzle_input.splitlines()) |
| 35 | + starts = [idx for idx, char in enumerate(ops) if char != " "] + [longest_line + 1] |
| 36 | + operators = ops.split() |
| 37 | + |
79 | 38 | total = 0 |
80 | | - operators = [i for i in ops if i != " "] |
81 | | - # print(starts, ends, operators) |
82 | | - for start, end, op in zip(starts, ends, operators): |
83 | | - numbers = [] |
84 | | - for col in range(start, end): |
85 | | - number = "" |
86 | | - for line in nums: |
87 | | - if line[col] != " ": |
88 | | - number += line[col] |
89 | | - numbers.append(int(number)) |
90 | | - # print(numbers, op) |
91 | | - if op == "+": |
92 | | - total += sum(numbers) |
93 | | - else: |
94 | | - total += math.prod(numbers) |
| 39 | + for start, end, op in zip(starts, starts[1:], operators): |
| 40 | + # Collect all columns. |
| 41 | + numbers = [ |
| 42 | + int( |
| 43 | + # Collect all lines for one column. |
| 44 | + "".join( |
| 45 | + line[col] for line in nums if line[col] != " " |
| 46 | + ) |
| 47 | + ) |
| 48 | + for col in range(start, end - 1) |
| 49 | + ] |
| 50 | + total += aoc.LIST_OPS[op](numbers) |
95 | 51 | return total |
96 | 52 |
|
97 | | - |
98 | | - |
99 | | - # def solver(self, puzzle_input: InputType, part_one: bool) -> int | str: |
100 | | - |
101 | 53 | # vim:expandtab:sw=4:ts=4 |
0 commit comments