Day 7: Part 1

This commit is contained in:
LeMoonStar 2024-12-08 00:04:32 +01:00
parent 6f7872ed33
commit 0ff7e66083
2 changed files with 145 additions and 11 deletions

View file

@ -2,31 +2,156 @@ use super::{Answer, Day, DayImpl};
const CURRENT_DAY: u8 = 7; const CURRENT_DAY: u8 = 7;
type Data = Vec<u64>; #[derive(Debug, Clone, Copy)]
enum Operator {
Add,
Multiply,
}
impl Operator {
fn calculate(&self, a: u64, b: u64) -> u64 {
match self {
Operator::Multiply => a * b,
Operator::Add => a + b,
}
}
}
#[derive(Debug, Clone)]
struct CombinationIterator<'a, T>
where
T: Sized + Clone,
{
iteration: usize,
length: u32,
possibilities: &'a [T],
}
impl<'a, T> CombinationIterator<'a, T>
where
T: Sized + Clone,
{
fn get_index_on_position(&self, position: u32) -> usize {
(if position == 0 {
self.iteration
} else {
self.iteration / (self.possibilities.len().pow(position))
}) % self.possibilities.len()
}
fn new(possibilities: &'a [T], length: u32) -> Self {
Self {
iteration: 0,
length,
possibilities,
}
}
}
impl<'a, T> Iterator for CombinationIterator<'a, T>
where
T: Sized + Clone,
{
type Item = Vec<T>;
fn next(&mut self) -> Option<Self::Item> {
if self.get_index_on_position(self.length) != 0 {
return None;
}
let values = (0..self.length)
.map(|p| self.possibilities[self.get_index_on_position(p)].clone())
.collect();
self.iteration += 1;
return Some(values);
}
}
#[derive(Debug, Clone)]
pub struct CalibrationEquation {
pub result: u64,
pub parts: Vec<u64>,
}
impl CalibrationEquation {
fn calculate(&self, operations: Vec<Operator>) -> u64 {
let mut value = self.parts[0];
for i in 1..(self.parts.len()) {
value = operations[i - 1].calculate(value, self.parts[i]);
}
value
}
fn can_be_valid(&self) -> bool {
CombinationIterator::new(
&[Operator::Add, Operator::Multiply],
(self.parts.len() - 1) as u32,
)
.map(|o| self.calculate(o))
.collect::<Vec<_>>()
.contains(&self.result)
}
}
impl From<&str> for CalibrationEquation {
fn from(value: &str) -> Self {
let (first, second) = value.split_once(':').unwrap();
Self {
result: first.parse().unwrap(),
parts: second
.trim()
.split_whitespace()
.map(|v| v.parse().unwrap())
.collect(),
}
}
}
#[derive(Debug, Clone)]
pub struct Calibrator {
equations: Vec<CalibrationEquation>,
}
impl Calibrator {
pub fn get_valid_sum(&self) -> u64 {
self.equations
.iter()
.filter(|v| v.can_be_valid())
.map(|v| v.result)
.sum()
}
}
impl From<&str> for Calibrator {
fn from(value: &str) -> Self {
Self {
equations: value.lines().map(|v| v.into()).collect(),
}
}
}
type Data = Calibrator;
impl DayImpl<Data> for Day<CURRENT_DAY> { impl DayImpl<Data> for Day<CURRENT_DAY> {
fn init_test() -> (Self, Data) { fn init_test() -> (Self, Data) {
Self::init(include_str!("test_inputs/test07.txt")) Self::init(include_str!("test_inputs/test07.txt"))
} }
fn expected_results() -> (Answer, Answer) { fn expected_results() -> (Answer, Answer) {
(Answer::Number(0), Answer::Number(0)) (Answer::Number(3749), Answer::Number(0))
} }
fn init(input: &str) -> (Self, Data) { fn init(input: &str) -> (Self, Data) {
( (Self {}, input.into())
Self {},
input
.lines()
.map(|v| v.parse::<u64>().expect("error while parsing input."))
.collect(),
)
} }
fn one(&self, data: &mut Data) -> Answer { fn one(&self, data: &mut Data) -> Answer {
Answer::Number(data.len() as u64) Answer::Number(data.get_valid_sum())
} }
fn two(&self, data: &mut Data) -> Answer { fn two(&self, data: &mut Data) -> Answer {
Answer::Number(data.len() as u64) Answer::Number(0)
} }
} }

View file

@ -0,0 +1,9 @@
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