[Haskell-beginners] First code review

Emanuel Koczwara poczta at emanuelkoczwara.pl
Sat Feb 23 16:39:53 CET 2013


Hi,

Note: Following code is a solution for a problem from hackerrank.com
(Category: Artifical Intelligence / Single Player Games / Bot saves
princess).

Here is my first Haskell code! Short explanation of the problem: it's
standard path finding problem, we have a matrix where 'm' denotes the
bot, 'p' denotes the princess and '-' is for empty space.

Sample input (grid size followed by the grid itself, where each row is
separated by new line):

3
---
-m-
p--

Sample output:

DOWN
LEFT

Here is the code:

module Main where

import Data.List
import Data.Maybe

type Size = Int

type Grid = [String]

type Path = [Move]

type Heuristic = [[Int]]

type Position = (Int,Int)

data Move = LEFT | RIGHT | UP | DOWN deriving Show

getSize :: IO Size
getSize = readLn

getGrid :: Size -> IO Grid
getGrid s = sequence $ replicate s getLine

getHeuristic :: Size -> Position -> Heuristic
getHeuristic s p = map (getHeuristic' s p) [0..s-1]

getHeuristic' :: Size -> Position -> Int -> [Int]
getHeuristic' s p y = map (getHeuristic'' p y) [0..s-1]

getHeuristic'' :: Position -> Int -> Int -> Int
getHeuristic'' (x2, y2) y1 x1 = abs (x1 - x2) + (abs (y1 - y2))

getPos :: Char -> Size -> Grid -> Position
getPos c s g = (i `mod` s, i `div` s)
  where g' = concat g
        i = fromJust $ elemIndex c g'

getSteps :: Size -> Heuristic -> Position -> Position -> Path
getSteps s h b p | b == p = []
                 | otherwise = let (m,b') = getStep s h b 
                               in m : (getSteps s h b' p)

getStep :: Size -> Heuristic -> Position -> (Move,Position)
getStep s h b = head $ sortBy compareCost (getAvailableSteps s h b)
  where compareCost (_,(x1,y1)) (_,(x2,y2)) = 
          compare (h !! y1 !! x1) (h !! y2 !! x2)

getAvailableSteps :: Size -> Heuristic -> Position -> [(Move,Position)]
getAvailableSteps s h (x,y) = up ++ down ++ left ++ right
  where up = if y > 0 then [(UP, (x, y - 1))] else []
        down = if y < (s - 1) then [(DOWN, (x, y + 1))] else []
        left = if x > 0 then [(LEFT, (x - 1, y))] else []
        right = if x < (s - 1) then [(RIGHT, (x + 1, y))] else []

main :: IO ()
main = do
  size <- getSize
  grid <- getGrid size
  let botPos = getPos 'm' size grid
      princessPos = getPos 'p' size grid
      heuristic = getHeuristic size princessPos
      result = getSteps size heuristic botPos princessPos
  mapM_ print result

Please point out all my mistakes.

Emanuel





More information about the Beginners mailing list