use std::cmp::Ordering; use std::str::FromStr; fn main() { let mut input_file = Some("input".to_string()); let mut args = std::env::args(); while args.len() > 0 { let arg = args.nth(0); if arg.unwrap().eq("-f") { let value = args.nth(0); if value.is_some() { input_file = value; } else { println!("No value after argument: '-f'"); } } } println!("Input file: '{:?}'", input_file); let mut elves = elves_from_file(&input_file.unwrap()).expect("failed to read file"); elves.sort_by(|a, b| b.cmp_by_calories(a)); println!("[PART 1] Elf with most calories: {}", elves[0].calories()); let p2_elves: std::vec::Vec::<_> = elves.into_iter() .enumerate() .filter(|&(i, _)| i < 3 ) .map(|(_, e)| e) .collect(); let mut p2_calories: u32 = 0; for x in p2_elves { p2_calories += x.calories(); } println!("[PART 2] Top 3 elves have these calories: {}", p2_calories); } struct Elf { items: std::vec::Vec, } impl Elf { fn calories(&self) -> u32 { let mut value = 0; for x in &self.items { value += x; } return value; } fn cmp_by_calories(&self, b: &Elf) -> Ordering { return self.calories().cmp(&b.calories()); } } fn elves_from_file(file_name: &String) -> std::result::Result, String> { let contents = std::fs::read_to_string(file_name).expect("Couldn't read contents of file"); return std::result::Result::Ok(elves_from_string(&contents)); } fn elves_from_string(contents: &String) -> std::vec::Vec:: { let mut elves = std::vec::Vec::::new(); let mut current_elf = Elf { items: std::vec::Vec::::new(), }; for line in contents.lines() { if line.eq("") { elves.push(current_elf); current_elf = Elf { items: std::vec::Vec::::new(), }; } else { match u32::from_str(&line) { Ok(v) => { current_elf.items.push(v); }, Err(_) => { println!("WARNING: '{}' does not convert to u32, skipping.", line); continue; }, } } } if current_elf.items.len() > 0 { elves.push(current_elf); } return elves; } #[cfg(test)] mod tests { use super::*; #[test] fn test_from_empty_string() { let contents = "".to_string(); let elves = elves_from_string(&contents); assert_eq!(elves.len(), 0); } #[test] fn test_from_string() { let contents = r#"1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 "#.to_string(); let elves = elves_from_string(&contents); assert_eq!(elves.len(), 5); let first = vec![1000, 2000, 3000]; assert!(first.eq(&elves[0].items)); let last = vec![10000]; assert!(last.eq(&elves[4].items)); } #[test] fn test_calories() { let mut elf = Elf { items: std::vec::Vec::::new(), }; assert_eq!(elf.calories(), 0); elf.items.push(1000); elf.items.push(10000); assert_eq!(elf.calories(), 11000); } #[test] fn test_sort() { let mut v = std::vec::Vec::::new(); v.push(Elf { items: vec![5000, 50000], }); v.push(Elf { items: vec![1000, 10000], }); assert_eq!(v[0].calories(), 55000); v.sort_by(|a, b| a.cmp_by_calories(b)); assert_eq!(v[0].calories(), 11000); } }