Skip to content

Commit 52fdc0b

Browse files
committed
WIP: 9th day
1 parent b221b54 commit 52fdc0b

File tree

2 files changed

+142
-0
lines changed

2 files changed

+142
-0
lines changed

data/examples/09.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
2333133121414131402

src/bin/09.rs

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
advent_of_code::solution!(9);
2+
3+
#[derive(Debug, Copy, Clone)]
4+
enum Block {
5+
Free,
6+
File(usize),
7+
}
8+
9+
fn parse_data(input: &str) -> Vec<(usize, Block)> {
10+
input
11+
.bytes()
12+
.enumerate()
13+
.map(|(i, x)| {
14+
if i % 2 == 0 {
15+
((x - b'0') as usize, Block::File(i / 2))
16+
} else {
17+
((x - b'0') as usize, Block::Free)
18+
}
19+
})
20+
.collect()
21+
}
22+
23+
pub fn part_one(input: &str) -> Option<u64> {
24+
let data = parse_data(input);
25+
26+
let mut disk = vec![];
27+
let mut id = 0;
28+
for (i, x) in data.into_iter().enumerate() {
29+
if i % 2 == 0 {
30+
for _ in 0..x.0 {
31+
disk.push(Block::File(id));
32+
}
33+
id += 1;
34+
} else {
35+
for _ in 0..x.0 {
36+
disk.push(Block::Free);
37+
}
38+
}
39+
}
40+
41+
let mut i = 0;
42+
let mut j = disk.len() - 1;
43+
loop {
44+
while let Block::File(_) = disk[i] {
45+
i += 1;
46+
}
47+
48+
while let Block::Free = disk[j] {
49+
j -= 1;
50+
}
51+
52+
if i > j {
53+
break;
54+
}
55+
56+
disk.swap(i, j);
57+
}
58+
59+
let mut result = 0;
60+
for (i, block) in disk.iter().enumerate() {
61+
if let Block::File(id) = block {
62+
result += i as u64 * *id as u64;
63+
}
64+
}
65+
66+
Some(result)
67+
}
68+
69+
pub fn part_two(input: &str) -> Option<u64> {
70+
let data = parse_data(input);
71+
72+
let mut disk = data;
73+
disk.push((10, Block::Free));
74+
75+
for j in (0..10000).rev() {
76+
let file_index = disk.iter().position(|(_, block)| match block {
77+
Block::Free => false,
78+
Block::File(x) => *x == j,
79+
});
80+
81+
if file_index.is_none() {
82+
continue;
83+
}
84+
85+
let file_index = file_index.unwrap();
86+
87+
let file_block = disk[file_index].1;
88+
let file_size = disk[file_index].0;
89+
for i in 0..file_index {
90+
let free_block = disk[i].1;
91+
let free_size = disk[i].0;
92+
93+
if matches!(free_block, Block::Free) && free_size >= file_size {
94+
let left_free_space = disk[file_index - 1].0;
95+
let right_free_space = disk[file_index + 1].0;
96+
97+
disk[file_index - 1] =
98+
(left_free_space + file_size + right_free_space, Block::Free);
99+
disk.remove(file_index);
100+
disk.remove(file_index);
101+
102+
disk.insert(i, (file_size, file_block));
103+
disk.insert(i, (0, Block::Free));
104+
disk[i + 2] = (free_size - file_size, Block::Free);
105+
106+
break;
107+
}
108+
}
109+
}
110+
111+
let mut result = 0;
112+
let mut i = 0;
113+
for (size, block) in disk {
114+
if let Block::File(id) = block {
115+
for x in i..i + size {
116+
result += x * id;
117+
}
118+
}
119+
i += size;
120+
}
121+
122+
// 6239712239037 too low
123+
Some(result as u64)
124+
}
125+
126+
#[cfg(test)]
127+
mod tests {
128+
use super::*;
129+
130+
#[test]
131+
fn test_part_one() {
132+
let result = part_one(&advent_of_code::template::read_file("examples", DAY));
133+
assert_eq!(result, Some(1928));
134+
}
135+
136+
#[test]
137+
fn test_part_two() {
138+
let result = part_two(&advent_of_code::template::read_file("examples", DAY));
139+
assert_eq!(result, Some(2858));
140+
}
141+
}

0 commit comments

Comments
 (0)