@ -1,89 +1,68 @@ |
|||||||
use std::collections::{HashMap, HashSet}; |
|
||||||
|
|
||||||
#[derive(Hash, PartialEq, Eq, Clone, Debug, Copy)] |
#[derive(Hash, PartialEq, Eq, Clone, Debug, Copy)] |
||||||
pub struct Point(pub i32, pub i32); |
pub struct Point(pub i32, pub i32); |
||||||
|
|
||||||
impl Point { |
impl Point { |
||||||
pub fn get_neighbors(&self) -> Vec<Point> { |
pub fn get_neighbors(&self) -> Vec<Point> { |
||||||
vec![ |
vec![self.left(), self.right(), self.up(), self.down()] |
||||||
Point(self.0, self.1 + 1), |
|
||||||
Point(self.0, self.1 - 1), |
|
||||||
Point(self.0 - 1, self.1), |
|
||||||
Point(self.0 + 1, self.1), |
|
||||||
] |
|
||||||
} |
} |
||||||
} |
|
||||||
|
|
||||||
fn manhattan(c1: &Point, c2: &Point) -> i32 { |
|
||||||
return (c2.0 - c1.0).abs() + (c2.1 - c1.1).abs(); |
|
||||||
} |
|
||||||
|
|
||||||
pub fn astar(start: &Point, goal: &Point) -> Vec<Point> { |
|
||||||
let mut open_set : HashSet<Point> = HashSet::new(); |
|
||||||
open_set.insert(*start); |
|
||||||
|
|
||||||
let mut came_from: HashMap<Point, Point> = HashMap::new(); |
pub fn left(&self) -> Point { |
||||||
|
Point(self.0 - 1, self.1) |
||||||
|
} |
||||||
|
|
||||||
let mut gscore: HashMap<Point, i32> = HashMap::new(); |
pub fn right(&self) -> Point { |
||||||
gscore.insert(*start, 0); |
Point(self.0 + 1, self.1) |
||||||
|
} |
||||||
|
|
||||||
let mut fscore: HashMap<Point, i32> = HashMap::new(); |
// y values are reversed in ncurses
|
||||||
fscore.insert(*start, manhattan(&start, &goal)); |
pub fn down(&self) -> Point { |
||||||
|
Point(self.0, self.1 + 1) |
||||||
|
} |
||||||
|
|
||||||
let mut answer = Vec::new(); |
pub fn up(&self) -> Point { |
||||||
|
Point(self.0, self.1 - 1) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
let mut current: Point = *start; |
#[derive(Clone, Copy, PartialEq, Eq, Debug)] |
||||||
while !open_set.is_empty() { |
pub enum Direction { |
||||||
let mut min_score = i32::MAX; |
Up = 0, |
||||||
for c in open_set.iter() { |
Right = 1, |
||||||
let val = fscore[c]; |
Down = 2, |
||||||
current = if val < min_score { c.clone() } else { current }; |
Left = 3, |
||||||
min_score = if val < min_score { val } else { min_score }; |
} |
||||||
} |
|
||||||
|
|
||||||
if current == *goal { |
impl Direction { |
||||||
answer.push(current.clone()); |
pub fn from_u8(v: u8) -> Direction { |
||||||
while came_from.contains_key(¤t) { |
match v { |
||||||
current = came_from[¤t].clone(); |
0 => Direction::Up, |
||||||
if current != *start { |
1 => Direction::Right, |
||||||
answer.push(current.clone()); |
2 => Direction::Down, |
||||||
} |
3 => Direction::Left, |
||||||
} |
_ => panic!("Shouldn't happen") |
||||||
break; |
|
||||||
} |
} |
||||||
|
} |
||||||
|
|
||||||
open_set.remove(¤t); |
pub fn cw(&self) -> Direction { |
||||||
|
let val = *self as u8; |
||||||
let current_gscore = gscore[¤t]; |
Direction::from_u8((val + 1) % 4) |
||||||
|
} |
||||||
|
|
||||||
let all_neighbors: Vec<Point> = current.get_neighbors(); |
pub fn ccw(&self) -> Direction { |
||||||
for neighbor in all_neighbors.iter() { |
let val = *self as u8; |
||||||
let neighbor_score = if gscore.contains_key(&neighbor) { |
if val == 0 { |
||||||
gscore[neighbor] |
Direction::Left |
||||||
} else { |
} else { |
||||||
i32::MAX |
Direction::from_u8(val - 1) |
||||||
}; |
|
||||||
let score = current_gscore + 1; |
|
||||||
if score < neighbor_score { |
|
||||||
gscore.insert(neighbor.clone(), score); |
|
||||||
fscore.insert(neighbor.clone(), score + manhattan(&neighbor, &goal)); |
|
||||||
came_from.insert(neighbor.clone(), current.clone()); |
|
||||||
open_set.insert(neighbor.clone()); |
|
||||||
} |
|
||||||
} |
} |
||||||
} |
} |
||||||
|
|
||||||
answer |
pub fn relative_point(&self, p: &Point) -> Point { |
||||||
} |
match self { |
||||||
|
Direction::Up => p.up(), |
||||||
#[test] |
Direction::Left => p.left(), |
||||||
fn test_astar() { |
Direction::Right => p.right(), |
||||||
let start = Point(0, 0); |
Direction::Down => p.down(), |
||||||
|
} |
||||||
let goal = Point(10, 10); |
|
||||||
let answers: Vec<Point> = astar(&start, &goal); |
|
||||||
|
|
||||||
for a in answers.iter() { |
|
||||||
println!("{:?}", &a); |
|
||||||
} |
} |
||||||
} |
} |
||||||
|
Loading…
Reference in new issue