solution: day 9
This commit is contained in:
parent
05e2cdebf2
commit
c090ff640a
@ -6,7 +6,7 @@ pub mod d5;
|
||||
pub mod d6;
|
||||
pub mod d7;
|
||||
pub mod d8;
|
||||
// pub mod d9;
|
||||
pub mod d9;
|
||||
// pub mod d10;
|
||||
// pub mod d11;
|
||||
// pub mod d12;
|
||||
|
||||
169
src/days/d9.rs
Normal file
169
src/days/d9.rs
Normal file
@ -0,0 +1,169 @@
|
||||
use crate::prelude::*;
|
||||
|
||||
pub type I = Vec<Block>;
|
||||
pub type O = usize;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum Block {
|
||||
Empty { size: usize },
|
||||
Taken { id: usize, size: usize }
|
||||
}
|
||||
|
||||
fn _parse_silver (i: SS) -> Vec<Block> {
|
||||
let mut switch = true;
|
||||
let mut out = Vec::with_capacity(i.len() * 10);
|
||||
let mut id = 0;
|
||||
for c in i.chars() {
|
||||
let val = (c as u8 - b'0') as usize;
|
||||
if switch {
|
||||
out.push(Block::Taken { id, size: val });
|
||||
id += 1;
|
||||
} else {
|
||||
out.extend((0..val).map(|_| Block::Empty { size: 1 }));
|
||||
}
|
||||
switch = !switch;
|
||||
}
|
||||
|
||||
out
|
||||
}
|
||||
|
||||
fn _parse_gold (i: SS) -> Vec<Block> {
|
||||
let mut switch = true;
|
||||
let mut out = Vec::with_capacity(i.len() * 10);
|
||||
let mut id = 0;
|
||||
for c in i.chars() {
|
||||
let val = (c as u8 - b'0') as usize;
|
||||
if switch {
|
||||
out.push(Block::Taken { id, size: val });
|
||||
id += 1;
|
||||
} else {
|
||||
out.push(Block::Empty { size: val });
|
||||
}
|
||||
switch = !switch;
|
||||
}
|
||||
|
||||
out
|
||||
}
|
||||
|
||||
fn _checksum (data: &I) -> usize {
|
||||
let mut position = 0;
|
||||
let mut sum = 0;
|
||||
|
||||
for d in data {
|
||||
match d {
|
||||
Block::Taken { id, size } => {
|
||||
for _ in 0..*size {
|
||||
sum += position * id;
|
||||
position += 1;
|
||||
}
|
||||
},
|
||||
Block::Empty { size } => position += size
|
||||
}
|
||||
}
|
||||
|
||||
sum
|
||||
}
|
||||
|
||||
fn _silver (mut data: I) -> O {
|
||||
let mut left = 0;
|
||||
let mut right = data.len() - 1;
|
||||
|
||||
while left < right {
|
||||
while di!(data[right], Block::Empty { size: 0 }) {
|
||||
right -= 1;
|
||||
}
|
||||
|
||||
let Block::Taken { id, mut size } = data[right] else { break; };
|
||||
data[right] = Block::Empty { size: 0 };
|
||||
|
||||
while size > 0 {
|
||||
while di!(data[left], Block::Taken { id: 0, size: 0 }) {
|
||||
left += 1;
|
||||
}
|
||||
|
||||
data[left] = Block::Taken { id, size: 1 };
|
||||
size -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
_checksum(&data)
|
||||
}
|
||||
|
||||
fn _gold (mut data: I) -> O {
|
||||
let mut left = 0;
|
||||
let mut right = data.len() - 1;
|
||||
|
||||
'outer : while left < right {
|
||||
while di!(data[right], Block::Empty { size: 0 }) {
|
||||
right -= 1;
|
||||
}
|
||||
|
||||
'mid : loop {
|
||||
if left >= right {
|
||||
right -= 1;
|
||||
left = 0;
|
||||
continue 'outer;
|
||||
}
|
||||
|
||||
while let Block::Taken { .. } = data[left] {
|
||||
left += 1;
|
||||
continue 'mid;
|
||||
}
|
||||
|
||||
let Block::Taken { id, size } = data[right] else { break; };
|
||||
|
||||
if let Block::Empty { size: size_block } = data[left] && size_block >= size {
|
||||
data[left] = Block::Taken { id, size };
|
||||
data[right] = Block::Empty { size };
|
||||
|
||||
if size_block > size {
|
||||
let rest = size_block - size;
|
||||
data.insert(left + 1, Block::Empty { size: rest });
|
||||
right += 1;
|
||||
}
|
||||
|
||||
left = 0;
|
||||
|
||||
} else {
|
||||
left += 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// 425499176500 low
|
||||
// println!("{:?}", data.iter().map(|e| match e {
|
||||
// Block::Empty { size } => format!("{}", ".".repeat(*size)),
|
||||
// Block::Taken { id, size } => format!("{}", id.to_string().repeat(*size))
|
||||
// }).collect::<String>());
|
||||
_checksum(&data)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
fn read () -> SS {
|
||||
inc!(9)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sample () {
|
||||
let data = "2333133121414131402";
|
||||
assert_eq!(_silver(_parse_silver(data)), 1928);
|
||||
assert_eq!(_gold(_parse_gold(data)), 2858);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn silver () {
|
||||
let ans = _silver(_parse_silver(read()));
|
||||
|
||||
assert_eq!(ans, 6310675819476)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gold () {
|
||||
let ans = _gold(_parse_gold(read()));
|
||||
|
||||
assert_eq!(ans, 1)
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user