Skip to content

Commit 70531c3

Browse files
committed
CQ problem 16
1 parent e9578a2 commit 70531c3

File tree

5 files changed

+100
-1
lines changed

5 files changed

+100
-1
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
54 68 69 73 20 b8
2+
69 73 60 61 20 7d
3+
74 65 73 74 21 e1
4+
31 40 fc 48 61

codingquest_clp_solutions/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@ pub mod helpers;
88
pub mod problem_13;
99
pub mod problem_14;
1010
pub mod problem_15;
11+
pub mod problem_16;
1112

1213
pub type Error = codingquest_clp::Error;
1314
pub type Result<T> = codingquest_clp::Result<T>;
1415

1516
build_solvers! {
16-
[13, 14, 15]
17+
[13, 14, 15, 16]
1718
}

codingquest_clp_solutions/src/problem_13.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ fn input() -> (Board, Moves) {
3737
(Board::from_input_data(&input_data), Moves::from_input_data(&input_data))
3838
}
3939

40+
#[derive(Debug)]
4041
struct Board {
4142
tiles: Vec<i32>,
4243
}
@@ -81,6 +82,7 @@ impl Deref for Board {
8182
}
8283
}
8384

85+
#[derive(Debug)]
8486
struct Moves {
8587
moves: Vec<(i32, i32)>,
8688
}

codingquest_clp_solutions/src/problem_15.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ fn sensor_data() -> Vec<Vec<u64>> {
1717
.safe_into_many_vecs()
1818
}
1919

20+
#[derive(Debug)]
2021
struct CelestialBody(HashMap<Pt, u64>);
2122

2223
impl CelestialBody {
@@ -31,6 +32,7 @@ impl From<HashMap<Pt, u64>> for CelestialBody {
3132
}
3233
}
3334

35+
#[derive(Debug)]
3436
struct CelestialBodies(Vec<CelestialBody>);
3537

3638
impl CelestialBodies {
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
use codingquest_clp::solvers_impl::input::get_input;
2+
use itertools::Itertools;
3+
4+
use crate::helpers::get_problem_input_data;
5+
6+
pub fn solve() -> u64 {
7+
let message: Message = message_data().into();
8+
message.fix()
9+
}
10+
11+
fn message_data() -> Vec<Vec<String>> {
12+
get_input(get_problem_input_data(16).unwrap())
13+
.unwrap()
14+
.safe_into_many_vecs()
15+
}
16+
17+
#[derive(Debug)]
18+
struct Message {
19+
data: Vec<Vec<u8>>,
20+
row_checksums: Vec<u8>,
21+
col_checksums: Vec<u8>,
22+
}
23+
24+
impl Message {
25+
pub fn fix(&self) -> u64 {
26+
let (invalid_row, invalid_row_checksum_diff) = (0..self.data.len())
27+
.map(|i| (i, Self::checksum_diff(self.row_checksums[i], self.row(i))))
28+
.filter(|&(_, diff)| diff != 0)
29+
.exactly_one()
30+
.unwrap();
31+
let (invalid_col, invalid_col_checksum_diff) = (0..self.data[0].len())
32+
.map(|i| (i, Self::checksum_diff(self.col_checksums[i], self.col(i))))
33+
.filter(|&(_, diff)| diff != 0)
34+
.exactly_one()
35+
.unwrap();
36+
37+
if invalid_row_checksum_diff != invalid_col_checksum_diff {
38+
panic!("Invalid row {invalid_row}'s checksum diff ({invalid_row_checksum_diff}) is not equal to col {invalid_col}'s checksum diff ({invalid_col_checksum_diff})!");
39+
}
40+
41+
let wrong_byte = self.data[invalid_row][invalid_col];
42+
let correct_byte = wrong_byte.wrapping_sub(invalid_row_checksum_diff);
43+
(wrong_byte as u64) * (correct_byte as u64)
44+
}
45+
46+
fn row(&self, row: usize) -> impl Iterator<Item = u8> + '_ {
47+
self.data[row].iter().copied()
48+
}
49+
50+
fn col(&self, col: usize) -> impl Iterator<Item = u8> + '_ {
51+
self.data.iter().map(move |row| row[col])
52+
}
53+
54+
fn checksum_diff<D>(expected_checksum: u8, data: D) -> u8
55+
where
56+
D: IntoIterator<Item = u8>,
57+
{
58+
let actual_checksum = data
59+
.into_iter()
60+
.fold(0u8, |acc, byte| acc.wrapping_add(byte));
61+
actual_checksum.wrapping_sub(expected_checksum)
62+
}
63+
}
64+
65+
impl From<Vec<Vec<String>>> for Message {
66+
fn from(value: Vec<Vec<String>>) -> Self {
67+
let value = value
68+
.into_iter()
69+
.map(|row| {
70+
row.into_iter()
71+
.map(|byte| u8::from_str_radix(&byte, 16).unwrap())
72+
.collect_vec()
73+
})
74+
.collect_vec();
75+
76+
let data = value
77+
.iter()
78+
.take(value.len() - 1)
79+
.map(|row| row.iter().take(row.len() - 1).copied().collect_vec())
80+
.collect_vec();
81+
let row_checksums = value
82+
.iter()
83+
.take(value.len() - 1)
84+
.map(|row| row.last().copied().unwrap())
85+
.collect_vec();
86+
let col_checksums = value.last().cloned().unwrap();
87+
88+
Self { data, row_checksums, col_checksums }
89+
}
90+
}

0 commit comments

Comments
 (0)