Skip to content

Commit

Permalink
refactor(2023): update day 14
Browse files Browse the repository at this point in the history
  • Loading branch information
believer committed Dec 14, 2023
1 parent f20ce28 commit 538fb96
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 60 deletions.
97 changes: 37 additions & 60 deletions rust/2023/src/day_14.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
//! I knew brute forcing it wouldn't work. The description even mentions
//! cycles so the grid must repeat itself. So, find the cycle
//! and then find the target iteration in the cycle.
//!
//! Will probably refactor this later to make it more readable.

use std::collections::HashMap;

Expand All @@ -25,20 +23,18 @@ pub fn input_generator(input: &str) -> Input {
}
}

/* Part One
*
*
*/
// Your puzzle answer was
#[doc = r#"```
use advent_of_code_2023::day_14::*;
let data = include_str!("../input/2023/day14.txt");
assert_eq!(solve_part_01(&input_generator(data)), 108614);
```"#]
#[aoc(day14, part1)]
pub fn solve_part_01(input: &Input) -> i32 {
let mut grid = input.grid.clone();
fn calculate_load(grid: &Grid<u8>) -> i32 {
grid.data
.iter()
.enumerate()
.map(|(i, &x)| match x {
b'O' => grid.height - (i as i32) / grid.width,
_ => 0,
})
.sum()
}

fn tilt_north(grid: &mut Grid<u8>) {
for x in 0..grid.width {
for y in 0..grid.height {
let point = Point::new(x, y);
Expand All @@ -49,8 +45,8 @@ pub fn solve_part_01(input: &Input) -> i32 {

// Move until we hit the north wall
while y > 0 {
let above = Point::new(x, y) + UP;
let current = Point::new(x, y);
let above = current + UP;

match grid[above] {
b'.' => grid.swap(above, current),
Expand All @@ -62,15 +58,24 @@ pub fn solve_part_01(input: &Input) -> i32 {
}
}
}
}

grid.data
.iter()
.enumerate()
.map(|(i, &x)| match x {
b'O' => grid.height - (i as i32) / grid.width,
_ => 0,
})
.sum()
/* Part One
*
*
*/
// Your puzzle answer was
#[doc = r#"```
use advent_of_code_2023::day_14::*;
let data = include_str!("../input/2023/day14.txt");
assert_eq!(solve_part_01(&input_generator(data)), 108614);
```"#]
#[aoc(day14, part1)]
pub fn solve_part_01(input: &Input) -> i32 {
let mut grid = input.grid.clone();

tilt_north(&mut grid);
calculate_load(&grid)
}

/* Part Two
Expand All @@ -89,33 +94,13 @@ pub fn solve_part_02(input: &Input) -> i32 {

seen.insert(grid.clone(), 0);

// This basically does the same as part 1 but for each direction.
//
// There must be a cycle in the grid. Loop until we get to a
// state we've seen before
// state we've seen before.
let (start, end) = loop {
// North
for x in 0..grid.width {
for y in 0..grid.height {
let point = Point::new(x, y);

// Only move round rocks
if grid[point] == b'O' {
let mut y = y;

// Move until we hit the north wall
while y > 0 {
let above = Point::new(x, y) + UP;
let current = Point::new(x, y);

match grid[above] {
b'.' => grid.swap(above, current),
_ => break,
};

y -= 1;
}
}
}
}
tilt_north(&mut grid);

// West
for x in 0..grid.width {
Expand All @@ -126,8 +111,8 @@ pub fn solve_part_02(input: &Input) -> i32 {
let mut x = x;

while x > 0 {
let left = Point::new(x, y) + LEFT;
let current = Point::new(x, y);
let left = current + LEFT;

match grid[left] {
b'.' => grid.swap(left, current),
Expand All @@ -151,8 +136,8 @@ pub fn solve_part_02(input: &Input) -> i32 {
let mut y = y;

while y < grid.height - 1 {
let below = Point::new(x, y) + DOWN;
let current = Point::new(x, y);
let below = current + DOWN;

match grid[below] {
b'.' => grid.swap(below, current),
Expand All @@ -174,8 +159,8 @@ pub fn solve_part_02(input: &Input) -> i32 {
let mut x = x;

while x < grid.width - 1 {
let right = Point::new(x, y) + RIGHT;
let current = Point::new(x, y);
let right = current + RIGHT;

match grid[right] {
b'.' => grid.swap(right, current),
Expand Down Expand Up @@ -203,15 +188,7 @@ pub fn solve_part_02(input: &Input) -> i32 {
let target = start + remainder;
let (target_grid, _) = seen.iter().find(|(_, &v)| v == target).unwrap();

target_grid
.data
.iter()
.enumerate()
.map(|(i, &x)| match x {
b'O' => target_grid.height - (i as i32) / target_grid.width,
_ => 0,
})
.sum()
calculate_load(target_grid)
}

#[cfg(test)]
Expand Down
45 changes: 45 additions & 0 deletions rust/2023/src/grid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,55 @@ impl<T: Copy + PartialEq> Grid<T> {
.collect()
}

/// Find if the grid contains a point
///
/// # Example
///
/// ```
/// use advent_of_code_2023::grid::Grid;
/// use advent_of_code_2023::point::Point;
///
/// let data = "...#
/// .#..
/// ..#.";
///
/// let grid: Grid<u8> = Grid::from(data);
///
/// let existing_point = Point::new(2, 1);
/// let non_existing_point = Point::new(3, 3);
///
/// assert!(grid.contains(existing_point));
/// assert!(!grid.contains(non_existing_point));
/// ```
pub fn contains(&self, point: Point) -> bool {
point.x >= 0 && point.x < self.width && point.y >= 0 && point.y < self.height
}

/// Swap the values of two points in the grid
///
/// # Example
///
/// ```
/// use advent_of_code_2023::grid::Grid;
/// use advent_of_code_2023::point::Point;
///
/// let data = "...#
/// .#..
/// ..#.";
///
/// let mut grid: Grid<u8> = Grid::from(data);
///
/// let point_a = Point::new(3, 0);
/// let point_b = Point::new(2, 0);
///
/// assert_eq!(grid[point_a], b'#');
/// assert_eq!(grid[point_b], b'.');
///
/// grid.swap(point_a, point_b);
///
/// assert_eq!(grid[point_a], b'.');
/// assert_eq!(grid[point_b], b'#');
/// ```
pub fn swap(&mut self, a: Point, b: Point) {
let a = (self.width * a.y + a.x) as usize;
let b = (self.width * b.y + b.x) as usize;
Expand Down

0 comments on commit 538fb96

Please sign in to comment.