grid: improve ergonomics with more trait impls and other improvements
update puzzles to pass tests, some performance gains
This commit is contained in:
18
src/day10.rs
18
src/day10.rs
@ -1,19 +1,19 @@
|
||||
use aoc_runner_derive::{aoc, aoc_generator};
|
||||
use grid::Grid;
|
||||
use itertools::Itertools;
|
||||
use std::io::{BufRead, Lines};
|
||||
use std::io::BufRead;
|
||||
|
||||
#[aoc_generator(day10)]
|
||||
pub fn get_input(input: &[u8]) -> TrailMap {
|
||||
TrailMap::from(input.lines())
|
||||
TrailMap::from(input)
|
||||
}
|
||||
|
||||
pub struct TrailMap {
|
||||
map: Grid<u8>,
|
||||
}
|
||||
|
||||
impl<T: BufRead> From<Lines<T>> for TrailMap {
|
||||
fn from(input: Lines<T>) -> Self {
|
||||
impl<T: BufRead> From<T> for TrailMap {
|
||||
fn from(input: T) -> Self {
|
||||
Self { map: input.into() }
|
||||
}
|
||||
}
|
||||
@ -29,13 +29,13 @@ impl TrailMap {
|
||||
.collect_vec()
|
||||
}
|
||||
fn count_reachable_from(&self, pos: &(i64, i64), needle: u8, visited: &mut Grid<bool>) -> u64 {
|
||||
if visited.get(pos) == Some(true) {
|
||||
if visited.get(pos) == Some(&true) {
|
||||
return 0;
|
||||
} else {
|
||||
visited.set(pos, true);
|
||||
}
|
||||
let our_val = self.map.get(pos).unwrap();
|
||||
if our_val == needle {
|
||||
if *our_val == needle {
|
||||
return 1;
|
||||
}
|
||||
// adjacents that are +1
|
||||
@ -43,7 +43,7 @@ impl TrailMap {
|
||||
.iter()
|
||||
.map(|(x_ofs, y_ofs)| (pos.0 + x_ofs, pos.1 + y_ofs)) // get target 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
|
||||
.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))
|
||||
.sum()
|
||||
@ -51,14 +51,14 @@ impl TrailMap {
|
||||
|
||||
fn count_paths_to(&self, pos: &(i64, i64), needle: u8) -> u64 {
|
||||
let our_val = self.map.get(pos).unwrap();
|
||||
if our_val == needle {
|
||||
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(|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
|
||||
.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))
|
||||
.sum::<u64>()
|
||||
|
14
src/day12.rs
14
src/day12.rs
@ -1,5 +1,3 @@
|
||||
use std::io::BufRead;
|
||||
|
||||
use aoc_runner_derive::{aoc, aoc_generator};
|
||||
use grid::{Coord2d, Grid};
|
||||
|
||||
@ -10,7 +8,7 @@ pub struct Farm {
|
||||
impl From<&[u8]> for Farm {
|
||||
fn from(input: &[u8]) -> Self {
|
||||
Self {
|
||||
map: Grid::from(input.lines()),
|
||||
map: Grid::from(input),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -27,9 +25,9 @@ impl Farm {
|
||||
.fold((1, 0), |(area, perimeter), adj| {
|
||||
match self.map.get(adj) {
|
||||
Some(plant) if plant == our_plant => {
|
||||
if visited.get(adj) == Some(false) {
|
||||
if visited.get(adj) == Some(&false) {
|
||||
// add the perimeter of the growth from there if not visited yet
|
||||
let (add_area, add_perimeter) = self.compute_region(&adj, visited);
|
||||
let (add_area, add_perimeter) = self.compute_region(adj, visited);
|
||||
(area + add_area, perimeter + add_perimeter)
|
||||
} else {
|
||||
(area, perimeter)
|
||||
@ -99,9 +97,9 @@ impl Farm {
|
||||
.fold((1, self.count_corners(pos)), |(area, corners), adj| {
|
||||
match self.map.get(adj) {
|
||||
Some(plant) if plant == our_plant => {
|
||||
if visited.get(adj) == Some(false) {
|
||||
if visited.get(adj) == Some(&false) {
|
||||
// add the perimeter of the growth from there if not visited yet
|
||||
let (n_area, n_corners) = self.region_corners(&adj, visited);
|
||||
let (n_area, n_corners) = self.region_corners(adj, visited);
|
||||
(area+n_area, corners+n_corners)
|
||||
} else { (area, corners) }
|
||||
}
|
||||
@ -110,7 +108,7 @@ impl Farm {
|
||||
})
|
||||
}
|
||||
fn regions_discount_cost(&self) -> u64 {
|
||||
let mut visited = Grid::with_shape(self.map.width(), self.map.height(), false);
|
||||
let mut visited = self.map.same_shape(false);
|
||||
let mut cost = 0;
|
||||
for y in 0..self.map.height() {
|
||||
for x in 0..self.map.width() {
|
||||
|
12
src/day6.rs
12
src/day6.rs
@ -3,14 +3,14 @@ use bitflags::bitflags;
|
||||
use rayon::iter::ParallelIterator;
|
||||
use rayon::slice::ParallelSlice;
|
||||
use std::fmt;
|
||||
use std::io::{BufRead, Lines};
|
||||
use std::io::BufRead;
|
||||
use std::ops::BitAnd;
|
||||
|
||||
use grid::Grid;
|
||||
|
||||
#[aoc_generator(day6)]
|
||||
pub fn get_input(input: &[u8]) -> Map {
|
||||
Map::from(input.lines())
|
||||
Map::from(input)
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
@ -96,8 +96,8 @@ pub struct Map {
|
||||
path: Vec<((i64, i64), FacingDirection)>,
|
||||
}
|
||||
|
||||
impl<T: BufRead> From<Lines<T>> for Map {
|
||||
fn from(input: Lines<T>) -> Self {
|
||||
impl<T: BufRead> From<T> for Map {
|
||||
fn from(input: T) -> Self {
|
||||
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());
|
||||
@ -114,7 +114,7 @@ impl<T: BufRead> From<Lines<T>> for Map {
|
||||
}
|
||||
|
||||
impl Map {
|
||||
fn look(&self, dir: &FacingDirection) -> Option<u8> {
|
||||
fn look(&self, dir: &FacingDirection) -> Option<&u8> {
|
||||
self.grid.get(&dir.pos_ofs(self.guard_pos))
|
||||
}
|
||||
/// Move one step in the facing direction, return if we are still inside the bounds
|
||||
@ -132,7 +132,7 @@ impl Map {
|
||||
}
|
||||
self.visited_from.set(
|
||||
&new_pos,
|
||||
self.visited_from.get(&new_pos).unwrap() | self.guard_facing.into(),
|
||||
*self.visited_from.get(&new_pos).unwrap() | self.guard_facing.into(),
|
||||
);
|
||||
self.guard_pos = new_pos;
|
||||
StepOutcome::Continue
|
||||
|
@ -2,19 +2,19 @@ use aoc_runner_derive::{aoc, aoc_generator};
|
||||
use grid::Grid;
|
||||
use itertools::Itertools;
|
||||
use std::collections::HashSet;
|
||||
use std::io::{BufRead, Lines};
|
||||
use std::io::BufRead;
|
||||
|
||||
#[aoc_generator(day8)]
|
||||
pub fn get_input(input: &[u8]) -> AntennaMap {
|
||||
AntennaMap::from(input.lines())
|
||||
AntennaMap::from(input)
|
||||
}
|
||||
|
||||
pub struct AntennaMap {
|
||||
map: Grid<u8>,
|
||||
}
|
||||
|
||||
impl<T: BufRead> From<Lines<T>> for AntennaMap {
|
||||
fn from(input: Lines<T>) -> Self {
|
||||
impl<T: BufRead> From<T> for AntennaMap {
|
||||
fn from(input: T) -> Self {
|
||||
Self { map: Grid::from(input) }
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user