From b5da2fa328ad63d683d66da65e656ed2ee64878c Mon Sep 17 00:00:00 2001 From: Curtis McEnroe Date: Mon, 27 Nov 2017 17:11:18 -0500 Subject: Move to 2016 directory --- 2016/src/bin/day04.rs | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 2016/src/bin/day04.rs (limited to '2016/src/bin/day04.rs') diff --git a/2016/src/bin/day04.rs b/2016/src/bin/day04.rs new file mode 100644 index 0000000..8e724c2 --- /dev/null +++ b/2016/src/bin/day04.rs @@ -0,0 +1,123 @@ +use std::io::{self, Read}; +use std::str::FromStr; + +struct Room { + name: String, + sector_id: u32, + checksum: String, +} + +impl FromStr for Room { + type Err = (); + fn from_str(s: &str) -> Result { + let mut iter = s.trim_right_matches(']') + .rsplitn(3, |c| c == '-' || c == '['); + + let checksum = iter.next().ok_or(())?; + let sector_id = iter.next().ok_or(())?; + let name = iter.next().ok_or(())?; + + Ok(Room { + name: name.into(), + sector_id: sector_id.parse().map_err(|_| ())?, + checksum: checksum.into(), + }) + } +} + +impl Room { + fn checksum(&self) -> String { + let mut letters = [ + (0, 'a'), (0, 'b'), (0, 'c'), (0, 'd'), (0, 'e'), (0, 'f'), (0, 'g'), (0, 'h'), + (0, 'i'), (0, 'j'), (0, 'k'), (0, 'l'), (0, 'm'), (0, 'n'), (0, 'o'), (0, 'p'), + (0, 'q'), (0, 'r'), (0, 's'), (0, 't'), (0, 'u'), (0, 'v'), (0, 'w'), (0, 'x'), + (0, 'y'), (0, 'z'), + ]; + + for letter in self.name.chars().filter(|c| c.is_alphabetic()) { + let index = letter as u8 - b'a'; + letters[index as usize].0 -= 1; + } + + letters.sort(); + + letters.into_iter() + .map(|l| l.1) + .take(5) + .collect() + } + + fn verify_checksum(&self) -> bool { + self.checksum == self.checksum() + } + + fn decrypt_name(&self) -> String { + self.name.chars() + .map(|c| { + match c { + '-' => ' ', + _ => rotate(c, self.sector_id), + } + }) + .collect() + } +} + +fn rotate(c: char, n: u32) -> char { + let c = c as u8 + (n % 26) as u8; + if c > b'z' { + (c - 26) as char + } else { + c as char + } +} + +fn solve1(input: &str) -> u32 { + input.lines() + .map(str::parse) + .map(Result::unwrap) + .filter(Room::verify_checksum) + .map(|room| room.sector_id) + .sum() +} + +fn solve2(input: &str) -> Option { + input.lines() + .map(str::parse) + .map(Result::unwrap) + .filter(Room::verify_checksum) + .filter_map(|r| { + match r.decrypt_name().as_str() { + "northpole object storage" => Some(r.sector_id), + _ => None, + } + }) + .next() +} + +fn main() { + let mut input = String::new(); + io::stdin().read_to_string(&mut input).unwrap(); + + println!("Part 1: {}", solve1(&input)); + if let Some(sector_id) = solve2(&input) { + println!("Part 2: {}", sector_id); + } +} + +#[test] +fn part1() { + let input = " +aaaaa-bbb-z-y-x-123[abxyz] +a-b-c-d-e-f-g-h-987[abcde] +not-a-real-room-404[oarel] +totally-real-room-200[decoy] +"; + assert_eq!(1514, solve1(&input[1..])); +} + +#[test] +fn part2() { + let room: Room = "qzmt-zixmtkozy-ivhz-343[zimth]".parse().unwrap(); + assert_eq!("very encrypted name", room.decrypt_name()); +} -- cgit 1.4.1 8ad63d683d66da65e656ed2ee64878c&follow=1'>Move to 2016 directoryJune McEnroe