#![feature(test)] use std::{collections::BinaryHeap, fs::read_to_string}; fn main() { let input = read_to_string("input.txt").expect("need input file"); let (max, top3) = initial(&input); println!("{max}, {top3}"); let (max, top3) = idiomatic(&input); println!("{max}, {top3}"); } fn idiomatic(input: &str) -> (u32, u32) { let mut sums: BinaryHeap<_> = input .split_terminator("\n\n") .map(|block| { block .split_terminator('\n') .map(|line| line.parse::().unwrap_or_default()) .sum() }) .collect(); let max = sums.pop().unwrap_or_default(); let top3 = max + sums.pop().unwrap_or_default() + sums.pop().unwrap_or_default(); (max, top3) } fn initial(input: &str) -> (u32, u32) { let numbers = input.split_terminator('\n').map(|s| s.parse::().ok()); let mut elves = vec![0]; for number in numbers { match number { Some(ration) => { *elves.last_mut().unwrap() += ration; } None => elves.push(0), } } let (index, max) = elves.iter().enumerate().max_by_key(|(_, v)| **v).unwrap(); let mut elves = elves.clone(); elves.remove(index); let (index, second) = elves.iter().enumerate().max_by_key(|(_, v)| **v).unwrap(); let mut elves = elves.clone(); elves.remove(index); let third = elves.iter().max().unwrap(); let top3 = max + second + third; (*max, top3) } #[cfg(test)] mod tests { use std::{ fs::File, io::{BufRead, BufReader}, }; use super::*; extern crate test; use test::Bencher; #[bench] fn bench_initial(b: &mut Bencher) { let input = read_to_string("input.txt").expect("need input file"); b.iter(|| initial(&input)); } #[bench] fn bench_idiomatic(b: &mut Bencher) { let input = read_to_string("input.txt").expect("need input file"); b.iter(|| idiomatic(&input)); } #[bench] fn bench_read_string(b: &mut Bencher) { b.iter(|| { read_to_string("input.txt") .unwrap() .split_terminator('\n') .for_each(drop); }); } #[bench] fn bench_lines(b: &mut Bencher) { b.iter(|| { BufReader::new(File::open("input.txt").unwrap()) .lines() .for_each(drop); }); } }