Skip to content

Commit

Permalink
Day 23: A Long Walk (part 1)
Browse files Browse the repository at this point in the history
  • Loading branch information
ephemient committed Dec 25, 2023
1 parent 8269af6 commit 8d2b1e1
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 3 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@ Development occurs in language-specific directories:
|[Day20.hs](hs/src/Day20.hs)|[Day20.kt](kt/aoc2023-lib/src/commonMain/kotlin/com/github/ephemient/aoc2023/Day20.kt)|[day20.py](py/aoc2023/day20.py)|[day20.rs](rs/src/day20.rs)|
|[Day21.hs](hs/src/Day21.hs)|[Day21.kt](kt/aoc2023-lib/src/commonMain/kotlin/com/github/ephemient/aoc2023/Day21.kt)|[day21.py](py/aoc2023/day21.py)|[day21.rs](rs/src/day21.rs)|
|[Day22.hs](hs/src/Day22.hs)|[Day22.kt](kt/aoc2023-lib/src/commonMain/kotlin/com/github/ephemient/aoc2023/Day22.kt)|[day22.py](py/aoc2023/day22.py)|[day22.rs](rs/src/day22.rs)|
||[Day23.kt](kt/aoc2023-lib/src/commonMain/kotlin/com/github/ephemient/aoc2023/Day23.kt)|||
||[Day23.kt](kt/aoc2023-lib/src/commonMain/kotlin/com/github/ephemient/aoc2023/Day23.kt)||[day23.rs](rs/src/day23.rs) ½|
|[Day24.hs](hs/src/Day24.hs) ½|[Day24.kt](kt/aoc2023-lib/src/commonMain/kotlin/com/github/ephemient/aoc2023/Day24.kt) ½|[day24.py](py/aoc2023/day24.py) ½|[day24.rs](rs/src/day24.rs) ½|
7 changes: 6 additions & 1 deletion rs/benches/criterion.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use aoc2023::{
day1, day10, day11, day12, day13, day14, day15, day16, day17, day18, day19, day2, day20, day21,
day22, day24, day3, day4, day5, day6, day7, day8, day9,
day22, day23, day24, day3, day4, day5, day6, day7, day8, day9,
};
use criterion::{black_box, Criterion};
use std::env;
Expand Down Expand Up @@ -149,6 +149,11 @@ fn aoc2023_bench(c: &mut Criterion) -> io::Result<()> {
g.bench_function("part 2", |b| b.iter(|| day22::part2(black_box(&data))));
g.finish();

let data = get_day_input(23)?;
let mut g = c.benchmark_group("day 23");
g.bench_function("part 1", |b| b.iter(|| day23::part1(black_box(&data))));
g.finish();

let data = get_day_input(24)?;
let mut g = c.benchmark_group("day 24");
g.bench_function("part 1", |b| b.iter(|| day24::part1(black_box(&data))));
Expand Down
106 changes: 106 additions & 0 deletions rs/src/day23.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
use std::collections::{BTreeMap, BTreeSet};

pub fn part1(data: &str) -> Option<usize> {
let grid = data.lines().map(|line| line.as_bytes()).collect::<Vec<_>>();
let graph = grid
.iter()
.enumerate()
.flat_map(|(y, row)| {
let grid = &grid;
row.iter().enumerate().filter_map(move |(x, c)| {
if [b'.', b'<', b'>', b'^', b'v'].contains(c) {
let mut edges = BTreeMap::new();
if b".<".contains(c) && x > 0 && b".<".contains(&row[x - 1]) {
edges.insert((y, x - 1), 1);
}
if b".>".contains(c) && x + 1 < row.len() && b".>".contains(&row[x + 1]) {
edges.insert((y, x + 1), 1);
}
if b".^".contains(c) && y > 0 {
let row = grid[y - 1];
if x < row.len() && b".^".contains(&row[x]) {
edges.insert((y - 1, x), 1);
}
}
if b".v".contains(c) && y + 1 < grid.len() {
let row = grid[y + 1];
if x < row.len() && b".v".contains(&row[x]) {
edges.insert((y + 1, x), 1);
}
}
Some(((y, x), edges))
} else {
None
}
})
})
.collect::<BTreeMap<_, _>>();
let start = *graph.keys().next()?;
let end = *graph.keys().next_back()?;

let mut stack = vec![(start, BTreeSet::from([start]), 0)];
let mut best = None::<usize>;
while let Some((node, used, distance)) = stack.pop() {
if node == end {
best = Some(best.map_or(distance, |best| best.max(distance)));
}
let Some(edges) = graph.get(&node) else {
continue;
};
for (next, weight) in edges {
let mut used = used.clone();
if used.insert(*next) {
stack.push((*next, used, distance + weight));
}
}
}

best
}

pub fn part2(data: &str) -> Option<usize> {
part1(&data.replace(|c| "<>^v".contains(c), "."))
}

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

static EXAMPLE: &str = indoc! {"
#.#####################
#.......#########...###
#######.#########.#.###
###.....#.>.>.###.#.###
###v#####.#v#.###.#.###
###.>...#.#.#.....#...#
###v###.#.#.#########.#
###...#.#.#.......#...#
#####.#.#.#######.#.###
#.....#.#.#.......#...#
#.#####.#.#.#########v#
#.#...#...#...###...>.#
#.#.#v#######v###.###v#
#...#.>.#...>.>.#.###.#
#####v#.#.###v#.#.###.#
#.....#...#...#.#.#...#
#.#########.###.#.#.###
#...###...#...#...#.###
###.###.#.###v#####v###
#...#...#.#.>.>.#.>.###
#.###.###.#.###.#.#v###
#.....###...###...#...#
#####################.#
"};

#[test]
fn part1_examples() {
assert_eq!(Some(94), part1(EXAMPLE));
}

#[test]
fn part2_examples() {
assert_eq!(Some(154), part2(EXAMPLE));
}
}
1 change: 1 addition & 0 deletions rs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub mod day2;
pub mod day20;
pub mod day21;
pub mod day22;
pub mod day23;
pub mod day24;
pub mod day3;
pub mod day4;
Expand Down
9 changes: 8 additions & 1 deletion rs/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use aoc2023::{
day1, day10, day11, day12, day13, day14, day15, day16, day17, day18, day19, day2, day20, day21,
day22, day24, day3, day4, day5, day6, day7, day8, day9,
day22, day23, day24, day3, day4, day5, day6, day7, day8, day9,
};
use std::collections::HashSet;
use std::env;
Expand Down Expand Up @@ -195,6 +195,13 @@ fn main() -> io::Result<()> {
println!();
}

if args.is_empty() || args.contains("23") {
println!("Day 23");
let data = get_day_input(23)?;
println!("{:?}", day23::part1(&data).expect("error"));
println!();
}

if args.is_empty() || args.contains("24") {
println!("Day 24");
let data = get_day_input(24)?;
Expand Down

0 comments on commit 8d2b1e1

Please sign in to comment.