Skip to content

Commit

Permalink
Day 9: Disk Defragmenter
Browse files Browse the repository at this point in the history
  • Loading branch information
ephemient committed Dec 9, 2024
1 parent 9c1fa8e commit c7256f7
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 3 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ Development occurs in language-specific directories:
|[Day6.hs](hs/src/Day6.hs)|[Day6.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day6.kt)|[day6.py](py/aoc2024/day6.py)|[day6.rs](rs/src/day6.rs)|
|[Day7.hs](hs/src/Day7.hs)|[Day7.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day7.kt)|[day7.py](py/aoc2024/day7.py)|[day7.rs](rs/src/day7.rs)|
|[Day8.hs](hs/src/Day8.hs)|[Day8.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day8.kt)|[day8.py](py/aoc2024/day8.py)|[day8.rs](rs/src/day8.rs)|
|[Day9.hs](hs/src/Day9.hs)|[Day9.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day9.kt)|[day9.py](py/aoc2024/day9.py)||
|[Day9.hs](hs/src/Day9.hs)|[Day9.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day9.kt)|[day9.py](py/aoc2024/day9.py)|[day9.rs](rs/src/day9.rs)|
8 changes: 7 additions & 1 deletion rs/benches/criterion.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use aoc2024::{day1, day2, day3, day4, day5, day6, day7, day8};
use aoc2024::{day1, day2, day3, day4, day5, day6, day7, day8, day9};
use criterion::{black_box, Criterion};
use std::env;
use std::fs;
Expand Down Expand Up @@ -62,6 +62,12 @@ fn aoc2024_bench(c: &mut Criterion) -> io::Result<()> {
g.bench_function("part 2", |b| b.iter(|| day8::part2(black_box(&data))));
g.finish();

let data = get_day_input(9)?;
let mut g = c.benchmark_group("day 9");
g.bench_function("part 1", |b| b.iter(|| day9::part1(black_box(&data))));
g.bench_function("part 2", |b| b.iter(|| day9::part2(black_box(&data))));
g.finish();

Ok(())
}

Expand Down
83 changes: 83 additions & 0 deletions rs/src/day9.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
fn tri_range(offset: u64, size: u64) -> u64 {
(2 * offset + size - 1) * size / 2
}

pub fn part1(data: &str) -> u64 {
let mut sizes = data
.chars()
.filter_map(|c| c.to_digit(10))
.collect::<Vec<_>>();
let (mut total, mut offset) = (0, 0);
for i in 0..sizes.len() {
let size = sizes[i];
if i % 2 == 0 {
total += i as u64 / 2 * tri_range(offset, size.into());
offset += size as u64;
} else {
let mut free_size = size;
for (j, size) in sizes.iter_mut().enumerate().skip(i + 1).step_by(2).rev() {
if free_size == 0 {
break;
}
let used_size = free_size.min(*size);
total += j as u64 / 2 * tri_range(offset, used_size.into());
offset += used_size as u64;
free_size -= used_size;
*size -= used_size;
}
}
}
total
}

pub fn part2(data: &str) -> u64 {
let mut chunks = data
.chars()
.filter_map(|c| c.to_digit(10))
.scan(0, |acc, size| {
let offset = *acc;
*acc = offset + size;
Some((offset, size))
})
.collect::<Vec<_>>();
(0..chunks.len())
.step_by(2)
.rev()
.map(|i| {
let (mut offset, size) = chunks[i];
if let Some((free_offset, free_size)) = chunks
.iter_mut()
.take(i)
.skip(1)
.step_by(2)
.find(|(_, free_size)| size <= *free_size)
{
offset = *free_offset;
*free_offset += size;
*free_size -= size;
}
i as u64 / 2 * tri_range(offset.into(), size.into())
})
.sum()
}

#[cfg(test)]
mod tests {
use super::*;
use indoc::indoc;
use pretty_assertions::assert_eq;

static EXAMPLE: &str = indoc! {"
2333133121414131402
"};

#[test]
fn part1_examples() {
assert_eq!(1928, part1(EXAMPLE));
}

#[test]
fn part2_examples() {
assert_eq!(2858, part2(EXAMPLE));
}
}
1 change: 1 addition & 0 deletions rs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ pub mod day5;
pub mod day6;
pub mod day7;
pub mod day8;
pub mod day9;
10 changes: 9 additions & 1 deletion rs/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use anyhow::anyhow;
use aoc2024::{day1, day2, day3, day4, day5, day6, day7, day8};
use aoc2024::{day1, day2, day3, day4, day5, day6, day7, day8, day9};
use std::collections::HashSet;
use std::env;
use std::fs;
Expand Down Expand Up @@ -81,5 +81,13 @@ fn main() -> anyhow::Result<()> {
println!();
}

if args.is_empty() || args.contains("9") {
println!("Day 9");
let data = get_day_input(9)?;
println!("{:?}", day9::part1(&data));
println!("{:?}", day9::part2(&data));
println!();
}

Ok(())
}

0 comments on commit c7256f7

Please sign in to comment.