solution: day 9
This commit is contained in:
parent
05e2cdebf2
commit
c090ff640a
@ -6,7 +6,7 @@ pub mod d5;
|
|||||||
pub mod d6;
|
pub mod d6;
|
||||||
pub mod d7;
|
pub mod d7;
|
||||||
pub mod d8;
|
pub mod d8;
|
||||||
// pub mod d9;
|
pub mod d9;
|
||||||
// pub mod d10;
|
// pub mod d10;
|
||||||
// pub mod d11;
|
// pub mod d11;
|
||||||
// pub mod d12;
|
// 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