Skip to content

Commit 7377f52

Browse files
committed
Cleaned up the tests
1 parent f57288d commit 7377f52

1 file changed

Lines changed: 19 additions & 18 deletions

File tree

A_Star_Search/Haskell/abhin4v/AStarSearch_test.hs

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
{-# LANGUAGE TemplateHaskell #-}
1+
{-# LANGUAGE TemplateHaskell, GeneralizedNewtypeDeriving #-}
22

33
module AStarSearchTest where
44

55
import AStarSearch
6+
import Data.Hashable (Hashable)
67
import Data.List (foldl')
7-
import Data.Maybe (fromJust)
8+
import Data.Maybe (fromJust, fromMaybe)
89
import Data.Sequence ((|>))
910
import Test.QuickCheck
1011
import Test.QuickCheck.All
@@ -14,24 +15,24 @@ import qualified Data.Sequence as Seq
1415
-- We use A* search to find the shortest path (path with least number of moves) of a knight
1516
-- from a start square to a goal square on a chess board.
1617

17-
type Square = (Int, Int)
18+
newtype Square = Square (Int, Int) deriving (Eq, Hashable, Show)
1819
type Path = [Square]
1920

2021
-- Finds the next squares a knight can move to from a given square
21-
nextKnightPos (x, y) =
22-
filter isValidMove . map (\(dx, dy) -> (x + dx, y + dy)) $ moves
22+
nextKnightPos (Square (x, y)) =
23+
map Square . filter isValidMove . map (\(dx, dy) -> (x + dx, y + dy)) $ moves
2324
where
2425
moves = [(1,2), (1,-2), (-1,2), (-1,-2), (2,1), (2,-1), (-2,1), (-2,-1)]
2526
isValidMove (x, y) = and [x > 0, x < 9, y > 0, y < 9]
2627

2728
-- Creates the heuristic function given a goal square. The heuristic used is half of the max of
2829
-- the distance between x coordinates and the distance between y coordinates.
29-
mkHeuristic (gx, gy) (x, y) = max (abs (x-gx)) (abs (y-gy)) `div` 2
30+
mkHeuristic (Square (gx, gy)) (Square (x, y)) = max (abs (x-gx)) (abs (y-gy)) `div` 2
3031

31-
-- Finds the shortest path of the knight
32+
-- Finds the shortest path of the knight, returns empty path if the goal is invalid
3233
knightsShortestPath :: Square -> Square -> Path
3334
knightsShortestPath initSq goalSq =
34-
snd . fromJust
35+
snd . fromMaybe (0, [])
3536
$ astarSearch initSq (== goalSq) (flip zip (repeat 1) . nextKnightPos) (mkHeuristic goalSq)
3637

3738
-- Finds the shortest path using breadth first search. Used for checking if the path returned by
@@ -40,7 +41,7 @@ bfs :: Square -> Square -> Path
4041
bfs startSq goalSq =
4142
bfs' goalSq (Map.singleton startSq noSuchSq) (Seq.singleton startSq)
4243
where
43-
noSuchSq = (-1,-1)
44+
noSuchSq = Square (-1, -1)
4445

4546
bfs' goalSq tracks open = let
4647
(first, rest) = Seq.splitAt 1 open
@@ -58,30 +59,30 @@ bfs startSq goalSq =
5859
else []
5960

6061
-- Setup to generate arbitrary squares for testing
61-
newtype TestSquare = TestSquare { sq :: Square } deriving (Show)
62-
63-
instance Arbitrary TestSquare where
62+
instance Arbitrary Square where
6463
arbitrary = do
6564
x <- choose (1, 8)
6665
y <- choose (1, 8)
67-
return $ TestSquare (x, y)
66+
return $ Square (x, y)
6867

6968
-- Properties to test
7069
prop_path_starts_with_start_square startSq goalSq =
71-
head (knightsShortestPath (sq startSq) (sq goalSq)) == sq startSq
70+
head (knightsShortestPath startSq goalSq) == startSq
7271

7372
prop_path_ends_with_goal_square startSq goalSq =
74-
last (knightsShortestPath (sq startSq) (sq goalSq)) == sq goalSq
73+
last (knightsShortestPath startSq goalSq) == goalSq
7574

7675
prop_path_consists_of_valid_knights_moves startSq goalSq =
77-
let path = knightsShortestPath (sq startSq) (sq goalSq)
76+
let path = knightsShortestPath startSq goalSq
7877
in all isValidKnightsMove $ zip path (tail path)
7978
where
8079
isValidKnightsMove (sqFrom, sqTo) = sqTo `elem` nextKnightPos sqFrom
8180

81+
prop_no_path_for_invalid_goal startSq =
82+
knightsShortestPath startSq (Square (-1, -1)) == []
83+
8284
prop_path_is_shortest startSq goalSq =
83-
let path = knightsShortestPath (sq startSq) (sq goalSq)
84-
in length path == length (bfs (sq startSq) (sq goalSq))
85+
length (knightsShortestPath startSq goalSq) == length (bfs startSq goalSq)
8586

8687
-- Tests all the properties 1000 times each
8788
testAllProps = $forAllProperties $ quickCheckWithResult (stdArgs {maxSuccess = 1000})

0 commit comments

Comments
 (0)