Skip to content

Commit b42fc55

Browse files
committed
Day08
1 parent c27fea7 commit b42fc55

File tree

2 files changed

+92
-8
lines changed

2 files changed

+92
-8
lines changed

src/day08.rs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
use std::{
2+
cmp,
3+
collections::{HashMap, HashSet},
4+
fs,
5+
path::PathBuf,
6+
};
7+
8+
use itertools::iproduct;
9+
10+
pub fn day08(mut input_path: PathBuf) {
11+
input_path.push("08.txt");
12+
let content = fs::read_to_string(input_path).unwrap();
13+
14+
let (antennas, corner) = read(&content);
15+
16+
println!("{:?}", count_antinodes(&antennas, ((0, 0), corner), antinodes_part1));
17+
println!("{:?}", count_antinodes(&antennas, ((0, 0), corner), antinodes_part2));
18+
}
19+
20+
// Positive y-direction is up!
21+
type Position = (i32, i32);
22+
type ResonancePoints = HashMap<char, Vec<Position>>;
23+
24+
fn read(input: &str) -> (ResonancePoints, (i32, i32)) {
25+
let (mut x_max, mut y_max) = (0, 0);
26+
let mut antennas = HashMap::new();
27+
for (y, line) in input.lines().enumerate() {
28+
y_max = y_max.max(y);
29+
for (x, c) in line.chars().enumerate() {
30+
x_max = x_max.max(x);
31+
if c != '.' {
32+
antennas
33+
.entry(c)
34+
.or_insert(Vec::new())
35+
.push((x as i32, -(y as i32)))
36+
}
37+
}
38+
}
39+
(antennas, (x_max as i32, -(y_max as i32)))
40+
}
41+
42+
fn count_antinodes(
43+
antennas: &ResonancePoints,
44+
bounds: (Position, Position),
45+
generate_antinodes: fn(&[Position], (Position, Position)) -> Vec<Position>,
46+
) -> usize {
47+
antennas
48+
.iter()
49+
.flat_map(|(_, positions)| generate_antinodes(&positions, bounds))
50+
.collect::<HashSet<_>>()
51+
.len()
52+
}
53+
54+
fn antinodes_part1(antennas: &[Position], bounds: (Position, Position)) -> Vec<Position> {
55+
iproduct!(antennas, antennas)
56+
.filter(|(p1, p2)| p1 != p2)
57+
.map(|((x1, y1), (x2, y2))| (2 * x1 - x2, 2 * y1 - y2))
58+
.filter(|p| is_inside(*p, bounds))
59+
.collect()
60+
}
61+
62+
fn antinodes_part2(antennas: &[Position], bounds: (Position, Position)) -> Vec<Position> {
63+
iproduct!(antennas, antennas)
64+
.filter(|(p1, p2)| p1 != p2)
65+
.flat_map(|((x1, y1), (x2, y2))| {
66+
(0..)
67+
.map(move |i| ((i+1) * x1 - i * x2, (i+ 1) * y1 - i * y2))
68+
.take_while(|p| is_inside(*p, bounds))
69+
})
70+
.collect()
71+
}
72+
73+
fn is_inside(p: Position, bounds: (Position, Position)) -> bool {
74+
// ugh
75+
let (x, y) = p;
76+
let ((x1, y1), (x2, y2)) = bounds;
77+
let [x_min, x_max] = cmp::minmax(x1, x2);
78+
let [y_min, y_max] = cmp::minmax(y1, y2);
79+
x_min <= x && x <= x_max && y_min <= y && y <= y_max
80+
}

src/main.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
use std::path::PathBuf;
1+
#![feature(cmp_minmax)]
2+
23
use clap::Parser;
4+
use std::path::PathBuf;
35

46
mod day01;
57
mod day02;
@@ -8,6 +10,7 @@ mod day04;
810
mod day05;
911
mod day06;
1012
mod day07;
13+
mod day08;
1114

1215
#[derive(Parser)]
1316
struct Args {
@@ -19,12 +22,13 @@ fn main() {
1922
let args = Args::parse();
2023
let input = PathBuf::from("input");
2124
match args.day {
22-
1 => day01::day01(input),
23-
2 => day02::day02(input),
24-
3 => day03::day03(input),
25-
4 => day04::day04(input),
26-
5 => day05::day05(input),
27-
7 => day07::day07(input),
28-
_ => day06::day06(input),
25+
1 => day01::day01(input),
26+
2 => day02::day02(input),
27+
3 => day03::day03(input),
28+
4 => day04::day04(input),
29+
5 => day05::day05(input),
30+
6 => day06::day06(input),
31+
7 => day07::day07(input),
32+
_ => day08::day08(input),
2933
}
3034
}

0 commit comments

Comments
 (0)