module Exercise03 where import Text.Printf (printf) --import Data.List (intercalate) import Data.List ( delete, intercalate ) --import Debug.Trace -- 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 = [ s | let l = intRoot (length xss),let r = i `div` l, let c = i `mod` l , y<-[0..(l-1)] , x<-[0..(l-1)], let s = selectRow xss (r * l + y) !! (c * l + x) ] -- HA 3.1b) isValidSubsection :: [Int] -> Bool isValidSubsection xs = null [ x | x<-xs, x /= 0 && x `elem` delete x xs] isValidSudoku :: [[Int]] -> Bool isValidSudoku xss = null [ x | x<-[0..(length xss - 1)], not ( isValidSubsection (selectRow xss x) && isValidSubsection (selectColumn xss x) && isValidSubsection (selectSquare xss x) )] -- HA 3.1c) setCell :: [[Int]] -> (Int,Int) -> Int -> [[Int]] setCell xss (j, k) x = [ if i /= j then selectRow xss i else [ if ii /= k then selectRow xss j !! ii else x | ii<-[0..(length xss - 1)]] | i<-[0..(length xss - 1)]] -- [ a | i<-[0..(length xss - 1)], if (i /= j) then let a =selectRow xss x else let a = [ b | ii<-[0..(length xss - 1)], if (ii /= k) then b = (selectRow xss j) !! ii else b = x ] ] -- HA 3.1d) {-WETT-} solveSudoku :: [[Int]] -> [[Int]] solveSudoku xss | snd s = fst s | otherwise = [] where s = solve xss (0,0) 1 nextKoordinaten :: (Int,Int) -> Int -> (Int, Int) nextKoordinaten (x,y) l | y == l-1 = (x + 1, 0) | otherwise = (x, y+1) solve :: [[Int]] -> (Int,Int) -> Int -> ([[Int]],Bool) --True wenn valide, false wenn nicht möglich solve xss (x,y) i | x == length xss && y == 0 = (xss,True) | selectRow xss x !! y /= 0 = solve xss (nextKoordinaten (x,y) (length xss)) 1 | not ( isValidSudoku ( setCell xss (x,y) i) ) = if i < length xss then solve xss (x,y) (i+1) else (xss,False) | otherwise = if snd k then k else (if i < length xss then solve xss (x,y) (i+1) else (xss,False) ) where k =solve (setCell xss (x,y) i) (nextKoordinaten (x,y) (length xss)) 1 {- | xss == [[]] = [[]] | null [(y,x)| y<-[0..length xss -1] ,x<-[0..length xss-1], selectRow xss y !! x == 0 ] = xss |otherwise = head (filter isValidSudoku [ solveSudoku (setCell xss koordinaten i) |let koordinaten = head [ (x,y) | x<-[0..length xss -1], y<-[0..length xss -1] , selectRow xss x !! y == 0 ] , i <- [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)