DP is cool but actually wtf
This commit is contained in:
Tyler Beckman 2023-12-14 01:16:38 -07:00
parent f26ca8924c
commit c585c139a5
Signed by: Ty
GPG key ID: 2813440C772555A4
2 changed files with 148 additions and 0 deletions

145
lib/src/day14/mod.rs Normal file
View 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()
}
}

View file

@ -6,6 +6,7 @@ use day10::Day10;
use day11::Day11;
use day12::Day12;
use day13::Day13;
use day14::Day14;
use day2::Day2;
use day3::Day3;
use day4::Day4;
@ -24,6 +25,7 @@ pub mod day10;
pub mod day11;
pub mod day12;
pub mod day13;
pub mod day14;
pub mod day2;
pub mod day3;
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()),
}),
13 => Box::new(Day13 { input }),
14 => Box::new(Day14 { input }),
_ => panic!("Invalid day #"),
}
}