feat: day 9

This commit is contained in:
Lucy 2024-12-11 15:59:52 +01:00
parent 1e9030960d
commit a7bc0e746a
5 changed files with 162 additions and 2 deletions

View file

@ -4,7 +4,7 @@ version = "0.1.0"
edition = "2021" edition = "2021"
[features] [features]
full = ["day1", "day2", "day3", "day4", "day5", "day6", "day7", "day8"] full = ["day1", "day2", "day3", "day4", "day5", "day6", "day7", "day8", "day9"]
default = ["full"] default = ["full"]
day1 = [] day1 = []
day2 = [] day2 = []
@ -14,6 +14,7 @@ day5 = []
day6 = [] day6 = []
day7 = [] day7 = []
day8 = [] day8 = []
day9 = []
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

1
inputs/day09/example.txt Normal file
View file

@ -0,0 +1 @@
2333133121414131402

View file

@ -79,7 +79,7 @@ pub fn pt1(input: &str) -> usize {
debug!("new Map: \n{new_map}"); debug!("new Map: \n{new_map}");
antinode_positions.len() antinode_positions.len()
} }
// 225 is too high
pub fn pt2(input: &str) -> usize { pub fn pt2(input: &str) -> usize {
let char_positions = input let char_positions = input
.lines() .lines()

154
src/day09.rs Normal file
View file

@ -0,0 +1,154 @@
use std::collections::HashSet;
use tracing::debug;
pub fn pt1(input: &str) -> usize {
let mut disk_layout = input
.chars()
.map(|c| c.to_digit(10).unwrap())
.enumerate()
.flat_map(|(i, c)| {
(0..c)
.map(|_| if i % 2 == 0 { Some(i / 2) } else { None })
.collect::<Vec<_>>()
})
.collect::<Vec<_>>();
let mut min_pos = usize::MAX;
let dl = disk_layout.clone();
debug!(
"disk layout: {}",
disk_layout
.iter()
.map(|v| match v {
Some(v) => v.to_string(),
None => ".".to_string(),
})
.collect::<String>()
);
for (pos, segment) in disk_layout.iter_mut().enumerate() {
if segment.is_none() && pos < min_pos {
let next_candidate = dl
.iter()
.enumerate()
.rev()
.find(|(i, v)| v.is_some() && *i < min_pos);
match next_candidate {
Some((i, a)) => {
segment.replace(a.unwrap());
min_pos = i;
}
None => break,
};
}
}
debug!(
"disk layout: {}",
disk_layout
.iter()
.enumerate()
.filter(|(i, _v)| *i < min_pos)
.map(|(_i, v)| match v {
Some(v) => v.to_string(),
None => ".".to_string(),
})
.collect::<String>()
);
disk_layout
.into_iter()
.enumerate()
.filter(|(i, v)| v.is_some() && *i < min_pos)
.map(|(i, v)| v.unwrap() * i)
.sum()
}
#[derive(Clone)]
pub(crate) enum Segment {
Empty(usize),
File(usize, usize),
}
pub fn pt2(input: &str) -> usize {
let mut final_disk: Vec<usize> = Vec::new();
let disk_layout = input
.chars()
.map(|c| c.to_digit(10).unwrap())
.enumerate()
.map(|(i, c)| {
if i % 2 == 0 {
Segment::File(c as usize, i / 2)
} else {
Segment::Empty(c as usize)
}
})
.collect::<Vec<_>>();
let mut moved_segments = HashSet::new();
for (outer_pos, segment) in disk_layout.iter().enumerate() {
let mut s = segment.clone();
if moved_segments.contains(&outer_pos) {
s = match s {
Segment::File(v, _i) => Segment::Empty(v),
Segment::Empty(v) => Segment::Empty(v),
};
}
moved_segments.insert(outer_pos);
match s {
Segment::File(v, i) => {
final_disk.append(&mut vec![i; v]);
}
Segment::Empty(v) => {
let mut remaining_space = v;
while remaining_space > 0 {
if let Some((pos, v, i)) = disk_layout
.iter()
.enumerate()
.filter(|(_pos, s)| match s {
Segment::Empty(_) => false,
Segment::File(_v, _i) => true,
})
.filter(|(pos, _s)| !moved_segments.contains(pos))
.map(|(pos, s)| match s {
Segment::Empty(_) => unreachable!(),
Segment::File(v, i) => (pos, *v, *i),
})
.rev()
.find(|(_pos, v, _i)| *v <= remaining_space)
{
final_disk.append(&mut vec![i; v]);
remaining_space -= v;
moved_segments.insert(pos);
} else {
final_disk.append(&mut vec![0; remaining_space]);
remaining_space = 0;
}
}
}
}
}
debug!("disk layout: {final_disk:?}");
final_disk.iter().enumerate().map(|(a, b)| a * *b).sum()
}
#[cfg(test)]
mod tests {
use tracing_test::traced_test;
use super::{pt1, pt2};
use std::fs::read_to_string;
#[traced_test]
#[test]
pub fn test_pt1() {
let input =
read_to_string("./inputs/day09/example.txt").expect("Missing example.txt for day09");
assert_eq!(pt1(&input), 1928)
}
#[traced_test]
#[test]
pub fn test_pt2() {
let input =
read_to_string("./inputs/day09/example.txt").expect("Missing example.txt for day09");
assert_eq!(pt2(&input), 2858)
}
}

View file

@ -19,6 +19,8 @@ mod day06;
mod day07; mod day07;
#[cfg(feature = "day8")] #[cfg(feature = "day8")]
mod day08; mod day08;
#[cfg(feature = "day9")]
mod day09;
fn main() -> eyre::Result<()> { fn main() -> eyre::Result<()> {
color_eyre::install()?; color_eyre::install()?;
@ -41,6 +43,8 @@ fn main() -> eyre::Result<()> {
solve_day(7, day07::pt1, day07::pt2); solve_day(7, day07::pt1, day07::pt2);
#[cfg(feature = "day8")] #[cfg(feature = "day8")]
solve_day(8, day08::pt1, day08::pt2); solve_day(8, day08::pt1, day08::pt2);
#[cfg(feature = "day9")]
solve_day(9, day09::pt1, day09::pt2);
Ok(()) Ok(())
} }