use std::{fs::read_to_string, iter}; fn main() { let input = read_to_string("../input.txt").expect("failed to open input file"); let mut problems = input.lines(); let operator_line = problems.next_back().expect("file was empty"); let numbers: Vec<_> = problems.collect(); let operators: Vec<_> = operator_line.match_indices(['+', '*']).collect(); let last_operator = operators.last().expect("couldn't find any operators"); let grand_total: u64 = operators .windows(2) .map(|window| (window[0].0..window[1].0 - 1, window[0].1)) .chain(iter::once(( last_operator.0..operator_line.len(), last_operator.1, ))) .map(|(problem_range, operator)| { let numbers = problem_range.map(|column| { numbers .iter() .filter_map(|number_line| (number_line.as_bytes()[column] as char).to_digit(10)) .rev() .enumerate() .map(|(placement, digit)| u64::from(digit) * 10u64.pow(placement as u32)) .sum::() }); match operator { "+" => numbers.sum::(), "*" => numbers.product(), operator => panic!("unrecognised operator '{operator}'"), } }) .sum(); println!("The grand total is {grand_total}!"); }