Advertisement
Guest User

Untitled

a guest
Nov 13th, 2019
150
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. module Sudoku where
  2.  
  3. type Pos = (Int, Int)
  4. type Cell = (Pos, Int)
  5. type Sudoku = [Cell]
  6. type Block = Int
  7.  
  8. sudoku :: Sudoku
  9. sudoku = [((0,0),3),((0,1),6),((0,4),7),((0,5),1),((0,6),2),
  10.           ((1,1),5),((1,6),1),((1,7),8),
  11.           ((2,2),9),((2,3),2),((2,5),4),((2,6),7),
  12.           ((3,4),1),((3,5),3),((3,7),2),((3,8),8),
  13.           ((4,0),4),((4,3),5),((4,5),2),((4,8),9),
  14.           ((5,0),2),((5,1),7),((5,3),4),((5,4),6),
  15.           ((6,2),5),((6,3),3),((6,5),8),((6,6),9),
  16.           ((7,1),8),((7,2),3),((7,7),6),
  17.           ((8,2),7),((8,3),6),((8,4),9),((8,7),4),((8,8),3)]
  18. sudoku2 :: Sudoku
  19. sudoku2 = [((0,0),5),((0,1),3),((0,4),7),
  20.            ((1,0),6),((1,3),1),((1,4),9),((1,5),5),
  21.            ((2,1),9),((2,2),8),((2,7),6),
  22.            ((3,0),8),((3,4),6),((3,8),3),
  23.            ((4,0),4),((4,3),8),((4,5),3),((4,8),1),
  24.            ((5,0),7),((5,4),2),((5,8),6),
  25.            ((6,1),6),((6,6),2),((6,7),8),
  26.            ((7,3),4),((7,4),1),((7,5),9),((7,8),5),
  27.            ((8,4),8),((8,7),7),((8,8),9)]
  28.  
  29.  
  30. numsInRow :: Sudoku -> Int -> [Int]
  31. numsInRow [] y = []
  32. numsInRow (((a,b),c):xs) y
  33.     | a /= y = numsInRow xs y
  34.     | a == y = [c] ++ numsInRow xs y
  35.      
  36. numsInCol :: Sudoku -> Int -> [Int]
  37. numsInCol [] y = []
  38. numsInCol (((a,b),c):xs) y
  39.     | b /= y = numsInCol xs y
  40.     | b == y = [c] ++ numsInCol xs y
  41.  
  42. posToBlock :: Pos -> Block
  43. posToBlock (x,y) = x - (x `mod` 3) + y `div` 3
  44.  
  45. blockToPositions :: Block -> [Pos]
  46. blockToPositions 0 = [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
  47. blockToPositions 1 = [(0, 3), (0, 4), (0, 5), (1, 3), (1, 4), (1, 5), (2, 3), (2, 4), (2, 5)]
  48. blockToPositions 2 = [(0, 6), (0, 7), (0, 8), (1, 6), (1, 7), (1, 8), (2, 6), (2, 7), (2, 8)]
  49. blockToPositions 3 = [(3, 0), (3, 1), (3, 2), (4, 0), (4, 1), (4, 2), (5, 0), (5, 1), (5, 2)]
  50. blockToPositions 4 = [(3, 3), (3, 4), (3, 5), (4, 3), (4, 4), (4, 5), (5, 3), (5, 4), (5, 5)]
  51. blockToPositions 5 = [(3, 6), (3, 7), (3, 8), (4, 6), (4, 7), (4, 8), (5, 6), (5, 7), (5, 8)]
  52. blockToPositions 6 = [(6, 0), (6, 1), (6, 2), (7, 0), (7, 1), (7, 2), (8, 0), (8, 1), (8, 2)]
  53. blockToPositions 7 = [(6, 3), (6, 4), (6, 5), (7, 3), (7, 4), (7, 5), (8, 3), (8, 4), (8, 5)]
  54. blockToPositions 8 = [(6, 6), (6, 7), (6, 8), (7, 6), (7, 7), (7, 8), (8, 6), (8, 7), (8, 8)]
  55. blockToPositions x = error "bad block number x"
  56.  
  57. numsInBlock :: Sudoku -> Block -> [Int]
  58. numsInBlock [] y = []
  59. numsInBlock (((a,b),c):xs) y
  60.     | or [ (a,b) == x | x <- blockToPositions y] = [c] ++ numsInBlock xs y
  61.     | otherwise = numsInBlock xs y
  62.    
  63. allUnique :: Eq a => [a] -> Bool
  64. allUnique [] = True
  65. allUnique (x:xs) = x `notElem` xs && allUnique xs
  66.  
  67. isSudokuPuzzle :: Sudoku -> Bool
  68. isSudokuPuzzle [] = True
  69. isSudokuPuzzle (((a,b),c):xs) = a >= 0 && a <= 8 && b >= 0 && b <= 8 && c >= 1 && c <= 9 && (and [allUnique (numsInRow (((a,b),c):xs) x) | x <- [0..8]])
  70.  && (and [allUnique (numsInCol (((a,b),c):xs) x) | x <- [0..8]]) && (and [allUnique (numsInBlock (((a,b),c):xs) x) | x <- [0..8]])
  71.  && isSudokuPuzzle xs
  72.  
  73. isFilled :: Sudoku -> Bool
  74. isFilled (((a,b),c):xs)
  75.     | length (((a,b),c):xs) == 81 && allUnique [a | (a,b) <- (((a,b),c):xs)] = True
  76.     | otherwise = False
  77.  
  78. isSolved :: Sudoku -> Bool
  79. isSolved sudo = isFilled sudo && isSudokuPuzzle sudo
  80.  
  81. isBlank :: Sudoku -> Pos -> Bool
  82. isBlank [] x = True
  83. isBlank (((a,b),c):xs) x = (a,b) /= x && isBlank xs x
  84.  
  85. blankPositions :: Sudoku -> [Pos]
  86. blankPositions [] = []
  87. blankPositions sudo = [(x,y) | x <- [0..8], y <- [0..8], isBlank sudo (x,y)]
  88.  
  89. possibleNumsOnPos :: Sudoku -> Pos -> [Int]
  90. possibleNumsOnPos sudo (x,y) = [ a | a <- [1..9], isBlank sudo (x,y)
  91.  && a `notElem` numsInBlock sudo (posToBlock (x,y)) && a `notElem` numsInCol sudo y && a `notElem` numsInRow sudo x]
  92.  
  93. possibleNumsForBlankPos :: Sudoku -> [(Pos, [Int])]
  94. possibleNumsForBlankPos sudo = [(x, possibleNumsOnPos sudo x) | x <- blankPositions sudo]
  95.  
  96. hasSolution :: [(Pos, [Int])] -> Bool
  97. hasSolution [((a,b), x)] = x /= [] && length [((a,b), x)] < 81
  98. hasSolution [] = False
  99. hasSolution (((a,b), x): xs) = x /= [] && length (((a,b), x): xs) < 81 && hasSolution xs
  100.  
  101. uniqueNumForBlankPos :: [(Pos, [Int])] -> [(Pos, Int)]
  102. uniqueNumForBlankPos [] = []
  103. uniqueNumForBlankPos (((a,b), x ):ys)
  104.     | length x == 1 = [((a,b),x !! 0)] ++ uniqueNumForBlankPos ys
  105.     | length x /= 1 = uniqueNumForBlankPos ys
  106.    
  107. insertElem :: Sudoku -> Pos -> Int -> Sudoku
  108. insertElem sudo (a,b) x
  109.     | isBlank sudo (a,b) = ((a,b),x):sudo
  110.     | otherwise = error "position (a,b) is not blank"
  111.    
  112. step :: Sudoku -> [Sudoku]
  113. step sudo
  114.     | isSolved sudo = [sudo]
  115.     | hasSolution (possibleNumsForBlankPos sudo) && (uniqueNumForBlankPos (possibleNumsForBlankPos sudo)) /= [] = take 1 [insertElem sudo (a,b) c |
  116.     a <- [0..8], b <- [0..8], c <- possibleNumsOnPos sudo (a,b) ,(length (possibleNumsOnPos sudo (a,b)) == 1), isBlank sudo (a,b)]
  117.     | otherwise = take (length (possibleNumsOnPos sudo ((blankPositions sudo) !! 0)))
  118.     [insertElem sudo (a,b) c | a <- [0..8], b <- [0..8], c <- possibleNumsOnPos sudo (a,b), isBlank sudo (a,b)]
  119.  
  120.  
  121. solve :: Sudoku -> [Sudoku]
  122. solve sudo
  123.     | ((isSudokuPuzzle sudo) == False) = error "improper sudoku"
  124.     | (isSolved sudo) = sudo:[]
  125.     | (length (step sudo)) > 1 && (hasSolution (possibleNumsForBlankPos sudo))  = [((solve ((step sudo) !! a)) !! 0) |
  126.     a <- [0..((length (step sudo)) - 1)],(solve ((step sudo) !! a)) /= [], isSudokuPuzzle sudo, hasSolution (possibleNumsForBlankPos sudo)]
  127.     | (hasSolution (possibleNumsForBlankPos sudo)) = solve ((step sudo) !! 0)
  128.     | otherwise = []
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement