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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy