Skip to content

Commit 3845b0c

Browse files
committed
2024-08 Rust
1 parent 8edb9a3 commit 3845b0c

File tree

6 files changed

+219
-13
lines changed

6 files changed

+219
-13
lines changed

ReadMe.md

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
| Year-Day | Task | Scala | Rust | Others |
88
|----------|:-------------------------------------------------------------------------------|:-----------------------------------------------------------------------:|:----------------------------------------------:|:----------------------------------------------------------------------:|
9+
| 2024-08 | [Resonant Collinearity](https://adventofcode.com/2024/day/8) | [Scala](scala2/src/main/scala/jurisk/adventofcode/y2024/Advent08.scala) | [Rust](rust/y2024/src/bin/solution_2024_08.rs) | |
910
| 2024-07 | [Bridge Repair](https://adventofcode.com/2024/day/7) | [Scala](scala2/src/main/scala/jurisk/adventofcode/y2024/Advent07.scala) | [Rust](rust/y2024/src/bin/solution_2024_07.rs) | |
1011
| 2024-06 | [Guard Gallivant](https://adventofcode.com/2024/day/6) | [Scala](scala2/src/main/scala/jurisk/adventofcode/y2024/Advent06.scala) | [Rust](rust/y2024/src/bin/solution_2024_06.rs) | |
1112
| 2024-05 | [Print Queue](https://adventofcode.com/2024/day/5) | [Scala](scala2/src/main/scala/jurisk/adventofcode/y2024/Advent05.scala) | [Rust](rust/y2024/src/bin/solution_2024_05.rs) | |

rust/common/src/grid2d.rs

+40
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
clippy::cast_sign_loss
55
)]
66

7+
use std::convert::Infallible;
78
use std::fmt::{Debug, Formatter};
89
use std::iter::Sum;
910
use std::str::FromStr;
@@ -28,10 +29,16 @@ pub trait Grid2D<T> {
2829
where
2930
T: PartialEq;
3031

32+
fn filter_coords_by_value(&self, value: &T) -> Vec<Coords>
33+
where
34+
T: PartialEq;
35+
3136
fn count<F>(&self, f: F) -> usize
3237
where
3338
F: Fn(Coords, &T) -> bool;
3439

40+
fn valid_coords(&self, coords: Coords) -> bool;
41+
3542
fn get(&self, coords: Coords) -> Option<&T>;
3643

3744
fn set(&mut self, coords: Coords, value: T);
@@ -75,6 +82,18 @@ pub struct MatrixGrid2D<T> {
7582
data: Matrix<T>,
7683
}
7784

85+
impl<T> MatrixGrid2D<T> {
86+
#[expect(clippy::missing_panics_doc)]
87+
pub fn parse(input: &str, f: impl Fn(char) -> T) -> Self
88+
where
89+
T: TryFrom<char>,
90+
{
91+
Self {
92+
data: parse_matrix(input, |ch| Ok::<T, Infallible>(f(ch))).unwrap(),
93+
}
94+
}
95+
}
96+
7897
impl From<(usize, usize)> for Coords {
7998
fn from(value: (usize, usize)) -> Self {
8099
let (r, c) = value;
@@ -126,6 +145,22 @@ impl<T> Grid2D<T> for MatrixGrid2D<T> {
126145
})
127146
}
128147

148+
fn filter_coords_by_value(&self, value: &T) -> Vec<Coords>
149+
where
150+
T: PartialEq,
151+
{
152+
self.data
153+
.keys()
154+
.filter_map(|coords| {
155+
if self.data[coords] == *value {
156+
Some(Coords::from(coords))
157+
} else {
158+
None
159+
}
160+
})
161+
.collect()
162+
}
163+
129164
fn count<F>(&self, f: F) -> usize
130165
where
131166
F: Fn(Coords, &T) -> bool,
@@ -172,6 +207,11 @@ impl<T> Grid2D<T> for MatrixGrid2D<T> {
172207
fn columns(&self) -> usize {
173208
self.data.columns
174209
}
210+
211+
fn valid_coords(&self, coords: Coords) -> bool {
212+
let (r, c) = coords.into();
213+
self.data.within_bounds((r, c))
214+
}
175215
}
176216

177217
impl<T> FromStr for MatrixGrid2D<T>

rust/y2024/resources/08-test-00.txt

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
............
2+
........0...
3+
.....0......
4+
.......0....
5+
....0.......
6+
......A.....
7+
............
8+
............
9+
........A...
10+
.........A..
11+
............
12+
............

rust/y2024/resources/08.txt

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
....h.....Q..............Y........................
2+
...............................Y........C.........
3+
...............m..........x................B......
4+
........................Y..............qB.........
5+
......g4.........................h..Y.....q...c...
6+
................n.....R...........................
7+
.......................................w........5.
8+
........g...m...........................w5........
9+
..n...........R.1................W.......q.5......
10+
.........h...n.................e..................
11+
...............................R..........B....C..
12+
.........4................................5.e.....
13+
.......0..4......n.......x..w.....................
14+
.......g.....m........x..b.....W.....B.......w....
15+
..............m........................3......C...
16+
........q...0.......h....................C.3......
17+
..................3.....................D.........
18+
...............R..........3.............X.........
19+
..............................W............k2.....
20+
..........7............................2..........
21+
...............A.............................X...2
22+
.......................c...x......................
23+
....................................d.............
24+
.....1......................d.....................
25+
...........1...........................e..........
26+
.........0.7K.........................2.........W.
27+
...b......0.....A.................................
28+
......................1....ic.....................
29+
......b......................i....................
30+
..Q.....b..........................A..E...........
31+
...7.........................V....................
32+
........A.....................v......d............
33+
........v............c...................8E.......
34+
..............................V........8.....E..N.
35+
......................6...........................
36+
.......I....M....................V................
37+
...G......................a.......8...............
38+
.........r.9........a...i..................X......
39+
...............r..i...............e............N..
40+
.....H...........k....9.....6...............8.....
41+
.v.....................6................V.........
42+
.........v.......a........k..........D............
43+
Ha..........k.........K........E.......d..........
44+
...............y.MG..............6....D...........
45+
.........H..G...M......9.K..............N.........
46+
.......G.........................K................
47+
...............M.........I.......D................
48+
..................................................
49+
....r....y................9.......................
50+
....y................................N............
+115
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
use std::collections::HashSet;
2+
3+
use advent_of_code_common::grid2d::{Coords, Grid2D, MatrixGrid2D};
4+
5+
const DATA: &str = include_str!("../../resources/08.txt");
6+
7+
type R = usize;
8+
type Frequency = char;
9+
type Data = MatrixGrid2D<Option<Frequency>>;
10+
11+
fn parse_option_frequency(input: char) -> Option<Frequency> {
12+
if input == '.' { None } else { Some(input) }
13+
}
14+
15+
fn parse(input: &str) -> Data {
16+
MatrixGrid2D::parse(input, parse_option_frequency)
17+
}
18+
19+
fn helper(
20+
antinodes: &mut MatrixGrid2D<bool>,
21+
current: Coords,
22+
diff: Coords,
23+
limit: Option<usize>,
24+
count: usize,
25+
) {
26+
if antinodes.valid_coords(current) && limit.is_none_or(|l| count <= l) {
27+
if limit.is_none() || count != 0 {
28+
antinodes.set(current, true);
29+
}
30+
31+
helper(antinodes, current + diff, diff, limit, count + 1);
32+
}
33+
}
34+
35+
fn process_frequency(
36+
data: &Data,
37+
antinodes: &mut MatrixGrid2D<bool>,
38+
frequency: Frequency,
39+
limit: Option<usize>,
40+
) {
41+
let locations = data.filter_coords_by_value(&Some(frequency));
42+
for a in &locations {
43+
for b in &locations {
44+
if a != b {
45+
helper(antinodes, *a, *a - *b, limit, 0);
46+
}
47+
}
48+
}
49+
}
50+
51+
fn solve(data: &Data, limit: Option<usize>) -> R {
52+
let mut antinodes = data.map_by_coords(|_| false);
53+
let frequencies = data
54+
.iter()
55+
.flat_map(|(_, v)| v)
56+
.copied()
57+
.collect::<HashSet<_>>();
58+
for frequency in frequencies {
59+
process_frequency(data, &mut antinodes, frequency, limit);
60+
}
61+
antinodes.count(|_, v| *v)
62+
}
63+
64+
fn solve_1(data: &Data) -> R {
65+
solve(data, Some(1))
66+
}
67+
68+
fn solve_2(data: &Data) -> R {
69+
solve(data, None)
70+
}
71+
72+
fn main() {
73+
let data = parse(DATA);
74+
75+
let result_1 = solve_1(&data);
76+
println!("Part 1: {result_1}");
77+
78+
let result_2 = solve_2(&data);
79+
println!("Part 2: {result_2}");
80+
}
81+
82+
#[cfg(test)]
83+
mod tests {
84+
use super::*;
85+
86+
const TEST_DATA: &str = include_str!("../../resources/08-test-00.txt");
87+
88+
fn test_data() -> Data {
89+
parse(TEST_DATA)
90+
}
91+
92+
fn real_data() -> Data {
93+
parse(DATA)
94+
}
95+
96+
#[test]
97+
fn test_solve_1_test() {
98+
assert_eq!(solve_1(&test_data()), 14);
99+
}
100+
101+
#[test]
102+
fn test_solve_1_real() {
103+
assert_eq!(solve_1(&real_data()), 256);
104+
}
105+
106+
#[test]
107+
fn test_solve_2_test() {
108+
assert_eq!(solve_2(&test_data()), 34);
109+
}
110+
111+
#[test]
112+
fn test_solve_2_real() {
113+
assert_eq!(solve_2(&real_data()), 1005);
114+
}
115+
}

scala2/src/main/scala/jurisk/adventofcode/y2024/Advent08.scala

+1-13
Original file line numberDiff line numberDiff line change
@@ -57,18 +57,6 @@ object Advent08 {
5757
field
5858
}
5959

60-
private def update(
61-
field: Input,
62-
frequency: Char,
63-
a: Coords2D,
64-
b: Coords2D,
65-
limit: Option[Int],
66-
): Input =
67-
List((a, a - b), (b, b - a)).foldLeft(field) {
68-
case (field, (start, diff)) =>
69-
helper(field, frequency, start, diff, limit)
70-
}
71-
7260
private def processFrequency(
7361
field: Input,
7462
frequency: Char,
@@ -82,7 +70,7 @@ object Advent08 {
8270
}.flatten
8371

8472
pairs.foldLeft(field) { case (field, (a, b)) =>
85-
update(field, frequency, a, b, limit)
73+
helper(field, frequency, a, a - b, limit)
8674
}
8775
}
8876

0 commit comments

Comments
 (0)