Skip to content

Commit 0e4e731

Browse files
committed
chore: y2024::day_09
1 parent 2f62a51 commit 0e4e731

File tree

4 files changed

+135
-1
lines changed

4 files changed

+135
-1
lines changed

.run/run_aoc.run.xml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<component name="ProjectRunConfigurationManager">
2+
<configuration default="false" name="run_aoc" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
3+
<option name="buildProfileId" value="dev" />
4+
<option name="command" value="run --package aoclp_solutions --bin aoclp_solutions -- --year 2024 --day 9" />
5+
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
6+
<envs />
7+
<option name="emulateTerminal" value="true" />
8+
<option name="channel" value="DEFAULT" />
9+
<option name="requiredFeatures" value="true" />
10+
<option name="allFeatures" value="true" />
11+
<option name="withSudo" value="false" />
12+
<option name="buildTarget" value="REMOTE" />
13+
<option name="backtrace" value="SHORT" />
14+
<option name="isRedirectInput" value="false" />
15+
<option name="redirectInputPath" value="" />
16+
<method v="2">
17+
<option name="CARGO.BUILD_TASK_PROVIDER" enabled="true" />
18+
</method>
19+
</configuration>
20+
</component>

aoclp_solutions/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ pub mod y2025;
1010

1111
build_solvers! {
1212
{ 2017, [01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25] },
13-
{ 2024, [01, 02, 03, 04, 05, 06, 07, 08] },
13+
{ 2024, [01, 02, 03, 04, 05, 06, 07, 08, 09] },
1414
{ 2025, [01, 02, 03, 04, 05, 06] }
1515
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
use aoclp::solvers_impl::input::safe_get_input;
2+
use itertools::repeat_n;
3+
use strum::{EnumCount, EnumIs, FromRepr};
4+
5+
pub fn part_1() -> usize {
6+
let mut blocks = blocks();
7+
defrag_blocks(&mut blocks);
8+
checksum(blocks)
9+
}
10+
11+
pub fn part_2() -> usize {
12+
let mut blocks = blocks();
13+
defrag_files(&mut blocks);
14+
checksum(blocks)
15+
}
16+
17+
type Block = Option<usize>;
18+
19+
#[repr(usize)]
20+
#[derive(Debug, Copy, Clone, PartialEq, Eq, EnumIs, EnumCount, FromRepr)]
21+
enum BlockType {
22+
EmptySpace,
23+
File,
24+
}
25+
26+
impl BlockType {
27+
fn block(self, id: usize) -> Block {
28+
self.is_file().then_some(id)
29+
}
30+
31+
fn next_id(self, id: usize) -> usize {
32+
id + self as usize
33+
}
34+
35+
fn next_type(self) -> Self {
36+
Self::from_repr((self as usize + 1) % Self::COUNT).unwrap()
37+
}
38+
}
39+
40+
fn blocks() -> Vec<Block> {
41+
input()
42+
.chars()
43+
.fold((Vec::new(), 0, BlockType::File), |(mut acc, id, block_type), c| {
44+
let len = c.to_digit(10).unwrap() as usize;
45+
acc.extend(repeat_n(block_type.block(id), len));
46+
(acc, block_type.next_id(id), block_type.next_type())
47+
})
48+
.0
49+
}
50+
51+
fn defrag_blocks(blocks: &mut [Block]) {
52+
let mut i = 0;
53+
let mut last = blocks.len() - 1;
54+
while i <= last {
55+
if blocks[i].is_none() {
56+
while blocks[last].is_none() {
57+
last -= 1;
58+
}
59+
blocks[i] = blocks[last].take();
60+
last -= 1;
61+
}
62+
i += 1;
63+
}
64+
}
65+
66+
fn defrag_files(blocks: &mut Vec<Block>) {
67+
let mut i = blocks.len() - 1;
68+
while i > 0 {
69+
if let Some(id) = blocks[i] {
70+
let mut start = i;
71+
while start > 0 && blocks[start - 1].is_some_and(|block| block == id) {
72+
start -= 1;
73+
}
74+
if start == 0 {
75+
break;
76+
}
77+
let block_len = i - start + 1;
78+
79+
let mut target = 0;
80+
while target < start
81+
&& blocks[target..target + block_len]
82+
.iter()
83+
.any(Option::is_some)
84+
{
85+
target += 1;
86+
}
87+
if target < start {
88+
blocks.splice(start..=i, repeat_n(None, block_len));
89+
blocks.splice(target..target + block_len, repeat_n(Some(id), block_len));
90+
}
91+
92+
i = start - 1;
93+
} else {
94+
i -= 1;
95+
}
96+
}
97+
}
98+
99+
fn checksum<B>(blocks: B) -> usize
100+
where
101+
B: IntoIterator<Item = Block>,
102+
{
103+
blocks
104+
.into_iter()
105+
.enumerate()
106+
.fold(0, |acc, (i, block)| acc + block.map_or(0, |id| id * i))
107+
}
108+
109+
const EXAMPLE: &str = "2333133121414131402";
110+
111+
fn input() -> String {
112+
safe_get_input(2024, 9)
113+
}

aoclp_solutions/src/y2024/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ pub mod day_05;
66
pub mod day_06;
77
pub mod day_07;
88
pub mod day_08;
9+
pub mod day_09;

0 commit comments

Comments
 (0)