Skip to content

Commit 18ff5be

Browse files
Add Day 8: Part 1
1 parent 559f530 commit 18ff5be

File tree

3 files changed

+76
-9
lines changed

3 files changed

+76
-9
lines changed

README.md

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22

33
## Solutions
44

5-
| Advent of Code Page | Part 1 | Part 2 | Day |
6-
|------------------------------------------------------------------|--------|--------|------------------------|
7-
| [Day 1: Historian Hysteria](https://adventofcode.com/2024/day/1) ||| [day1.py](aoc/day1.py) |
8-
| [Day 2: Red-Nosed Reports](https://adventofcode.com/2024/day/2) ||| [day2.py](aoc/day2.py) |
9-
| [Day 3: Mull It Over](https://adventofcode.com/2024/day/3) ||| [day3.py](aoc/day3.py) |
10-
| [Day 4: Ceres Search](https://adventofcode.com/2024/day/4) ||| [day4.py](aoc/day4.py) |
11-
| [Day 5: Print Queue](https://adventofcode.com/2024/day/5) ||| [day5.py](aoc/day5.py) |
12-
| [Day 6: Guard Gallivant](https://adventofcode.com/2024/day/6) ||| [day6.py](aoc/day6.py) |
13-
| [Day 7: Bridge Repair](https://adventofcode.com/2024/day/7) ||| [day7.py](aoc/day7.py) |
5+
| Advent of Code Page | Part 1 | Part 2 | Day |
6+
|---------------------------------------------------------------------|--------|--------|------------------------|
7+
| [Day 1: Historian Hysteria](https://adventofcode.com/2024/day/1) ||| [day1.py](aoc/day1.py) |
8+
| [Day 2: Red-Nosed Reports](https://adventofcode.com/2024/day/2) ||| [day2.py](aoc/day2.py) |
9+
| [Day 3: Mull It Over](https://adventofcode.com/2024/day/3) ||| [day3.py](aoc/day3.py) |
10+
| [Day 4: Ceres Search](https://adventofcode.com/2024/day/4) ||| [day4.py](aoc/day4.py) |
11+
| [Day 5: Print Queue](https://adventofcode.com/2024/day/5) ||| [day5.py](aoc/day5.py) |
12+
| [Day 6: Guard Gallivant](https://adventofcode.com/2024/day/6) ||| [day6.py](aoc/day6.py) |
13+
| [Day 7: Bridge Repair](https://adventofcode.com/2024/day/7) ||| [day7.py](aoc/day7.py) |
14+
| [Day 8: Resonant Collinearity](https://adventofcode.com/2024/day/8) ||| [day8.py](aoc/day8.py) |

aoc/day8.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import sys
2+
from dataclasses import dataclass
3+
from itertools import combinations
4+
from pathlib import Path
5+
6+
7+
@dataclass
8+
class AntennaMap:
9+
rows: int
10+
cols: int
11+
positions: dict[str, set[tuple[int, int]]]
12+
13+
14+
def parse_input(lines: list[str]) -> AntennaMap:
15+
positions = [(c, (y, x)) for y, line in enumerate(lines) for x, c in enumerate(line) if c != "."]
16+
antennamap = {}
17+
for c, pos in positions:
18+
antennamap[c] = antennamap.get(c, set()) | {pos}
19+
return AntennaMap(len(lines), len(lines[0]), antennamap)
20+
21+
22+
def positions(am: AntennaMap) -> set[tuple[int, int]]:
23+
anodes_pos = set()
24+
25+
def is_in_field(pos):
26+
y, x = pos
27+
return 0 <= y < am.rows and 0 <= x < am.cols
28+
29+
for _, positions in am.positions.items():
30+
for (y1, x1), (y2, x2) in combinations(positions, 2):
31+
anodes_pos |= {
32+
pos for pos in [(y1 + (y1 - y2), x1 + (x1 - x2)), (y2 + (y2 - y1), x2 + (x2 - x1))] if is_in_field(pos)
33+
}
34+
return anodes_pos
35+
36+
37+
def part1(am: AntennaMap) -> int:
38+
return len(positions(am))
39+
40+
41+
def main():
42+
lines = parse_input(Path(sys.argv[1]).read_text().splitlines())
43+
print(f"Part 1: {part1(lines)}")
44+
45+
46+
if __name__ == "__main__":
47+
main()

test/test_day8.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
from aoc.day8 import parse_input, part1
2+
3+
TEST_INPUT = """............
4+
........0...
5+
.....0......
6+
.......0....
7+
....0.......
8+
......A.....
9+
............
10+
............
11+
........A...
12+
.........A..
13+
............
14+
............
15+
""".splitlines()
16+
17+
18+
def test_part1():
19+
assert part1(parse_input(TEST_INPUT)) == 14

0 commit comments

Comments
 (0)