Skip to content

Commit f2450bb

Browse files
committed
add day9
1 parent ba5e9e7 commit f2450bb

File tree

3 files changed

+129
-0
lines changed

3 files changed

+129
-0
lines changed

2024/day9/.gitignore

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
input.txt
2+
flamegraph.svg
3+
perf.data*
4+
### Rust
5+
# Generated by Cargo
6+
# will have compiled files and executables
7+
debug/
8+
target/
9+
10+
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
11+
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
12+
Cargo.lock
13+
14+
# These are backup files generated by rustfmt
15+
**/*.rs.bk
16+
17+
# MSVC Windows builds of rustc generate these, which store debugging information
18+
*.pdb
19+

2024/day9/Cargo.toml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[package]
2+
name = "day9"
3+
authors = ["mirsella <[email protected]>"]
4+
version = "0.1.0"
5+
edition = "2021"
6+
7+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8+
9+
[dependencies]
10+
regex = { workspace = true }
11+
itertools = { workspace = true }
12+
pathfinding = { workspace = true }
13+
rayon = { workspace = true }
14+
indexmap = { workspace = true }

2024/day9/src/main.rs

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
fn part1(input: &str) -> usize {
2+
let mut disk = input
3+
.chars()
4+
.fold((Vec::new(), true, 0), |(mut acc, is_file, mut id), char| {
5+
let n = char.to_digit(10).unwrap();
6+
if is_file {
7+
(0..n).for_each(|_| acc.push(Some(id)));
8+
} else {
9+
(0..n).for_each(|_| acc.push(None));
10+
id += 1;
11+
}
12+
(acc, !is_file, id)
13+
})
14+
.0;
15+
let mut count = 0;
16+
for i in 0..disk.len() {
17+
if disk[i].is_none() {
18+
if let Some(last_rev) = disk.iter().skip(i).rev().position(|&c| c.is_some()) {
19+
let last = disk.len() - last_rev - 1;
20+
disk[i] = disk[last];
21+
disk[last] = None;
22+
}
23+
}
24+
if let Some(id) = disk[i] {
25+
count += id * i;
26+
}
27+
}
28+
count
29+
}
30+
fn part2(input: &str) -> usize {
31+
let mut disk = input
32+
.chars()
33+
.fold((Vec::new(), true, 0), |(mut acc, is_file, mut id), char| {
34+
let n = char.to_digit(10).unwrap();
35+
if is_file {
36+
(0..n).for_each(|_| acc.push(Some(id)));
37+
} else {
38+
(0..n).for_each(|_| acc.push(None));
39+
id += 1;
40+
}
41+
(acc, !is_file, id)
42+
})
43+
.0;
44+
let mut i = disk.len() - 1;
45+
loop {
46+
let mut file_size = 0;
47+
if let Some(id) = disk[i] {
48+
while i - file_size > 0 && disk[i - file_size].is_some_and(|c| c == id) {
49+
file_size += 1;
50+
}
51+
}
52+
if file_size > 0 {
53+
for j in 0..i {
54+
let mut empty_size = 0;
55+
while j + empty_size < i && disk[j + empty_size].is_none() {
56+
empty_size += 1;
57+
}
58+
if empty_size >= file_size {
59+
(0..file_size).for_each(|k| {
60+
disk[j + k] = disk[i - k];
61+
disk[i - k] = None;
62+
});
63+
}
64+
}
65+
i -= file_size;
66+
} else if i > 1 {
67+
i -= 1;
68+
} else {
69+
break;
70+
}
71+
}
72+
disk.iter().enumerate().fold(0, |mut acc, (i, c)| {
73+
if let Some(id) = c {
74+
acc += id * i;
75+
}
76+
acc
77+
})
78+
}
79+
fn main() {
80+
let input = include_str!("../input.txt");
81+
println!("Part 1: {}", part1(input));
82+
println!("Part 2: {}", part2(input));
83+
}
84+
85+
#[cfg(test)]
86+
mod tests {
87+
const INPUT: &str = "2333133121414131402";
88+
#[test]
89+
fn part1() {
90+
assert_eq!(super::part1(INPUT), 1928);
91+
}
92+
#[test]
93+
fn part2() {
94+
assert_eq!(super::part2(INPUT), 2858);
95+
}
96+
}

0 commit comments

Comments
 (0)