Renames and cleanup
This commit is contained in:
parent
37a9684fe1
commit
33c706e71e
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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'
|
||||||
|
|
Loading…
Reference in New Issue