Skip to content

Commit 559e05d

Browse files
committed
2017 day 10
1 parent 677fa30 commit 559e05d

File tree

3 files changed

+82
-6
lines changed

3 files changed

+82
-6
lines changed

crates/aoc/src/main.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,9 @@ fn main() {
3535
exit(1);
3636
}
3737

38-
println!("Puzzle │ Part 1 │ Part 2 │ Time ");
39-
println!("────────┼─────────────────────────────┼─────────────────────────────┼───────────");
38+
// FIXME support 80 character wide output (without time?)
39+
println!("Puzzle │ Part 1 │ Part 2 │ Time ");
40+
println!("────────┼──────────────────────────────────┼──────────────────────────────────┼───────────");
4041

4142
let mut total = Duration::default();
4243
for (year, day, f) in puzzles {
@@ -56,8 +57,8 @@ fn main() {
5657

5758
// Hack to treat "🎄" as two characters wide
5859
// ("🎄" is 1 wide in Unicode 8 but 2 wide in Unicode 9+)
59-
let part1_width = if part1 == "🎄" { 26 } else { 27 };
60-
let part2_width = if part2 == "🎄" { 26 } else { 27 };
60+
let part1_width = if part1 == "🎄" { 31 } else { 32 };
61+
let part2_width = if part2 == "🎄" { 31 } else { 32 };
6162

6263
println!(
6364
"{year:#} {day:#} │ {part1:<part1_width$} │ {part2:<part2_width$} │ {}",
@@ -71,9 +72,11 @@ fn main() {
7172
}
7273
}
7374

74-
println!("────────┴─────────────────────────────┴─────────────────────────────┼───────────");
7575
println!(
76-
" │ {}",
76+
"────────┴──────────────────────────────────┴──────────────────────────────────┼───────────"
77+
);
78+
println!(
79+
" │ {}",
7780
format_duration(total),
7881
);
7982
}

crates/year2017/src/day10.rs

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
use std::array;
2+
use utils::md5;
3+
use utils::prelude::*;
4+
5+
/// Implementing a custom hash function.
6+
#[derive(Clone, Debug)]
7+
pub struct Day10<'a> {
8+
input: &'a str,
9+
}
10+
11+
impl<'a> Day10<'a> {
12+
pub fn new(input: &'a str, _: InputType) -> Result<Self, InputError> {
13+
// Parts 1 and 2 expect different input
14+
Ok(Self { input })
15+
}
16+
17+
#[must_use]
18+
pub fn part1(&self) -> u32 {
19+
let lengths = parser::u8()
20+
.with_suffix(b','.optional())
21+
.parse_all(self.input)
22+
.expect("input invalid for part 1");
23+
24+
let list = Self::knot_hash(lengths.iter().copied(), 1);
25+
26+
list[0] as u32 * list[1] as u32
27+
}
28+
29+
#[must_use]
30+
pub fn part2(&self) -> String {
31+
let lengths = self.input.bytes().chain([17, 31, 73, 47, 23]);
32+
33+
let sparse = Self::knot_hash(lengths, 64);
34+
35+
let dense: [u8; 16] = array::from_fn(|i| {
36+
sparse[16 * i..16 * (i + 1)]
37+
.iter()
38+
.fold(0, |acc, x| acc ^ x)
39+
});
40+
41+
let dense_hex = md5::to_hex(array::from_fn(|i| {
42+
u32::from_be_bytes(dense[4 * i..4 * (i + 1)].try_into().unwrap())
43+
}));
44+
45+
String::from_utf8(dense_hex.to_vec()).unwrap()
46+
}
47+
48+
fn knot_hash(lengths: impl Iterator<Item = u8> + Clone, rounds: u32) -> [u8; 256] {
49+
let mut list = array::from_fn(|i| i as u8);
50+
let mut position = 0;
51+
let mut skip = 0;
52+
53+
for _ in 0..rounds {
54+
for length in lengths.clone() {
55+
list[0..length as usize].reverse();
56+
list.rotate_left((length as usize + skip) % 256);
57+
position = (position + length as usize + skip) % 256;
58+
skip += 1;
59+
}
60+
}
61+
62+
list.rotate_right(position);
63+
list
64+
}
65+
}
66+
67+
examples!(Day10<'_> -> (u32, &'static str) [
68+
{input: "", part2: "a2582a3a0e66e6e86e3812dcb672a272"},
69+
{input: "AoC 2017", part2: "33efeb34ea91902bb2f59c9920caa6cd"},
70+
{input: "1,2,3", part2: "3efbe78a8d82f29979031a4aa0b16a9d"},
71+
{input: "1,2,4", part2: "63960835bcdc130f0b66d7ff4f6a5a8e"},
72+
]);

crates/year2017/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,5 @@ utils::year!(2017 => year2017, ${
1111
7 => day07::Day07<'_>,
1212
8 => day08::Day08,
1313
9 => day09::Day09,
14+
10 => day10::Day10<'_>,
1415
});

0 commit comments

Comments
 (0)