parent
59f78b9069
commit
dc69aea676
@ -0,0 +1,13 @@ |
|||||||
|
[package] |
||||||
|
name = "day17" |
||||||
|
version = "0.1.0" |
||||||
|
authors = ["inga-lovinde <52715130+inga-lovinde@users.noreply.github.com>"] |
||||||
|
edition = "2018" |
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html |
||||||
|
|
||||||
|
[dependencies] |
||||||
|
enum-map = "0.6.4" |
||||||
|
ndarray = "0.14.0" |
||||||
|
strum = "0.20.0" |
||||||
|
strum_macros = "0.20.1" |
@ -0,0 +1,105 @@ |
|||||||
|
use enum_map::Enum; |
||||||
|
use strum_macros::EnumIter; |
||||||
|
|
||||||
|
#[derive(Clone, Copy, Enum, Eq, PartialEq)] |
||||||
|
pub enum State { |
||||||
|
Dead = 0, |
||||||
|
Alive = 1, |
||||||
|
} |
||||||
|
|
||||||
|
impl Default for State { |
||||||
|
fn default() -> Self { Self::Dead } |
||||||
|
} |
||||||
|
|
||||||
|
impl State { |
||||||
|
fn from_number(number: u8) -> Self { |
||||||
|
match number { |
||||||
|
0 => Self::Dead, |
||||||
|
1 => Self::Alive, |
||||||
|
_ => panic!("unsupported number {}", number), |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
fn get_number(&self) -> u8 { |
||||||
|
*self as u8 |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// terribly error-prone but I'm lazy :(
|
||||||
|
#[derive(Copy, Clone, Enum, EnumIter)] |
||||||
|
pub enum Direction { |
||||||
|
MinusMinusMinus = 0, |
||||||
|
MinusMinusSame = 1, |
||||||
|
MinusMinusPlus = 2, |
||||||
|
MinusSameMinus = 3, |
||||||
|
MinusSameSame = 4, |
||||||
|
MinusSamePlus = 5, |
||||||
|
MinusPlusMinus = 6, |
||||||
|
MinusPlusSame = 7, |
||||||
|
MinusPlusPlus = 8, |
||||||
|
SameMinusMinus = 9, |
||||||
|
SameMinusSame = 10, |
||||||
|
SameMinusPlus = 11, |
||||||
|
SameSameMinus = 12, |
||||||
|
SameSamePlus = 13, |
||||||
|
SamePlusMinus = 14, |
||||||
|
SamePlusSame = 15, |
||||||
|
SamePlusPlus = 16, |
||||||
|
PlusMinusMinus = 17, |
||||||
|
PlusMinusSame = 18, |
||||||
|
PlusMinusPlus = 19, |
||||||
|
PlusSameMinus = 20, |
||||||
|
PlusSameSame = 21, |
||||||
|
PlusSamePlus = 22, |
||||||
|
PlusPlusMinus = 23, |
||||||
|
PlusPlusSame = 24, |
||||||
|
PlusPlusPlus = 25, |
||||||
|
} |
||||||
|
|
||||||
|
impl Direction { |
||||||
|
fn get_offset(&self) -> u16 { |
||||||
|
*self as u16 |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
pub struct CellState { |
||||||
|
neighbours_states: u32, |
||||||
|
state: u8, |
||||||
|
} |
||||||
|
|
||||||
|
impl CellState { |
||||||
|
pub fn new() -> Self { |
||||||
|
Self { |
||||||
|
neighbours_states: 0, |
||||||
|
state: 0, |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
pub fn update_neighbour_state(&mut self, direction: Direction, new_state: State) -> () { |
||||||
|
self.neighbours_states = (self.neighbours_states & !(0b1 << direction.get_offset())) | ((new_state.get_number() as u32) << direction.get_offset()); |
||||||
|
} |
||||||
|
|
||||||
|
pub fn update_state(&mut self, new_state: State) { |
||||||
|
self.state = new_state.get_number(); |
||||||
|
} |
||||||
|
|
||||||
|
pub fn from_number(number: u32) -> Self { |
||||||
|
CellState { |
||||||
|
state: (number >> 26) as u8, |
||||||
|
neighbours_states: (number & 0x3ffffff) as u32, |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
pub fn get_number(&self) -> u32 { |
||||||
|
((self.state as u32) << 26) | (self.neighbours_states as u32) |
||||||
|
} |
||||||
|
|
||||||
|
pub fn get_state(&self) -> State { |
||||||
|
State::from_number(self.state) |
||||||
|
} |
||||||
|
|
||||||
|
pub fn get_neighbour_state(&self, direction: Direction) -> State { |
||||||
|
State::from_number(((self.neighbours_states >> direction.get_offset()) & 0b1) as u8) |
||||||
|
} |
||||||
|
} |
||||||
|
|
@ -0,0 +1,148 @@ |
|||||||
|
use std::default::Default; |
||||||
|
use std::ops::{Index, IndexMut}; |
||||||
|
use ndarray::Array3; |
||||||
|
|
||||||
|
use crate::binary::Direction; |
||||||
|
|
||||||
|
#[derive(Copy, Clone)] |
||||||
|
pub struct CellLocation { |
||||||
|
pub x: usize, |
||||||
|
pub y: usize, |
||||||
|
pub z: usize, |
||||||
|
} |
||||||
|
|
||||||
|
impl CellLocation { |
||||||
|
pub fn new(x: usize, y: usize, z: usize) -> Self { |
||||||
|
Self { |
||||||
|
x, |
||||||
|
y, |
||||||
|
z, |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
fn new_option(x_option: Option<usize>, y_option: Option<usize>, z_option: Option<usize>) -> Option<Self> { |
||||||
|
match (x_option, y_option, z_option) { |
||||||
|
(Some(x), Some(y), Some(z)) => Some(Self::new(x, y, z)), |
||||||
|
_ => None, |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl<T> Index<CellLocation> for Array3<T> { |
||||||
|
type Output = T; |
||||||
|
fn index<'a>(&'a self, cell_location: CellLocation) -> &'a T { |
||||||
|
&self[[cell_location.x, cell_location.y, cell_location.z]] |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl<T> IndexMut<CellLocation> for Array3<T> { |
||||||
|
fn index_mut<'a>(&'a mut self, cell_location: CellLocation) -> &'a mut T { |
||||||
|
&mut self[[cell_location.x, cell_location.y, cell_location.z]] |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
pub struct BoardMetadata { |
||||||
|
corner: CellLocation, |
||||||
|
} |
||||||
|
|
||||||
|
struct CellLocationWithBoardMetadata { |
||||||
|
corner: CellLocation, |
||||||
|
location: Option<CellLocation>, |
||||||
|
} |
||||||
|
|
||||||
|
impl CellLocationWithBoardMetadata { |
||||||
|
fn new(corner: CellLocation, location: Option<CellLocation>) -> CellLocationWithBoardMetadata { |
||||||
|
CellLocationWithBoardMetadata { |
||||||
|
corner, |
||||||
|
location, |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
fn get_x_minus(&self) -> CellLocationWithBoardMetadata { |
||||||
|
CellLocationWithBoardMetadata::new(self.corner, match self.location { |
||||||
|
Some(location) if location.x > 0 => Some(CellLocation { x: location.x-1, ..location }), |
||||||
|
_ => None |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
fn get_x_plus(&self) -> CellLocationWithBoardMetadata { |
||||||
|
CellLocationWithBoardMetadata::new(self.corner, match self.location { |
||||||
|
Some(location) if location.x < self.corner.x - 1 => Some(CellLocation { x: location.x+1, ..location }), |
||||||
|
_ => None |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
fn get_y_minus(&self) -> CellLocationWithBoardMetadata { |
||||||
|
CellLocationWithBoardMetadata::new(self.corner, match self.location { |
||||||
|
Some(location) if location.y > 0 => Some(CellLocation { y: location.y-1, ..location }), |
||||||
|
_ => None |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
fn get_y_plus(&self) -> CellLocationWithBoardMetadata { |
||||||
|
CellLocationWithBoardMetadata::new(self.corner, match self.location { |
||||||
|
Some(location) if location.y < self.corner.y - 1 => Some(CellLocation { y: location.y+1, ..location }), |
||||||
|
_ => None |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
fn get_z_minus(&self) -> CellLocationWithBoardMetadata { |
||||||
|
CellLocationWithBoardMetadata::new(self.corner, match self.location { |
||||||
|
Some(location) if location.z > 0 => Some(CellLocation { z: location.z-1, ..location }), |
||||||
|
_ => None |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
fn get_z_plus(&self) -> CellLocationWithBoardMetadata { |
||||||
|
CellLocationWithBoardMetadata::new(self.corner, match self.location { |
||||||
|
Some(location) if location.z < self.corner.z - 1 => Some(CellLocation { z: location.z+1, ..location }), |
||||||
|
_ => None |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl BoardMetadata { |
||||||
|
pub fn new(corner: CellLocation) -> Self { |
||||||
|
BoardMetadata { |
||||||
|
corner, |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
pub fn get_neighbour_location(&self, cell_location: CellLocation, direction: Direction) -> Option<CellLocation> { |
||||||
|
let cell_with_metadata = CellLocationWithBoardMetadata::new(self.corner, Some(cell_location)); |
||||||
|
|
||||||
|
// terribly error-prone but I'm lazy :(
|
||||||
|
match direction { |
||||||
|
Direction::MinusMinusMinus => cell_with_metadata.get_x_minus().get_y_minus().get_z_minus().location, |
||||||
|
Direction::MinusMinusSame => cell_with_metadata.get_x_minus().get_y_minus().location, |
||||||
|
Direction::MinusMinusPlus => cell_with_metadata.get_x_minus().get_y_minus().get_z_plus().location, |
||||||
|
Direction::MinusSameMinus => cell_with_metadata.get_x_minus().get_z_minus().location, |
||||||
|
Direction::MinusSameSame => cell_with_metadata.get_x_minus().location, |
||||||
|
Direction::MinusSamePlus => cell_with_metadata.get_x_minus().get_z_plus().location, |
||||||
|
Direction::MinusPlusMinus => cell_with_metadata.get_x_minus().get_y_plus().get_z_minus().location, |
||||||
|
Direction::MinusPlusSame => cell_with_metadata.get_x_minus().get_y_plus().location, |
||||||
|
Direction::MinusPlusPlus => cell_with_metadata.get_x_minus().get_y_plus().get_z_plus().location, |
||||||
|
Direction::SameMinusMinus => cell_with_metadata.get_y_minus().get_z_minus().location, |
||||||
|
Direction::SameMinusSame => cell_with_metadata.get_y_minus().location, |
||||||
|
Direction::SameMinusPlus => cell_with_metadata.get_y_minus().get_z_plus().location, |
||||||
|
Direction::SameSameMinus => cell_with_metadata.get_z_minus().location, |
||||||
|
Direction::SameSamePlus => cell_with_metadata.get_z_plus().location, |
||||||
|
Direction::SamePlusMinus => cell_with_metadata.get_y_plus().get_z_minus().location, |
||||||
|
Direction::SamePlusSame => cell_with_metadata.get_y_plus().location, |
||||||
|
Direction::SamePlusPlus => cell_with_metadata.get_y_plus().get_z_plus().location, |
||||||
|
Direction::PlusMinusMinus => cell_with_metadata.get_x_plus().get_y_minus().get_z_minus().location, |
||||||
|
Direction::PlusMinusSame => cell_with_metadata.get_x_plus().get_y_minus().location, |
||||||
|
Direction::PlusMinusPlus => cell_with_metadata.get_x_plus().get_y_minus().get_z_plus().location, |
||||||
|
Direction::PlusSameMinus => cell_with_metadata.get_x_plus().get_z_minus().location, |
||||||
|
Direction::PlusSameSame => cell_with_metadata.get_x_plus().location, |
||||||
|
Direction::PlusSamePlus => cell_with_metadata.get_x_plus().get_z_plus().location, |
||||||
|
Direction::PlusPlusMinus => cell_with_metadata.get_x_plus().get_y_plus().get_z_minus().location, |
||||||
|
Direction::PlusPlusSame => cell_with_metadata.get_x_plus().get_y_plus().location, |
||||||
|
Direction::PlusPlusPlus => cell_with_metadata.get_x_plus().get_y_plus().get_z_plus().location, |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
pub fn create_board_from_shape_fn<T, F: Fn(CellLocation) -> T>(&self, f: F) -> Array3<T> { |
||||||
|
Array3::from_shape_fn((self.corner.x, self.corner.y, self.corner.z), |(x, y, z)| f(CellLocation::new(x, y, z))) |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,163 @@ |
|||||||
|
use enum_map::EnumMap; |
||||||
|
use ndarray::{Array2, Array3}; |
||||||
|
use strum::IntoEnumIterator; |
||||||
|
|
||||||
|
use crate::binary::CellState; |
||||||
|
use crate::binary::Direction; |
||||||
|
use crate::binary::State; |
||||||
|
use crate::board_metadata::BoardMetadata; |
||||||
|
use crate::board_metadata::CellLocation; |
||||||
|
use crate::rules::Rules; |
||||||
|
|
||||||
|
const RESERVE: usize = 10; |
||||||
|
|
||||||
|
struct CellInfo { |
||||||
|
neighbours: EnumMap<Direction, Option<CellLocation>>, |
||||||
|
state: CellState, |
||||||
|
} |
||||||
|
|
||||||
|
impl CellInfo { |
||||||
|
fn new(neighbours: EnumMap<Direction, Option<CellLocation>>) -> CellInfo { |
||||||
|
CellInfo { |
||||||
|
neighbours, |
||||||
|
state: CellState::new(), |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
fn update_neighbour_state(&mut self, direction: Direction, new_state: State) -> () { |
||||||
|
self.state.update_neighbour_state(direction, new_state) |
||||||
|
} |
||||||
|
|
||||||
|
fn update_state(&mut self, new_state: State) { |
||||||
|
self.state.update_state(new_state) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
pub struct Game { |
||||||
|
cell_rules: Vec<State>, |
||||||
|
board: Array3<CellInfo>, |
||||||
|
corner: CellLocation, |
||||||
|
} |
||||||
|
|
||||||
|
impl Game { |
||||||
|
// only updates the state of this cell for it and its neighbours;
|
||||||
|
// only state of this cell is used from new_cell
|
||||||
|
fn update_cell(&mut self, location: CellLocation, new_state: State) { |
||||||
|
//println!("Updating cell {}:{}", location.row, location.column);
|
||||||
|
self.board[location].update_state(new_state); |
||||||
|
|
||||||
|
for direction in Direction::iter() { |
||||||
|
match self.board[location].neighbours[direction] { |
||||||
|
Some(neighbour_location) => { |
||||||
|
//println!("Updating neighbour cell {}:{}", neighbour_location.row, neighbour_location.column);
|
||||||
|
self.board[neighbour_location].update_neighbour_state(direction, new_state); |
||||||
|
}, |
||||||
|
_ => {}, |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
fn build_cell_rules<T: Rules>() -> Vec<State> { |
||||||
|
let mut result = vec![State::Dead; 1 << 27]; |
||||||
|
|
||||||
|
for i in 0..1usize << 27 { |
||||||
|
let original_state = CellState::from_number(i as u32); |
||||||
|
let mut neighbour_counts = EnumMap::new(); |
||||||
|
for direction in Direction::iter() { |
||||||
|
neighbour_counts[original_state.get_neighbour_state(direction)] += 1usize; |
||||||
|
} |
||||||
|
|
||||||
|
let new_state = T::get_next_state(original_state.get_state(), neighbour_counts); |
||||||
|
result[i] = new_state; |
||||||
|
//println!("Rule #{}: for state_counts [{}, {}, {}, {}] and old state {} new state is {}", i, state_counts[0], state_counts[1], state_counts[2], state_counts[3], current_state, new_state);
|
||||||
|
} |
||||||
|
|
||||||
|
result |
||||||
|
} |
||||||
|
|
||||||
|
fn get_next_state(&self, cell_info: &CellInfo) -> State { |
||||||
|
self.cell_rules[cell_info.state.get_number() as usize] |
||||||
|
} |
||||||
|
|
||||||
|
pub fn next_step(&mut self) -> usize { |
||||||
|
let mut changes: Vec<_> = vec![]; |
||||||
|
for x in 0..self.corner.x { |
||||||
|
for y in 0..self.corner.y { |
||||||
|
for z in 0..self.corner.z { |
||||||
|
let location = CellLocation::new(x, y, z); |
||||||
|
let cell = &self.board[location]; |
||||||
|
let next_state = self.get_next_state(cell); |
||||||
|
//println!("location: {}:{}, neighbours state {}, old state {}, next state {}", location.row, location.column, cell.neighbours_states, cell.state, next_state);
|
||||||
|
if next_state != cell.state.get_state() { |
||||||
|
changes.push((location, next_state)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
let changes_count = changes.len(); |
||||||
|
for (location, new_state) in changes { |
||||||
|
self.update_cell(location, new_state); |
||||||
|
} |
||||||
|
|
||||||
|
changes_count |
||||||
|
} |
||||||
|
|
||||||
|
pub fn from_input<R: Rules>(input_data: &[String]) -> Self { |
||||||
|
let rows = input_data.len(); |
||||||
|
let columns = input_data[0].len(); |
||||||
|
let mut states = Array2::default((rows, columns)); |
||||||
|
|
||||||
|
for row in 0..rows { |
||||||
|
let chars = input_data[row].chars().collect::<Vec<_>>(); |
||||||
|
for column in 0..columns { |
||||||
|
let ch = chars[column]; |
||||||
|
states[[row, column]] = match ch { |
||||||
|
'.' => State::Dead, |
||||||
|
'#' => State::Alive, |
||||||
|
_ => panic!("unsupported state"), |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
let corner = CellLocation::new(rows + 2*RESERVE, columns + 2*RESERVE, 1 + 2*RESERVE); |
||||||
|
let board_metadata = BoardMetadata::new(corner); |
||||||
|
let board = board_metadata.create_board_from_shape_fn(|cell_location| { |
||||||
|
CellInfo::new(R::get_neighbours(cell_location, &board_metadata, &states)) |
||||||
|
}); |
||||||
|
|
||||||
|
let cell_rules = Self::build_cell_rules::<R>(); |
||||||
|
|
||||||
|
let mut game = Game { |
||||||
|
board, |
||||||
|
cell_rules, |
||||||
|
corner, |
||||||
|
}; |
||||||
|
|
||||||
|
for row in 0..rows { |
||||||
|
for column in 0..columns { |
||||||
|
let location = CellLocation::new(row + RESERVE, column + RESERVE, RESERVE); |
||||||
|
game.update_cell(location, states[(row, column)]); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return game; |
||||||
|
} |
||||||
|
|
||||||
|
/*pub fn print_board(&self) {
|
||||||
|
for row in (&self.board).genrows() { |
||||||
|
println!("{}", row.iter().map(|cell| { |
||||||
|
match cell.state.get_state() { |
||||||
|
State::Floor => '.', |
||||||
|
State::SeatEmpty => 'L', |
||||||
|
State::SeatOccupied => '#', |
||||||
|
State::None => '0', |
||||||
|
} |
||||||
|
}).collect::<String>()); |
||||||
|
} |
||||||
|
}*/ |
||||||
|
|
||||||
|
pub fn get_count_of_cells_for_state(&self, state: State) -> usize { |
||||||
|
(&self.board).iter().filter(|&cell| cell.state.get_state() == state).count() |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,39 @@ |
|||||||
|
#![feature(trait_alias)] |
||||||
|
|
||||||
|
use std::io::{self, BufRead}; |
||||||
|
|
||||||
|
mod binary; |
||||||
|
mod board_metadata; |
||||||
|
mod game; |
||||||
|
mod rules; |
||||||
|
mod rules_easy; |
||||||
|
|
||||||
|
use binary::State; |
||||||
|
use game::Game; |
||||||
|
use rules::Rules; |
||||||
|
use rules_easy::RulesEasy; |
||||||
|
|
||||||
|
fn solve<T: Rules>(lines: &[String]) { |
||||||
|
let mut game = Game::from_input::<T>(&lines); |
||||||
|
|
||||||
|
//game.print_board();
|
||||||
|
|
||||||
|
for i in 1.. { |
||||||
|
let changes_count = game.next_step(); |
||||||
|
println!("Iteration {}; changed cells: {}; alive_cells: {}", i, changes_count, game.get_count_of_cells_for_state(State::Alive)); |
||||||
|
//game.print_board();
|
||||||
|
if changes_count == 0 { |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
//game.print_board();
|
||||||
|
println!("Board stabilized at {} occupied seats", game.get_count_of_cells_for_state(State::Alive)); |
||||||
|
} |
||||||
|
|
||||||
|
fn main() { |
||||||
|
let stdin = io::stdin(); |
||||||
|
let lines: Vec<_> = stdin.lock().lines().map(|line| line.unwrap()).collect(); |
||||||
|
|
||||||
|
solve::<RulesEasy>(&lines); |
||||||
|
} |
@ -0,0 +1,9 @@ |
|||||||
|
use enum_map::EnumMap; |
||||||
|
use ndarray::Array2; |
||||||
|
use crate::binary::{Direction, State}; |
||||||
|
use crate::board_metadata::{BoardMetadata,CellLocation}; |
||||||
|
|
||||||
|
pub trait Rules { |
||||||
|
fn get_next_state(current_state: State, neighbour_counts: EnumMap<State, usize>) -> State; |
||||||
|
fn get_neighbours(cell_location: CellLocation, board_metadata: &BoardMetadata, original_states: &Array2<State>) -> EnumMap<Direction, Option<CellLocation>>; |
||||||
|
} |
@ -0,0 +1,28 @@ |
|||||||
|
use enum_map::EnumMap; |
||||||
|
use ndarray::Array2; |
||||||
|
use strum::IntoEnumIterator; |
||||||
|
use crate::binary::{Direction, State}; |
||||||
|
use crate::board_metadata::{BoardMetadata,CellLocation}; |
||||||
|
use crate::rules::Rules; |
||||||
|
|
||||||
|
pub struct RulesEasy {} |
||||||
|
|
||||||
|
impl Rules for RulesEasy { |
||||||
|
fn get_next_state(current_state: State, neighbour_counts: EnumMap<State, usize>) -> State { |
||||||
|
match current_state { |
||||||
|
State::Alive if neighbour_counts[State::Alive] == 2 => State::Alive, |
||||||
|
_ if neighbour_counts[State::Alive] == 3 => State::Alive, |
||||||
|
_ => State::Dead, |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
fn get_neighbours(cell_location: CellLocation, board_metadata: &BoardMetadata, _original_states: &Array2<State>) -> EnumMap<Direction, Option<CellLocation>> { |
||||||
|
let mut neighbours = EnumMap::new(); |
||||||
|
|
||||||
|
for direction in Direction::iter() { |
||||||
|
neighbours[direction] = board_metadata.get_neighbour_location(cell_location, direction); |
||||||
|
} |
||||||
|
|
||||||
|
neighbours |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue