module Exercise03 where import Text.Printf (printf) import Data.List (intercalate) 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 = [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 = [xss!!m!!j|m<-di,j<-[(i `mod`roo)*roo..((i`mod`roo)*roo+roo -1)]] where di =[(i `div` roo)*roo..((i `div`roo)*roo+roo-1)] roo=intRoot (length xss) -- HA 3.1b) isValidSubsection :: [Int] -> Bool isValidSubsection (x:xs) |null xs =True |x/=0 && x `elem` xs =False |otherwise =isValidSubsection xs isValidSudoku :: [[Int]] -> Bool isValidSudoku xss = and [isValidSubsection( selectRow xss i)|i<-[0..(length xss-1)]]&&and[isValidSubsection( selectColumn xss i)|i<-[0..(length xss-1)]]&&and[isValidSubsection( selectSquare xss i)|i<-[0..(length xss-1)]] -- HA 3.1c) setCell :: [[Int]] -> (Int,Int) -> Int -> [[Int]] setCell (xs:xss) (j,k) x |j==0 =setCell1 xs k x :xss |otherwise =xs:setCell xss (j-1,k) x setCell1:: [Int]->Int->Int->[Int] setCell1 (y:ys) k x | k==0 =x:ys | otherwise =y:setCell1 ys (k-1) x -- HA 3.1d) {-WETT-} solveSudoku :: [[Int]] -> [[Int]] solveSudoku xss |isValidSudoku xss && null(isNull xss) =xss |otherwise=if x /=[[]] then x else [] where x=solveSudoku2 xss (isNull xss) 0 (sol xss (head(isNull xss))) remSudoku :: [[Int]]->[Int]->(Int,Int)->[Int] remSudoku xss xs (a,b)=[y|y<-xs,isValidSudoku(setCell xss (a,b) y)] sol:: [[Int]]->(Int,Int)->[Int] sol xss (a,b) =[y|y<-[1..length xss],isValidSudoku(setCell xss (a,b) y)] solveSudoku2 ::[[Int]]->[(Int,Int)]->Int->[Int]->[[Int]] solveSudoku2 xss ys y xs |null xs =[[]] solveSudoku2 xss ys y (x:xs) |y==length ys-1 && null xs =setCell xss (ys!!y) x |y==length ys-1 =[[]] |solved==[[]] =solveSudoku2 xss ys y xs |otherwise =solved where solve xss ys y=solveSudoku2 xss ys (y+1) (sol xss (ys!!(y+1))) solved = solve (setCell xss (ys!!y) x) ys y isNull::[[Int]]->[(Int,Int)] isNull xss =[(i,j)|i<-[0..(length xss-1)],j<-[0..(length xss-1)],xss!!i!!j==0] {-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)