module Exercise03 where import Text.Printf (printf) import Data.List (intercalate) -- HA 3.1a) i selectRow :: [[Int]] -> Int -> [Int] selectRow xss i = xss!!i -- HA 3.1a) ii selectColumn :: [[Int]] -> Int -> [Int] selectColumn xss i = [y!!i | y<-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 = [selectRow xss y !! z | y<-[num| num <- [0..length (selectRow xss 0)], num >= div i (intRoot (length (selectRow xss 0))) * intRoot (length (selectRow xss 0)), num < (div i (intRoot (length (selectRow xss 0)))+1) * intRoot (length (selectRow xss 0))], z <- [num| num <- [0..length (selectRow xss 0)], num >= mod i (intRoot (length (selectRow xss 0))) * intRoot (length (selectRow xss 0)), num < (mod i (intRoot (length (selectRow xss 0)))+1) * intRoot (length (selectRow xss 0))]] -- HA 3.1b) isValidSubsection :: [Int] -> Bool isValidSubsection xs = null [x | x <- xs, x /= 0, x < 0 || x > length xs || length [y | y <- xs, x == y] > 1] isValidSudoku :: [[Int]] -> Bool isValidSudoku xss = null [y |y <- [0..length (selectRow xss 0)-1], not(isValidSubsection (selectRow xss y) && isValidSubsection(selectColumn xss y) && isValidSubsection(selectSquare xss y))] -- HA 3.1c) setCell :: [[Int]] -> (Int,Int) -> Int -> [[Int]] setCell xss (j, k) n | j == 0 = [[x|y <- [0..length (selectRow xss 0) - 1], x <- [0..length (selectRow xss 0)], (y /= k && x == selectRow xss j !! y) || (x == n && y == k)]] ++ [selectRow xss i|i<- [j+1..length (selectRow xss 0)-1]] | j == length(selectRow xss 0) - 1= [selectRow xss i |i<- [0..j-1]] ++ [[x|y <- [0..length (selectRow xss 0) - 1], x <- [0..length (selectRow xss 0)], (y /= k && x == selectRow xss j !! y) || (x == n && y == k)]] | otherwise = [selectRow xss i |i<- [0..j-1]] ++ [[x|y <- [0..length (selectRow xss 0) - 1], x <- [0..length (selectRow xss 0)], (y /= k && x == selectRow xss j !! y) || (x == n && y == k)]] ++[selectRow xss i|i<- [j+1..length (selectRow xss 0)-1]] -- HA 3.1d) {-WETT-} customHeadFunc :: [[[Int]]] -> [[Int]] customHeadFunc xsss | null xsss = [] | otherwise = head xsss solveSudoku :: [[Int]] -> [[Int]] solveSudoku xss -- | trace ("solver " ++ show xss) False = undefined | not (isValidSudoku xss) = [] | null[x | i <- [0..length (selectRow xss 0)-1], x <- selectRow xss i, x == 0] = xss | otherwise = customHeadFunc [yss | j <- [0..length (selectRow xss 0)-1], j == head [x | x<-[0..length (selectRow xss 0)-1], not (null [y | y<- selectRow xss x, y == 0])], k <- [0..length (selectRow xss 0)-1], k == head[x | x<-[0..length (selectRow xss 0)-1], selectRow xss j !! x == 0], i <- [x | x <- [1..length (selectRow xss 0)], null[y |y <- selectRow xss j, x == y], null[y | y <- selectColumn xss k, x == y]],yss <- [solveSudoku (setCell xss (j,k) i)], not(null yss)] {-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)