use std::env; use std::io::BufReader; use std::io::BufRead; use std::fs::File; use std::process; use std::collections::{HashSet, HashMap}; #[macro_use] extern crate text_io; struct Guard { id: u32, minutes: Vec, total: Option, max_min: Option } fn main() { let args: Vec = env::args().collect(); if args.len() != 2 { println!("Wrong number of arguments. Provide just a file name."); process::exit(1); } let filename = &args[1]; println!("Using file {} as input.", filename); let f = match File::open(filename) { Ok(file) => file, Err(e) => { println!("Failed to open file {}. {:?}", filename, e); process::exit(1); } }; let file = BufReader::new(&f); let mut lines: Vec = file.lines() .map(|line| line.expect("Could not parse line.")) .collect(); &lines.sort(); // exercise 1 let mut guards: HashMap = HashMap::new(); let mut id: Option = None; let mut start_min: Option = None; for line in &lines { let (year, month, day, hour, minute, command): (u32, u32, u32, u32, u32, String); scan!(line.bytes() => "[{}-{}-{} {}:{}]", year, month, day, hour, minute); command = (&line[19..]).to_string(); match command.as_ref() { "falls asleep" => { println!("Debug: line: '{}', cmd: '{}', start_min: {}", &line, &command, minute); start_min = Some(minute); } "wakes up" => { println!("Debug: line: '{}', cmd: '{}', end_min: {}", &line, &command, minute); let gid = id.expect("Id not set."); if !guards.contains_key(&gid) { let minutes = vec![0; 60]; let g = Guard { id: gid, minutes, total: None, max_min: None }; guards.insert(gid, g); } let mut guard_opt = guards.get_mut(&gid); let mut guard = guard_opt.expect("Guard not set."); let min = start_min.expect("start_min not set."); for i in 0..60 { if min <= i && i <= minute { guard.minutes[i as usize] += 1; } } } _ => { let new_id: u32; scan!(command.bytes() => "Guard #{} begins shift", new_id); println!("Debug: line: '{}', cmd: '{}', id: {}", &line, &command, new_id); id = Some(new_id); start_min = None; } } } let ids: Vec = guards.keys().map(|v| *v).collect(); let mut guard_id: u32 = 0; let mut best_total = 0; for id in &ids { let mut guard_opt = (&mut guards).get_mut(&id); let mut guard = guard_opt.expect("Guard not set."); println!("Debug: Guard {}", guard.id); let total = guard.minutes.iter().fold(0, |acc, x| acc + x); guard.total = Some(total); let mut best_index: usize = 0; for i in 1..60 { if guard.minutes[i as usize] > guard.minutes[best_index] { best_index = i; println!("Debug: Best index for guard {} is now {}", &id, &i); } } guard.max_min = Some(best_index); if total > best_total { best_total = total; guard_id = *id; } } let guard = guards.get(&guard_id).expect("Guard not set."); let mut index = 0; let mut best_minute = 0; for i in 0..60 { let val = guard.minutes[i as usize]; if val > best_minute { index = i; best_minute = val; } } let mut guard_id_2: usize = 0; let mut guard_max_min: usize = 0; let mut guard_max_val: u32 = 0; for id in &ids { let guard = &guards.get(id).expect("guard not set"); let max_min = guard.max_min.expect("max_min not set."); let val = guard.minutes[max_min]; if val > guard_max_val { guard_id_2 = *id as usize; guard_max_min = max_min; guard_max_val = val; println!("Best guard max_min combo is now guard {} and minute {}, value: {}", &id, &max_min, &val); } } println!("1. Guard id: {}", guard_id); println!("1. Minute index: {}", index); println!("1. Result: {}", index * guard_id); println!("2. Guard id: {}", guard_id_2); println!("2. Minute index: {}", guard_max_min); println!("2. Result: {}", guard_max_min * guard_id_2); }