module Exercise03 where import Text.Printf (printf) import Data.List -- 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 = [x | xs <- temp , x <- xs] where r = intRoot (length xss) row = i `div` r column = mod i r result = [selectColumn xss ((column*r) + j) | j <- [0..(r-1)]] temp = [selectColumn result ((row*r) + j)|j <- [0..(r-1)]] -- HA 3.1b) isValidSubsection :: [Int] -> Bool isValidSubsection xs = (nub test) == test where test = [x | x <- xs , not(x == 0)] isValidSudoku :: [[Int]] -> Bool isValidSudoku xss = and all where all = ([isValidSubsection xs | xs <- xss] ++ [isValidSubsection (selectColumn xss j)| j <- [0..((length xss) - 1)]] ++ [isValidSubsection (selectSquare xss j) | j <- [0..((length xss) - 1)]]) -- HA 3.1c) setCell :: [[Int]] -> (Int,Int) -> Int -> [[Int]] setCell xss (j, k) x = if (j,k) == (-1,-1) then [[]] else [selectRow xss i | i <- [0..(j-1)]] ++ [row] ++ [selectRow xss i | i <- [(j+1)..((length xss) - 1)]] where row = [(selectRow xss j) !! u | u <- [0..(k-1)]] ++ [x] ++ [(selectRow xss j) !! u | u <- [(k+1)..((length xss) -1)] ] -- HA 3.1d) {-WETT-} solveSudoku :: [[Int]] -> [[Int]] solveSudoku [[]] = [] solveSudoku xss | isFull xss && isValidSudoku xss = xss | isValidSudoku xss = if (findIndex (/= []) solved) == Nothing then [] else solved !! elimmaybe(findIndex (/= []) solved) | otherwise = [] where yss = [setCell xss (findEmpty xss) j | j <- [1 .. (length xss)], isValidSudoku (setCell xss (findEmpty xss) j)] solvables = [isValidSudoku xs | xs <- yss] solved = [solveSudoku xs | xs <- yss] isFull :: [[Int]] -> Bool isFull xss = and xs where xs = [x /= 0 | xs <- xss , x <- xs] findEmpty :: [[Int]] -> (Int , Int) findEmpty xss =if and verif then (-1,-1) else (elimmaybe (findIndex (/= Nothing) indexes) , elimmaybe(indexes !! elimmaybe((findIndex (/= Nothing) indexes)))) where indexes = [findIndex (== 0) xs | xs <- xss] verif = [x == Nothing | x <- indexes] elimmaybe :: Maybe Int -> Int elimmaybe (Just x) = x elimmaybe Nothing = -1 {-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)