From 5959cb8ecda2da5fc7ff65a11be2f4d4f7aa6c55 Mon Sep 17 00:00:00 2001 From: Smaug123 Date: Fri, 14 May 2021 17:59:28 +0100 Subject: [PATCH] Day 10 --- Cargo.lock | 4 ++ Cargo.toml | 1 + day_10/Cargo.toml | 9 +++ day_10/input.txt | 1 + day_10/src/main.rs | 140 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 155 insertions(+) create mode 100644 day_10/Cargo.toml create mode 100644 day_10/input.txt create mode 100644 day_10/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 6f688e3..4fa1668 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,6 +4,10 @@ name = "day_1" version = "0.1.0" +[[package]] +name = "day_10" +version = "0.1.0" + [[package]] name = "day_11" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 7998132..1aeb412 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ members = [ "day_6", "day_7", "day_8", + "day_10", "day_11", "day_12", "day_13", diff --git a/day_10/Cargo.toml b/day_10/Cargo.toml new file mode 100644 index 0000000..fa4f09f --- /dev/null +++ b/day_10/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "day_10" +version = "0.1.0" +authors = ["Smaug123 "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/day_10/input.txt b/day_10/input.txt new file mode 100644 index 0000000..78d64f1 --- /dev/null +++ b/day_10/input.txt @@ -0,0 +1 @@ +165,1,255,31,87,52,24,113,0,91,148,254,158,2,73,153 diff --git a/day_10/src/main.rs b/day_10/src/main.rs new file mode 100644 index 0000000..5d8c3b5 --- /dev/null +++ b/day_10/src/main.rs @@ -0,0 +1,140 @@ +fn input_1() -> Vec { + let input = include_str!("../input.txt"); + input + .trim() + .split(',') + .map(|l| l.parse().unwrap()) + .collect::>() +} + +fn input_2() -> Vec { + let input = include_str!("../input.txt"); + input.trim().chars().map(|c| c as u8).collect::>() +} + +fn rev(start: usize, length: usize, b: &mut [T]) +where + T: Copy, +{ + for j in 0..(length / 2) { + let tmp = b[(start + j) % b.len()]; + b[(start + j) % b.len()] = b[(start + length - j - 1) % b.len()]; + b[(start + length - j - 1) % b.len()] = tmp; + } +} + +struct HashState { + v: Vec, + curr_pos: usize, + skip_size: usize, +} + +fn new_state(size: usize) -> HashState { + HashState { + v: (0..size).map(|i| i as u8).collect(), + curr_pos: 0, + skip_size: 0, + } +} + +fn execute_round(state: &mut HashState, input: &[u8]) { + for &i in input { + let i = i as usize; + rev(state.curr_pos, i, &mut state.v); + state.curr_pos = (state.curr_pos + i + state.skip_size) % state.v.len(); + state.skip_size += 1; + } +} + +fn part_1(size: usize, input: &[u8]) -> u32 { + let mut state = new_state(size); + execute_round(&mut state, input); + state.v[0] as u32 * state.v[1] as u32 +} + +fn densify(v: &[u8]) -> Vec { + v.chunks_exact(16) + .map(|i| i.iter().fold(0, |x, y| x ^ y)) + .collect() +} + +// Convert a number from 0 to 15 into an ASCII hex char +fn to_hex(i: u8) -> u8 { + if i < 10 { + i + b'0' + } else { + i - 10 + b'a' + } +} + +pub fn knot_hash_unsalted(bytes: &[u8]) -> String { + let mut state = new_state(256); + for _ in 0..64 { + execute_round(&mut state, &bytes); + } + let dense = densify(&state.v); + let mut answer = vec![0u8; 2 * dense.len()]; + for (i, b) in dense.iter().enumerate() { + answer[2 * i] = to_hex(b / 16); + answer[2 * i + 1] = to_hex(b % 16); + } + String::from_utf8(answer).unwrap() +} + +pub fn knot_hash(bytes: &[u8]) -> String { + let mut copy: Vec = bytes.to_vec(); + copy.extend(vec![17, 31, 73, 47, 23]); + knot_hash_unsalted(©) +} + +fn part_2(input: &[u8]) -> String { + knot_hash(input) +} + +fn main() { + let input = input_1(); + println!("part 1 => {}", part_1(256, &input)); + + let mut input = input_2(); + input.extend(vec![17, 31, 73, 47, 23]); + println!("part 2 => {}", part_2(&input)); +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn part1_known() { + let mut state = new_state(5); + execute_round(&mut state, &[3, 4, 1, 5]); + assert_eq!(state.v, vec![3, 4, 2, 1, 0]); + assert_eq!(state.skip_size, 4); + assert_eq!(state.curr_pos, 4); + } + + #[test] + fn part2_known() { + assert_eq!(knot_hash("".as_bytes()), "a2582a3a0e66e6e86e3812dcb672a272"); + assert_eq!( + knot_hash("AoC 2017".as_bytes()), + "33efeb34ea91902bb2f59c9920caa6cd" + ); + assert_eq!( + knot_hash("1,2,3".as_bytes()), + "3efbe78a8d82f29979031a4aa0b16a9d" + ); + assert_eq!( + knot_hash("1,2,4".as_bytes()), + "63960835bcdc130f0b66d7ff4f6a5a8e" + ); + } + + #[test] + fn test_day_10() { + let input = input_1(); + assert_eq!(part_1(256, &input), 4114); + let input = input_2(); + assert_eq!(part_2(&input), "2f8c3d2100fdd57cec130d928b0fd2dd"); + } +}