Skip to content

Commit

Permalink
Merge pull request #55 from ephemient/rs/day6
Browse files Browse the repository at this point in the history
  • Loading branch information
ephemient authored Dec 6, 2024
2 parents d36204f + ccd394b commit 004fc0b
Show file tree
Hide file tree
Showing 7 changed files with 176 additions and 3 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ Development occurs in language-specific directories:
|[Day3.hs](hs/src/Day3.hs)|[Day3.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day3.kt)|[day3.py](py/aoc2024/day3.py)|[day3.rs](rs/src/day3.rs)|
|[Day4.hs](hs/src/Day4.hs)|[Day4.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day4.kt)|[day4.py](py/aoc2024/day4.py)|[day4.rs](rs/src/day4.rs)|
|[Day5.hs](hs/src/Day5.hs)|[Day5.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day5.kt)|[day5.py](py/aoc2024/day5.py)|[day5.rs](rs/src/day5.rs)|
|[Day6.hs](hs/src/Day6.hs)|[Day6.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day6.kt)|[day6.py](py/aoc2024/day6.py)||
|[Day6.hs](hs/src/Day6.hs)|[Day6.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day6.kt)|[day6.py](py/aoc2024/day6.py)|[day6.rs](rs/src/day6.rs)|
8 changes: 8 additions & 0 deletions rs/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ path = "src/main.rs"
[dependencies]
anyhow = "1.0"
array-util = "1"
if_chain = "1"
itertools = "0.13"
thiserror = "2"
rayon = "1.10"

[dev-dependencies]
criterion = "0.5.1"
Expand Down
8 changes: 7 additions & 1 deletion rs/benches/criterion.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use aoc2024::{day1, day2, day3, day4, day5};
use aoc2024::{day1, day2, day3, day4, day5, day6};
use criterion::{black_box, Criterion};
use std::env;
use std::fs;
Expand Down Expand Up @@ -44,6 +44,12 @@ fn aoc2024_bench(c: &mut Criterion) -> io::Result<()> {
g.bench_function("part 2", |b| b.iter(|| day5::part2(black_box(&data))));
g.finish();

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

Ok(())
}

Expand Down
147 changes: 147 additions & 0 deletions rs/src/day6.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
use if_chain::if_chain;
use rayon::iter::{IntoParallelIterator, ParallelIterator};
use std::collections::BTreeSet;
use std::str::FromStr;

#[derive(Clone, Debug)]
struct Data {
initial_pos: (usize, usize),
max_bounds: (usize, usize),
obstacles: BTreeSet<(usize, usize)>,
}

impl FromStr for Data {
type Err = ();

fn from_str(value: &str) -> Result<Self, Self::Err> {
let mut initial_pos = None;
let mut max_bounds = (0, 0);
let mut obstacles = BTreeSet::new();
for (y, line) in value.lines().enumerate() {
max_bounds = (y + 1, max_bounds.1.max(line.len()));
for (x, b) in line.bytes().enumerate() {
match b {
b'^' => match initial_pos {
None => initial_pos = Some((y, x)),
Some(_) => return Err(()),
},
b'#' => {
obstacles.insert((y, x));
}
_ => {}
}
}
}
Ok(Data {
initial_pos: initial_pos.ok_or(())?,
max_bounds,
obstacles,
})
}
}

#[derive(Clone)]
struct Visitor<'a> {
state: Option<((usize, usize), (isize, isize))>,
max_bounds: (usize, usize),
obstacles: &'a BTreeSet<(usize, usize)>,
}

impl Iterator for Visitor<'_> {
type Item = ((usize, usize), (isize, isize));

fn next(&mut self) -> Option<Self::Item> {
match &mut self.state {
Some((pos, dir)) => {
let state = (*pos, *dir);
if_chain! {
if let Some(y) = pos.0.checked_add_signed(dir.0);
if y < self.max_bounds.0;
if let Some(x) = pos.1.checked_add_signed(dir.1);
if x < self.max_bounds.1;
then {
if self.obstacles.contains(&(y, x)) {
*dir = (dir.1, -dir.0);
} else {
*pos = (y, x);
}
}
else {
self.state = None;
}
}
Some(state)
}
None => None,
}
}
}

impl Data {
fn iter(&self) -> Visitor {
Visitor {
state: Some((self.initial_pos, (-1, 0))),
max_bounds: self.max_bounds,
obstacles: &self.obstacles,
}
}
}

pub fn part1(data: &str) -> Option<usize> {
Some(
data.parse::<Data>()
.ok()?
.iter()
.map(|(pos, _)| pos)
.collect::<BTreeSet<_>>()
.len(),
)
}

pub fn part2(data: &str) -> Option<usize> {
let data = data.parse::<Data>().ok()?;
let mut candidates = data.iter().map(|(pos, _)| pos).collect::<BTreeSet<_>>();
candidates.remove(&data.initial_pos);
Some(
candidates
.into_par_iter()
.filter(|candidate| {
let mut data = data.clone();
assert!(data.obstacles.insert(*candidate));
let mut visited = BTreeSet::new();
let ok = data.iter().any(|state| !visited.insert(state));
ok
})
.count(),
)
}

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

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

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

#[test]
fn part2_examples() {
assert_eq!(Some(6), part2(EXAMPLE));
}
}
1 change: 1 addition & 0 deletions rs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ pub mod day2;
pub mod day3;
pub mod day4;
pub mod day5;
pub mod day6;
11 changes: 10 additions & 1 deletion rs/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use aoc2024::{day1, day2, day3, day4, day5};
use anyhow::anyhow;
use aoc2024::{day1, day2, day3, day4, day5, day6};
use std::collections::HashSet;
use std::env;
use std::fs;
Expand Down Expand Up @@ -56,5 +57,13 @@ fn main() -> anyhow::Result<()> {
println!();
}

if args.is_empty() || args.contains("6") {
println!("Day 6");
let data = get_day_input(6)?;
println!("{:?}", day6::part1(&data).ok_or(anyhow!("None"))?);
println!("{:?}", day6::part2(&data).ok_or(anyhow!("None"))?);
println!();
}

Ok(())
}

0 comments on commit 004fc0b

Please sign in to comment.