[Rust/2023/14] Add solution
This commit is contained in:
parent
2be8c03fe5
commit
632001d074
6 changed files with 174 additions and 2 deletions
File diff suppressed because one or more lines are too long
157
Rust/2023/14.rs
Normal file
157
Rust/2023/14.rs
Normal file
|
@ -0,0 +1,157 @@
|
|||
#![feature(test)]
|
||||
|
||||
use std::{
|
||||
hash::Hash,
|
||||
ops::{Index, IndexMut},
|
||||
};
|
||||
|
||||
use itertools::Itertools;
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
type Input = Grid;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
enum Cell {
|
||||
Empty,
|
||||
Cube,
|
||||
Rounded,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct Grid {
|
||||
grid: Vec<Vec<Cell>>,
|
||||
rotation: u8,
|
||||
}
|
||||
|
||||
fn setup(input: &str) -> Input {
|
||||
let grid = input
|
||||
.lines()
|
||||
.map(|line| {
|
||||
line.bytes()
|
||||
.map(|b| match b {
|
||||
b'.' => Cell::Empty,
|
||||
b'#' => Cell::Cube,
|
||||
b'O' => Cell::Rounded,
|
||||
_ => panic!(),
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
.collect();
|
||||
Grid { grid, rotation: 0 }
|
||||
}
|
||||
|
||||
impl Grid {
|
||||
fn width(&self) -> usize {
|
||||
if self.rotation % 2 == 0 {
|
||||
self.grid[0].len()
|
||||
} else {
|
||||
self.grid.len()
|
||||
}
|
||||
}
|
||||
|
||||
fn height(&self) -> usize {
|
||||
if self.rotation % 2 == 0 {
|
||||
self.grid.len()
|
||||
} else {
|
||||
self.grid[0].len()
|
||||
}
|
||||
}
|
||||
|
||||
fn index(&self, i: usize, j: usize) -> (usize, usize) {
|
||||
let w = self.grid[0].len();
|
||||
let h = self.grid.len();
|
||||
match self.rotation % 4 {
|
||||
0 => (i, j),
|
||||
1 => (w - j - 1, i),
|
||||
2 => (h - i - 1, w - j - 1),
|
||||
3 => (j, h - i - 1),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn tilt_north(&mut self) {
|
||||
for i in 1..self.height() {
|
||||
for j in 0..self.width() {
|
||||
if !matches!(self[(i, j)], Cell::Rounded) {
|
||||
continue;
|
||||
}
|
||||
let mut k = i;
|
||||
while k > 0 && matches!(self[(k - 1, j)], Cell::Empty) {
|
||||
self[(k, j)] = Cell::Empty;
|
||||
self[(k - 1, j)] = Cell::Rounded;
|
||||
k -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn total_load(&self) -> usize {
|
||||
self.grid
|
||||
.iter()
|
||||
.rev()
|
||||
.enumerate()
|
||||
.map(|(i, row)| row.iter().filter(|x| matches!(x, Cell::Rounded)).count() * (i + 1))
|
||||
.sum()
|
||||
}
|
||||
|
||||
fn cycle(&mut self) {
|
||||
for i in 0..4 {
|
||||
self.rotation = i;
|
||||
self.tilt_north();
|
||||
}
|
||||
}
|
||||
|
||||
fn hash(&self) -> impl Hash + Eq {
|
||||
type Chunk = u128;
|
||||
self.grid
|
||||
.iter()
|
||||
.flatten()
|
||||
.chunks(Chunk::BITS as _)
|
||||
.into_iter()
|
||||
.map(|c| c.fold(0, |acc, x| acc << 1 | matches!(x, Cell::Rounded) as Chunk))
|
||||
.fold(0, |a, b| a ^ b)
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<(usize, usize)> for Grid {
|
||||
type Output = Cell;
|
||||
|
||||
fn index(&self, (i, j): (usize, usize)) -> &Self::Output {
|
||||
let (i, j) = self.index(i, j);
|
||||
&self.grid[i][j]
|
||||
}
|
||||
}
|
||||
|
||||
impl IndexMut<(usize, usize)> for Grid {
|
||||
fn index_mut(&mut self, (i, j): (usize, usize)) -> &mut Self::Output {
|
||||
let (i, j) = self.index(i, j);
|
||||
&mut self.grid[i][j]
|
||||
}
|
||||
}
|
||||
|
||||
fn part1(input: &Input) -> usize {
|
||||
let mut grid = input.clone();
|
||||
grid.tilt_north();
|
||||
grid.total_load()
|
||||
}
|
||||
|
||||
fn part2(input: &Input) -> usize {
|
||||
let mut grid = input.clone();
|
||||
let mut n = 1000000000u32;
|
||||
let mut hist = FxHashMap::default();
|
||||
while n > 0 {
|
||||
if let Some(k) = hist.insert(grid.hash(), n) {
|
||||
let cycle_length = k - n;
|
||||
n %= cycle_length;
|
||||
break;
|
||||
}
|
||||
grid.cycle();
|
||||
n -= 1;
|
||||
}
|
||||
for _ in 0..n {
|
||||
grid.cycle();
|
||||
}
|
||||
grid.total_load()
|
||||
}
|
||||
|
||||
aoc::main!(2023, 14, ex: 1);
|
|
@ -262,3 +262,6 @@ path = "2023/12.rs"
|
|||
[[bin]]
|
||||
name = "2023_13"
|
||||
path = "2023/13.rs"
|
||||
[[bin]]
|
||||
name = "2023_14"
|
||||
path = "2023/14.rs"
|
||||
|
|
10
examples/2023/14/1
Normal file
10
examples/2023/14/1
Normal file
|
@ -0,0 +1,10 @@
|
|||
O....#....
|
||||
O.OO#....#
|
||||
.....##...
|
||||
OO.#O....O
|
||||
.O.....O#.
|
||||
O.#..O.#.#
|
||||
..O..#O..O
|
||||
.......O..
|
||||
#....###..
|
||||
#OO..#....
|
1
examples/2023/14/1.1
Normal file
1
examples/2023/14/1.1
Normal file
|
@ -0,0 +1 @@
|
|||
136
|
1
examples/2023/14/1.2
Normal file
1
examples/2023/14/1.2
Normal file
|
@ -0,0 +1 @@
|
|||
64
|
Loading…
Add table
Add a link
Reference in a new issue