Solve 06
This commit is contained in:
parent
ab29172d43
commit
53e172f9c6
2 changed files with 133 additions and 0 deletions
106
src/bin/06.rs
Normal file
106
src/bin/06.rs
Normal 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),
|
||||
}
|
||||
}
|
||||
}
|
||||
27
src/lib.rs
27
src/lib.rs
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue