use itertools::Itertools; use crate::spatial; pub fn day6_part1(input: &str) -> String { let problems = parse(input, false); let answers = problems .iter() .map(|(operands, operator)| evaluate(operands, *operator)) .collect_vec(); dbg!(answers).iter().sum::().to_string() } pub fn day6_part2(input: &str) -> String { let problems = parse(input, true); let answers = problems .iter() .map(|(operands, operator)| evaluate(operands, *operator)) .collect_vec(); dbg!(answers).iter().sum::().to_string() } fn evaluate(operands: &[u64], operator: Operator) -> u64 { match operator { Operator::Plus => operands.iter().sum(), Operator::Times => operands.iter().product(), } } #[derive(Clone, Copy, Debug)] enum Operator { Plus, Times, } fn parse(input: &str, cephalopod_style: bool) -> Vec<(Vec, Operator)> { let rows: Vec> = input.lines().map(|line| line.chars().collect()).collect(); let mut problems = vec![]; let mut beginning_of_last_problem = 0; for col in 0..=rows[0].len() { let is_river = col == rows[0].len() || (0..rows.len()).all(|row| rows[row][col] == ' '); if !is_river { continue; } problems.push( (0..rows.len()) .map(|row| rows[row][beginning_of_last_problem..col].to_vec()) .collect_vec(), ); beginning_of_last_problem = col + 1; } let parsed_problems = problems.into_iter().map(|problem| { let operands = if !cephalopod_style { problem[..problem.len() - 1].to_vec() } else { spatial::transpose(&problem[..problem.len() - 1]) } .iter() .map(|line| line.iter().collect::().trim().parse().unwrap()) .collect(); let operator = problem[problem.len() - 1].iter().collect::(); let operator = match operator.trim() { "+" => Operator::Plus, "*" => Operator::Times, _ => unreachable!("{operator}"), }; (operands, operator) }); parsed_problems.collect() }