Advertisement
Guest User

Sudoku Solver

a guest
Jun 12th, 2019
103
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import Data.Time.Clock
  2. import Data.List
  3. import Data.Function (on)
  4. import Data.Char
  5. import Control.Monad
  6.  
  7. data Number = Known Int | Uncertain [Int] deriving (Show, Eq)
  8. instance Ord Number where
  9.   (Known _) <= (Uncertain _) = True
  10.   (Uncertain _) <= (Known _) = False
  11.   a <= b = (allPossible a) <= (allPossible b)
  12. e = Uncertain [1..9] -- empty cell can be anything
  13. k n = Known n
  14. type Sudoku = [[Number]]
  15. type Coords = (Int, Int)
  16. isUncertain (Uncertain _) = True
  17. isUncertain _ = False
  18. isKnown (Uncertain _) = False
  19. isKnown _ = True
  20.  
  21. canBe :: Int -> Number -> Bool
  22. canBe i (Known n) = n == i
  23. canBe i (Uncertain ns) = i `elem` ns
  24.  
  25. allPossible :: Number -> [Int]
  26. allPossible (Known n) = [n]
  27. allPossible (Uncertain l) = l
  28.  
  29. inSameSquare (a, b) (x, y) = (a `div` 3, b `div` 3) == (x `div` 3, y `div` 3)
  30. inSameColumn (a, b) (x, y) = a == x
  31. inSameRow (a, b) (x, y) = b == y
  32. inSameX (a, b) (x, y)
  33.   | a == b && x == y  =True
  34.   | a + b == 8 && x + y == 8  =True
  35.   | otherwise =False
  36.  
  37. neighbours :: (Coords -> Coords -> Bool) -> Sudoku -> Coords -> [Number]
  38. neighbours criteria sudoku (a, b) = [sudoku !!y!!x | x <- [0..8], y <- [0..8], (a, b) /= (x, y), criteria (a, b) (x, y)]
  39.  
  40. allCriteria = [inSameSquare, inSameColumn, inSameRow, inSameX]
  41. allNeighbours (a, b) (x, y) = any (\f -> f (a,b) (x,y)) allCriteria
  42.  
  43. isSolved sudoku = all (==False) $ map (\y -> any isUncertain y) sudoku
  44. invert numbers = foldl (\acc z -> delete z acc) [1..9] numbers
  45.  
  46. solve :: Sudoku -> Sudoku
  47. solve oldSudoku
  48.   | isSolved oldSudoku = oldSudoku
  49.   | oldSudoku == newSudoku = oldSudoku
  50.   | otherwise = solve newSudoku
  51.   where newSudoku = [[newValue oldSudoku (x, y) | x <- [0..8]] | y <- [0..8]]
  52.         newValue sudoku (x, y)
  53.           | isKnown $ sudoku !!y!!x = sudoku !!y!!x
  54.           | length allPossibleValues == 1 = k $ head allPossibleValues
  55.           | otherwise = Uncertain allPossibleValues
  56.           where allPossibleValues = invert (
  57.                     concat [n | c <- allCriteria, v <- subsequences (neighbours c sudoku (x, y)), let n = nub $ concat $ map allPossible v, length v == length n]
  58.                   )
  59.                        
  60.  
  61. allKnowns :: [Number] -> [Int]
  62. allKnowns numbers = nub $ map numberToInt $ filter isKnown numbers
  63.  
  64. -- main = interact $ show . solve . map(\y -> map(\x -> toNumber x) y) . lines
  65. main = do
  66.   sudokuString <- getContents
  67.   let solvedSudoku = solve $ map(\y -> map(\x -> toNumber x) y) $ lines sudokuString
  68.   printSudoku solvedSudoku
  69.   return $ show solvedSudoku
  70.  
  71. toNumber :: Char -> Number
  72. toNumber c
  73.   | isDigit c = k (read (c:[]))
  74.   | otherwise = e
  75.  
  76. numberToInt (Known n) = n
  77. printSudoku = putStr . showSudoku
  78. showSudoku :: Sudoku -> String
  79. showSudoku sudoku = unlines $ map(\y -> map(\x -> toChar x) y) sudoku
  80. toChar (Known n) = head $ show n
  81. toChar (Uncertain []) = '?'
  82. toChar (Uncertain _) = '.'
  83.  
  84.  
  85. sudoku1 = [[(k 7), (k 8), e, e, e, e, e, e, e],
  86.            [e, (k 9), e, (k 6), (k 7), (k 1), e, (k 3), (k 8)],
  87.            [e, e, (k 4), e, (k 8), e, e, e, e],
  88.            [(k 1), (k 5), e, (k 2), e, e, (k 3), e, (k 9)],
  89.            [(k 4), (k 3), e, (k 8), e, (k 5), e, (k 6), (k 7)],
  90.            [(k 9), e, (k 8), e, e, (k 7), e, (k 2), (k 4)],
  91.            [e, e, e, e, (k 3), e, (k 2), e, e],
  92.            [(k 8), (k 4), e, (k 5), (k 2), (k 6), e, (k 9), e],
  93.            [e, e, e, e, e, e, e, (k 5), (k 1)]]
  94.  
  95. sudoku2 = [[e, (k 2), (k 6), e, e, e, e, e, (k 9)],
  96.            [e, e, (k 4), e, (k 3), (k 9), e, e, e],
  97.            [(k 8), e, e, (k 4), e, e, e, e, (k 1)],
  98.            [e, (k 8), e, (k 3), (k 2), e, e, (k 7), e],
  99.            [e, e, e, e, e, e, e, e, e],
  100.            [e, (k 9), e, e, (k 5), (k 7), e, (k 4), e],
  101.            [(k 4), e, e, e, e, (k 1), e, e, (k 7)],
  102.            [e, e, e, (k 7), (k 4), e, (k 5), e, e],
  103.            [(k 1), e, e, e, e, e, (k 8), (k 2), e]]
  104.  
  105. -- sudoku3 is really really hard
  106. sudoku3 = [[(k 3), e, e, e, e, e, e, (k 2), e],
  107.            [e, (k 5), e, e, (k 9), e, (k 6), e, (k 1)],
  108.            [(k 1), e, e, e, e, e, (k 4), e, (k 3)],
  109.            [e, e, (k 2), e, e, (k 1), e, (k 9), e],
  110.            [e, (k 8), e, e, (k 5), e, e, (k 4), e],
  111.            [e, (k 9), e, (k 2), e, e, (k 5), e, e],
  112.            [(k 6), e, (k 7), e, e, e, e, e, (k 8)],
  113.            [(k 8), e, (k 4), e, (k 2), e, e, (k 6), e],
  114.            [e, (k 3), e, e, e, e, e, e, (k 4)]]
  115.  
  116. sudokuX = [[e, e, e, (k 3), e, e, (k 6), e, e],
  117.            [e, (k 4), e, e, e, e, e, e, e],
  118.            [e, (k 5), e, (k 1), e, e, (k 2), e, e],
  119.            [e, e, e, (k 5), e, (k 7), e, e, e],
  120.            [e, e, (k 3), e, (k 9), e, (k 1), e, e],
  121.            [e, e, e, e, e, e, e, (k 8), e],
  122.            [(k 4), (k 9), e, e, e, e, (k 8), (k 7), e],
  123.            [(k 7), e, e, e, (k 1), e, e, e, e],
  124.            [(k 6), (k 2), (k 8), e, e, e, (k 9), e, e]]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement