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