Skip to content

Commit 95bc555

Browse files
committed
[2024] Day 9 initial solution
1 parent ce39351 commit 95bc555

File tree

4 files changed

+153
-1
lines changed

4 files changed

+153
-1
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Thank you to [Eric Wastl](http://was.tl) for running this incredible yearly even
1313
- [Day 06: Guard Gallivant](aoc_2024/src/day_06.rs)
1414
- [Day 07: Bridge Repair](aoc_2024/src/day_07.rs)
1515
- [Day 08: Resonant Collinearity](aoc_2024/src/day_08.rs)
16+
- [Day 09: Disk Fragmenter](aoc_2024/src/day_09.rs)
1617
<!-- MARKER -->
1718

1819
## [2023](https://adventofcode.com/2023) [![aoc_2023](https://github.com/connorslade/advent-of-code/actions/workflows/aoc_2023.yml/badge.svg)](https://github.com/connorslade/advent-of-code/actions/workflows/aoc_2023.yml)

aoc_2024/src/day_09.rs

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
use common::{solution, Answer};
2+
use itertools::Itertools;
3+
4+
solution!("Disk Fragmenter", 9);
5+
6+
fn part_a(input: &str) -> Answer {
7+
let mut problem = Problem::parse(input);
8+
problem.sort_blocks();
9+
problem.score_blocks().into()
10+
}
11+
12+
fn part_b(input: &str) -> Answer {
13+
let mut problem = Problem::parse(input);
14+
problem.sort_files();
15+
problem.score_files().into()
16+
}
17+
18+
#[derive(Debug)]
19+
struct Problem {
20+
blocks: Vec<Option<u32>>,
21+
files: Vec<File>,
22+
}
23+
24+
#[derive(Debug)]
25+
struct File {
26+
pos: u32,
27+
size: u8,
28+
id: u32,
29+
}
30+
31+
impl Problem {
32+
fn parse(input: &str) -> Self {
33+
let mut blocks = Vec::new();
34+
let mut files = Vec::new();
35+
36+
let mut id = 0;
37+
let mut pos = 0;
38+
39+
for (idx, chr) in input.trim().char_indices() {
40+
let num = chr.to_digit(10).unwrap() as u8;
41+
42+
if idx % 2 == 1 {
43+
for _ in 0..num {
44+
blocks.push(None);
45+
}
46+
} else {
47+
files.push(File { pos, size: num, id });
48+
for _ in 0..num {
49+
blocks.push(Some(id));
50+
}
51+
id += 1;
52+
}
53+
54+
pos += num as u32;
55+
}
56+
57+
Self { blocks, files }
58+
}
59+
60+
fn sort_blocks(&mut self) {
61+
loop {
62+
let empty = self.blocks.iter().position(|x| x.is_none()).unwrap();
63+
let last = self.blocks.iter().rposition(|x| x.is_some()).unwrap();
64+
65+
if last > empty {
66+
self.blocks.swap(empty, last);
67+
} else {
68+
break;
69+
}
70+
}
71+
}
72+
73+
fn sort_files(&mut self) {
74+
let max_id = self.files.last().unwrap().id;
75+
for id in (0..=max_id).rev() {
76+
let file_idx = self.files.iter().position(|x| x.id == id).unwrap();
77+
let file = &self.files[file_idx];
78+
79+
let mut new_pos = None;
80+
for (a, b) in self.files.iter().tuple_windows() {
81+
let free = (b.pos) - (a.pos + a.size as u32);
82+
let pos = a.pos + a.size as u32;
83+
84+
if pos > file.pos {
85+
break;
86+
}
87+
88+
if free >= file.size as u32 {
89+
new_pos = Some(pos);
90+
break;
91+
}
92+
}
93+
94+
if let Some(new_pos) = new_pos {
95+
self.files[file_idx].pos = new_pos;
96+
}
97+
98+
self.files.sort_by_key(|x| x.pos);
99+
}
100+
}
101+
102+
fn score_blocks(&self) -> u64 {
103+
let mut sum = 0;
104+
105+
for (idx, id) in self.blocks.iter().enumerate() {
106+
sum += idx as u64 * id.unwrap_or_default() as u64;
107+
}
108+
109+
sum
110+
}
111+
112+
fn score_files(&self) -> u64 {
113+
let mut sum = 0;
114+
let mut last = 0;
115+
let mut idx = 0;
116+
for x in &self.files {
117+
for _ in last..x.pos {
118+
idx += 1;
119+
}
120+
121+
for _ in 0..x.size {
122+
sum += idx * x.id as u64;
123+
idx += 1;
124+
}
125+
126+
last = x.pos + x.size as u32;
127+
}
128+
sum
129+
}
130+
}
131+
132+
#[cfg(test)]
133+
mod test {
134+
use indoc::indoc;
135+
136+
const CASE: &str = indoc! {"
137+
2333133121414131402
138+
"};
139+
140+
#[test]
141+
fn part_a() {
142+
assert_eq!(super::part_a(CASE), 1928.into());
143+
}
144+
145+
#[test]
146+
fn part_b() {
147+
assert_eq!(super::part_b(CASE), 2858.into());
148+
}
149+
}

aoc_2024/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ mod day_05;
88
mod day_06;
99
mod day_07;
1010
mod day_08;
11+
mod day_09;
1112
// [import_marker]
1213

1314
pub const SOLUTIONS: &[Solution] = &[
@@ -19,5 +20,6 @@ pub const SOLUTIONS: &[Solution] = &[
1920
day_06::SOLUTION,
2021
day_07::SOLUTION,
2122
day_08::SOLUTION,
23+
day_09::SOLUTION,
2224
// [list_marker]
2325
];

aoc_lib/src/matrix.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ impl<T> Matrix<T> {
4343
pos.x() < self.size.x() && pos.y() < self.size.y()
4444
}
4545

46-
pub fn iter(&self) -> impl Iterator<Item = (Vec2<usize>, &T)> + use<'_, T> {
46+
pub fn iter(&self) -> impl Iterator<Item = (Vec2<usize>, &T)> {
4747
(0..self.data.len()).map(|x| {
4848
let pos = vector!(x % self.size.x(), x / self.size.x());
4949
let data = self.get(pos).unwrap();

0 commit comments

Comments
 (0)