Day 14
DP is cool but actually wtf
This commit is contained in:
parent
f26ca8924c
commit
c585c139a5
2 changed files with 148 additions and 0 deletions
145
lib/src/day14/mod.rs
Normal file
145
lib/src/day14/mod.rs
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
use std::{collections::HashMap, num::NonZeroUsize};
|
||||||
|
|
||||||
|
use clru::CLruCache;
|
||||||
|
use itertools::Itertools;
|
||||||
|
|
||||||
|
use crate::utils::Day;
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct Day14 {
|
||||||
|
pub input: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
const SIZE: usize = 100; // More efficient to hardcode the input size, for less allocations
|
||||||
|
|
||||||
|
impl Day14 {
|
||||||
|
fn rotate(left: bool, array: &mut [[char; SIZE]; SIZE]) {
|
||||||
|
let mut rot = [['.'; SIZE]; SIZE];
|
||||||
|
match left {
|
||||||
|
false => for i in 0..SIZE {
|
||||||
|
for j in 0..SIZE {
|
||||||
|
rot[i][j] = array[SIZE - j - 1][i];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
true => for i in 0..SIZE {
|
||||||
|
for j in 0..SIZE {
|
||||||
|
rot[i][j] = array[j][SIZE - i - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*array = rot;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Day for Day14 {
|
||||||
|
fn part1(&mut self) -> String {
|
||||||
|
let mut square_rocks = HashMap::<usize /* column index */, usize /* row index */>::new();
|
||||||
|
let mut new_dish = vec![vec![false; self.input.lines().next().unwrap().len()]; self.input.lines().count()];
|
||||||
|
for (i, row) in self.input.lines().enumerate() {
|
||||||
|
for (j, char) in row.chars().enumerate() {
|
||||||
|
match char {
|
||||||
|
'.' => continue,
|
||||||
|
'#' => { square_rocks.insert(j, i); },
|
||||||
|
'O' => {
|
||||||
|
let mut k = square_rocks.get(&j).map(|n| n + 1).unwrap_or(0);
|
||||||
|
loop {
|
||||||
|
if new_dish[k][j] != true { new_dish[k][j] = true; break }
|
||||||
|
else { k += 1; }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => panic!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dbg print lines
|
||||||
|
// println!(
|
||||||
|
// "{}",
|
||||||
|
// new_dish
|
||||||
|
// .iter()
|
||||||
|
// .map(|l| l.iter().map(|b| if *b { 'O' } else { '.' }).collect::<String>())
|
||||||
|
// .collect::<Vec<_>>()
|
||||||
|
// .join("\n")
|
||||||
|
// );
|
||||||
|
|
||||||
|
new_dish.into_iter().enumerate().map(|(i, line)| line.into_iter().filter_map(|rock| if rock { Some(SIZE - i) } else { None }).sum::<usize>()).sum::<usize>().to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part2(&mut self) -> String {
|
||||||
|
let mut direction = 0u8; // 0 -> North, 1 -> East, 2 -> South, 3 -> West
|
||||||
|
let mut new_dish: [[char; SIZE]; SIZE] = self.input.lines().map(|line| line.chars().collect_vec().try_into().unwrap()).collect_vec().try_into().unwrap();
|
||||||
|
let mut cache = CLruCache::<(u8, [[char; SIZE]; SIZE]), [[char; SIZE]; SIZE]>::new(NonZeroUsize::new(100).unwrap());
|
||||||
|
|
||||||
|
for i in 0..390625u128 {
|
||||||
|
if i % 100000 == 0 { println!("{:.02}%, {}", i as f64 / 4000000000f64 * 100f64, cache.len()); }
|
||||||
|
|
||||||
|
// Cache check
|
||||||
|
let cache_ref = new_dish.clone();
|
||||||
|
if let Some(result) = cache.get(&(direction, cache_ref)) {
|
||||||
|
new_dish = *result;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for _ in 0..10240 {
|
||||||
|
// Based on direction, flip the input
|
||||||
|
match direction {
|
||||||
|
0 => (),
|
||||||
|
1 => Self::rotate(true, &mut new_dish),
|
||||||
|
2 => {
|
||||||
|
for row in new_dish.iter_mut() {
|
||||||
|
row.reverse();
|
||||||
|
}
|
||||||
|
new_dish.reverse();
|
||||||
|
},
|
||||||
|
3 => Self::rotate(false, &mut new_dish),
|
||||||
|
_ => panic!()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init tracking
|
||||||
|
let mut square_rocks = HashMap::<usize /* column index */, usize /* row index */>::new();
|
||||||
|
let clone = new_dish.clone();
|
||||||
|
|
||||||
|
for (i, row) in clone.iter().enumerate() {
|
||||||
|
for (j, char) in row.iter().enumerate() {
|
||||||
|
match char {
|
||||||
|
'.' => continue,
|
||||||
|
'#' => { square_rocks.insert(j, i); },
|
||||||
|
'O' => {
|
||||||
|
new_dish[i][j] = '.';
|
||||||
|
let mut k = square_rocks.get(&j).map(|n| n + 1).unwrap_or(0);
|
||||||
|
loop {
|
||||||
|
if new_dish[k][j] != 'O' { new_dish[k][j] = 'O'; break }
|
||||||
|
else { k += 1; }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => panic!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Based on direction, tilt the direction again
|
||||||
|
// Based on direction, flip the input
|
||||||
|
match direction {
|
||||||
|
0 => (),
|
||||||
|
1 => Self::rotate(false, &mut new_dish),
|
||||||
|
2 => {
|
||||||
|
for row in new_dish.iter_mut() {
|
||||||
|
row.reverse();
|
||||||
|
}
|
||||||
|
new_dish.reverse();
|
||||||
|
},
|
||||||
|
3 => Self::rotate(true, &mut new_dish),
|
||||||
|
_ => panic!()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop direction
|
||||||
|
if direction != 0 { direction -= 1; } else { direction = 3; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache store
|
||||||
|
cache.put((direction, cache_ref), new_dish);
|
||||||
|
}
|
||||||
|
|
||||||
|
new_dish.into_iter().enumerate().map(|(i, line)| line.into_iter().filter_map(|rock| if rock == 'O' { Some(SIZE - i) } else { None }).sum::<usize>()).sum::<usize>().to_string()
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,6 +6,7 @@ use day10::Day10;
|
||||||
use day11::Day11;
|
use day11::Day11;
|
||||||
use day12::Day12;
|
use day12::Day12;
|
||||||
use day13::Day13;
|
use day13::Day13;
|
||||||
|
use day14::Day14;
|
||||||
use day2::Day2;
|
use day2::Day2;
|
||||||
use day3::Day3;
|
use day3::Day3;
|
||||||
use day4::Day4;
|
use day4::Day4;
|
||||||
|
@ -24,6 +25,7 @@ pub mod day10;
|
||||||
pub mod day11;
|
pub mod day11;
|
||||||
pub mod day12;
|
pub mod day12;
|
||||||
pub mod day13;
|
pub mod day13;
|
||||||
|
pub mod day14;
|
||||||
pub mod day2;
|
pub mod day2;
|
||||||
pub mod day3;
|
pub mod day3;
|
||||||
pub mod day4;
|
pub mod day4;
|
||||||
|
@ -68,6 +70,7 @@ pub fn get_day(day: u8, input: String) -> Box<dyn Day> {
|
||||||
cache: CLruCache::new(NonZeroUsize::new(10000).unwrap()),
|
cache: CLruCache::new(NonZeroUsize::new(10000).unwrap()),
|
||||||
}),
|
}),
|
||||||
13 => Box::new(Day13 { input }),
|
13 => Box::new(Day13 { input }),
|
||||||
|
14 => Box::new(Day14 { input }),
|
||||||
_ => panic!("Invalid day #"),
|
_ => panic!("Invalid day #"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue