tangled
alpha
login
or
join now
nove.dev
/
aoc-2024
0
fork
atom
retroactive, to derust my rust
0
fork
atom
overview
issues
pulls
pipelines
day8 part2
nove.dev
3 months ago
337abcfc
4524b400
+71
-7
4 changed files
expand all
collapse all
unified
split
Cargo.lock
Cargo.toml
src
day8.rs
lib.rs
+7
Cargo.lock
···
15
15
name = "aoc2024"
16
16
version = "0.1.0"
17
17
dependencies = [
18
18
+
"gcd",
18
19
"itertools",
19
20
"regex",
20
21
]
···
24
25
version = "1.15.0"
25
26
source = "registry+https://github.com/rust-lang/crates.io-index"
26
27
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
28
28
+
29
29
+
[[package]]
30
30
+
name = "gcd"
31
31
+
version = "2.3.0"
32
32
+
source = "registry+https://github.com/rust-lang/crates.io-index"
33
33
+
checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a"
27
34
28
35
[[package]]
29
36
name = "itertools"
+1
Cargo.toml
···
4
4
edition = "2024"
5
5
6
6
[dependencies]
7
7
+
gcd = "2.3.0"
7
8
itertools = "0.14.0"
8
9
regex = "1.12.2"
+56
-7
src/day8.rs
···
1
1
-
use std::{collections::{HashMap, HashSet}, convert::Infallible, str::FromStr};
1
1
+
use std::{
2
2
+
collections::{HashMap, HashSet},
3
3
+
convert::Infallible,
4
4
+
str::FromStr,
5
5
+
};
2
6
7
7
+
use gcd::Gcd;
3
8
use itertools::Itertools;
4
9
5
10
pub fn day8_part1(input: &str) -> String {
···
9
14
}
10
15
11
16
pub fn day8_part2(input: &str) -> String {
12
12
-
todo!()
17
17
+
let city: City = input.parse().unwrap();
18
18
+
let antinodes: HashSet<Point> = city.resonant_antinodes().collect();
19
19
+
antinodes.len().to_string()
13
20
}
14
21
15
22
fn antinodes(antenna1: Point, antenna2: Point) -> (Option<Point>, Option<Point>) {
16
23
let distance: Vector2 = (antenna1, antenna2).into();
17
24
let antinode1 = antenna2 + distance;
18
25
let antinode2 = antenna1 - distance;
19
19
-
dbg!(antenna1, antenna2, distance, antinode1, antinode2);
20
26
(antinode1, antinode2)
21
27
}
22
28
29
29
+
fn resonant_antinodes(antenna1: Point, antenna2: Point, width: usize, height: usize) -> Vec<Point> {
30
30
+
let distance: Vector2 = (antenna1, antenna2).into();
31
31
+
let distance = distance.simplified();
32
32
+
let mut last_antinode = antenna1;
33
33
+
let mut antinodes = vec![last_antinode];
34
34
+
while let Some(next_antinode) = last_antinode + distance {
35
35
+
if next_antinode.row >= height || next_antinode.col >= width {
36
36
+
break;
37
37
+
} else {
38
38
+
antinodes.push(next_antinode);
39
39
+
last_antinode = next_antinode;
40
40
+
}
41
41
+
}
42
42
+
let mut last_antinode = antenna1;
43
43
+
while let Some(next_antinode) = last_antinode - distance {
44
44
+
if next_antinode.row >= height || next_antinode.col >= width {
45
45
+
break;
46
46
+
} else {
47
47
+
antinodes.push(next_antinode);
48
48
+
last_antinode = next_antinode;
49
49
+
}
50
50
+
}
51
51
+
antinodes
52
52
+
}
53
53
+
23
54
#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash, Debug)]
24
55
struct Point {
25
56
row: usize,
···
74
105
}
75
106
}
76
107
108
108
+
impl Vector2 {
109
109
+
fn simplified(&self) -> Self {
110
110
+
let mut retval = *self;
111
111
+
let pos_col_distance: usize = retval.col_distance.unsigned_abs();
112
112
+
let pos_row_distance: usize = retval.row_distance.unsigned_abs();
113
113
+
let gcd = pos_col_distance.gcd(pos_row_distance);
114
114
+
if gcd != 1 {
115
115
+
retval.col_distance /= gcd as isize;
116
116
+
retval.row_distance /= gcd as isize;
117
117
+
}
118
118
+
retval
119
119
+
}
120
120
+
}
121
121
+
77
122
#[derive(Debug)]
78
123
struct City {
79
124
width: usize,
···
116
161
retval.into_values().collect()
117
162
}
118
163
fn antenna_pairs(&self) -> impl Iterator<Item = (Point, Point)> {
119
119
-
let ap: Vec<(Point, Point)> = self.antenna_groups
164
164
+
self
165
165
+
.antenna_groups
120
166
.iter()
121
167
.flat_map(|group| group.iter().combinations(2))
122
122
-
.map(|combination| (*combination[0], *combination[1])).collect();
123
123
-
dbg!(&ap);
124
124
-
ap.into_iter()
168
168
+
.map(|combination| (*combination[0], *combination[1]))
125
169
}
126
170
fn antinodes(&self) -> impl Iterator<Item = Point> {
127
171
self.antenna_pairs()
128
172
.map(|(from, to)| antinodes(from, to))
129
173
.flat_map(|(a1, a2)| [a1, a2])
130
174
.flatten()
175
175
+
.filter(|p| p.row < self.height && p.col < self.width)
176
176
+
}
177
177
+
fn resonant_antinodes(&self) -> impl Iterator<Item = Point> {
178
178
+
self.antenna_pairs()
179
179
+
.flat_map(|(from, to)| resonant_antinodes(from, to, self.width, self.height))
131
180
.filter(|p| p.row < self.height && p.col < self.width)
132
181
}
133
182
}
+7
src/lib.rs
···
361
361
// assert!(result.parse::<u64>().unwrap() < 414); //too high
362
362
assert_eq!(result, "369");
363
363
}
364
364
+
#[test]
365
365
+
fn day8_part2_test() {
366
366
+
let test_result = day8::day8_part2(include_str!("../input/day8.test.txt"));
367
367
+
assert_eq!(test_result, "34");
368
368
+
let result = day8::day8_part2(include_str!("../input/day8.txt"));
369
369
+
assert_eq!(result, "1169");
370
370
+
}
364
371
365
372
#[test]
366
373
fn day7_part1_test() {