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()
 | 
					            .collect_vec()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    fn count_reachable_from(&self, pos: &(i64, i64), needle: u8, visited: &mut Grid<bool>) -> u64 {
 | 
					    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;
 | 
					            return 0;
 | 
				
			||||||
        } else {
 | 
					        } 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 {
 | 
					        if our_val == needle {
 | 
				
			||||||
            return 1;
 | 
					            return 1;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -42,7 +42,7 @@ impl TrailMap {
 | 
				
			|||||||
        [(-1, 0), (1, 0), (0, -1), (0, 1)] // left, right, up, down
 | 
					        [(-1, 0), (1, 0), (0, -1), (0, 1)] // left, right, up, down
 | 
				
			||||||
            .iter()
 | 
					            .iter()
 | 
				
			||||||
            .map(|(x_ofs, y_ofs)| (pos.0 + x_ofs, pos.1 + y_ofs)) // get target position
 | 
					            .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
 | 
					            .filter(|(_, val)| *val == Some(our_val + 1)) // only interested if it's our value + 1
 | 
				
			||||||
            .map(|(pos, _)| pos) // discard the value
 | 
					            .map(|(pos, _)| pos) // discard the value
 | 
				
			||||||
            .map(|pos| self.count_reachable_from(&pos, needle, visited))
 | 
					            .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 {
 | 
					    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 {
 | 
					        if our_val == needle {
 | 
				
			||||||
            return 1;
 | 
					            return 1;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        [(-1, 0), (1, 0), (0, -1), (0, 1)] // left, right, up, down
 | 
					        [(-1, 0), (1, 0), (0, -1), (0, 1)] // left, right, up, down
 | 
				
			||||||
            .iter()
 | 
					            .iter()
 | 
				
			||||||
            .map(|(x_ofs, y_ofs)| (pos.0 + x_ofs, pos.1 + y_ofs)) // get target position
 | 
					            .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
 | 
					            .filter(|(_, val)| *val == Some(our_val + 1)) // only interested if it's our value + 1
 | 
				
			||||||
            .map(|(pos, _)| pos) // discard the value
 | 
					            .map(|(pos, _)| pos) // discard the value
 | 
				
			||||||
            .map(|mov| self.count_paths_to(&mov, needle))
 | 
					            .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 aoc_runner_derive::{aoc, aoc_generator};
 | 
				
			||||||
use bitflags::bitflags;
 | 
					use bitflags::bitflags;
 | 
				
			||||||
 | 
					use rayon::iter::ParallelIterator;
 | 
				
			||||||
 | 
					use rayon::slice::ParallelSlice;
 | 
				
			||||||
use std::fmt;
 | 
					use std::fmt;
 | 
				
			||||||
use std::io::{BufRead, Lines};
 | 
					use std::io::{BufRead, Lines};
 | 
				
			||||||
use std::ops::BitAnd;
 | 
					use std::ops::BitAnd;
 | 
				
			||||||
@@ -14,10 +16,10 @@ pub fn get_input(input: &[u8]) -> Map {
 | 
				
			|||||||
#[repr(u8)]
 | 
					#[repr(u8)]
 | 
				
			||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
 | 
					#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
 | 
				
			||||||
enum FacingDirection {
 | 
					enum FacingDirection {
 | 
				
			||||||
    Up = b'^',
 | 
					    Up = 1,
 | 
				
			||||||
    Down = b'v',
 | 
					    Down = 2,
 | 
				
			||||||
    Left = b'<',
 | 
					    Left = 4,
 | 
				
			||||||
    Right = b'>',
 | 
					    Right = 8,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl FacingDirection {
 | 
					impl FacingDirection {
 | 
				
			||||||
@@ -45,6 +47,7 @@ enum StepOutcome {
 | 
				
			|||||||
    Continue,
 | 
					    Continue,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Eq, PartialEq)]
 | 
				
			||||||
enum RunOutcome {
 | 
					enum RunOutcome {
 | 
				
			||||||
    LeftMap,
 | 
					    LeftMap,
 | 
				
			||||||
    LoopFound,
 | 
					    LoopFound,
 | 
				
			||||||
@@ -98,7 +101,7 @@ impl<T: BufRead> From<Lines<T>> for Map {
 | 
				
			|||||||
        let grid = Grid::from(input);
 | 
					        let grid = Grid::from(input);
 | 
				
			||||||
        let mut visited_from: Grid<DirectionSet> = Grid::new(grid.width() as i64);
 | 
					        let mut visited_from: Grid<DirectionSet> = Grid::new(grid.width() as i64);
 | 
				
			||||||
        visited_from.data.resize(grid.data.len(), DirectionSet::empty());
 | 
					        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;
 | 
					        let guard_facing = FacingDirection::Up;
 | 
				
			||||||
        Self {
 | 
					        Self {
 | 
				
			||||||
            grid,
 | 
					            grid,
 | 
				
			||||||
@@ -112,31 +115,24 @@ impl<T: BufRead> From<Lines<T>> for Map {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
impl Map {
 | 
					impl Map {
 | 
				
			||||||
    fn look(&self, dir: &FacingDirection) -> Option<u8> {
 | 
					    fn look(&self, dir: &FacingDirection) -> Option<u8> {
 | 
				
			||||||
        match dir {
 | 
					        self.grid.get(&dir.pos_ofs(self.guard_pos))
 | 
				
			||||||
            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),
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    /// Move one step in the facing direction, return if we are still inside the bounds
 | 
					    /// 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 {
 | 
					    fn step_guard<const RECORD_PATH: bool>(&mut self) -> StepOutcome {
 | 
				
			||||||
        let new_pos = self.guard_facing.pos_ofs(self.guard_pos);
 | 
					        let new_pos = self.guard_facing.pos_ofs(self.guard_pos);
 | 
				
			||||||
        if self
 | 
					        if self
 | 
				
			||||||
            .visited_from
 | 
					            .visited_from
 | 
				
			||||||
            .get(new_pos.0, new_pos.1)
 | 
					            .get(&new_pos)
 | 
				
			||||||
            .is_some_and(|dirs| dirs.contains(self.guard_facing.into()))
 | 
					            .is_some_and(|dirs| dirs.contains(self.guard_facing.into()))
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return StepOutcome::LoopFound;
 | 
					            StepOutcome::LoopFound
 | 
				
			||||||
        }
 | 
					        } else if self.grid.set(&new_pos, b'X').is_some() {
 | 
				
			||||||
        if self.grid.set(new_pos.0, new_pos.1, b'X') {
 | 
					 | 
				
			||||||
            if RECORD_PATH {
 | 
					            if RECORD_PATH {
 | 
				
			||||||
                self.path.push((new_pos, self.guard_facing));
 | 
					                self.path.push((new_pos, self.guard_facing));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            self.visited_from.set(
 | 
					            self.visited_from.set(
 | 
				
			||||||
                new_pos.0,
 | 
					                &new_pos,
 | 
				
			||||||
                new_pos.1,
 | 
					                self.visited_from.get(&new_pos).unwrap() | self.guard_facing.into(),
 | 
				
			||||||
                self.visited_from.get(new_pos.0, new_pos.1).unwrap() | self.guard_facing.into(),
 | 
					 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
            self.guard_pos = new_pos;
 | 
					            self.guard_pos = new_pos;
 | 
				
			||||||
            StepOutcome::Continue
 | 
					            StepOutcome::Continue
 | 
				
			||||||
@@ -168,7 +164,7 @@ pub fn part1(map: &Map) -> u64 {
 | 
				
			|||||||
    let mut map = map.clone();
 | 
					    let mut map = map.clone();
 | 
				
			||||||
    map.run_guard::<false>();
 | 
					    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
 | 
					// PROBLEM 2 solution
 | 
				
			||||||
@@ -178,28 +174,19 @@ pub fn part2(input_map: &Map) -> u64 {
 | 
				
			|||||||
    let mut path_map = input_map.clone();
 | 
					    let mut path_map = input_map.clone();
 | 
				
			||||||
    path_map.run_guard::<true>();
 | 
					    path_map.run_guard::<true>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let mut tested_position: grid::Grid<bool> = grid::Grid::new(path_map.grid.width() as i64);
 | 
					    path_map
 | 
				
			||||||
    tested_position.data.resize(path_map.grid.data.len(), false);
 | 
					        .path
 | 
				
			||||||
 | 
					        .par_windows(2)
 | 
				
			||||||
    let mut loop_count = 0u64;
 | 
					        .filter(|prev_cur| {
 | 
				
			||||||
    let mut last_posdir = (input_map.guard_pos, input_map.guard_facing);
 | 
					            let last_posdir = prev_cur[0];
 | 
				
			||||||
 | 
					 | 
				
			||||||
    for ((x, y), dir) in path_map.path.iter() {
 | 
					 | 
				
			||||||
        if !tested_position.get(*x, *y).unwrap() {
 | 
					 | 
				
			||||||
            tested_position.set(*x, *y, true);
 | 
					 | 
				
			||||||
            let mut test_map = input_map.clone();
 | 
					            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_pos = last_posdir.0;
 | 
				
			||||||
            test_map.guard_facing = last_posdir.1;
 | 
					            test_map.guard_facing = last_posdir.1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if let RunOutcome::LoopFound = test_map.run_guard::<false>() {
 | 
					            test_map.run_guard::<false>() == RunOutcome::LoopFound
 | 
				
			||||||
                loop_count += 1
 | 
					        })
 | 
				
			||||||
            }
 | 
					        .count() as u64
 | 
				
			||||||
            last_posdir = ((*x, *y), *dir);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    loop_count
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[cfg(test)]
 | 
					#[cfg(test)]
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -43,7 +43,7 @@ impl AntennaMap {
 | 
				
			|||||||
                let offset = (a.0 - b.0, a.1 - b.1);
 | 
					                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 }) {
 | 
					                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);
 | 
					                    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
 | 
					                        // left the grid
 | 
				
			||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
@@ -58,14 +58,14 @@ impl AntennaMap {
 | 
				
			|||||||
#[aoc(day8, part1)]
 | 
					#[aoc(day8, part1)]
 | 
				
			||||||
pub fn part1(map: &AntennaMap) -> u64 {
 | 
					pub fn part1(map: &AntennaMap) -> u64 {
 | 
				
			||||||
    let antinodes = map.find_antinodes(1, Some(1));
 | 
					    let antinodes = map.find_antinodes(1, Some(1));
 | 
				
			||||||
    antinodes.count(true) as u64
 | 
					    antinodes.count(&true) as u64
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// PROBLEM 2 solution
 | 
					// PROBLEM 2 solution
 | 
				
			||||||
#[aoc(day8, part2)]
 | 
					#[aoc(day8, part2)]
 | 
				
			||||||
pub fn part2(map: &AntennaMap) -> u64 {
 | 
					pub fn part2(map: &AntennaMap) -> u64 {
 | 
				
			||||||
    let antinodes = map.find_antinodes(0, None);
 | 
					    let antinodes = map.find_antinodes(0, None);
 | 
				
			||||||
    antinodes.count(true) as u64
 | 
					    antinodes.count(&true) as u64
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[cfg(test)]
 | 
					#[cfg(test)]
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,6 +4,42 @@ use std::{
 | 
				
			|||||||
    iter::repeat,
 | 
					    iter::repeat,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Clone)]
 | 
				
			||||||
 | 
					pub struct Coord2d {
 | 
				
			||||||
 | 
					    pub x: i64,
 | 
				
			||||||
 | 
					    pub y: i64,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub trait AsCoord2d {
 | 
				
			||||||
 | 
					    fn to_coord(self) -> Coord2d;
 | 
				
			||||||
 | 
					    fn x(&self) -> i64;
 | 
				
			||||||
 | 
					    fn y(&self) -> i64;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl AsCoord2d for Coord2d {
 | 
				
			||||||
 | 
					    fn to_coord(self) -> Coord2d {
 | 
				
			||||||
 | 
					        self
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    fn x(&self) -> i64 {
 | 
				
			||||||
 | 
					        self.x
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    fn y(&self) -> i64 {
 | 
				
			||||||
 | 
					        self.y
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl AsCoord2d for (i64, i64) {
 | 
				
			||||||
 | 
					    fn to_coord(self) -> Coord2d {
 | 
				
			||||||
 | 
					        Coord2d { x: self.0, y: self.1 }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    fn x(&self) -> i64 {
 | 
				
			||||||
 | 
					        self.0
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    fn y(&self) -> i64 {
 | 
				
			||||||
 | 
					        self.1
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Clone)]
 | 
					#[derive(Clone)]
 | 
				
			||||||
pub struct Grid<T> {
 | 
					pub struct Grid<T> {
 | 
				
			||||||
    pub data: Vec<T>,
 | 
					    pub data: Vec<T>,
 | 
				
			||||||
@@ -29,8 +65,8 @@ impl<T: Copy + Eq + PartialEq + Display + Debug> Grid<T> {
 | 
				
			|||||||
    pub fn height(&self) -> usize {
 | 
					    pub fn height(&self) -> usize {
 | 
				
			||||||
        return self.data.len() / self.width();
 | 
					        return self.data.len() / self.width();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    fn pos(&self, x: i64, y: i64) -> i64 {
 | 
					    fn pos<C: AsCoord2d>(&self, c: &C) -> i64 {
 | 
				
			||||||
        y * self.width + x
 | 
					        c.y() * self.width + c.x()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    pub fn coord(&self, pos: i64) -> Option<(i64, i64)> {
 | 
					    pub fn coord(&self, pos: i64) -> Option<(i64, i64)> {
 | 
				
			||||||
        if pos < 0 || pos >= self.data.len() as i64 {
 | 
					        if pos < 0 || pos >= self.data.len() as i64 {
 | 
				
			||||||
@@ -39,57 +75,58 @@ impl<T: Copy + Eq + PartialEq + Display + Debug> Grid<T> {
 | 
				
			|||||||
            Some((pos % self.width, pos / self.width))
 | 
					            Some((pos % self.width, pos / self.width))
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    fn valid_pos(&self, x: i64, y: i64) -> Option<usize> {
 | 
					    fn valid_pos<C: AsCoord2d>(&self, c: &C) -> Option<usize> {
 | 
				
			||||||
        if x < 0 || x >= self.width {
 | 
					        if c.x() < 0 || c.x() >= self.width {
 | 
				
			||||||
            return None;
 | 
					            return None;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if y < 0 || y >= self.data.len() as i64 / self.width {
 | 
					        if c.y() < 0 || c.y() >= self.data.len() as i64 / self.width {
 | 
				
			||||||
            return None;
 | 
					            return None;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        let pos = self.pos(x, y);
 | 
					        let pos = self.pos(c);
 | 
				
			||||||
        if pos < 0 || pos as usize >= self.data.len() {
 | 
					        if pos < 0 || pos as usize >= self.data.len() {
 | 
				
			||||||
            return None;
 | 
					            return None;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        self.pos(x, y).try_into().ok()
 | 
					        self.pos(c).try_into().ok()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    pub fn get(&self, x: i64, y: i64) -> Option<T> {
 | 
					    pub fn get<C: AsCoord2d>(&self, c: &C) -> Option<T> {
 | 
				
			||||||
        match self.valid_pos(x, y) {
 | 
					        match self.valid_pos(c) {
 | 
				
			||||||
            Some(pos) => Some(self.data[pos]),
 | 
					            Some(pos) => Some(self.data[pos]),
 | 
				
			||||||
            None => None,
 | 
					            None => None,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    pub fn set(&mut self, x: i64, y: i64, val: T) -> bool {
 | 
					    pub fn set<C: AsCoord2d>(&mut self, c: &C, val: T) -> Option<T> {
 | 
				
			||||||
        match self.valid_pos(x, y) {
 | 
					        match self.valid_pos(c) {
 | 
				
			||||||
            Some(pos) => {
 | 
					            Some(pos) => {
 | 
				
			||||||
 | 
					                let res = Some(self.data[pos]);
 | 
				
			||||||
                self.data[pos] = val;
 | 
					                self.data[pos] = val;
 | 
				
			||||||
                true
 | 
					                res
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            None => false,
 | 
					            None => None,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    pub fn row(&self, y: i64) -> Option<&[T]> {
 | 
					    pub fn row(&self, y: i64) -> Option<&[T]> {
 | 
				
			||||||
        if y < self.height() as i64 {
 | 
					        if y < self.height() as i64 {
 | 
				
			||||||
            Some(&self.data[self.pos(0, y) as usize..self.pos(self.width, y) as usize])
 | 
					            Some(&self.data[self.pos(&(0, y)) as usize..self.pos(&(self.width, y)) as usize])
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            None
 | 
					            None
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn find(&self, haystack: T) -> Option<(i64, i64)> {
 | 
					    pub fn find(&self, haystack: &T) -> Option<(i64, i64)> {
 | 
				
			||||||
        self.coord(
 | 
					        self.coord(
 | 
				
			||||||
            self.data
 | 
					            self.data
 | 
				
			||||||
                .iter()
 | 
					                .iter()
 | 
				
			||||||
                .enumerate()
 | 
					                .enumerate()
 | 
				
			||||||
                .find_map(|(pos, val)| if *val == haystack { Some(pos as i64) } else { None })
 | 
					                .find_map(|(pos, val)| if val == haystack { Some(pos as i64) } else { None })
 | 
				
			||||||
                .unwrap_or(-1),
 | 
					                .unwrap_or(-1),
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    pub fn count(&self, haystack: T) -> usize {
 | 
					    pub fn count(&self, haystack: &T) -> usize {
 | 
				
			||||||
        self.data.iter().filter(|item| **item == haystack).count()
 | 
					        self.data.iter().filter(|item| *item == haystack).count()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn forward_slice(&self, x: i64, y: i64, len: i64) -> Option<&[T]> {
 | 
					    pub fn forward_slice<C: AsCoord2d>(&self, start: &C, len: i64) -> Option<&[T]> {
 | 
				
			||||||
        let pos = (self.valid_pos(x, y), self.valid_pos(x + len - 1, y));
 | 
					        let pos = (self.valid_pos(start), self.valid_pos(&(start.x() + len - 1, start.y())));
 | 
				
			||||||
        match pos {
 | 
					        match pos {
 | 
				
			||||||
            (Some(pos1), Some(pos2)) => Some(&self.data[pos1..pos2 + 1]),
 | 
					            (Some(pos1), Some(pos2)) => Some(&self.data[pos1..pos2 + 1]),
 | 
				
			||||||
            _ => None,
 | 
					            _ => None,
 | 
				
			||||||
@@ -151,7 +188,7 @@ impl Display for Grid<u8> {
 | 
				
			|||||||
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
 | 
					    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
 | 
				
			||||||
        for y in 0..self.height() {
 | 
					        for y in 0..self.height() {
 | 
				
			||||||
            for x in 0..self.width() {
 | 
					            for x in 0..self.width() {
 | 
				
			||||||
                f.write_fmt(format_args!("{}",self.get(x as i64, y as i64).unwrap() as char))?;
 | 
					                f.write_fmt(format_args!("{}", self.get(&(x as i64, y as i64)).unwrap() as char))?;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            f.write_char('\n')?;
 | 
					            f.write_char('\n')?;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -181,21 +218,21 @@ FBCG";
 | 
				
			|||||||
    #[test]
 | 
					    #[test]
 | 
				
			||||||
    fn indexing() {
 | 
					    fn indexing() {
 | 
				
			||||||
        let grid = unchecked_load();
 | 
					        let grid = unchecked_load();
 | 
				
			||||||
        assert_eq!(grid.get(0, 0), Some(b'A'));
 | 
					        assert_eq!(grid.get(&(0, 0)), Some(b'A'));
 | 
				
			||||||
        assert_eq!(grid.get(3, 3), Some(b'G'));
 | 
					        assert_eq!(grid.get(&(3, 3)), Some(b'G'));
 | 
				
			||||||
        assert_eq!(grid.get(-1, 0), None);
 | 
					        assert_eq!(grid.get(&(-1, 0)), None);
 | 
				
			||||||
        assert_eq!(grid.get(0, -1), None);
 | 
					        assert_eq!(grid.get(&(0, -1)), None);
 | 
				
			||||||
        assert_eq!(grid.get(5, 0), None);
 | 
					        assert_eq!(grid.get(&(5, 0)), None);
 | 
				
			||||||
        assert_eq!(grid.get(0, 5), None);
 | 
					        assert_eq!(grid.get(&(0, 5)), None);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[test]
 | 
					    #[test]
 | 
				
			||||||
    fn forward_slice() {
 | 
					    fn forward_slice() {
 | 
				
			||||||
        let grid = unchecked_load();
 | 
					        let grid = unchecked_load();
 | 
				
			||||||
        assert_eq!(grid.forward_slice(0, 0, 2), Some(b"AB".as_slice()));
 | 
					        assert_eq!(grid.forward_slice(&(0, 0), 2), Some(b"AB".as_slice()));
 | 
				
			||||||
        assert_eq!(grid.forward_slice(2, 0, 2), Some(b"CD".as_slice()));
 | 
					        assert_eq!(grid.forward_slice(&(2, 0), 2), Some(b"CD".as_slice()));
 | 
				
			||||||
        assert_eq!(grid.forward_slice(2, 0, 3), None);
 | 
					        assert_eq!(grid.forward_slice(&(2, 0), 3), None);
 | 
				
			||||||
        assert_eq!(grid.forward_slice(0, 2, 4), Some(b"IJKL".as_slice()));
 | 
					        assert_eq!(grid.forward_slice(&(0, 2), 4), Some(b"IJKL".as_slice()));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[test]
 | 
					    #[test]
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user