Add day9
This commit is contained in:
parent
4532f27fad
commit
03bc848853
7
day9/Cargo.lock
generated
Normal file
7
day9/Cargo.lock
generated
Normal file
@ -0,0 +1,7 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "day9"
|
||||
version = "0.1.0"
|
||||
6
day9/Cargo.toml
Normal file
6
day9/Cargo.toml
Normal file
@ -0,0 +1,6 @@
|
||||
[package]
|
||||
name = "day9"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
119
day9/src/main.rs
Normal file
119
day9/src/main.rs
Normal file
@ -0,0 +1,119 @@
|
||||
use std::{cmp::Ordering, fmt::Display};
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
struct Space {
|
||||
id: Option<usize>,
|
||||
}
|
||||
|
||||
impl Display for Space {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
if let Some(i) = self.id {
|
||||
i.to_string()
|
||||
} else {
|
||||
".".to_string()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for Space {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for Space {
|
||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||
if self.id.is_none() {
|
||||
return Ordering::Less;
|
||||
}
|
||||
if other.id.is_none() {
|
||||
return Ordering::Greater;
|
||||
}
|
||||
self.id.unwrap().cmp(&other.id.unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
fn parse(input: &str) -> Vec<Space> {
|
||||
input
|
||||
.chars()
|
||||
.enumerate()
|
||||
.filter(|(_, c)| c.is_ascii_digit())
|
||||
.flat_map(|(c_idx, c)| {
|
||||
(0..c.to_digit(10).unwrap()).map(move |_| Space {
|
||||
id: if c_idx % 2 == 0 {
|
||||
Some(c_idx / 2)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
})
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn checksum(filesystem: &[Space]) -> usize {
|
||||
filesystem
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(c_idx, c)| if let Some(v) = c.id { c_idx * v } else { 0 })
|
||||
.sum()
|
||||
}
|
||||
|
||||
fn part1(filesystem: &mut [Space]) -> usize {
|
||||
for space_idx in 0..filesystem.len() {
|
||||
if filesystem[space_idx].id.is_none() {
|
||||
let last = filesystem
|
||||
.iter()
|
||||
.enumerate()
|
||||
.rev()
|
||||
.find(|(_, n)| n.id.is_some())
|
||||
.unwrap();
|
||||
if last.0 < space_idx {
|
||||
break;
|
||||
}
|
||||
filesystem.swap(space_idx, last.0);
|
||||
};
|
||||
}
|
||||
checksum(filesystem)
|
||||
}
|
||||
|
||||
fn get_chunk_size(filesystem: &[Space], idx: usize) -> usize {
|
||||
let mut chunk_size = 0;
|
||||
while idx + chunk_size < filesystem.len() && filesystem[idx + chunk_size] == filesystem[idx] {
|
||||
chunk_size += 1;
|
||||
}
|
||||
chunk_size
|
||||
}
|
||||
|
||||
fn part2(filesystem: &mut [Space]) -> usize {
|
||||
for move_id in (0..=filesystem.iter().max().unwrap().id.unwrap()).rev() {
|
||||
let move_idx = filesystem
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find(|(_, c)| c.id.unwrap_or(move_id + 1) == move_id)
|
||||
.unwrap()
|
||||
.0;
|
||||
let move_chunk_size = get_chunk_size(filesystem, move_idx);
|
||||
for free_idx in 0..move_idx {
|
||||
if filesystem[free_idx].id.is_some() {
|
||||
continue;
|
||||
}
|
||||
if get_chunk_size(filesystem, free_idx) >= move_chunk_size {
|
||||
for i in 0..move_chunk_size {
|
||||
filesystem.swap(move_idx + i, free_idx + i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
checksum(filesystem)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut input = parse(include_str!("../input.txt"));
|
||||
println!("{}", part1(&mut input.clone()));
|
||||
println!("{}", part2(&mut input));
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user