1
0
Fork 0

Compare commits

..

2 commits

Author SHA1 Message Date
9abfac63da
Replace assert_example!
It does not provide much value and cannot be used in some cases.
2025-12-12 07:40:25 +01:00
69ea94bec0
Solve 12 2025-12-12 07:13:50 +01:00
12 changed files with 144 additions and 90 deletions

View file

@ -1,18 +1,16 @@
use aoc::*;
const INPUT: &str = include_str!("../../input/01");
fn main() { fn main() {
println!("Part 1: {}", part1(INPUT)); let input = include_str!("../../input/01");
println!("Part 2: {}", part2(INPUT)); println!("Part 1: {}", part1(input));
println!("Part 2: {}", part2(input));
} }
#[test] #[test]
fn example() { fn example() {
assert_example!(part1, "01-test", 3); let input = include_str!("../../input/01-test");
assert_eq!(part1(input), 3);
assert_eq!(part2("R1000"), 10); assert_eq!(part2("R1000"), 10);
assert_eq!(part2("R950"), 10); assert_eq!(part2("R950"), 10);
assert_example!(part2, "01-test", 6); assert_eq!(part2(input), 6);
} }
fn part1(input: &str) -> usize { fn part1(input: &str) -> usize {

View file

@ -1,16 +1,14 @@
use aoc::*;
const INPUT: &str = include_str!("../../input/02");
fn main() { fn main() {
println!("Part 1: {}", part1(INPUT)); let input = include_str!("../../input/02");
println!("Part 2: {}", part2(INPUT)); println!("Part 1: {}", part1(input));
println!("Part 2: {}", part2(input));
} }
#[test] #[test]
fn example() { fn example() {
assert_example!(part1, "02-test", 1227775554); let input = include_str!("../../input/02-test");
assert_example!(part2, "02-test", 4174379265); assert_eq!(part1(input), 1227775554);
assert_eq!(part2(input), 4174379265);
} }
fn part1(input: &str) -> usize { fn part1(input: &str) -> usize {

View file

@ -1,16 +1,14 @@
use aoc::*;
const INPUT: &str = include_str!("../../input/03");
fn main() { fn main() {
println!("Part 1: {}", part1(INPUT)); let input = include_str!("../../input/03");
println!("Part 2: {}", part2(INPUT)); println!("Part 1: {}", part1(input));
println!("Part 2: {}", part2(input));
} }
#[test] #[test]
fn example() { fn example() {
assert_example!(part1, "03-test", 357); let input = include_str!("../../input/03-test");
assert_example!(part2, "03-test", 3121910778619); assert_eq!(part1(input), 357);
assert_eq!(part2(input), 3121910778619);
} }
fn part1(input: &str) -> i64 { fn part1(input: &str) -> i64 {

View file

@ -2,17 +2,17 @@ use aoc::*;
use glam::IVec2; use glam::IVec2;
use std::collections::HashSet; use std::collections::HashSet;
const INPUT: &str = include_str!("../../input/04");
fn main() { fn main() {
println!("Part 1: {}", part1(INPUT)); let input = include_str!("../../input/04");
println!("Part 2: {}", part2(INPUT)); println!("Part 1: {}", part1(input));
println!("Part 2: {}", part2(input));
} }
#[test] #[test]
fn example() { fn example() {
assert_example!(part1, "04-test", 13); let input = include_str!("../../input/04-test");
assert_example!(part2, "04-test", 43); assert_eq!(part1(input), 13);
assert_eq!(part2(input), 43);
} }
fn part1(input: &str) -> usize { fn part1(input: &str) -> usize {

View file

@ -1,17 +1,16 @@
use aoc::*;
use itertools::Itertools; use itertools::Itertools;
const INPUT: &str = include_str!("../../input/05");
fn main() { fn main() {
println!("Part 1: {}", part1(INPUT)); let input = include_str!("../../input/05");
println!("Part 2: {}", part2(INPUT)); println!("Part 1: {}", part1(input));
println!("Part 2: {}", part2(input));
} }
#[test] #[test]
fn example() { fn example() {
assert_example!(part1, "05-test", 3); let input = include_str!("../../input/05-test");
assert_example!(part2, "05-test", 14); assert_eq!(part1(input), 3);
assert_eq!(part2(input), 14);
assert_eq!(part2("1-10\n5-6\n\n"), 10); assert_eq!(part2("1-10\n5-6\n\n"), 10);
assert_eq!(part2("1-10\n8-20\n\n"), 20); assert_eq!(part2("1-10\n8-20\n\n"), 20);
assert_eq!(part2("1-1\n2-2\n3-3\n\n"), 3); assert_eq!(part2("1-1\n2-2\n3-3\n\n"), 3);

View file

@ -3,17 +3,17 @@ use aoc::*;
use itertools::Itertools; use itertools::Itertools;
use std::str::FromStr; use std::str::FromStr;
const INPUT: &str = include_str!("../../input/06");
fn main() { fn main() {
println!("Part 1: {}", part1(INPUT)); let input = include_str!("../../input/06");
println!("Part 2: {}", part2(INPUT)); println!("Part 1: {}", part1(input));
println!("Part 2: {}", part2(input));
} }
#[test] #[test]
fn example() { fn example() {
assert_example!(part1, "06-test", 4277556); let input = include_str!("../../input/06-test");
assert_example!(part2, "06-test", 3263827); assert_eq!(part1(input), 4277556);
assert_eq!(part2(input), 3263827);
} }
fn part1(input: &str) -> usize { fn part1(input: &str) -> usize {

View file

@ -1,18 +1,17 @@
use aoc::*;
use cached::proc_macro::cached; use cached::proc_macro::cached;
use std::collections::HashSet; use std::collections::HashSet;
const INPUT: &str = include_str!("../../input/07");
fn main() { fn main() {
println!("Part 1: {}", part1(INPUT)); let input = include_str!("../../input/07");
println!("Part 2: {}", part2(INPUT)); println!("Part 1: {}", part1(input));
println!("Part 2: {}", part2(input));
} }
#[test] #[test]
fn example() { fn example() {
assert_example!(part1, "07-test", 21); let input = include_str!("../../input/07-test");
assert_example!(part2, "07-test", 40); assert_eq!(part1(input), 21);
assert_eq!(part2(input), 40);
} }
fn part1(input: &str) -> usize { fn part1(input: &str) -> usize {
@ -52,10 +51,7 @@ fn split_count(splitters: &HashSet<i32>, beams: HashSet<i32>) -> (usize, HashSet
(count, result) (count, result)
} }
#[cached( #[cached(key = "(i32, usize)", convert = r#"{ (beam, depth) }"#)]
key = "(i32, usize)",
convert = r#"{ (beam, depth) }"#
)]
fn timelines(beam: i32, depth: usize, splitters: &[HashSet<i32>]) -> usize { fn timelines(beam: i32, depth: usize, splitters: &[HashSet<i32>]) -> usize {
if depth >= splitters.len() { if depth >= splitters.len() {
return 1; return 1;

View file

@ -1,19 +1,18 @@
use aoc::*;
use itertools::Itertools; use itertools::Itertools;
use std::cmp::Reverse; use std::cmp::Reverse;
use std::collections::HashSet; use std::collections::HashSet;
const INPUT: &str = include_str!("../../input/08");
fn main() { fn main() {
println!("Part 1: {}", part1(INPUT, 1000)); let input = include_str!("../../input/08");
println!("Part 2: {}", part2(INPUT)); println!("Part 1: {}", part1(input, 1000));
println!("Part 2: {}", part2(input));
} }
#[test] #[test]
fn example() { fn example() {
assert_eq!(part1(include_str!("../../input/08-test"), 10), 40); let input = include_str!("../../input/08-test");
assert_example!(part2, "08-test", 25272); assert_eq!(part1(input, 10), 40);
assert_eq!(part2(input), 25272);
} }
fn part1(input: &str, n: usize) -> usize { fn part1(input: &str, n: usize) -> usize {

View file

@ -1,19 +1,16 @@
use aoc::*;
use glam::I64Vec2; use glam::I64Vec2;
use itertools::Itertools; use itertools::Itertools;
use rayon::prelude::*; use rayon::prelude::*;
use std::collections::HashMap; use std::collections::HashMap;
const INPUT: &str = include_str!("../../input/09");
fn main() { fn main() {
println!("Part 1: {}", part1(INPUT)); let input = include_str!("../../input/09");
println!("Part 2: {}", part2(INPUT)); println!("Part 1: {}", part1(input));
println!("Part 2: {}", part2(input));
} }
#[test] #[test]
fn example() { fn example() {
assert_example!(part1, "09-test", 50);
assert!(Line(I64Vec2::new(0, 10), I64Vec2::ZERO).contains(I64Vec2::new(0, 0))); assert!(Line(I64Vec2::new(0, 10), I64Vec2::ZERO).contains(I64Vec2::new(0, 0)));
assert!(Line(I64Vec2::new(0, 10), I64Vec2::ZERO).contains(I64Vec2::new(0, 10))); assert!(Line(I64Vec2::new(0, 10), I64Vec2::ZERO).contains(I64Vec2::new(0, 10)));
assert!(Line(I64Vec2::new(0, 10), I64Vec2::ZERO).contains(I64Vec2::new(0, 5))); assert!(Line(I64Vec2::new(0, 10), I64Vec2::ZERO).contains(I64Vec2::new(0, 5)));
@ -22,7 +19,10 @@ fn example() {
assert!(!Line(I64Vec2::ONE, I64Vec2::ONE).contains(I64Vec2::new(1, 10))); assert!(!Line(I64Vec2::ONE, I64Vec2::ONE).contains(I64Vec2::new(1, 10)));
assert!(Line(I64Vec2::ONE, I64Vec2::ONE).contains(I64Vec2::new(1, 1))); assert!(Line(I64Vec2::ONE, I64Vec2::ONE).contains(I64Vec2::new(1, 1)));
assert!(!Line(I64Vec2::ONE, I64Vec2::ONE).contains(I64Vec2::ZERO)); assert!(!Line(I64Vec2::ONE, I64Vec2::ONE).contains(I64Vec2::ZERO));
assert_example!(part2, "09-test", 24);
let input = include_str!("../../input/09-test");
assert_eq!(part1(input), 50);
assert_eq!(part2(input), 24);
} }
fn part1(input: &str) -> u64 { fn part1(input: &str) -> u64 {

View file

@ -1,18 +1,17 @@
use aoc::*;
use microlp::{ComparisonOp, OptimizationDirection, Problem}; use microlp::{ComparisonOp, OptimizationDirection, Problem};
use std::collections::VecDeque; use std::collections::VecDeque;
const INPUT: &str = include_str!("../../input/10");
fn main() { fn main() {
println!("Part 1: {}", part1(INPUT)); let input = include_str!("../../input/10");
println!("Part 2: {}", part2(INPUT)); println!("Part 1: {}", part1(input));
println!("Part 2: {}", part2(input));
} }
#[test] #[test]
fn example() { fn example() {
assert_example!(part1, "10-test", 7); let input = include_str!("../../input/10-test");
assert_example!(part2, "10-test", 33); assert_eq!(part1(input), 7);
assert_eq!(part2(input), 33);
} }
fn part1(input: &str) -> usize { fn part1(input: &str) -> usize {

82
src/bin/12.rs Normal file
View file

@ -0,0 +1,82 @@
use aoc::*;
use glam::USizeVec2;
use itertools::Itertools;
fn main() {
let input = include_str!("../../input/12");
println!("Part 1: {}", part1(input));
}
fn part1(input: &str) -> usize {
let (presents, regions) = parse_input(input);
regions.into_iter().filter(|r| r.fits(&presents)).count()
}
fn parse_input(input: &str) -> (Vec<Present>, Vec<Region>) {
let chunks = input.split("\n\n").collect_vec();
let (presents, regions) = chunks.split_at(chunks.len() - 1);
let presents = presents.iter().map(|p| Present::parse(p)).collect();
let regions = regions
.iter()
.flat_map(|chunk| chunk.lines())
.map(Region::parse)
.collect();
(presents, regions)
}
#[derive(Copy, Clone)]
struct Present {
area: usize,
}
impl Present {
fn parse(input: &str) -> Self {
let area = input
.lines()
.skip(1)
.flat_map(|line| line.chars())
.filter(|&c| c == '#')
.count();
Self { area }
}
}
struct Region {
size: USizeVec2,
presents: Vec<usize>,
}
impl Region {
fn fits(&self, presents: &[Present]) -> bool {
let total_present_area: usize = self
.pick_presents(presents)
.into_iter()
.map(|(n, present)| n * present.area)
.sum();
total_present_area <= self.area()
}
fn pick_presents(&self, presents: &[Present]) -> Vec<(usize, Present)> {
self.presents
.iter()
.copied()
.enumerate()
.map(|(i, n)| (n, presents[i]))
.collect()
}
fn area(&self) -> usize {
self.size.x * self.size.y
}
fn parse(line: &str) -> Self {
let (size, presents) = line.split_once(": ").unwrap();
let (x, y) = size.split_once('x').unwrap();
let size = USizeVec2::new(x.parse().unwrap(), y.parse().unwrap());
let presents = parse_ws_separated(presents).collect();
Self { size, presents }
}
}

View file

@ -93,21 +93,6 @@ where
a / gcd * b a / gcd * b
} }
/// Given a function and a name of a file in the `input` directory,
/// assert that the function applied to the contents of the file returns the expected result.
#[macro_export]
macro_rules! assert_example {
($solve:ident, $file:expr, $expected:expr) => {
assert_eq!(
$solve(include_str!(concat!("../../input/", $file))),
$expected,
"{}, {}",
stringify!($solve),
$file,
)
};
}
/// 4 directions. Start pointing right and go CCW. /// 4 directions. Start pointing right and go CCW.
pub const DIRECTIONS4: [IVec2; 4] = [ pub const DIRECTIONS4: [IVec2; 4] = [
IVec2::new(1, 0), IVec2::new(1, 0),