feat(day7): init

This commit is contained in:
uku 2024-12-08 00:04:49 +01:00
parent 8ee1f29eed
commit a67033d39b
Signed by: uku
SSH key fingerprint: SHA256:4P0aN6M8ajKukNi6aPOaX0LacanGYtlfjmN+m/sHY/o
2 changed files with 161 additions and 0 deletions

159
src/solutions/day_07.rs Normal file
View file

@ -0,0 +1,159 @@
use crate::common::{Answer, Solution};
pub struct Day07;
impl Solution for Day07 {
fn name(&self) -> &'static str {
"Bridge Repair"
}
fn part_a(&self, input: &str) -> Answer {
let sum = input
.lines()
.map(|l| l.split_once(": ").unwrap())
.map(|(a, b)| {
let nums = b
.split_whitespace()
.map(|n| n.parse::<u64>().unwrap())
.collect::<Vec<_>>();
(a.parse::<u64>().unwrap(), nums)
})
.filter_map(|(total, nums)| {
let max = 2u32.pow(nums.len() as u32);
for i in 0..max {
let bits = Operation::from_binary(i, nums.len() - 1);
let mut nums = nums.iter();
let mut computed = *nums.next().unwrap();
for (&num, op) in nums.zip(bits) {
computed = op.apply(computed, num);
}
if computed == total {
return Some(total);
}
}
None
})
.sum::<u64>();
Answer::Number(sum)
}
fn part_b(&self, input: &str) -> Answer {
let sum = input
.lines()
.map(|l| l.split_once(": ").unwrap())
.map(|(a, b)| {
let nums = b
.split_whitespace()
.map(|n| n.parse::<u64>().unwrap())
.collect::<Vec<_>>();
(a.parse::<u64>().unwrap(), nums)
})
.filter_map(|(total, nums)| {
let max = 3u32.pow(nums.len() as u32);
for i in 0..max {
let bits = Operation::from_ternary(i, nums.len() - 1);
let mut nums = nums.iter();
let mut computed = *nums.next().unwrap();
for (&num, op) in nums.zip(bits) {
computed = op.apply(computed, num);
}
if computed == total {
return Some(total);
}
}
None
})
.sum::<u64>();
Answer::Number(sum)
}
}
#[derive(Debug)]
enum Operation {
Addition,
Multiplication,
Concatenation,
}
impl Operation {
fn from_binary(mut number: u32, length: usize) -> Vec<Self> {
let mut vec = Vec::with_capacity(length);
while number != 0 || vec.len() < length {
vec.push(Self::parse_mod(number % 2));
number >>= 1;
}
vec
}
fn from_ternary(mut number: u32, length: usize) -> Vec<Self> {
let mut vec = Vec::with_capacity(length);
for _ in 0..length {
vec.push(Self::parse_mod(number));
number /= 3;
}
vec
}
fn parse_mod(num: u32) -> Self {
match num % 3 {
0 => Self::Addition,
1 => Self::Multiplication,
2 => Self::Concatenation,
_ => unreachable!(),
}
}
fn apply(&self, a: u64, b: u64) -> u64 {
match self {
Operation::Addition => a + b,
Operation::Multiplication => a * b,
Operation::Concatenation => format!("{a}{b}").parse::<u64>().unwrap(),
}
}
}
#[cfg(test)]
mod test {
use super::Day07;
use crate::common::Solution;
use indoc::indoc;
const INPUT: &str = indoc! {"
190: 10 19
3267: 81 40 27
83: 17 5
156: 15 6
7290: 6 8 6 15
161011: 16 10 13
192: 17 8 14
21037: 9 7 18 13
292: 11 6 16 20
"};
#[test]
fn part_a() {
assert_eq!(Day07.part_a(INPUT), 3749.into());
}
#[test]
fn part_b() {
assert_eq!(Day07.part_b(INPUT), 11387.into());
}
}

View file

@ -6,6 +6,7 @@ mod day_03;
mod day_04;
mod day_05;
mod day_06;
mod day_07;
pub const SOLUTIONS: &[&dyn Solution] = &[
&day_01::Day01,
@ -14,4 +15,5 @@ pub const SOLUTIONS: &[&dyn Solution] = &[
&day_04::Day04,
&day_05::Day05,
&day_06::Day06,
&day_07::Day07,
];