1
0
Fork 0

day(14): add solution

Signed-off-by: Matej Focko <mfocko@redhat.com>
This commit is contained in:
Matej Focko 2023-12-14 10:50:35 +01:00
parent 0a4cc4c031
commit fdbca4409c
Signed by: mfocko
GPG key ID: 7C47D46246790496
2 changed files with 152 additions and 0 deletions

10
samples/day14.txt Normal file
View file

@ -0,0 +1,10 @@
O....#....
O.OO#....#
.....##...
OO.#O....O
.O.....O#.
O.#..O.#.#
..O..#O..O
.......O..
#....###..
#OO..#....

142
src/bin/day14.rs Normal file
View file

@ -0,0 +1,142 @@
use std::collections::HashMap;
use aoc_2023::*;
use indicatif::ProgressIterator;
use memoize::memoize;
type Output1 = usize;
type Output2 = Output1;
#[memoize]
fn slide_rocks(map: Vec<Vec<char>>) -> Vec<Vec<char>> {
let mut tilted: Vec<Vec<char>> = map.to_vec();
for x in 0..tilted[0].len() {
let mut next = 0;
for y in 0..tilted.len() {
match tilted[y][x] {
'#' | 'O' => {
next = y + 1;
}
'.' => {
while next < tilted.len() && tilted[next][x] == '.' {
next += 1;
}
if next < tilted.len() && tilted[next][x] == 'O' {
tilted[y][x] = 'O';
tilted[next][x] = '.';
}
}
_ => unreachable!(),
}
}
}
tilted
}
#[memoize]
fn rotate_east(map: Vec<Vec<char>>) -> Vec<Vec<char>> {
let mut r = map.clone();
for y in 0..map.len() {
for (x, row) in r.iter_mut().enumerate().take(map[y].len()) {
row[map.len() - y - 1] = map[y][x];
}
}
r
}
#[memoize]
fn run_cycle(map: Vec<Vec<char>>) -> Vec<Vec<char>> {
let mut map = map;
for _ in 0..4 {
map = slide_rocks(map);
map = rotate_east(map);
}
map
}
fn total_load(m: &[Vec<char>]) -> usize {
let rows = m.len();
m.iter()
.enumerate()
.map(|(y, l)| (rows - y) * l.iter().filter(|&&c| c == 'O').count())
.sum()
}
struct Day14 {
map: Vec<Vec<char>>,
}
impl Solution<Output1, Output2> for Day14 {
fn new<P: AsRef<Path>>(pathname: P) -> Self {
let lines: Vec<String> = file_to_lines(pathname);
Self {
map: lines.iter().map(|l| l.chars().collect()).collect(),
}
}
fn part_1(&mut self) -> Output1 {
let tilted = slide_rocks(self.map.clone());
total_load(&tilted)
}
fn part_2(&mut self) -> Output2 {
let mut map = self.map.clone();
let iterations = 1000000000;
let mut remaining = 0;
let mut seen: HashMap<Vec<Vec<char>>, usize> = HashMap::new();
for i in (0..iterations).progress() {
seen.insert(map.clone(), i);
map = run_cycle(map);
if let Some(&old_i) = seen.get(&map) {
remaining = (iterations - i - 1) % (i - old_i + 1);
break;
}
}
for _ in 0..remaining {
map = run_cycle(map);
}
total_load(&map)
}
}
fn main() -> Result<()> {
Day14::main()
}
test_sample!(day_14, Day14, 136, 64);
#[cfg(test)]
mod day_14_extended {
use super::*;
#[test]
fn test_rotate_east() {
let m = vec![
vec!['#', 'O', 'O'],
vec!['.', '#', 'O'],
vec!['.', '.', 'O'],
];
assert_eq!(
rotate_east(m),
vec![
vec!['.', '.', '#'],
vec!['.', '#', 'O'],
vec!['O', 'O', 'O'],
]
)
}
}