Personal tools

Views

Haskell Quiz/Knight's Travails/Solution Nroets

From HaskellWiki

import System.Environment (getArgs)import System.Exit (exitFailure)-- The first argument is a list of "squares" that can be reached. The "squares" are ordered-- with the ones that can be reached in the smallest number of moves first.-- What is a "square" ? It is a sequence of moves in reverse order (list of strings). So the-- head is also the square that have been reached.-- Note that the "squares" are built at the same time, so if the compiler is doing it's job,-- the "squares" should be sharing their tails and a maximum of one linked list element-- should be allocated for each square.
shortest [] end forbid = Nothing
shortest (s1:start) end forbid =ifhead s1 == end then Just (tail$reverse s1)else shortest (start ++(signs1 21)++(signs1 12)) end (head s1 : forbid)-- We add 'head s1' to 'forbid' to prevent making an exponential number of calls.where
col =fromEnum$head$head s1
row =fromEnum$last$head s1
signs1 c r = newLoc (-c)(-r)++ newLoc (-c) r ++ newLoc c (-r)++ newLoc c r
newLoc c r =if col + c <fromEnum'a'|| col + c >fromEnum'h'||
row + r <fromEnum'1'|| row + r >fromEnum'8'||head s1 `elem` forbid then[]else[([toEnum(col + c)::Char,toEnum(row + r)::Char] : s1)]
test = shortest [["a8"]]"b7"["b6"]
test2 = shortest [["a8"]]"g6"["b6","c7"]
test3 = shortest [["a8"]]"h2"["b6","a6","b5","d5","e6","d6","f6","f5","g3","h3","g2","d3","f3","e3"]
test4 = shortest [["h8"]]"a8"["c7","a4","c4","d5","d7","d6","e7","c6","d4","c7","c3","c2"]-- If the algorithm does not prune properly, then test4 can take close to 8^11 = 8 billion-- iterations.
usage ="Usage: knight_travails startpos endpos [forbidden positions]"
main =do
args <- getArgs
iflength args <2thendoputStrLn("Insufficient arguments.\n\n"++ usage)
exitFailure
elselet result = shortest [[ args !!0]](args !!1)(drop2 args)incase result of
Nothing ->do{putStrLn"No solutions"}
Just ps ->do{print ps }