Works kinda

This commit is contained in:
2025-10-08 21:30:12 +02:00
parent 836a6de2a7
commit 4913843e28
5 changed files with 48 additions and 27 deletions

View File

@ -50,12 +50,14 @@ extra-doc-files: CHANGELOG.md
-- Extra source files to be distributed with the package, such as examples, or a tutorial module. -- Extra source files to be distributed with the package, such as examples, or a tutorial module.
-- extra-source-files: -- extra-source-files:
common warnings common default
ghc-options: -Wall ghc-options: -Wall
-threaded
-rtsopts
library library
-- Import common warning flags. -- Import common warning flags.
import: warnings import: default
-- Modules exported by the library. -- Modules exported by the library.
exposed-modules: Sudoku exposed-modules: Sudoku
@ -71,6 +73,7 @@ library
, matrix , matrix
, vector , vector
, parallel , parallel
, deepseq
-- Directories containing source files. -- Directories containing source files.
hs-source-dirs: src hs-source-dirs: src
@ -80,7 +83,7 @@ library
executable Estinien executable Estinien
-- Import common warning flags. -- Import common warning flags.
import: warnings import: default
-- .hs or .lhs file containing the Main module. -- .hs or .lhs file containing the Main module.
main-is: Main.hs main-is: Main.hs

9
easy.sudoku Normal file
View File

@ -0,0 +1,9 @@
X X 3 1 6 5 7 9 8
6 1 9 X X X 2 4 5
5 8 7 X 4 X 1 X 6
4 X 6 X 1 2 9 8 3
X 9 X 8 X 4 6 X 2
X X X 6 X 3 4 X 1
9 X 2 5 X 7 8 X X
8 X X 4 2 1 3 X 9
1 X X X X 6 5 2 7

View File

@ -1,9 +1,9 @@
1 2 3 4 5 X 7 8 9 X 7 3 X X X X X 8
4 5 6 7 X 9 1 2 3 X 5 4 X 3 X X X X
7 8 9 1 2 X 4 5 6 2 8 X X 9 X X X X
2 3 4 5 6 7 X 9 1 X X X 5 6 X 4 X X
5 6 7 8 9 X 2 3 4 X X X X X 4 7 X X
8 9 1 2 3 4 5 6 7 X 6 X 8 X X 9 X X
6 7 8 9 1 2 3 4 5 X 3 X X 8 X X X 2
9 1 2 3 4 5 6 7 8 X 9 X X 5 3 X X X
3 4 5 6 7 8 9 1 2 X 4 X X 7 1 X 9 X

9
full.sudoku Normal file
View File

@ -0,0 +1,9 @@
1 2 3 4 5 X 7 8 9
4 5 6 7 8 X 1 2 3
7 X X X X X X X X
2 3 X X X X X X X
5 6 7 8 9 X 2 3 4
8 X 1 2 3 X 5 6 7
6 7 8 9 1 X 3 4 5
9 1 2 3 4 X 6 7 8
3 4 5 6 7 X 9 1 2

View File

@ -1,4 +1,5 @@
{-# LANGUAGE OverloadedStrings, LambdaCase, MultiWayIf #-} {-# LANGUAGE OverloadedStrings, LambdaCase, MultiWayIf #-}
{-# LANGUAGE DeriveGeneric, DeriveAnyClass #-}
module Sudoku ( isValid module Sudoku ( isValid
, Cell(..) , Cell(..)
, Grid(..) , Grid(..)
@ -18,6 +19,9 @@ import Control.Parallel
import Control.Parallel.Strategies import Control.Parallel.Strategies
import Text.Printf import Text.Printf
import Data.List import Data.List
import Control.Monad
import Control.DeepSeq
import GHC.Generics (Generic)
data Cell where data Cell where
One :: Cell One :: Cell
@ -30,7 +34,7 @@ data Cell where
Eight :: Cell Eight :: Cell
Nine :: Cell Nine :: Cell
Unknown :: Cell Unknown :: Cell
deriving (Eq) deriving (Eq, Generic, NFData)
instance Show Cell where instance Show Cell where
show One = "1" show One = "1"
@ -69,11 +73,11 @@ instance Show Square where
-- Grid is 9x9 -- Grid is 9x9
newtype Grid = Grid (Matrix Cell) newtype Grid = Grid (Matrix Cell)
deriving Eq deriving (Eq, Generic, NFData)
instance Show Grid where instance Show Grid where
show (Grid m) = prettyMatrix m show (Grid m) = prettyMatrix m
emptyGrid :: Grid emptyGrid :: Grid
emptyGrid = coerce $ matrix 9 9 (const Unknown) emptyGrid = coerce $ matrix 9 9 (const Unknown)
@ -124,7 +128,7 @@ isValid g = and $ flip (parMap rpar) [1..9]
let row = isValidRow (getRow i g) let row = isValidRow (getRow i g)
col = isValidColumn (getColumn i g) col = isValidColumn (getColumn i g)
square = isValidSquare (getSquare i g) square = isValidSquare (getSquare i g)
in col `par` square `par` row && col && square in row && col && square
) )
updateCell :: Int -> Int -> Cell -> Grid -> Grid updateCell :: Int -> Int -> Cell -> Grid -> Grid
@ -151,17 +155,13 @@ place c pos g = coerce $ setElem c pos (coerce g)
solve :: Grid -> Grid solve :: Grid -> Grid
solve g = let left = leftToPlace g in solve g = let left = leftToPlace g in
case nub $ go g left of case nub $ runEval (go [g] left) of
[] -> error "No solution D:" [] -> error "No solution D:"
[x] -> x [x] -> x
xs -> error (printf "%d solutions" $ length xs) xs -> error (printf "%d solutions" $ length xs)
where go :: Grid -> [Cell] -> [Grid] where go :: [Grid] -> [Cell] -> Eval [Grid]
go g [] = if isValid g then pure g else mempty go gs [] = filterM (pure . isValid) gs
go g (x:xs) = if not $ isValid g then mempty else go gs (x:xs) = filterM (pure . isValid) gs >>=
let empties = findEmpty g in pure . (>>= \g' -> findEmpty g' >>= pure . (g',)) >>=
go' xs $ flip (x `place`) g <$> empties parList rdeepseq . ((uncurry $ flip (place x)) <$>) >>=
flip go xs
go' :: [Cell] -> [Grid] -> [Grid]
go' _ [] = []
go' xs (g:gs) = let sol = go g xs in
sol `par` go' xs gs <> sol