feat: day 9
This commit is contained in:
parent
1e9030960d
commit
a7bc0e746a
|
@ -4,7 +4,7 @@ version = "0.1.0"
|
|||
edition = "2021"
|
||||
|
||||
[features]
|
||||
full = ["day1", "day2", "day3", "day4", "day5", "day6", "day7", "day8"]
|
||||
full = ["day1", "day2", "day3", "day4", "day5", "day6", "day7", "day8", "day9"]
|
||||
default = ["full"]
|
||||
day1 = []
|
||||
day2 = []
|
||||
|
@ -14,6 +14,7 @@ day5 = []
|
|||
day6 = []
|
||||
day7 = []
|
||||
day8 = []
|
||||
day9 = []
|
||||
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
|
1
inputs/day09/example.txt
Normal file
1
inputs/day09/example.txt
Normal file
|
@ -0,0 +1 @@
|
|||
2333133121414131402
|
|
@ -79,7 +79,7 @@ pub fn pt1(input: &str) -> usize {
|
|||
debug!("new Map: \n{new_map}");
|
||||
antinode_positions.len()
|
||||
}
|
||||
// 225 is too high
|
||||
|
||||
pub fn pt2(input: &str) -> usize {
|
||||
let char_positions = input
|
||||
.lines()
|
||||
|
|
154
src/day09.rs
Normal file
154
src/day09.rs
Normal 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)
|
||||
}
|
||||
}
|
|
@ -19,6 +19,8 @@ mod day06;
|
|||
mod day07;
|
||||
#[cfg(feature = "day8")]
|
||||
mod day08;
|
||||
#[cfg(feature = "day9")]
|
||||
mod day09;
|
||||
|
||||
fn main() -> eyre::Result<()> {
|
||||
color_eyre::install()?;
|
||||
|
@ -41,6 +43,8 @@ fn main() -> eyre::Result<()> {
|
|||
solve_day(7, day07::pt1, day07::pt2);
|
||||
#[cfg(feature = "day8")]
|
||||
solve_day(8, day08::pt1, day08::pt2);
|
||||
#[cfg(feature = "day9")]
|
||||
solve_day(9, day09::pt1, day09::pt2);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue