Created
December 11, 2017 14:50
-
-
Save jtdowney/7ba01b5f0bf0e8000a229f924978466b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::env; | |
use std::result; | |
struct KnotHasher { | |
current: usize, | |
skip: usize, | |
state: Vec<u8>, | |
} | |
impl Default for KnotHasher { | |
fn default() -> KnotHasher { | |
let mut state = Vec::with_capacity(256); | |
for i in 0..256 { | |
state.push(i as u8); | |
} | |
KnotHasher { | |
current: 0, | |
skip: 0, | |
state, | |
} | |
} | |
} | |
impl KnotHasher { | |
fn round(&mut self, input: &[u8]) { | |
let length = self.state.len(); | |
for &i in input { | |
let i = i as usize; | |
for j in 0..i / 2 { | |
let a = (self.current + j) % length; | |
let b = (self.current + i - j - 1) % length; | |
self.state.swap(a, b); | |
} | |
self.current = (self.current + i + self.skip) % length; | |
self.skip += 1; | |
} | |
} | |
fn hash(&mut self, input: &[u8]) -> String { | |
let mut input = input.to_vec(); | |
input.push(17); | |
input.push(31); | |
input.push(73); | |
input.push(47); | |
input.push(23); | |
for _ in 0..64 { | |
self.round(&input); | |
} | |
self.state | |
.chunks(16) | |
.map(|block| block.iter().fold(0, |acc, b| acc ^ b)) | |
.map(|b| format!("{:x}", b)) | |
.collect() | |
} | |
} | |
fn part1(input: &str) { | |
let input: Vec<u8> = input | |
.split(',') | |
.map(|v| v.trim().parse()) | |
.filter_map(result::Result::ok) | |
.collect(); | |
let mut hasher = KnotHasher::default(); | |
hasher.round(&input); | |
let answer: u32 = hasher.state.iter().take(2).map(|&v| u32::from(v)).product(); | |
println!("part 1: {}", answer); | |
} | |
fn part2(input: &str) { | |
let input = input.as_bytes(); | |
let mut hasher = KnotHasher::default(); | |
let hash = hasher.hash(input); | |
println!("part 2: {}", hash); | |
} | |
fn main() { | |
let input = env::args().nth(1).expect("input"); | |
part1(&input); | |
part2(&input); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment