#![warn(missing_debug_implementations)]
#![warn(missing_docs)]
use std::collections;
use super::error::Error;
use super::grid::Grid;
use super::qa::Qa;
use super::qr::Qr;
use super::Sqrid;
pub trait MapQa<Item, const W: u16, const H: u16, const WORDS: usize, const SIZE: usize> {
fn new(item: Item) -> Self;
fn get(&self, qa: &Qa<W, H>) -> &Item;
fn set(&mut self, qa: Qa<W, H>, item: Item);
}
impl<Item, const W: u16, const H: u16, const WORDS: usize, const SIZE: usize>
MapQa<Item, W, H, WORDS, SIZE> for Grid<Item, W, H, SIZE>
where
Item: Copy,
{
fn new(item: Item) -> Self {
Grid::<Item, W, H, SIZE>::repeat(item)
}
fn get(&self, qa: &Qa<W, H>) -> &Item {
&self[qa]
}
fn set(&mut self, qa: Qa<W, H>, item: Item) {
self[qa] = item;
}
}
impl<Item, const W: u16, const H: u16, const WORDS: usize, const SIZE: usize>
MapQa<Item, W, H, WORDS, SIZE> for (collections::HashMap<Qa<W, H>, Item>, Item)
{
fn new(item: Item) -> Self {
(Default::default(), item)
}
fn get(&self, qa: &Qa<W, H>) -> &Item {
self.0.get(qa).unwrap_or(&self.1)
}
fn set(&mut self, qa: Qa<W, H>, item: Item) {
self.0.insert(qa, item);
}
}
impl<Item, const W: u16, const H: u16, const WORDS: usize, const SIZE: usize>
MapQa<Item, W, H, WORDS, SIZE> for (collections::BTreeMap<Qa<W, H>, Item>, Item)
{
fn new(item: Item) -> Self {
(Default::default(), item)
}
fn get(&self, qa: &Qa<W, H>) -> &Item {
self.0.get(qa).unwrap_or(&self.1)
}
fn set(&mut self, qa: Qa<W, H>, item: Item) {
self.0.insert(qa, item);
}
}
pub fn camefrom_into_path<
MapQaQr,
const W: u16,
const H: u16,
const WORDS: usize,
const SIZE: usize,
>(
map: MapQaQr,
orig: &Qa<W, H>,
dest: &Qa<W, H>,
) -> Result<Vec<Qr>, Error>
where
MapQaQr: MapQa<Option<Qr>, W, H, WORDS, SIZE>,
{
let distance = Qa::manhattan(orig, dest);
let mut ret = collections::VecDeque::<Qr>::with_capacity(2 * distance);
let mut qa = *dest;
if map.get(&qa).is_none() {
return Err(Error::DestinationUnreachable);
}
let mut maxiter = W as usize * H as usize + 1;
while &qa != orig {
let qr = map.get(&qa).ok_or(Error::InvalidMovement)?;
ret.push_front(-qr);
qa = (qa + qr).or(Err(Error::InvalidMovement))?;
maxiter -= 1;
if maxiter == 0 {
return Err(Error::Loop);
}
}
Ok(Vec::from(ret))
}
impl<const W: u16, const H: u16, const D: bool, const WORDS: usize, const SIZE: usize>
Sqrid<W, H, D, WORDS, SIZE>
{
pub fn camefrom_into_path<MapQaQr>(
map: MapQaQr,
orig: &Qa<W, H>,
dest: &Qa<W, H>,
) -> Result<Vec<Qr>, Error>
where
MapQaQr: MapQa<Option<Qr>, W, H, WORDS, SIZE>,
{
super::camefrom_into_path(map, orig, dest)
}
}