Dieser Commit ist enthalten in:
Sebastian Tobie 2024-12-08 01:43:53 +01:00
Ursprung 20ad63acaf
Commit bd97c2e422
2 geänderte Dateien mit 190 neuen und 0 gelöschten Zeilen

9
examples/2024/07.txt Normale Datei
Datei anzeigen

@ -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

181
src/bin/2024/07.rs Normale Datei
Datei anzeigen

@ -0,0 +1,181 @@
#![cfg_attr(debug_assertions, allow(unused_imports))]
use std::ops::{Add, AddAssign, BitXor, Mul};
use advent_of_code::{
numberlength,
strings::{convert_to_array, parsenumber},
};
use advent_of_code_macros::{include_data, include_example};
use log::*;
use num::{pow::Pow, Integer};
include_data!(DATA 2024 07);
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
enum Operation {
Add,
Multiply,
Concat,
}
impl Operation {
fn op<
T: Integer
+ Add
+ Mul
+ Pow<u32, Output = T>
+ std::ops::DivAssign
+ AddAssign
+ From<u32>
+ Copy,
>(
self,
a: T,
b: T,
) -> T {
match self {
Operation::Add => a + b,
Operation::Multiply => a * b,
Operation::Concat => {
let ta = a * T::from(10).pow(numberlength(b));
ta + b
}
}
}
}
fn get_data(line: &str) -> (u64, Vec<u64>) {
let (result, numbers) = line.split_once(':').unwrap();
(
parsenumber(result.trim()),
Vec::from(convert_to_array::<_, _, ' '>(numbers, parsenumber)),
)
}
fn test_equation(result: u64, numbers: Vec<u64>, ops: Vec<Operation>) -> bool {
let mut numberiter = numbers.iter();
let mut opiter = ops.iter();
let mut calcresult = numberiter.next().unwrap().clone();
let mut next_number;
debug_assert!(numbers.len() - 1 == ops.len());
loop {
next_number = numberiter.next().cloned();
if next_number.is_none() {
return calcresult == result;
}
calcresult = opiter.next().unwrap().op(calcresult, next_number.unwrap())
}
}
fn get_ops(len: usize, conf: usize) -> Vec<Operation> {
let mut shift = 0;
let mut ops = Vec::with_capacity(len);
loop {
match (conf & (0b1 << shift)) >> shift {
0 => ops.push(Operation::Add),
1 => ops.push(Operation::Multiply),
_ => unreachable!(),
};
shift += 1;
if ops.len() == len {
break;
}
}
ops
}
fn get_ops_with_concat(len: u32) -> Vec<Vec<Operation>> {
let mut ops = Vec::with_capacity(3u64.saturating_pow(len) as usize);
for i in [Operation::Add, Operation::Concat, Operation::Multiply] {
if len > 1 {
for mut oplist in get_ops_with_concat(len - 1) {
oplist.insert(0, i);
ops.push(oplist);
}
} else {
ops.push(vec![i]);
}
}
ops
}
#[inline]
fn pow2(i: usize) -> usize {
2_u64.pow(i as u32) as usize - 1
}
fn solution1(data: Vec<(u64, Vec<u64>)>) -> u64 {
let mut output = 0;
for line in data {
for i in 0..=pow2(line.1.len()) {
if test_equation(line.0, line.1.clone(), get_ops(line.1.len() - 1, i)) {
output += line.0;
break;
}
}
}
output
}
fn solution2(data: Vec<(u64, Vec<u64>)>) -> u128 {
let mut output = 0;
for line in data {
for ops in get_ops_with_concat((line.1.len() - 1) as u32) {
if test_equation(line.0, line.1.clone(), ops) {
output += line.0 as u128;
break;
}
}
}
output
}
fn main() {
let data = convert_to_array::<_, _, '\n'>(DATA, get_data);
println!("Found Calibration Total: {}", solution1(data.clone()));
println!("Calibration total with Concat: {}", solution2(data.clone()));
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_test_equation() {
for c in [
(
190,
Vec::from([10, 19]),
Vec::from([Operation::Multiply]),
true,
),
(
3267,
Vec::from([81, 40, 27]),
Vec::from([Operation::Add, Operation::Multiply]),
true,
),
(
3267,
Vec::from([81, 40, 27]),
Vec::from([Operation::Multiply, Operation::Add]),
true,
),
(
292,
Vec::from([11, 6, 16, 20]),
Vec::from([Operation::Add, Operation::Multiply, Operation::Add]),
true,
),
(
292,
Vec::from([11, 6, 16, 20]),
Vec::from([Operation::Add, Operation::Multiply, Operation::Multiply]),
false,
),
] {
assert_eq!(test_equation(c.0, c.1.into(), c.2.into()), c.3)
}
}
}