Skip to content

Commit a96e8a0

Browse files
committed
[2024] Slight day 9 cleanup
1 parent 95bc555 commit a96e8a0

File tree

1 file changed

+57
-51
lines changed

1 file changed

+57
-51
lines changed

aoc_2024/src/day_09.rs

Lines changed: 57 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,94 @@
11
use common::{solution, Answer};
2-
use itertools::Itertools;
2+
use itertools::{repeat_n, Itertools};
33

44
solution!("Disk Fragmenter", 9);
55

66
fn part_a(input: &str) -> Answer {
7-
let mut problem = Problem::parse(input);
8-
problem.sort_blocks();
9-
problem.score_blocks().into()
7+
let mut problem = Blocks::parse(input);
8+
problem.sort();
9+
problem.score().into()
1010
}
1111

1212
fn part_b(input: &str) -> Answer {
13-
let mut problem = Problem::parse(input);
14-
problem.sort_files();
15-
problem.score_files().into()
13+
let mut problem = Files::parse(input);
14+
problem.sort();
15+
problem.score().into()
1616
}
1717

18-
#[derive(Debug)]
19-
struct Problem {
18+
struct Blocks {
2019
blocks: Vec<Option<u32>>,
20+
}
21+
22+
struct Files {
2123
files: Vec<File>,
2224
}
2325

24-
#[derive(Debug)]
2526
struct File {
2627
pos: u32,
2728
size: u8,
2829
id: u32,
2930
}
3031

31-
impl Problem {
32+
impl Blocks {
3233
fn parse(input: &str) -> Self {
3334
let mut blocks = Vec::new();
34-
let mut files = Vec::new();
3535

3636
let mut id = 0;
37-
let mut pos = 0;
38-
3937
for (idx, chr) in input.trim().char_indices() {
40-
let num = chr.to_digit(10).unwrap() as u8;
38+
let count = chr.to_digit(10).unwrap() as u8;
4139

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-
}
40+
let is_block = idx % 2 == 0;
41+
let item = is_block.then_some(id);
5342

54-
pos += num as u32;
43+
blocks.extend(repeat_n(item, count as usize));
44+
id += is_block as u32;
5545
}
5646

57-
Self { blocks, files }
47+
Self { blocks }
5848
}
5949

60-
fn sort_blocks(&mut self) {
50+
fn sort(&mut self) {
6151
loop {
6252
let empty = self.blocks.iter().position(|x| x.is_none()).unwrap();
6353
let last = self.blocks.iter().rposition(|x| x.is_some()).unwrap();
6454

65-
if last > empty {
66-
self.blocks.swap(empty, last);
67-
} else {
55+
if last <= empty {
6856
break;
6957
}
58+
59+
self.blocks.swap(empty, last);
7060
}
7161
}
7262

73-
fn sort_files(&mut self) {
63+
fn score(&self) -> u64 {
64+
self.blocks
65+
.iter()
66+
.enumerate()
67+
.map(|(idx, id)| idx as u64 * id.unwrap_or_default() as u64)
68+
.sum()
69+
}
70+
}
71+
72+
impl Files {
73+
fn parse(input: &str) -> Self {
74+
let mut files = Vec::new();
75+
let (mut id, mut pos) = (0, 0);
76+
77+
for (idx, chr) in input.trim().char_indices() {
78+
let size = chr.to_digit(10).unwrap() as u8;
79+
80+
if idx % 2 == 0 {
81+
files.push(File { pos, size, id });
82+
id += 1;
83+
}
84+
85+
pos += size as u32;
86+
}
87+
88+
Self { files }
89+
}
90+
91+
fn sort(&mut self) {
7492
let max_id = self.files.last().unwrap().id;
7593
for id in (0..=max_id).rev() {
7694
let file_idx = self.files.iter().position(|x| x.id == id).unwrap();
@@ -99,32 +117,20 @@ impl Problem {
99117
}
100118
}
101119

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 {
120+
fn score(&self) -> u64 {
113121
let mut sum = 0;
114122
let mut last = 0;
115123
let mut idx = 0;
124+
116125
for x in &self.files {
117-
for _ in last..x.pos {
118-
idx += 1;
119-
}
126+
idx += x.pos - last;
120127

121-
for _ in 0..x.size {
122-
sum += idx * x.id as u64;
123-
idx += 1;
124-
}
128+
sum += (x.id as u64 * x.size as u64 * (x.size as u64 + 2 * idx as u64 - 1)) / 2;
129+
idx += x.size as u32;
125130

126131
last = x.pos + x.size as u32;
127132
}
133+
128134
sum
129135
}
130136
}

0 commit comments

Comments
 (0)