multiple: genericize Grid over coordinate type, parallelism for day 11
This commit is contained in:
12
src/day10.rs
12
src/day10.rs
@ -29,12 +29,12 @@ impl TrailMap {
|
||||
.collect_vec()
|
||||
}
|
||||
fn count_reachable_from(&self, pos: &(i64, i64), needle: u8, visited: &mut Grid<bool>) -> u64 {
|
||||
if visited.get(pos.0, pos.1) == Some(true) {
|
||||
if visited.get(pos) == Some(true) {
|
||||
return 0;
|
||||
} else {
|
||||
visited.set(pos.0, pos.1, true);
|
||||
visited.set(pos, true);
|
||||
}
|
||||
let our_val = self.map.get(pos.0, pos.1).unwrap();
|
||||
let our_val = self.map.get(pos).unwrap();
|
||||
if our_val == needle {
|
||||
return 1;
|
||||
}
|
||||
@ -42,7 +42,7 @@ impl TrailMap {
|
||||
[(-1, 0), (1, 0), (0, -1), (0, 1)] // left, right, up, down
|
||||
.iter()
|
||||
.map(|(x_ofs, y_ofs)| (pos.0 + x_ofs, pos.1 + y_ofs)) // get target position
|
||||
.map(|(x, y)| ((x, y), self.map.get(x, y))) // get value at that position
|
||||
.map(|target_pos| (target_pos, self.map.get(&target_pos))) // get value at that position
|
||||
.filter(|(_, val)| *val == Some(our_val + 1)) // only interested if it's our value + 1
|
||||
.map(|(pos, _)| pos) // discard the value
|
||||
.map(|pos| self.count_reachable_from(&pos, needle, visited))
|
||||
@ -50,14 +50,14 @@ impl TrailMap {
|
||||
}
|
||||
|
||||
fn count_paths_to(&self, pos: &(i64, i64), needle: u8) -> u64 {
|
||||
let our_val = self.map.get(pos.0, pos.1).unwrap();
|
||||
let our_val = self.map.get(pos).unwrap();
|
||||
if our_val == needle {
|
||||
return 1;
|
||||
}
|
||||
[(-1, 0), (1, 0), (0, -1), (0, 1)] // left, right, up, down
|
||||
.iter()
|
||||
.map(|(x_ofs, y_ofs)| (pos.0 + x_ofs, pos.1 + y_ofs)) // get target position
|
||||
.map(|(x, y)| ((x, y), self.map.get(x, y))) // get value at that position
|
||||
.map(|target_pos| (target_pos, self.map.get(&target_pos))) // get value at that position
|
||||
.filter(|(_, val)| *val == Some(our_val + 1)) // only interested if it's our value + 1
|
||||
.map(|(pos, _)| pos) // discard the value
|
||||
.map(|mov| self.count_paths_to(&mov, needle))
|
||||
|
61
src/day6.rs
61
src/day6.rs
@ -1,5 +1,7 @@
|
||||
use aoc_runner_derive::{aoc, aoc_generator};
|
||||
use bitflags::bitflags;
|
||||
use rayon::iter::ParallelIterator;
|
||||
use rayon::slice::ParallelSlice;
|
||||
use std::fmt;
|
||||
use std::io::{BufRead, Lines};
|
||||
use std::ops::BitAnd;
|
||||
@ -14,10 +16,10 @@ pub fn get_input(input: &[u8]) -> Map {
|
||||
#[repr(u8)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
enum FacingDirection {
|
||||
Up = b'^',
|
||||
Down = b'v',
|
||||
Left = b'<',
|
||||
Right = b'>',
|
||||
Up = 1,
|
||||
Down = 2,
|
||||
Left = 4,
|
||||
Right = 8,
|
||||
}
|
||||
|
||||
impl FacingDirection {
|
||||
@ -45,6 +47,7 @@ enum StepOutcome {
|
||||
Continue,
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq)]
|
||||
enum RunOutcome {
|
||||
LeftMap,
|
||||
LoopFound,
|
||||
@ -98,7 +101,7 @@ impl<T: BufRead> From<Lines<T>> for Map {
|
||||
let grid = Grid::from(input);
|
||||
let mut visited_from: Grid<DirectionSet> = Grid::new(grid.width() as i64);
|
||||
visited_from.data.resize(grid.data.len(), DirectionSet::empty());
|
||||
let guard_pos = grid.find(b'^').expect("Guard not found");
|
||||
let guard_pos = grid.find(&b'^').expect("Guard not found");
|
||||
let guard_facing = FacingDirection::Up;
|
||||
Self {
|
||||
grid,
|
||||
@ -112,31 +115,24 @@ impl<T: BufRead> From<Lines<T>> for Map {
|
||||
|
||||
impl Map {
|
||||
fn look(&self, dir: &FacingDirection) -> Option<u8> {
|
||||
match dir {
|
||||
FacingDirection::Up => self.grid.get(self.guard_pos.0, self.guard_pos.1 - 1),
|
||||
FacingDirection::Down => self.grid.get(self.guard_pos.0, self.guard_pos.1 + 1),
|
||||
FacingDirection::Left => self.grid.get(self.guard_pos.0 - 1, self.guard_pos.1),
|
||||
FacingDirection::Right => self.grid.get(self.guard_pos.0 + 1, self.guard_pos.1),
|
||||
}
|
||||
self.grid.get(&dir.pos_ofs(self.guard_pos))
|
||||
}
|
||||
/// Move one step in the facing direction, return if we are still inside the bounds
|
||||
fn step_guard<const RECORD_PATH: bool>(&mut self) -> StepOutcome {
|
||||
let new_pos = self.guard_facing.pos_ofs(self.guard_pos);
|
||||
if self
|
||||
.visited_from
|
||||
.get(new_pos.0, new_pos.1)
|
||||
.get(&new_pos)
|
||||
.is_some_and(|dirs| dirs.contains(self.guard_facing.into()))
|
||||
{
|
||||
return StepOutcome::LoopFound;
|
||||
}
|
||||
if self.grid.set(new_pos.0, new_pos.1, b'X') {
|
||||
StepOutcome::LoopFound
|
||||
} else if self.grid.set(&new_pos, b'X').is_some() {
|
||||
if RECORD_PATH {
|
||||
self.path.push((new_pos, self.guard_facing));
|
||||
}
|
||||
self.visited_from.set(
|
||||
new_pos.0,
|
||||
new_pos.1,
|
||||
self.visited_from.get(new_pos.0, new_pos.1).unwrap() | self.guard_facing.into(),
|
||||
&new_pos,
|
||||
self.visited_from.get(&new_pos).unwrap() | self.guard_facing.into(),
|
||||
);
|
||||
self.guard_pos = new_pos;
|
||||
StepOutcome::Continue
|
||||
@ -168,7 +164,7 @@ pub fn part1(map: &Map) -> u64 {
|
||||
let mut map = map.clone();
|
||||
map.run_guard::<false>();
|
||||
|
||||
(map.grid.count(b'X') + map.grid.count(b'-') + map.grid.count(b'|') + map.grid.count(b'^')) as u64
|
||||
map.grid.count(&b'X') as u64 + 1 // 'X' path positions + 1 starting position
|
||||
}
|
||||
|
||||
// PROBLEM 2 solution
|
||||
@ -178,28 +174,19 @@ pub fn part2(input_map: &Map) -> u64 {
|
||||
let mut path_map = input_map.clone();
|
||||
path_map.run_guard::<true>();
|
||||
|
||||
let mut tested_position: grid::Grid<bool> = grid::Grid::new(path_map.grid.width() as i64);
|
||||
tested_position.data.resize(path_map.grid.data.len(), false);
|
||||
|
||||
let mut loop_count = 0u64;
|
||||
let mut last_posdir = (input_map.guard_pos, input_map.guard_facing);
|
||||
|
||||
for ((x, y), dir) in path_map.path.iter() {
|
||||
if !tested_position.get(*x, *y).unwrap() {
|
||||
tested_position.set(*x, *y, true);
|
||||
path_map
|
||||
.path
|
||||
.par_windows(2)
|
||||
.filter(|prev_cur| {
|
||||
let last_posdir = prev_cur[0];
|
||||
let mut test_map = input_map.clone();
|
||||
test_map.grid.set(*x, *y, b'#');
|
||||
test_map.grid.set(&prev_cur[1].0, b'#').unwrap();
|
||||
test_map.guard_pos = last_posdir.0;
|
||||
test_map.guard_facing = last_posdir.1;
|
||||
|
||||
if let RunOutcome::LoopFound = test_map.run_guard::<false>() {
|
||||
loop_count += 1
|
||||
}
|
||||
last_posdir = ((*x, *y), *dir);
|
||||
}
|
||||
}
|
||||
|
||||
loop_count
|
||||
test_map.run_guard::<false>() == RunOutcome::LoopFound
|
||||
})
|
||||
.count() as u64
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -43,7 +43,7 @@ impl AntennaMap {
|
||||
let offset = (a.0 - b.0, a.1 - b.1);
|
||||
for i in (start..).map_while(|i| if Some(i - start) != reps { Some(i as i64) } else { None }) {
|
||||
let node_pos = (a.0 + i * offset.0, a.1 + i * offset.1);
|
||||
if !antinodes.set(node_pos.0, node_pos.1, true) {
|
||||
if antinodes.set(&node_pos, true).is_none() {
|
||||
// left the grid
|
||||
break;
|
||||
}
|
||||
@ -58,14 +58,14 @@ impl AntennaMap {
|
||||
#[aoc(day8, part1)]
|
||||
pub fn part1(map: &AntennaMap) -> u64 {
|
||||
let antinodes = map.find_antinodes(1, Some(1));
|
||||
antinodes.count(true) as u64
|
||||
antinodes.count(&true) as u64
|
||||
}
|
||||
|
||||
// PROBLEM 2 solution
|
||||
#[aoc(day8, part2)]
|
||||
pub fn part2(map: &AntennaMap) -> u64 {
|
||||
let antinodes = map.find_antinodes(0, None);
|
||||
antinodes.count(true) as u64
|
||||
antinodes.count(&true) as u64
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
Reference in New Issue
Block a user