diff options
Diffstat (limited to '2016/aoc4/src/main.rs')
-rw-r--r-- | 2016/aoc4/src/main.rs | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/2016/aoc4/src/main.rs b/2016/aoc4/src/main.rs new file mode 100644 index 0000000..ea1edd8 --- /dev/null +++ b/2016/aoc4/src/main.rs @@ -0,0 +1,83 @@ +use std::io::BufReader; +use std::io::prelude::*; +use std::fs::File; +use std::collections::BTreeMap; + +#[derive(Debug)] +struct Room { + encrypted_name: String, + sector_id: u32, + checksum: String +} + +impl Room { + fn new(line: String) -> Room { + let name_length = line.find(char::is_numeric).unwrap(); + let (name, sector_and_check) = line.split_at(name_length); + let (sector, check) = sector_and_check.split_at(sector_and_check.len()-7); + + Room { + encrypted_name: name.trim_matches('-').to_string(), + sector_id: sector.parse().unwrap(), + checksum: check.trim_matches(|c| c=='[' || c==']').to_string() + } + } + + fn is_valid(&self) -> bool { + let mut char_counts: BTreeMap<char, i32> = BTreeMap::new(); + let chars = self.encrypted_name.chars() + .filter(|&c| c != '-'); + for c in chars { + *char_counts.entry(c).or_insert(0) += 1; + } + + let mut vec_char_counts = char_counts.iter().collect::<Vec<_>>(); + vec_char_counts.sort_by_key(|&(_, &value)| -value); + let expected_checksum = vec_char_counts + .iter() + .take(5) + .map(|&(&key, _)| key) + .collect::<String>(); + + expected_checksum == self.checksum + } + + fn decrypt_name(&self) -> String { + self.encrypted_name.chars().map(|c| { + if c == '-' { + ' ' + } else { + let current_digit = c as u8 - 'a' as u8; + let new_digit = ((current_digit as u32 + self.sector_id) % 26) as u8; + (new_digit + 'a' as u8) as char + } + }).collect() + } +} + +fn main() { + let rooms = read_file(); + let valid_rooms = rooms.iter() + .filter(|r| r.is_valid()) + .collect::<Vec<_>>(); + let sector_sum: u32 = valid_rooms.iter() + .map(|r| r.sector_id) + .sum(); + + println!("Sector sum {}", sector_sum); + + let north_poles = rooms.iter() + .filter(|r| r.decrypt_name().contains("north")) + .inspect(|r| println!("{} {}", r.decrypt_name(), r.sector_id)) + .collect::<Vec<_>>(); + println!("{:?}", north_poles); +} + +fn read_file() -> Vec<Room> { + let file = BufReader::new(File::open("input.txt").unwrap()); + file.lines() + .map(|line| line.unwrap().trim().to_string()) + .filter(|line| line.len() > 0) + .map(Room::new) + .collect() +} |