This commit is contained in:
nora 2024-12-09 19:21:33 +01:00
parent 1199519970
commit b0c80722a9
8 changed files with 141 additions and 10 deletions

9
2024/Cargo.lock generated
View file

@ -189,6 +189,15 @@ dependencies = [
"smallvec",
]
[[package]]
name = "day09"
version = "0.1.0"
dependencies = [
"divan",
"helper",
"nom",
]
[[package]]
name = "divan"
version = "0.1.16"

15
2024/day09/Cargo.toml Normal file
View file

@ -0,0 +1,15 @@
[package]
name = "day09"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
nom.workspace = true
helper.workspace = true
divan.workspace = true
[[bench]]
name = "benches"
harness = false

View file

@ -0,0 +1,3 @@
fn main() {
day09::bench();
}

1
2024/day09/input.txt Normal file

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
2333133121414131402

91
2024/day09/src/lib.rs Normal file
View file

@ -0,0 +1,91 @@
use std::iter;
use helper::{Day, Variants};
pub fn main() {
helper::main::<Day09>(include_str!("../input.txt"));
}
struct Day09;
helper::define_variants! {
day => crate::Day09;
part1 {
basic => crate::part1;
}
part2 {
basic => crate::part2;
}
}
impl Day for Day09 {
fn part1() -> Variants {
part1_variants!(construct_variants)
}
fn part2() -> Variants {
part2_variants!(construct_variants)
}
}
fn part1(input: &str) -> u64 {
let input = &input[0..input.len() - 1];
let mut blocks = Vec::new();
let mut is_file = true;
let mut id = 0;
for b in input.bytes() {
debug_assert!(b.is_ascii_digit());
let len = (b - b'0') as usize;
if is_file {
blocks.extend(iter::repeat_n(Some(id), len));
id += 1;
} else {
blocks.extend(iter::repeat_n(None, len));
}
is_file = !is_file;
}
let mut next_insert_idx = blocks.iter().position(|b| b.is_none()).unwrap();
for i in (0..blocks.len()).rev() {
if next_insert_idx >= i {
break;
}
match blocks[i] {
Some(block) => {
blocks[next_insert_idx] = Some(block);
blocks[i] = None;
next_insert_idx = next_insert_idx
+ blocks[next_insert_idx..]
.iter()
.position(|b| b.is_none())
.unwrap();
}
None => {}
}
}
blocks
.iter()
.enumerate()
.filter_map(|(i, b)| b.map(|b| b as u64 * i as u64))
.sum()
}
fn part2(_input: &str) -> u64 {
0
}
helper::tests! {
day09 Day09;
part1 {
small => 1928;
default => 6432869891895;
}
part2 {
small => 0;
default => 0;
}
}
helper::benchmarks! {}

3
2024/day09/src/main.rs Normal file
View file

@ -0,0 +1,3 @@
fn main() {
day09::main();
}

View file

@ -46,23 +46,31 @@ impl Variant {
}
}
pub fn test_part1<D: Day>(inputs: &[(&str, u64)]) {
pub fn test_part1<D: Day>(inputs: &[(&str, &str, u64)]) {
for variant in D::part1().variants {
for input in inputs {
let actual = (variant.f)(input.0);
if actual != input.1 {
panic!("failed: {}: {actual} != {}", variant.name, input.1);
let (path, input, expected) = *input;
let actual = (variant.f)(input);
if actual != expected {
panic!(
"failed: {}: {}: {} != {}",
path, variant.name, actual, expected
);
}
}
}
}
pub fn test_part2<D: Day>(inputs: &[(&str, u64)]) {
pub fn test_part2<D: Day>(inputs: &[(&str, &str, u64)]) {
for variant in D::part2().variants {
for input in inputs {
let actual = (variant.f)(input.0);
if actual != input.1 {
panic!("failed: {}: {actual} != {}", variant.name, input.1);
let (path, input, expected) = *input;
let actual = (variant.f)(input);
if actual != expected {
panic!(
"failed: {}: {}: {} != {}",
path, variant.name, actual, expected
);
}
}
}
@ -209,7 +217,7 @@ macro_rules! tests {
fn part1() {
helper::test_part1::<super::$day>(&[
$(
(include_str!($file1), $p1),
($file1, include_str!($file1), $p1),
)*
]);
}
@ -218,7 +226,7 @@ macro_rules! tests {
fn part2() {
helper::test_part2::<super::$day>(&[
$(
(include_str!($file2), $p2),
($file2, include_str!($file2), $p2),
)*
]);
}