Skip to content

Commit 185fc13

Browse files
committed
Add, solve day 10
1 parent a0236c8 commit 185fc13

File tree

3 files changed

+157
-0
lines changed

3 files changed

+157
-0
lines changed

day10/Cargo.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[package]
2+
name = "day10"
3+
version = "0.1.0"
4+
authors = ["Peter Goodspeed-Niklaus <[email protected]>"]
5+
6+
[dependencies]
7+
util = { path = "../util" }

day10/src/lib.rs

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
pub const LOOP_SIZE: usize = 256;
2+
type Element = u8;
3+
4+
pub struct LoopHash {
5+
elements: Vec<Element>,
6+
position: usize,
7+
skip: usize,
8+
}
9+
10+
impl LoopHash {
11+
pub fn of_length(size: usize) -> LoopHash {
12+
assert!(size > 0);
13+
assert!(size - 1 <= Element::max_value() as usize);
14+
let mut elements = Vec::with_capacity(size);
15+
// ensure that this works if `size - 1 == Element::max_size()`
16+
elements.extend((0 as Element)..((size - 1) as Element));
17+
elements.push((size - 1) as Element);
18+
assert_eq!(elements.len(), size);
19+
LoopHash {
20+
elements: elements,
21+
position: 0,
22+
skip: 0,
23+
}
24+
}
25+
26+
pub fn new() -> LoopHash {
27+
LoopHash::of_length(LOOP_SIZE)
28+
}
29+
30+
pub fn twist<T>(&mut self, length: T)
31+
where
32+
T: Into<usize>,
33+
{
34+
let length: usize = length.into();
35+
self.reverse(length);
36+
self.position = (self.position + self.skip + length) % self.elements.len();
37+
self.skip += 1;
38+
}
39+
40+
fn reverse(&mut self, length: usize) {
41+
for raw_index in 0..(length / 2) {
42+
let head_index = (self.position + raw_index) % self.elements.len();
43+
let tail_index = (self.elements.len() + self.position + length - raw_index - 1) %
44+
self.elements.len();
45+
self.elements.swap(head_index, tail_index);
46+
}
47+
}
48+
49+
pub fn initial_product(&self) -> usize {
50+
self.elements[0] as usize * self.elements[1] as usize
51+
}
52+
53+
pub fn twist_list<S, T>(&mut self, list: &S)
54+
where
55+
S: AsRef<[T]>,
56+
T: Copy + Into<usize>,
57+
{
58+
for &length in list.as_ref() {
59+
self.twist(length);
60+
}
61+
}
62+
}
63+
64+
pub fn hash<S, T>(list: &S) -> String
65+
where
66+
S: AsRef<[T]>,
67+
T: Copy + Into<usize>,
68+
{
69+
let mut lh = LoopHash::new();
70+
for _ in 0..64 {
71+
lh.twist_list(list);
72+
lh.twist_list(&[17_u8, 31, 73, 47, 23]);
73+
}
74+
75+
lh.elements
76+
.chunks(16)
77+
.map(|chunk| chunk.iter().fold(0 as Element, |l, r| l ^ r))
78+
.map(|dense| format!("{:02x}", dense))
79+
.collect()
80+
}
81+
82+
83+
#[cfg(test)]
84+
mod tests {
85+
use super::*;
86+
87+
#[test]
88+
fn test_example() {
89+
let mut lh = LoopHash::of_length(5);
90+
lh.twist(3_usize);
91+
assert_eq!(lh.elements, vec![2, 1, 0, 3, 4]);
92+
assert_eq!(lh.position, 3);
93+
assert_eq!(lh.skip, 1);
94+
lh.twist(4_usize);
95+
assert_eq!(lh.elements, vec![4, 3, 0, 1, 2]);
96+
assert_eq!(lh.position, 3);
97+
assert_eq!(lh.skip, 2);
98+
lh.twist(1_usize);
99+
assert_eq!(lh.elements, vec![4, 3, 0, 1, 2]);
100+
assert_eq!(lh.position, 1);
101+
assert_eq!(lh.skip, 3);
102+
lh.twist(5_usize);
103+
assert_eq!(lh.elements, vec![3, 4, 2, 1, 0]);
104+
assert_eq!(lh.position, 4);
105+
assert_eq!(lh.skip, 4);
106+
}
107+
108+
#[test]
109+
fn test_example_compact() {
110+
let mut lh = LoopHash::of_length(5);
111+
lh.twist_list(&[3_usize, 4, 1, 5]);
112+
assert_eq!(lh.initial_product(), 12);
113+
}
114+
115+
#[test]
116+
fn test_hash_examples() {
117+
let cases = [
118+
("", "a2582a3a0e66e6e86e3812dcb672a272"),
119+
("AoC 2017", "33efeb34ea91902bb2f59c9920caa6cd"),
120+
("1,2,3", "3efbe78a8d82f29979031a4aa0b16a9d"),
121+
("1,2,4", "63960835bcdc130f0b66d7ff4f6a5a8e"),
122+
];
123+
for &(input, expected) in cases.iter() {
124+
assert_eq!(hash(&input.as_bytes()), expected);
125+
}
126+
}
127+
}

day10/src/main.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
extern crate day10;
2+
use day10::{LoopHash, hash};
3+
4+
extern crate util;
5+
use util::{file_as_by, read_file};
6+
7+
fn main() {
8+
for hash_chain in file_as_by::<usize, _>("input.txt", |line| {
9+
line.split(',')
10+
.filter(|ref token| !token.is_empty())
11+
.collect()
12+
}).expect("Problem parsing input")
13+
{
14+
println!("Computing hash using: {:?}", hash_chain);
15+
let mut lh = LoopHash::new();
16+
lh.twist_list(&hash_chain);
17+
println!("Initial product: {}", lh.initial_product());
18+
}
19+
20+
// part 2
21+
let input_str = read_file("input.txt");
22+
println!("Hash of input file: {}", hash(&input_str.trim().as_bytes()))
23+
}

0 commit comments

Comments
 (0)