-
Notifications
You must be signed in to change notification settings - Fork 0
/
sudoku.hs
57 lines (45 loc) · 1.8 KB
/
sudoku.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import Data.Char
import Data.Maybe
import CSP
sudokuVars :: [Var]
sudokuVars = [ l : show n | l <- ['a'..'i'], n <- [1..9]]
sudokuDomains :: Domains
sudokuDomains = map (\r -> (r,[1..9])) sudokuVars
toVar :: (Int, Int) -> String
toVar (r,c) = chr (ord 'a' + r) : show (c+1)
cartProd :: t => [t] -> [t] -> [t]
cartProd xs ys = [(x,y) | x <- xs, y <- ys]
subIndex :: Int -> [Int]
subIndex n = cartProd [row..row+2] [col..col+2]
where
row = 3 * div (n - 1) 3
col = 3 * mod (n - 1) 3
sudokuCsp :: CSP
sudokuCsp = CSP ("Sudoku!", sudokuDomains, map allDiffConstraint (rows ++ cols ++ subs))
where
rows = map (\l -> map (\n -> l : show n) [1..9]) ['a'..'i']
cols = map (\n -> map (\l -> l : show n) ['a'..'i']) [1..9]
subs = map (map toVar . subIndex) [1..9]
showSudokuNode csp assignment pos
| length (getDomain pos csp) == 1 = show $ head $ getDomain pos csp
| isNothing val = " "
| otherwise = show $ fromJust val
where val = lookupVar assignment pos
sudokuTable csp assignment = toTable $ cspVars csp
where
toTable l
| l == [] = []
| otherwise = (map (showSudokuNode csp assignment) $ take 9 l) : (toTable $ drop 9 l)
showSudoku csp assignment = sep ++ (foldl1 foldtable $ map showRow $ sudokuTable csp assignment) ++ sep
where
showRow rw = "| " ++ (foldl1 foldrow rw) ++ " |\n"
foldrow x y = x ++ " | " ++ y
foldtable x y = x ++ sep ++ y
sep = "+" ++ (concat $ replicate 9 "---+") ++ "\n"
printSudoku :: CSP -> IO()
printSudoku csp = putStr $ showSudoku csp []
trySudoku :: CSP -> (CSP -> (Maybe Assignment,Int)) -> IO()
trySudoku csp f
| isNothing result = putStr $ "Nothing!\n Visited nodes: " ++ (show nodes) ++ "\n"
| otherwise = putStr $ (showSudoku csp (fromJust result)) ++ "Visited nodes: " ++ (show nodes) ++ "\n"
where (result,nodes) = f csp