Advertisement
Guest User

Untitled

a guest
Oct 16th, 2019
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. module Sudoku where
  2.  
  3. import Data.List
  4. import Data.Monoid
  5.  
  6. sudoku :: [[Int]] -> [[Int]]
  7. sudoku = head . getAnswers . return
  8.  
  9.     where getAnswers :: [[[Int]]] -> [[[Int]]]
  10.           getAnswers = appEndo . mconcat $ map (Endo . flip (>>=) . tryCell) allPos
  11.  
  12.           setCell :: (Int,Int) -> [[Int]] -> Int -> [[Int]]
  13.           setCell (i,j) xss n = zipWith f [0..] xss
  14.               where f a xs
  15.                         | a == j = zipWith g [0..] xs
  16.                         | otherwise = xs
  17.                     g  b x
  18.                         | b == i = n
  19.                         | otherwise = x
  20.  
  21.           readCell :: (Int,Int) -> [[Int]] -> Int
  22.           readCell (i,j) = (!! i) . (!! j)
  23.  
  24.           tryCell :: (Int,Int) -> [[Int]] -> [[[Int]]]
  25.           tryCell p s
  26.               | readCell p s == 0 = filter validSolution $ map (setCell p s) [1..9]
  27.               | otherwise = [s]
  28.  
  29.           allPos :: [(Int,Int)]
  30.           allPos = let xs = [0..8]
  31.                    in do i <- xs
  32.                          j <- xs
  33.                          return (i,j)
  34.  
  35.           validSolution :: [[Int]] -> Bool
  36.           validSolution s = validateBy rows && validateBy cols && validateBy squares
  37.  
  38.               where validateBy f = all isValid . f $ s
  39.  
  40.                     rows = id
  41.  
  42.                     cols = transpose
  43.  
  44.                     squares p = let slices = do let xs = [0,3,6]
  45.                                                 a <- xs
  46.                                                 b <- xs
  47.                                                 return (a,b)
  48.                                 in map (slice p) slices
  49.                         where slice puzzle (x,y) = let f = (take 3) . (drop y)
  50.                                                        g = (take 3) . (drop x)
  51.                                                    in f puzzle >>= g
  52.  
  53.                     isValid xs = let nonZeros = filter (/= 0) xs
  54.                                  in nonZeros == nub nonZeros
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement