2016/04
This commit is contained in:
165
2016/04/src/main.rs
Normal file
165
2016/04/src/main.rs
Normal file
@@ -0,0 +1,165 @@
|
||||
#[macro_use] extern crate lazy_static;
|
||||
extern crate regex;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::str::FromStr;
|
||||
use std::io::{self, BufRead};
|
||||
|
||||
use regex::Regex;
|
||||
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct Room {
|
||||
enc_name: String,
|
||||
sector_id: u32,
|
||||
checksum: Vec<char>
|
||||
}
|
||||
|
||||
impl Room {
|
||||
pub fn encoded_name(&self) -> &str {
|
||||
self.enc_name.as_str()
|
||||
}
|
||||
|
||||
pub fn decoded_name(&self) -> String {
|
||||
self.enc_name.chars()
|
||||
.map(|x| {
|
||||
if x == '-' {
|
||||
' '
|
||||
} else {
|
||||
((((x as u32 - 97 + self.sector_id()) % 26) + 97) as u8) as char
|
||||
}
|
||||
})
|
||||
.collect::<String>()
|
||||
}
|
||||
|
||||
pub fn sector_id(&self) -> u32 {
|
||||
self.sector_id
|
||||
}
|
||||
|
||||
pub fn checksum(&self) -> &Vec<char> {
|
||||
&self.checksum
|
||||
}
|
||||
|
||||
pub fn calculate_checksum(&self) -> Vec<char> {
|
||||
let map = self.enc_name.chars()
|
||||
.filter(|x| *x != '-')
|
||||
.fold(HashMap::new(), |mut map, x| {
|
||||
*map.entry(x).or_insert(0) += 1;
|
||||
|
||||
map
|
||||
});
|
||||
|
||||
let mut vec: Vec<_> = map.iter().collect();
|
||||
|
||||
vec.sort_by(|a, b| if a.1 != b.1 { b.1.cmp(a.1) } else { a.0.cmp(b.0) });
|
||||
|
||||
vec.iter().take(5).map(|x| *x.0).collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
pub fn verify(&self) -> bool {
|
||||
*self.checksum() == self.calculate_checksum()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Room {
|
||||
type Err = ();
|
||||
|
||||
fn from_str(s: &str) -> Result<Room, ()> {
|
||||
lazy_static! {
|
||||
static ref RE: Regex = Regex::new(r"^(.*)-(\d+)\[([a-z]+)\]$").unwrap();
|
||||
}
|
||||
|
||||
if let Some(caps) = RE.captures(s) {
|
||||
let enc_name = String::from(caps.at(1).unwrap());
|
||||
let sector_id = caps.at(2).unwrap().parse::<u32>().unwrap();
|
||||
let checksum = caps.at(3).unwrap().chars().collect::<Vec<_>>();
|
||||
|
||||
return Ok(Room {
|
||||
enc_name: enc_name,
|
||||
sector_id: sector_id,
|
||||
checksum: checksum
|
||||
});
|
||||
}
|
||||
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn main() {
|
||||
let stdin = io::stdin();
|
||||
|
||||
let input = stdin.lock().lines()
|
||||
.filter_map(|x| x.ok())
|
||||
.filter_map(|x| Room::from_str(&x).ok())
|
||||
.filter(|x| x.verify())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let count: i64 = input.iter()
|
||||
.map(|x| x.sector_id() as i64)
|
||||
.sum();
|
||||
|
||||
for room in input {
|
||||
println!("{}: {}", room.sector_id(), room.decoded_name());
|
||||
}
|
||||
|
||||
println!("count={}", count);
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::str::FromStr;
|
||||
|
||||
#[test]
|
||||
fn example_01() {
|
||||
let room = Room::from_str("aaaaa-bbb-z-y-x-123[abxyz]").unwrap();
|
||||
|
||||
assert_eq!("aaaaa-bbb-z-y-x", room.encoded_name());
|
||||
assert_eq!(123, room.sector_id());
|
||||
assert_eq!(&vec!['a', 'b', 'x', 'y', 'z'], room.checksum());
|
||||
|
||||
assert_eq!(true, room.verify());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn example_02() {
|
||||
let room = Room::from_str("a-b-c-d-e-f-g-h-987[abcde]").unwrap();
|
||||
|
||||
assert_eq!("a-b-c-d-e-f-g-h", room.encoded_name());
|
||||
assert_eq!(987, room.sector_id());
|
||||
assert_eq!(&vec!['a', 'b', 'c', 'd', 'e'], room.checksum());
|
||||
|
||||
assert_eq!(true, room.verify());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn example_03() {
|
||||
let room = Room::from_str("not-a-real-room-404[oarel]").unwrap();
|
||||
|
||||
assert_eq!("not-a-real-room", room.encoded_name());
|
||||
assert_eq!(404, room.sector_id());
|
||||
assert_eq!(&vec!['o', 'a', 'r', 'e', 'l'], room.checksum());
|
||||
|
||||
assert_eq!(true, room.verify());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn example_04() {
|
||||
let room = Room::from_str("totally-real-room-200[decoy]").unwrap();
|
||||
|
||||
assert_eq!("totally-real-room", room.encoded_name());
|
||||
assert_eq!(200, room.sector_id());
|
||||
assert_eq!(&vec!['d', 'e', 'c', 'o', 'y'], room.checksum());
|
||||
|
||||
assert_eq!(false, room.verify());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn example_05() {
|
||||
let room = Room::from_str("qzmt-zixmtkozy-ivhz-343[decoy]").unwrap();
|
||||
|
||||
assert_eq!(String::from("very encrypted name"), room.decoded_name());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user