import List
import Array
import Control.Monad.State
strToArray :: String -> Array (Int, Int) Int
strToArray s = array ((0,0), (8,8)) $ zip [(m,n) | m <- [0 .. 8], n <- [0 ..8]] $
map read (concat (map words $ lines s))
display :: Array (Int, Int) Int -> IO()
display grid = do {
forM_ [0..8] $ \m -> do {
forM_ [0..8] $ \n -> do {
putStr $ show (grid!(m, n)) ++ " ";
};
putStrLn "";
};
putStrLn "";
}
solve :: Int->Int->StateT (Array (Int, Int) Int) IO ()
solve x y = do {
grid <- get;
if grid!(x,y) /= 0 then
if (x == 8) && ( y == 8) then
lift (display grid)
else
solve ((x+1) `mod` 9) (if x == 8 then (y+1) else y)
else
do {
forM_ [1..9] $ \c -> do {
if (verify grid x y c) then
put (grid //[((x,y),c)]) >> solve x y
else
return ()
};
put (grid //[((x,y),0)]);
}
}
main :: IO ()
main = do {
s <- getContents;
evalStateT (solve 0 0) (strToArray s);
}
loopUntil :: [Int]->(Int->Bool)->Bool
loopUntil s f =
case s of
x:xs -> if (f x) then (loopUntil xs f) else False
[] -> True
verify1 :: Array (Int, Int) Int -> Int -> Int -> Int -> Bool
verify1 grid x y c = loopUntil [0 .. 8] $ \i ->
not (grid!(i,y) == c || grid!(x,i) == c)
verify2 :: Array (Int, Int) Int -> Int -> Int -> Int -> Bool
verify2 grid x y c =
let { xs = (x `quot` 3)*3} in
let { ys = (y `quot` 3)*3} in
loopUntil [xs .. xs+2] $ \i ->
loopUntil [ys .. ys+2] $ \j -> not (grid!(i,j) == c)
verify :: Array (Int, Int) Int -> Int -> Int -> Int -> Bool
verify grid x y c = (verify1 grid x y c) && (verify2 grid x y c)
Monday, December 6, 2010
A Imperative Style Haskell Sudoku Solver
Here is the Haskell equivalent of the Sudoku solver in C. I tried to do a line-by-line translation from C to Haskell. I hope the program shows that Haskell is a better imperative language than the imperative languages :-)
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment