module Exercise03 where import Text.Printf (printf) import Data.List import Data.Maybe smallSudokuFalse :: [[Int]] smallSudokuFalse = [[0,0,2,0], [0,1,0,0], [0,0,0,0], [2,1,0,0]] smallSudokuTrue :: [[Int]] smallSudokuTrue = [[1, 4, 0, 0], [0, 0, 0, 0], [4, 3, 2, 1], [0, 0, 0, 0]] easySudoku :: [[Int]] easySudoku = [[8,9,6,7,5,2,4,1,3], [5,2,3,6,1,4,9,8,7], [4,7,1,8,9,3,2,6,5], [9,5,4,3,6,7,8,2,1], [3,1,8,2,4,5,7,9,6], [7,6,2,1,8,9,5,3,4], [6,8,9,5,7,1,3,4,2], [2,4,7,9,3,6,1,5,8], [1,3,5,4,2,8,6,7,9]] -- HA 3.1a) i selectRow :: [[Int]] -> Int -> [Int] selectRow xss i = xss !! i -- HA 3.1a) ii selectColumn :: [[Int]] -> Int -> [Int] selectColumn xss i = [xs !! i | xs <- xss] -- HA 3.1a) iii intRoot :: Int -> Int intRoot = floor . sqrt . fromIntegral --return numbers in square as a list. squares are numbered from left to right and top to bottom --e.g. : --[0,1,2] --[3,4,5] --[6,7,8] selectSquare :: [[Int]] -> Int -> [Int] selectSquare xss i = [ rows !! y | rows <- [xss !! (x+(sl * (i `div` sl))) | x <- [0..(sl-1)]], y <- [(sl*(i `mod` sl))..((sl*(i`mod`sl))+sl-1)]] where sl = intRoot (length xss) -- HA 3.1b) isValidSubsection :: [Int] -> Bool isValidSubsection xs = all (\a -> length a == 1) (filter (\a -> 0 < head a) (group (sort xs))) isValidSudoku :: [[Int]] -> Bool isValidSudoku xss = all isValidSubsection ([selectRow xss x | x <- ps] ++ [selectColumn xss x | x <- ps] ++ [selectSquare xss x | x <- ps]) where ps = [0..(length xss - 1)] -- HA 3.1c) setCell :: [[Int]] -> (Int,Int) -> Int -> [[Int]] setCell xss (j, k) x = take j xss ++ [take k (xss !! j) ++ [x] ++ drop (k+1) (xss !! j)] ++ drop (j+1) xss -- HA 3.1d) {-WETT-} solveSudoku :: [[Int]] -> [[Int]] solveSudoku xss | not (isValidSudoku xss) = [] | 0 `notElem` concat xss = xss | otherwise = fromMaybe [] (find (/=[]) [ solveSudoku (setCell xss (head [(j, k) | j <- [0..(length xss - 1)], k <- [0..(length xss - 1)], (xss !! j) !! k == 0]) n) | n <- [1..(length xss)]]) {-TTEW-} hardSudoku :: [[Int]] hardSudoku = [[8,0,0,0,0,0,0,0,0], [0,0,3,6,0,0,0,0,0], [0,7,0,0,9,0,2,0,0], [0,5,0,0,0,7,0,0,0], [0,0,0,0,4,5,7,0,0], [0,0,0,1,0,0,0,3,0], [0,0,1,0,0,0,0,6,8], [0,0,8,5,0,0,0,1,0], [0,9,0,0,0,0,4,0,0]] -- Utility method to show a sudoku -- show sudoku with -- >>> putStr (showSudoku sudoku) showSudoku :: [[Int]] -> String showSudoku xss = unlines $ intercalate [showDivider] $ chunksOf squareSize $ map showRow xss where size = length xss squareSize = intRoot size numberSize = size `div` 10 + 1 showRowSection xs = unwords $ map (printf ("%0" ++ show numberSize ++ "d")) xs showRow xs = intercalate "|" $ map showRowSection $ chunksOf squareSize xs showDivider = intercalate "+" $ replicate squareSize $ replicate ((numberSize + 1) * squareSize - 1) '-' chunksOf :: Int -> [e] -> [[e]] chunksOf i [] = [] chunksOf i ls = take i ls : chunksOf i (drop i ls)