Skip to content

Commit

Permalink
2024-16 (#33)
Browse files Browse the repository at this point in the history
  • Loading branch information
jurisk authored Dec 16, 2024
1 parent 08578fb commit d51d5d7
Show file tree
Hide file tree
Showing 19 changed files with 736 additions and 36 deletions.
2 changes: 2 additions & 0 deletions ReadMe.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

| Year-Day | Task | Scala | Rust | Others |
|----------|:-------------------------------------------------------------------------------|:-----------------------------------------------------------------------:|:----------------------------------------------:|:----------------------------------------------------------------------:|
| 2024-16 | [Reindeer Maze](https://adventofcode.com/2024/day/16) | [Scala](scala2/src/main/scala/jurisk/adventofcode/y2024/Advent16.scala) | [Rust](rust/y2024/src/bin/solution_2024_16.rs) | |
| 2024-15 | [Warehouse Woes](https://adventofcode.com/2024/day/15) | [Scala](scala2/src/main/scala/jurisk/adventofcode/y2024/Advent15.scala) | [Rust](rust/y2024/src/bin/solution_2024_15.rs) | |
| 2024-14 | [Restroom Redoubt](https://adventofcode.com/2024/day/14) | [Scala](scala2/src/main/scala/jurisk/adventofcode/y2024/Advent14.scala) | [Rust](rust/y2024/src/bin/solution_2024_14.rs) | |
| 2024-13 | [Claw Contraption](https://adventofcode.com/2024/day/13) | [Scala](scala2/src/main/scala/jurisk/adventofcode/y2024/Advent13.scala) | [Rust](rust/y2024/src/bin/solution_2024_13.rs) | |
| 2024-12 | [Garden Groups](https://adventofcode.com/2024/day/12) | [Scala](scala2/src/main/scala/jurisk/adventofcode/y2024/Advent12.scala) | [Rust](rust/y2024/src/bin/solution_2024_12.rs) | |
Expand Down
2 changes: 1 addition & 1 deletion rust/common/src/grid2d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ pub struct MatrixGrid2D<T> {

impl MatrixGrid2D<char> {
#[must_use]
pub fn char_field(input: &str) -> Self {
pub fn parse_char_field(input: &str) -> Self {
MatrixGrid2D::<char>::parse(input, identity)
}
}
Expand Down
15 changes: 15 additions & 0 deletions rust/y2024/resources/16-test-00.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
###############
#.......#....E#
#.#.###.#.###.#
#.....#.#...#.#
#.###.#####.#.#
#.#.#.......#.#
#.#.#####.###.#
#...........#.#
###.#.#####.#.#
#...#.....#.#.#
#.#.#.###.#.#.#
#.....#...#.#.#
#.###.#.#.#.#.#
#S..#.....#...#
###############
17 changes: 17 additions & 0 deletions rust/y2024/resources/16-test-01.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#################
#...#...#...#..E#
#.#.#.#.#.#.#.#.#
#.#.#.#...#...#.#
#.#.#.#.###.#.#.#
#...#.#.#.....#.#
#.#.#.#.#.#####.#
#.#...#.#.#.....#
#.#.#####.#.###.#
#.#.#.......#...#
#.#.###.#####.###
#.#.#...#.....#.#
#.#.#.#####.###.#
#.#.#.........#.#
#.#.#.#########.#
#S#.............#
#################
141 changes: 141 additions & 0 deletions rust/y2024/resources/16.txt

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion rust/y2024/src/bin/solution_2024_12.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ type R = usize;
type Data = MatrixGrid2D<char>;

fn parse(input: &str) -> Data {
MatrixGrid2D::char_field(input)
MatrixGrid2D::parse_char_field(input)
}

fn perimeter(coords: &HashSet<Coords>) -> R {
Expand Down
2 changes: 1 addition & 1 deletion rust/y2024/src/bin/solution_2024_15.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ fn parse(input: &str) -> Result<Input, Error> {

let directions: Vec<Direction> = b.chars().flat_map(Direction::try_from_caret).collect();

let char_field: MatrixGrid2D<char> = MatrixGrid2D::char_field(&a);
let char_field: MatrixGrid2D<char> = MatrixGrid2D::parse_char_field(&a);

let robot = char_field
.find_coords_by_value(&'@')
Expand Down
168 changes: 168 additions & 0 deletions rust/y2024/src/bin/solution_2024_16.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
use std::collections::HashSet;

use advent_of_code_common::direction::Direction;
use advent_of_code_common::grid2d::{Coords, Grid2D, MatrixGrid2D};
use advent_of_code_common::parsing::Error;
use advent_of_code_common::rotation::Rotation;
use pathfinding::prelude::{astar, astar_bag};

const DATA: &str = include_str!("../../resources/16.txt");

type R = i32;

#[derive(Copy, Clone, Eq, PartialEq, Hash)]
struct State {
position: Coords,
direction: Direction,
}

impl State {
fn go_straight(&self) -> Self {
Self {
position: self.position + self.direction,
direction: self.direction,
}
}

fn turn(&self, rotation: Rotation) -> Self {
Self {
position: self.position,
direction: self.direction.rotate(rotation),
}
}

fn successors(&self, field: &MatrixGrid2D<bool>) -> Vec<(State, R)> {
vec![
(self.go_straight(), 1),
(self.turn(Rotation::Left90), 1000),
(self.turn(Rotation::Right90), 1000),
]
.into_iter()
.filter(|(s, _)| field.get(s.position) == Some(&false))
.collect()
}

fn heuristic(&self, end: Coords) -> R {
self.position.manhattan_distance(end) as R
}
}

type Input = (State, MatrixGrid2D<bool>, Coords);

fn parse(input: &str) -> Result<Input, Error> {
let char_field = MatrixGrid2D::parse_char_field(input);
let start = char_field
.find_coords_by_value(&'S')
.ok_or("Start not found")?;
let end = char_field
.find_coords_by_value(&'E')
.ok_or("End not found")?;
let field = char_field.map_by_values(|c| {
match c {
'#' => true,
'S' | 'E' | '.' => false,
_ => panic!("Unknown character {c} in field"),
}
});
Ok((
State {
position: start,
direction: Direction::East,
},
field,
end,
))
}

fn solve_1(data: &Input) -> R {
let (state, field, end) = data;
let (_, result) = astar(
state,
|s| s.successors(field),
|s| s.heuristic(*end),
|c| c.position == *end,
)
.expect("Expected a solution");
result
}

fn solve_2(data: &Input) -> usize {
let (state, field, end) = data;
let (results, _) = astar_bag(
state,
|s| s.successors(field),
|s| s.heuristic(*end),
|c| c.position == *end,
)
.expect("Expected a solution");

let mut visited = HashSet::new();
for result in results {
for s in result {
visited.insert(s.position);
}
}
visited.len()
}

fn main() -> Result<(), Error> {
let data = parse(DATA)?;

let result_1 = solve_1(&data);
println!("Part 1: {result_1}");

let result_2 = solve_2(&data);
println!("Part 2: {result_2}");

Ok(())
}

#[cfg(test)]
mod tests {
use super::*;

const TEST_DATA_0: &str = include_str!("../../resources/16-test-00.txt");
const TEST_DATA_1: &str = include_str!("../../resources/16-test-01.txt");

fn test_data_0() -> Input {
parse(TEST_DATA_0).unwrap()
}

fn test_data_1() -> Input {
parse(TEST_DATA_1).unwrap()
}

fn real_data() -> Input {
parse(DATA).unwrap()
}

#[test]
fn test_solve_1_test_0() {
assert_eq!(solve_1(&test_data_0()), 7036);
}

#[test]
fn test_solve_1_test_1() {
assert_eq!(solve_1(&test_data_1()), 11048);
}

#[test]
fn test_solve_1_real() {
assert_eq!(solve_1(&real_data()), 74392);
}

#[test]
fn test_solve_2_test_0() {
assert_eq!(solve_2(&test_data_0()), 45);
}

#[test]
fn test_solve_2_test_1() {
assert_eq!(solve_2(&test_data_1()), 64);
}

#[test]
fn test_solve_2_real() {
assert_eq!(solve_2(&real_data()), 426);
}
}
16 changes: 15 additions & 1 deletion scala2/src/main/resources/2024/16-test-00.txt
Original file line number Diff line number Diff line change
@@ -1 +1,15 @@
noop
###############
#.......#....E#
#.#.###.#.###.#
#.....#.#...#.#
#.###.#####.#.#
#.#.#.......#.#
#.#.#####.###.#
#...........#.#
###.#.#####.#.#
#...#.....#.#.#
#.#.#.###.#.#.#
#.....#...#.#.#
#.###.#.#.#.#.#
#S..#.....#...#
###############
17 changes: 17 additions & 0 deletions scala2/src/main/resources/2024/16-test-01.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#################
#...#...#...#..E#
#.#.#.#.#.#.#.#.#
#.#.#.#...#...#.#
#.#.#.#.###.#.#.#
#...#.#.#.....#.#
#.#.#.#.#.#####.#
#.#...#.#.#.....#
#.#.#####.#.###.#
#.#.#.......#...#
#.#.###.#####.###
#.#.#...#.....#.#
#.#.#.#####.###.#
#.#.#.........#.#
#.#.#.#########.#
#S#.............#
#################
Loading

0 comments on commit d51d5d7

Please sign in to comment.