Minor refactoring

master
Abhinav Sarkar 2012-01-10 13:00:54 +05:30
parent 034e6cbe6f
commit 84734e4113
1 changed files with 22 additions and 24 deletions

View File

@ -54,7 +54,7 @@ astar initState goalState hueristic =
else astar' pq'' seen' tracks' else astar' pq'' seen' tracks'
where where
-- Find the state with min f-cost -- Find the state with min f-cost
(state, cost) = snd . PQ.findMin $ pq (state, gcost) = snd . PQ.findMin $ pq
-- Delete the state from open set -- Delete the state from open set
pq' = PQ.deleteMin pq pq' = PQ.deleteMin pq
@ -65,17 +65,17 @@ astar initState goalState hueristic =
-- Find the successors (with their g and h costs) of the state -- Find the successors (with their g and h costs) of the state
-- which have not been seen yet -- which have not been seen yet
successors = filter (\(s, _, _) -> not $ S.member s seen') successors = filter (\(s, _, _) -> not $ S.member s seen')
$ succsWithPrio state cost $ successorsAndCosts state gcost
-- Insert the successors in the open set -- Insert the successors in the open set
pq'' = foldl (\q (s, c, h) -> PQ.insert (c + h) (s, c) q) pq' successors pq'' = foldl (\q (s, g, h) -> PQ.insert (g + h) (s, g) q) pq' successors
-- Insert the tracks of the successors -- Insert the tracks of the successors
tracks' = foldl (\m (s, _, _) -> M.insert s state m) tracks successors tracks' = foldl (\m (s, _, _) -> M.insert s state m) tracks successors
-- Finds the successors of a given state and their costs -- Finds the successors of a given state and their costs
succsWithPrio state cost = successorsAndCosts state gcost =
map (\(s,c) -> (s, cost + c, hueristic s goalState)) . succs $ state map (\(s,g) -> (s, gcost + g, hueristic s goalState)) . succs $ state
-- Constructs the path from the tracks and last state -- Constructs the path from the tracks and last state
findPath tracks state = findPath tracks state =
@ -89,7 +89,8 @@ type Point = (Int, Int)
-- A sliding puzzle -- A sliding puzzle
-- blank : which item is considered blank -- blank : which item is considered blank
-- pzState : the current state of the puzzle -- pzState : the current state of the puzzle
data Puzzle a = Puzzle { blank :: a, pzState :: Array Point a } deriving (Eq, Ord) data Puzzle a = Puzzle { blank :: a, blankPos :: Point, pzState :: Array Point a }
deriving (Eq, Ord)
-- Get puzzle size -- Get puzzle size
puzzleSize :: Puzzle a -> Int puzzleSize :: Puzzle a -> Int
@ -98,25 +99,24 @@ puzzleSize = fst . snd . A.bounds . pzState
-- Create a puzzle give the blank, the puzzle size and the puzzle state as a list, -- Create a puzzle give the blank, the puzzle size and the puzzle state as a list,
-- left to right, top to bottom. -- left to right, top to bottom.
-- Return Just puzzle if valid, Nothing otherwise -- Return Just puzzle if valid, Nothing otherwise
fromList :: a -> Int -> [a] -> Maybe (Puzzle a) fromList :: Ord a => a -> Int -> [a] -> Maybe (Puzzle a)
fromList b n xs = fromList b n xs =
if n * n /= length xs if (n * n /= length xs) || (b `notElem` xs)
then Nothing then Nothing
else Just . Puzzle b $ array ((1, 1), (n, n)) [((i, j), xs !! (n * (i-1) + (j-1))) else Just $ Puzzle { blank = b
| i <- range (1, n), j <- range (1, n)] , blankPos = let (d, r) = (fromJust . elemIndex b $ xs) `divMod` n
in (d + 1, r + 1)
, pzState = array ((1, 1), (n, n))
[((i, j), xs !! (n * (i-1) + (j-1)))
| i <- range (1, n), j <- range (1, n)]
}
-- Shows the puzzle state as a string -- Shows the puzzle state as a string
showPuzzleState :: Show a => Puzzle a -> String showPuzzleState :: Show a => Puzzle a -> String
showPuzzleState pz = showPuzzleState pz =
('\n' :) . concat . intersperse "\n" ('\n' :) . concat . intersperse "\n"
. map (concat . intersperse " ") . splitEvery len . map (concat . intersperse " ") . splitEvery (puzzleSize pz)
. map show . A.elems . pzState $ pz . map show . A.elems . pzState $ pz
where len = puzzleSize pz
-- Find the position of the blank
blankPos :: Ord a => Puzzle a -> Point
blankPos pz =
fst . fromJust . find (\(i, tile) -> tile == (blank pz)) . A.assocs . pzState $ pz
-- Get the legal neighbouring positions -- Get the legal neighbouring positions
neighbourPos :: Int -> Point -> [Point] neighbourPos :: Int -> Point -> [Point]
@ -126,10 +126,9 @@ neighbourPos len p@(x, y) =
-- Get the next legal puzzle states -- Get the next legal puzzle states
nextStates :: Ord a => Puzzle a -> [Puzzle a] nextStates :: Ord a => Puzzle a -> [Puzzle a]
nextStates pz = map (\p -> Puzzle (blank pz) (swap p blankAt (pzState pz))) nextStates pz = map (\p -> Puzzle (blank pz) p (swap p blankAt (pzState pz)))
$ neighbourPos len blankAt $ neighbourPos (puzzleSize pz) blankAt
where where
len = puzzleSize pz
blankAt = blankPos pz blankAt = blankPos pz
-- Make Puzzle an instance of GameState with unit step cost -- Make Puzzle an instance of GameState with unit step cost
@ -146,16 +145,15 @@ shufflePuzzle n pz =
if n == 0 if n == 0
then return pz then return pz
else do else do
let s = succs pz let s = nextStates pz
i <- getRandomR (0, length s - 1) i <- getRandomR (0, length s - 1)
shufflePuzzle (n - 1) (fst (s !! i)) shufflePuzzle (n - 1) (s !! i)
-- Calculates the number of inversions in puzzle -- Calculates the number of inversions in puzzle
inversions :: Ord a => Puzzle a -> Int inversions :: Ord a => Puzzle a -> Int
inversions pz = sum . map (\l -> length . filter (\e -> e < head l) $ (tail l)) inversions pz = sum . map (\l -> length . filter (\e -> e < head l) $ (tail l))
. filter ((> 1). length) . tails . filter ((> 1). length) . tails
. filter (not . (== b)) . A.elems . pzState $ pz . filter (not . (== (blank pz))) . A.elems . pzState $ pz
where b = blank pz
-- Calculates the puzzle pairty. The puzzle pairty is invariant under legal moves. -- Calculates the puzzle pairty. The puzzle pairty is invariant under legal moves.
puzzlePairty :: Ord a => Puzzle a -> Int puzzlePairty :: Ord a => Puzzle a -> Int