1
0

Compare commits

...

4 Commits

Author SHA1 Message Date
af98c60972 day 7 cleanup 2024-12-07 07:23:00 +01:00
38e2a96a7a day 7 part 2 2024-12-07 07:18:33 +01:00
226a1fde49 day 7 part 1 2024-12-07 06:50:13 +01:00
2392539b6e option part for grid 2024-12-06 17:22:57 +01:00
5 changed files with 170 additions and 16 deletions

View File

@@ -1,7 +1,4 @@
use std::{
collections::HashSet,
fs::read_to_string,
};
use std::{collections::HashSet, fs::read_to_string};
use crate::utils::grid::{Coord, Grid};

120
src/day07.rs Normal file
View File

@@ -0,0 +1,120 @@
use std::fs::read_to_string;
use itertools::Itertools;
use regex::Regex;
pub fn day_main() {
let input = read_to_string("input/day07.txt").unwrap();
let input = input.trim();
println!(" part1: {}", part1(input));
println!(" part2: {}", part2(input));
}
type RiddleResult = i64;
fn part1(input: &str) -> RiddleResult {
let regex = Regex::new("(\\d+)").unwrap();
input
.lines()
.map(|line| {
regex
.find_iter(line)
.map(|capture| capture.as_str().parse::<i64>().unwrap())
.collect_vec()
})
.filter(|v| well_calibrated(v))
.map(|v| v[0])
.sum()
}
fn well_calibrated(list: &[i64]) -> bool {
let expected = list[0];
let operands = list.iter().skip(1).copied().collect_vec();
let operators = ops(operands.len() - 1);
for ops in operators.into_iter() {
let v = ops
.into_iter()
.zip(operands.iter().skip(1))
.fold(operands[0], |acc, (op, val)| match op {
'*' => acc * val,
'+' => acc + val,
_ => panic!(),
});
if v == expected {
return true;
}
}
false
}
fn ops(n: usize) -> Vec<Vec<char>> {
if n == 1 {
return vec![vec!['+'], vec!['*']];
}
let v = ops(n - 1);
v.into_iter()
.flat_map(|vector| {
let mut v1 = vector.clone();
let mut v2 = vector;
v1.push('+');
v2.push('*');
[v1, v2]
})
.collect_vec()
}
fn part2(input: &str) -> RiddleResult {
let regex = Regex::new("(\\d+)").unwrap();
input
.lines()
.map(|line| {
regex
.find_iter(line)
.map(|capture| capture.as_str().parse::<i64>().unwrap())
.collect_vec()
})
.filter(|v| well(v[0], v[1], &v[2..]))
.map(|v| v[0])
.sum()
}
fn well(expected: i64, acc: i64, operands: &[i64]) -> bool {
if operands.is_empty() {
return expected == acc;
}
let next = operands[0];
let remainder = &operands[1..];
let v_mul = acc * next;
let v_plus = acc + next;
let v_concat = format!("{acc}{next}").parse().unwrap();
well(expected, v_mul, remainder)
|| well(expected, v_plus, remainder)
|| well(expected, v_concat, remainder)
}
#[cfg(test)]
mod test {
use super::{part1, part2};
const TEST_INPUT: &str = r"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 test1() {
assert_eq!(part1(TEST_INPUT), 3749);
}
#[test]
fn test2() {
assert_eq!(part2(TEST_INPUT), 11387);
}
}

View File

@@ -4,4 +4,5 @@ pub mod day03;
pub mod day04;
pub mod day05;
pub mod day06;
pub mod day07;
pub mod utils;

View File

@@ -11,6 +11,7 @@ fn main() {
(4, day04::day_main),
(5, day05::day_main),
(6, day06::day_main),
(7, day07::day_main),
]);
let day: Option<u8> = args().nth(1).and_then(|a| a.parse().ok());
let Some(day) = day else {

View File

@@ -39,12 +39,22 @@ impl<T> Grid<T> {
(c.1 * self.content_width + c.0) as usize
}
pub fn get(&self, c: Coord) -> &T {
&self.content[self.index_of(c)]
pub fn get(&self, c: Coord) -> Option<&T> {
let index = self.index_of(c);
if index < self.content.len() {
Some(&self.content[self.index_of(c)])
} else {
None
}
}
pub fn get_mut(&mut self, c: Coord) -> Option<&mut T> {
let index = self.index_of(c);
if index < self.content.len() {
Some(&mut self.content[index])
} else {
None
}
pub fn get_mut(&mut self, c: Coord) -> &mut T {
let index_of = self.index_of(c);
&mut self.content[index_of]
}
pub fn set(&mut self, c: Coord, value: T) {
@@ -90,13 +100,14 @@ impl<T> Index<Coord> for Grid<T> {
#[inline]
fn index(&self, index: Coord) -> &Self::Output {
self.get(index)
&self.content[self.index_of(index)]
}
}
impl<T> IndexMut<Coord> for Grid<T> {
fn index_mut(&mut self, index: Coord) -> &mut Self::Output {
self.get_mut(index)
let index_of = self.index_of(index);
&mut self.content[index_of]
}
}
@@ -115,17 +126,25 @@ mod test {
((1, 0), '.'),
((1, 1), '#'),
]));
assert_eq!(&'.', grid.get((0, 0)));
assert_eq!(&'.', grid.get((0, 1)));
assert_eq!(&'.', grid.get((1, 0)));
assert_eq!(&'#', grid.get((1, 1)));
assert_eq!('.', grid[(0, 0)]);
assert_eq!('.', grid[(0, 1)]);
assert_eq!('.', grid[(1, 0)]);
assert_eq!('#', grid[(1, 1)]);
}
#[test]
fn mutate_by_index() {
let mut grid = generate();
grid[(0, 1)] = 'x';
assert_eq!(&'x', grid.get((0, 1)));
assert_eq!('x', grid[(0, 1)]);
}
#[test]
fn mutate_option() {
let mut grid = generate();
if let Some(value) = grid.get_mut((0, 1)) {
*value = 'x';
}
assert_eq!('x', grid[(0, 1)]);
}
fn generate() -> Grid<char> {
@@ -157,4 +176,20 @@ mod test {
];
assert_eq!(v, generate().entries().collect_vec());
}
#[should_panic]
#[test]
fn out_of_bounds_panics() {
generate()[(-1, 3)];
}
#[test]
fn option_success() {
assert_eq!(Some(&'.'), generate().get((0, 0)));
}
#[test]
fn option_out_of_bounds() {
assert_eq!(None, generate().get((30, 0)));
}
}