Renames and cleanup

custom-accumulator
Abhinav Sarkar 2018-06-26 11:48:14 +05:30
parent 37a9684fe1
commit 33c706e71e
2 changed files with 40 additions and 31 deletions

View File

@ -15,13 +15,14 @@ dependencies:
- base >= 4.7 && < 5 - base >= 4.7 && < 5
executables: executables:
hasdoku: sudoku:
main: Sudoku.hs main: Sudoku.hs
source-dirs: src source-dirs: src
ghc-options: ghc-options:
- -threaded - -threaded
- -rtsopts - -rtsopts
- -with-rtsopts=-N - -with-rtsopts=-N
- -O2
dependencies: dependencies:
- split - split

View File

@ -64,11 +64,11 @@ pruneGrid = fixM pruneGrid'
where where
fixM f x = f x >>= \x' -> if x' == x then return x else fixM f x' fixM f x = f x >>= \x' -> if x' == x then return x else fixM f x'
isFinishedGrid :: Grid -> Bool isGridFilled :: Grid -> Bool
isFinishedGrid grid = null [ () | Possible _ <- concat grid ] isGridFilled grid = null [ () | Possible _ <- concat grid ]
isInvalidGrid :: Grid -> Bool isGridInvalid :: Grid -> Bool
isInvalidGrid grid = isGridInvalid grid =
any isInvalidRow grid any isInvalidRow grid
|| any isInvalidRow (Data.List.transpose grid) || any isInvalidRow (Data.List.transpose grid)
|| any isInvalidRow (subGridsToRows grid) || any isInvalidRow (subGridsToRows grid)
@ -85,39 +85,47 @@ isInvalidGrid grid =
| y `elem` xs = True | y `elem` xs = True
| otherwise = hasDups' ys (y:xs) | otherwise = hasDups' ys (y:xs)
solve :: Grid -> Maybe Grid nextGrids :: Grid -> (Grid, Grid)
solve grid = pruneGrid grid >>= solve' nextGrids grid =
let (i, first@(Fixed _), rest) =
fixCell
. Data.List.minimumBy (compare `Data.Function.on` (possibilityCount . snd))
. filter (isPossible . snd)
. zip [0..]
. concat
$ grid
in (replace2D i first grid, replace2D i rest grid)
where where
solve' grid isPossible (Possible _) = True
| isInvalidGrid grid = Nothing isPossible _ = False
| isFinishedGrid grid = Just grid
| otherwise =
let (grid1, grid2) = nextGrids grid
in solve grid1 <|> solve grid2
nextGrids grid = possibilityCount (Possible xs) = length xs
let (i, first@(Fixed _), rest) = splitPossible . smallestPossible $ grid possibilityCount (Fixed _) = 1
in (replace2D i first grid, replace2D i rest grid)
smallestPossible grid = fixCell (i, Possible [x, y]) = (i, Fixed x, Fixed y)
Data.List.minimumBy (compare `Data.Function.on` (length . possibleVals . snd)) fixCell (i, Possible (x:xs)) = (i, Fixed x, Possible xs)
[(i, c) | (i, c@(Possible _)) <- zip [0..] $ concat grid] fixCell _ = error "Impossible case"
possibleVals (Fixed x) = [x]
possibleVals (Possible xs) = xs
splitPossible (i, Possible (x:[y])) = (i, Fixed x, Fixed y)
splitPossible (i, Possible (x:xs)) = (i, Fixed x, Possible xs)
splitPossible _ = error "Impossible case"
replace2D :: Int -> a -> [[a]] -> [[a]]
replace2D i v = let (x, y) = (i `quot` 9, i `mod` 9) in replace x (replace y (const v)) replace2D i v = let (x, y) = (i `quot` 9, i `mod` 9) in replace x (replace y (const v))
replace p f xs = [if i == p then f x else x | (x, i) <- zip xs [0..]] replace p f xs = [if i == p then f x else x | (x, i) <- zip xs [0..]]
solve :: Grid -> Maybe Grid
solve grid = pruneGrid grid >>= solve'
where
solve' grid'
| isGridInvalid grid = Nothing
| isGridFilled grid' = Just grid'
| otherwise =
let (grid1, grid2) = nextGrids grid'
in solve grid1 <|> solve grid2
main :: IO ()
main = do main = do
grids <- lines <$> getContents inputs <- lines <$> getContents
Control.Monad.forM_ grids $ \grid -> Control.Monad.forM_ inputs $ \input ->
case readGrid grid of case readGrid input of
Nothing -> putStrLn "Invalid grid" Nothing -> putStrLn "Invalid input"
Just grid -> case solve grid of Just grid -> case solve grid of
Nothing -> putStrLn "No solution found" Nothing -> putStrLn "No solution found"
Just grid' -> putStrLn $ showGrid grid' Just grid' -> putStrLn $ showGrid grid'