1
0
Fork 0
This commit is contained in:
Lars Martens 2025-12-06 13:39:17 +01:00
parent ab29172d43
commit 53e172f9c6
Signed by: haselkern
GPG key ID: B5CF1F363C179AD4
2 changed files with 133 additions and 0 deletions

106
src/bin/06.rs Normal file
View file

@ -0,0 +1,106 @@
use anyhow::bail;
use aoc::*;
use itertools::Itertools;
use std::str::FromStr;
const INPUT: &str = include_str!("../../input/06");
fn main() {
println!("Part 1: {}", part1(INPUT));
println!("Part 2: {}", part2(INPUT));
}
#[test]
fn example() {
assert_example!(part1, "06-test", 4277556);
assert_example!(part2, "06-test", 3263827);
}
fn part1(input: &str) -> usize {
let (numbers, ops) = parse_input1(input);
let num_problems = numbers[0].len();
let mut grand_total = 0;
for problem in 0..num_problems {
let op = ops[problem];
grand_total += numbers
.iter()
.map(|row| row[problem])
.reduce(|a, b| op.calc(a, b))
.unwrap();
}
grand_total
}
fn parse_input1(input: &str) -> (Vec<Vec<usize>>, Vec<Op>) {
let mut rows = Vec::new();
let mut ops = Vec::new();
for line in input.lines() {
if line.contains('+') {
ops = parse_ws_separated(line).collect();
} else {
rows.push(parse_ws_separated(line).collect());
}
}
(rows, ops)
}
fn part2(input: &str) -> usize {
let lines = input
.lines()
.map(|line| line.chars().collect_vec())
.collect_vec();
let lines = transpose(lines)
.into_iter()
.map(|row| row.into_iter().join("").replace(' ', "").to_owned())
.collect_vec();
lines.split(|row| row.is_empty()).map(solve_problem).sum()
}
fn solve_problem(problem: &[String]) -> usize {
let mut problem = problem.iter();
let first_line = problem.next().unwrap();
let (n, op): (usize, Op) = if let Some(n) = first_line.strip_suffix('+') {
(n.parse().unwrap(), Op::Add)
} else if let Some(n) = first_line.strip_suffix('*') {
(n.parse().unwrap(), Op::Mul)
} else {
panic!("first line invalid format: '{first_line}'");
};
problem.fold(n, move |acc, row| {
let n = row.parse().unwrap();
op.calc(acc, n)
})
}
#[derive(Debug, Clone, Copy)]
enum Op {
Add,
Mul,
}
impl Op {
fn calc(&self, a: usize, b: usize) -> usize {
match self {
Op::Add => a + b,
Op::Mul => a * b,
}
}
}
impl FromStr for Op {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"+" => Ok(Op::Add),
"*" => Ok(Op::Mul),
_ => bail!("invalid op: '{}'", s),
}
}
}

View file

@ -127,3 +127,30 @@ pub const DIRECTIONS8: [IVec2; 8] = [
IVec2::new(0, -1),
IVec2::new(1, -1),
];
/// Transposes a Vec of Vecs.
///
/// ```rust
/// # use aoc::transpose;
/// let input = vec![vec![1, 2, 3], vec![4, 5, 6]];
/// let expected = vec![vec![1, 4], vec![2, 5], vec![3, 6]];
/// assert_eq!(transpose(input), expected);
/// ```
///
/// https://stackoverflow.com/a/64499219
pub fn transpose<T>(v: Vec<Vec<T>>) -> Vec<Vec<T>> {
if v.is_empty() {
return v;
}
let len = v[0].len();
let mut iters: Vec<_> = v.into_iter().map(|n| n.into_iter()).collect();
(0..len)
.map(|_| {
iters
.iter_mut()
.map(|n| n.next().unwrap())
.collect::<Vec<T>>()
})
.collect()
}