Skip to content

Commit aa460f1

Browse files
committed
Solve part 2 of day 1
1 parent 7ae763e commit aa460f1

File tree

2 files changed

+71
-39
lines changed

2 files changed

+71
-39
lines changed

src/2024/01.rs

+70-38
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,75 @@
1+
use std::str::FromStr;
2+
13
use eyre::{eyre, OptionExt, Report, Result};
4+
use nohash_hasher::IntMap;
25
use rayon::prelude::*;
36

47
use crate::meta::Problem;
58

6-
pub const HISTORIAN_HYSTERIA: Problem = Problem::partially_solved(&|input| -> Result<usize> {
7-
let (lhs, rhs) = input
8-
.lines()
9-
.map(|line| {
10-
let mut iter = line.split_ascii_whitespace();
11-
let a_str = iter.next().ok_or_eyre("empty line")?;
12-
let b_str = iter
13-
.next()
14-
.ok_or_else(|| eyre!("No whitespace on line: \"{line}\""))?;
15-
16-
debug_assert!(iter.next().is_none());
17-
18-
let a = a_str.parse()?;
19-
let b = b_str.parse()?;
20-
21-
Ok::<(usize, usize), Report>((a, b))
22-
})
23-
.try_fold((Vec::new(), Vec::new()), |(mut lhs, mut rhs), res| {
24-
let (a, b) = res?;
25-
26-
lhs.push(a);
27-
rhs.push(b);
28-
29-
Ok::<_, Report>((lhs, rhs))
30-
})
31-
.map(|(mut lhs, mut rhs)| {
32-
lhs.sort_unstable();
33-
rhs.sort_unstable();
34-
35-
(lhs, rhs)
36-
})?;
37-
38-
Ok(lhs
39-
.into_par_iter()
40-
.zip(rhs)
41-
.map(|(a, b)| a.abs_diff(b))
42-
.sum())
43-
});
9+
pub const HISTORIAN_HYSTERIA: Problem = Problem::solved(
10+
&|input| input.parse().map(LocationIds::total_distance),
11+
&|input| input.parse().map(LocationIds::total_similarity),
12+
);
13+
14+
#[derive(Debug, Default)]
15+
struct LocationIds {
16+
lhs: Vec<usize>,
17+
rhs: Vec<usize>,
18+
}
19+
20+
impl LocationIds {
21+
fn total_distance(self) -> usize {
22+
let LocationIds { mut lhs, mut rhs } = self;
23+
24+
lhs.sort_unstable();
25+
rhs.sort_unstable();
26+
27+
lhs.into_par_iter()
28+
.zip(rhs)
29+
.map(|(a, b)| a.abs_diff(b))
30+
.sum()
31+
}
32+
33+
fn total_similarity(self) -> usize {
34+
let LocationIds { lhs, rhs } = self;
35+
let mut cache = IntMap::default();
36+
37+
lhs.into_iter()
38+
.map(|id| {
39+
*cache
40+
.entry(id)
41+
.or_insert_with(|| rhs.par_iter().filter(|rhs_id| **rhs_id == id).count() * id)
42+
})
43+
.sum()
44+
}
45+
}
46+
47+
impl FromStr for LocationIds {
48+
type Err = Report;
49+
50+
fn from_str(s: &str) -> Result<Self> {
51+
s.lines()
52+
.map(|line| {
53+
let mut iter = line.split_ascii_whitespace();
54+
let a_str = iter.next().ok_or_eyre("empty line")?;
55+
let b_str = iter
56+
.next()
57+
.ok_or_else(|| eyre!("No whitespace on line: \"{line}\""))?;
58+
59+
debug_assert!(iter.next().is_none());
60+
61+
let a = a_str.parse()?;
62+
let b = b_str.parse()?;
63+
64+
Ok::<(usize, usize), Report>((a, b))
65+
})
66+
.try_fold(LocationIds::default(), |mut ids, res| {
67+
let (a, b) = res?;
68+
69+
ids.lhs.push(a);
70+
ids.rhs.push(b);
71+
72+
Ok::<_, Report>(ids)
73+
})
74+
}
75+
}

tests/integration.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ util::tests! {
4040
},
4141

4242
2024: {
43-
1: [2000468]
43+
1: [2000468, 18567089]
4444
}
4545
}
4646

0 commit comments

Comments
 (0)