    -----------------------------------------------------------------------------
    -- |
    -- Module    : Documentation.SBV.Examples.Puzzles.Sudoku
    -- Copyright : (c) Levent Erkok
    -- License   : BSD3
    -- Maintainer: erkokl@gmail.com
    -- Stability : experimental
    --
    -- The Sudoku solver, quintessential SMT solver example!
    -----------------------------------------------------------------------------

    {-# LANGUAGE CPP              #-}
    {-# LANGUAGE FlexibleContexts #-}

    {-# OPTIONS_GHC -Wall -Werror #-}

    module Documentation.SBV.Examples.Puzzles.Sudoku where

    #if MIN_VERSION_base(4,18,0)
    import Control.Monad (when, zipWithM_)
    #endif

    import Control.Monad.State.Lazy

    import Data.List     (transpose)

    import Data.SBV
    import Data.SBV.Control

    -------------------------------------------------------------------
    -- * Modeling Sudoku
    -------------------------------------------------------------------
    -- | A row is a sequence of digits that we represent symbolic integers
    type Row = [SInteger]

    -- | A Sudoku board is a sequence of 9 rows
    type Board = [Row]

    -- | Given a series of elements, make sure they are all different
    -- and they all are numbers between 1 and 9
    check :: [SInteger] -> SBool
    check :: [SInteger] -> SBool
    check [SInteger]
    grp = [SBool] -> SBool
    sAnd ([SBool] -> SBool) -> [SBool] -> SBool
    forall a b. (a -> b) -> a -> b
    $ [SInteger] -> SBool
    forall a. EqSymbolic a => [a] -> SBool
    distinct [SInteger]
    grp SBool -> [SBool] -> [SBool]
    forall a. a -> [a] -> [a]
    : (SInteger -> SBool) -> [SInteger] -> [SBool]
    forall a b. (a -> b) -> [a] -> [b]
    map SInteger -> SBool
    forall {a}. (OrdSymbolic a, Num a) => a -> SBool
    rangeFine [SInteger]
    grp
      where rangeFine :: a -> SBool
    rangeFine a
    x = a
    x a -> (a, a) -> SBool
    forall a. OrdSymbolic a => a -> (a, a) -> SBool
    `inRange` (a
    1, a
    9)

    -- | Given a full Sudoku board, check that it is valid
    valid :: Board -> SBool
    valid :: Board -> SBool
    valid Board
    rows = [SBool] -> SBool
    sAnd ([SBool] -> SBool) -> [SBool] -> SBool
    forall a b. (a -> b) -> a -> b
    $ Bool -> SBool
    forall a. SymVal a => a -> SBV a
    literal Bool
    sizesOK SBool -> [SBool] -> [SBool]
    forall a. a -> [a] -> [a]
    : ([SInteger] -> SBool) -> Board -> [SBool]
    forall a b. (a -> b) -> [a] -> [b]
    map [SInteger] -> SBool
    check (Board
    rows Board -> Board -> Board
    forall a. [a] -> [a] -> [a]
    ++ Board
    columns Board -> Board -> Board
    forall a. [a] -> [a] -> [a]
    ++ Board
    squares)
      where sizesOK :: Bool
    sizesOK = Board -> Int
    forall a. [a] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length Board
    rows Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    9 Bool -> Bool -> Bool
    && ([SInteger] -> Bool) -> Board -> Bool
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    all (\[SInteger]
    r -> [SInteger] -> Int
    forall a. [a] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length [SInteger]
    r Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    9) Board
    rows

            columns :: Board
    columns = Board -> Board
    forall a. [[a]] -> [[a]]
    transpose Board
    rows
            regions :: [Board]
    regions = [Board] -> [Board]
    forall a. [[a]] -> [[a]]
    transpose [Int -> [SInteger] -> Board
    forall a. Int -> [a] -> [[a]]
    chunk Int
    3 [SInteger]
    row | [SInteger]
    row <- Board
    rows]
            squares :: Board
    squares = [Board -> [SInteger]
    forall (t :: * -> *) a. Foldable t => t [a] -> [a]
    concat Board
    sq | Board
    sq <- Int -> Board -> [Board]
    forall a. Int -> [a] -> [[a]]
    chunk Int
    3 ([Board] -> Board
    forall (t :: * -> *) a. Foldable t => t [a] -> [a]
    concat [Board]
    regions)]

            chunk :: Int -> [a] -> [[a]]
            chunk :: forall a. Int -> [a] -> [[a]]
    chunk Int
    _ [] = []
            chunk Int
    i [a]
    xs = let ([a]
    f, [a]
    r) = Int -> [a] -> ([a], [a])
    forall a. Int -> [a] -> ([a], [a])
    splitAt Int
    i [a]
    xs in [a]
    f [a] -> [[a]] -> [[a]]
    forall a. a -> [a] -> [a]
    : Int -> [a] -> [[a]]
    forall a. Int -> [a] -> [[a]]
    chunk Int
    i [a]
    r

    -- | A puzzle is simply a list of rows. Put 0 to indicate blanks.
    type Puzzle = [[Integer]]

    -------------------------------------------------------------------
    -- * Solving Sudoku puzzles
    -------------------------------------------------------------------

    -- | Fill a given board, replacing 0's with appropriate elements to solve the puzzle
    fillBoard :: Puzzle -> IO Puzzle
    fillBoard :: Puzzle -> IO Puzzle
    fillBoard Puzzle
    board = Symbolic Puzzle -> IO Puzzle
    forall a. Symbolic a -> IO a
    runSMT (Symbolic Puzzle -> IO Puzzle) -> Symbolic Puzzle -> IO Puzzle
    forall a b. (a -> b) -> a -> b
    $ do
         let emptyCellCount :: Int
    emptyCellCount = [Integer] -> Int
    forall a. [a] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length ([Integer] -> Int) -> [Integer] -> Int
    forall a b. (a -> b) -> a -> b
    $ (Integer -> Bool) -> [Integer] -> [Integer]
    forall a. (a -> Bool) -> [a] -> [a]
    filter (Integer -> Integer -> Bool
    forall a. Eq a => a -> a -> Bool
    == Integer
    0) ([Integer] -> [Integer]) -> [Integer] -> [Integer]
    forall a b. (a -> b) -> a -> b
    $ Puzzle -> [Integer]
    forall (t :: * -> *) a. Foldable t => t [a] -> [a]
    concat Puzzle
    board
         [SInteger]
    subst <- Int -> Symbolic [SInteger]
    forall a. SymVal a => Int -> Symbolic [SBV a]
    mkFreeVars Int
    emptyCellCount
         SBool -> SymbolicT IO ()
    forall a. QuantifiedBool a => a -> SymbolicT IO ()
    forall (m :: * -> *) a.
    (SolverContext m, QuantifiedBool a) =>
    a -> m ()
    constrain (SBool -> SymbolicT IO ()) -> SBool -> SymbolicT IO ()
    forall a b. (a -> b) -> a -> b
    $ Board -> SBool
    valid ((Integer -> SInteger) -> [SInteger] -> Board
    forall {b}. (Integer -> b) -> [b] -> [[b]]
    fill Integer -> SInteger
    forall a. SymVal a => a -> SBV a
    literal [SInteger]
    subst)

         Query Puzzle -> Symbolic Puzzle
    forall a. Query a -> Symbolic a
    query (Query Puzzle -> Symbolic Puzzle)
    -> Query Puzzle -> Symbolic Puzzle
    forall a b. (a -> b) -> a -> b
    $ do CheckSatResult
    cs <- Query CheckSatResult
    checkSat
                    case CheckSatResult
    cs of
                      CheckSatResult
    Sat   -> do [Integer]
    vals <- (SInteger -> QueryT IO Integer)
    -> [SInteger] -> QueryT IO [Integer]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
    mapM SInteger -> QueryT IO Integer
    forall a. SymVal a => SBV a -> Query a
    getValue [SInteger]
    subst
                                  Puzzle -> Query Puzzle
    forall a. a -> QueryT IO a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (Puzzle -> Query Puzzle) -> Puzzle -> Query Puzzle
    forall a b. (a -> b) -> a -> b
    $ (Integer -> Integer) -> [Integer] -> Puzzle
    forall {b}. (Integer -> b) -> [b] -> [[b]]
    fill Integer -> Integer
    forall a. a -> a
    id [Integer]
    vals
                      CheckSatResult
    Unsat -> [Char] -> Query Puzzle
    forall a. HasCallStack => [Char] -> a
    error [Char]
    "Unsolvable puzzle!"
                      CheckSatResult
    _     -> [Char] -> Query Puzzle
    forall a. HasCallStack => [Char] -> a
    error ([Char] -> Query Puzzle) -> [Char] -> Query Puzzle
    forall a b. (a -> b) -> a -> b
    $ [Char]
    "Solver said: " [Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++ CheckSatResult -> [Char]
    forall a. Show a => a -> [Char]
    show CheckSatResult
    cs

     where fill :: (Integer -> b) -> [b] -> [[b]]
    fill Integer -> b
    xform = State [b] [[b]] -> [b] -> [[b]]
    forall s a. State s a -> s -> a
    evalState (([Integer] -> StateT [b] Identity [b]) -> Puzzle -> State [b] [[b]]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
    mapM ((Integer -> StateT [b] Identity b)
    -> [Integer] -> StateT [b] Identity [b]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
    mapM Integer -> StateT [b] Identity b
    forall {m :: * -> *}. MonadState [b] m => Integer -> m b
    replace) Puzzle
    board)
             where replace :: Integer -> m b
    replace Integer
    0 = do [b]
    supply <- m [b]
    forall s (m :: * -> *). MonadState s m => m s
    get
                                  case [b]
    supply of
                                    []     -> [Char] -> m b
    forall a. HasCallStack => [Char] -> a
    error [Char]
    "Run out of supplies while filling in the board!"
                                    (b
    s:[b]
    ss) -> [b] -> m ()
    forall s (m :: * -> *). MonadState s m => s -> m ()
    put [b]
    ss m () -> m b -> m b
    forall a b. m a -> m b -> m b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> b -> m b
    forall a. a -> m a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure b
    s
                   replace Integer
    n = b -> m b
    forall a. a -> m a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (b -> m b) -> b -> m b
    forall a b. (a -> b) -> a -> b
    $ Integer -> b
    xform Integer
    n

    -- | Solve a given puzzle and print the results
    sudoku :: Puzzle -> IO ()
    sudoku :: Puzzle -> IO ()
    sudoku Puzzle
    board = Puzzle -> IO Puzzle
    fillBoard Puzzle
    board IO Puzzle -> (Puzzle -> IO ()) -> IO ()
    forall a b. IO a -> (a -> IO b) -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= Puzzle -> IO ()
    displayBoard
     where displayBoard :: Puzzle -> IO ()
           displayBoard :: Puzzle -> IO ()
    displayBoard Puzzle
    puzzle = do
                let sh :: a -> a -> [Char]
    sh       a
    i a
    r = a -> [Char]
    forall a. Show a => a -> [Char]
    show a
    r [Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++ if a
    i a -> [a] -> Bool
    forall a. Eq a => a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` [a
    3, a
    6] then [Char]
    " " else [Char]
    ""
                    printRow :: a -> [b] -> IO ()
    printRow a
    i [b]
    r = do [Char] -> IO ()
    putStrLn ([Char] -> IO ()) -> [Char] -> IO ()
    forall a b. (a -> b) -> a -> b
    $ [Char]
    "    " [Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++ [[Char]] -> [Char]
    unwords ((Int -> b -> [Char]) -> [Int] -> [b] -> [[Char]]
    forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
    zipWith Int -> b -> [Char]
    forall {a} {a}. (Show a, Eq a, Num a) => a -> a -> [Char]
    sh [(Int
    1::Int)..] [b]
    r)
                                      Bool -> IO () -> IO ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    when (a
    i a -> [a] -> Bool
    forall a. Eq a => a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` [a
    3, a
    6]) (IO () -> IO ()) -> IO () -> IO ()
    forall a b. (a -> b) -> a -> b
    $ [Char] -> IO ()
    putStrLn [Char]
    ""
                (Int -> [Integer] -> IO ()) -> [Int] -> Puzzle -> IO ()
    forall (m :: * -> *) a b c.
    Applicative m =>
    (a -> b -> m c) -> [a] -> [b] -> m ()
    zipWithM_ Int -> [Integer] -> IO ()
    forall {b} {a}. (Show b, Eq a, Num a) => a -> [b] -> IO ()
    printRow [(Int
    1::Int)..] Puzzle
    puzzle

                let isValid :: SBool
    isValid = Board -> SBool
    valid (([Integer] -> [SInteger]) -> Puzzle -> Board
    forall a b. (a -> b) -> [a] -> [b]
    map ((Integer -> SInteger) -> [Integer] -> [SInteger]
    forall a b. (a -> b) -> [a] -> [b]
    map Integer -> SInteger
    forall a. SymVal a => a -> SBV a
    literal) Puzzle
    puzzle)
                case SBool -> Maybe Bool
    forall a. SymVal a => SBV a -> Maybe a
    unliteral SBool
    isValid of
                   Just Bool
    True  -> () -> IO ()
    forall a. a -> IO a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ()
                   Just Bool
    False -> [Char] -> IO ()
    forall a. HasCallStack => [Char] -> a
    error [Char]
    "Invalid solution generated!"
                   Maybe Bool
    Nothing    -> [Char] -> IO ()
    forall a. HasCallStack => [Char] -> a
    error [Char]
    "Impossible happened, got a symbolic result for valid."

    -------------------------------------------------------------------
    -- * Example boards
    -------------------------------------------------------------------

    -- | A random puzzle, found on the internet..
    puzzle1 :: Puzzle
    puzzle1 :: Puzzle
    puzzle1 = [ [Integer
    0, Integer
    6, Integer
    0,   Integer
    0, Integer
    0, Integer
    0,   Integer
    0, Integer
    1, Integer
    0]
              , [Integer
    0, Integer
    0, Integer
    0,   Integer
    6, Integer
    5, Integer
    1,   Integer
    0, Integer
    0, Integer
    0]
              , [Integer
    1, Integer
    0, Integer
    7,   Integer
    0, Integer
    0, Integer
    0,   Integer
    6, Integer
    0, Integer
    2]

              , [Integer
    6, Integer
    2, Integer
    0,   Integer
    3, Integer
    0, Integer
    5,   Integer
    0, Integer
    9, Integer
    4]
              , [Integer
    0, Integer
    0, Integer
    3,   Integer
    0, Integer
    0, Integer
    0,   Integer
    2, Integer
    0, Integer
    0]
              , [Integer
    4, Integer
    8, Integer
    0,   Integer
    9, Integer
    0, Integer
    7,   Integer
    0, Integer
    3, Integer
    6]

              , [Integer
    9, Integer
    0, Integer
    6,   Integer
    0, Integer
    0, Integer
    0,   Integer
    4, Integer
    0, Integer
    8]
              , [Integer
    0, Integer
    0, Integer
    0,   Integer
    7, Integer
    9, Integer
    4,   Integer
    0, Integer
    0, Integer
    0]
              , [Integer
    0, Integer
    5, Integer
    0,   Integer
    0, Integer
    0, Integer
    0,   Integer
    0, Integer
    7, Integer
    0] ]

    -- | Another random puzzle, found on the internet..
    puzzle2 :: Puzzle
    puzzle2 :: Puzzle
    puzzle2 = [ [Integer
    1, Integer
    0, Integer
    3,   Integer
    0, Integer
    0, Integer
    0,   Integer
    0, Integer
    8, Integer
    0]
              , [Integer
    0, Integer
    0, Integer
    6,   Integer
    0, Integer
    4, Integer
    8,   Integer
    0, Integer
    0, Integer
    0]
              , [Integer
    0, Integer
    4, Integer
    0,   Integer
    0, Integer
    0, Integer
    0,   Integer
    0, Integer
    0, Integer
    0]

              , [Integer
    2, Integer
    0, Integer
    0,   Integer
    0, Integer
    9, Integer
    6,   Integer
    1, Integer
    0, Integer
    0]
              , [Integer
    0, Integer
    9, Integer
    0,   Integer
    8, Integer
    0, Integer
    1,   Integer
    0, Integer
    4, Integer
    0]
              , [Integer
    0, Integer
    0, Integer
    4,   Integer
    3, Integer
    2, Integer
    0,   Integer
    0, Integer
    0, Integer
    8]

              , [Integer
    0, Integer
    0, Integer
    0,   Integer
    0, Integer
    0, Integer
    0,   Integer
    0, Integer
    7, Integer
    0]
              , [Integer
    0, Integer
    0, Integer
    0,   Integer
    1, Integer
    5, Integer
    0,   Integer
    4, Integer
    0, Integer
    0]
              , [Integer
    0, Integer
    6, Integer
    0,   Integer
    0, Integer
    0, Integer
    0,   Integer
    2, Integer
    0, Integer
    3] ]

    -- | Another random puzzle, found on the internet..
    puzzle3 :: Puzzle
    puzzle3 :: Puzzle
    puzzle3 = [ [Integer
    6, Integer
    0, Integer
    0,   Integer
    0, Integer
    1, Integer
    0,   Integer
    5, Integer
    0, Integer
    0]
              , [Integer
    8, Integer
    0, Integer
    3,   Integer
    0, Integer
    0, Integer
    0,   Integer
    0, Integer
    0, Integer
    0]
              , [Integer
    0, Integer
    0, Integer
    0,   Integer
    0, Integer
    6, Integer
    0,   Integer
    0, Integer
    2, Integer
    0]

              , [Integer
    0, Integer
    3, Integer
    0,   Integer
    1, Integer
    0, Integer
    8,   Integer
    0, Integer
    9, Integer
    0]
              , [Integer
    1, Integer
    0, Integer
    0,   Integer
    0, Integer
    9, Integer
    0,   Integer
    0, Integer
    0, Integer
    4]
              , [Integer
    0, Integer
    5, Integer
    0,   Integer
    2, Integer
    0, Integer
    3,   Integer
    0, Integer
    1, Integer
    0]

              , [Integer
    0, Integer
    7, Integer
    0,   Integer
    0, Integer
    3, Integer
    0,   Integer
    0, Integer
    0, Integer
    0]
              , [Integer
    0, Integer
    0, Integer
    0,   Integer
    0, Integer
    0, Integer
    0,   Integer
    3, Integer
    0, Integer
    6]
              , [Integer
    0, Integer
    0, Integer
    4,   Integer
    0, Integer
    5, Integer
    0,   Integer
    0, Integer
    0, Integer
    9] ]

    -- | According to the web, this is the toughest
    -- sudoku puzzle ever.. It even has a name: Al Escargot:
    -- <http://zonkedyak.blogspot.com/2006/11/worlds-hardest-sudoku-puzzle-al.html>
    puzzle4 :: Puzzle
    puzzle4 :: Puzzle
    puzzle4 = [ [Integer
    1, Integer
    0, Integer
    0,   Integer
    0, Integer
    0, Integer
    7,   Integer
    0, Integer
    9, Integer
    0]
              , [Integer
    0, Integer
    3, Integer
    0,   Integer
    0, Integer
    2, Integer
    0,   Integer
    0, Integer
    0, Integer
    8]
              , [Integer
    0, Integer
    0, Integer
    9,   Integer
    6, Integer
    0, Integer
    0,   Integer
    5, Integer
    0, Integer
    0]

              , [Integer
    0, Integer
    0, Integer
    5,   Integer
    3, Integer
    0, Integer
    0,   Integer
    9, Integer
    0, Integer
    0]
              , [Integer
    0, Integer
    1, Integer
    0,   Integer
    0, Integer
    8, Integer
    0,   Integer
    0, Integer
    0, Integer
    2]
              , [Integer
    6, Integer
    0, Integer
    0,   Integer
    0, Integer
    0, Integer
    4,   Integer
    0, Integer
    0, Integer
    0]

              , [Integer
    3, Integer
    0, Integer
    0,   Integer
    0, Integer
    0, Integer
    0,   Integer
    0, Integer
    1, Integer
    0]
              , [Integer
    0, Integer
    4, Integer
    0,   Integer
    0, Integer
    0, Integer
    0,   Integer
    0, Integer
    0, Integer
    7]
              , [Integer
    0, Integer
    0, Integer
    7,   Integer
    0, Integer
    0, Integer
    0,   Integer
    3, Integer
    0, Integer
    0] ]

    -- | This one has been called diabolical, apparently
    puzzle5 :: Puzzle
    puzzle5 :: Puzzle
    puzzle5 = [ [ Integer
    0, Integer
    9, Integer
    0,   Integer
    7, Integer
    0, Integer
    0,   Integer
    8, Integer
    6, Integer
    0]
              , [ Integer
    0, Integer
    3, Integer
    1,   Integer
    0, Integer
    0, Integer
    5,   Integer
    0, Integer
    2, Integer
    0]
              , [ Integer
    8, Integer
    0, Integer
    6,   Integer
    0, Integer
    0, Integer
    0,   Integer
    0, Integer
    0, Integer
    0]

              , [ Integer
    0, Integer
    0, Integer
    7,   Integer
    0, Integer
    5, Integer
    0,   Integer
    0, Integer
    0, Integer
    6]
              , [ Integer
    0, Integer
    0, Integer
    0,   Integer
    3, Integer
    0, Integer
    7,   Integer
    0, Integer
    0, Integer
    0]
              , [ Integer
    5, Integer
    0, Integer
    0,   Integer
    0, Integer
    1, Integer
    0,   Integer
    7, Integer
    0, Integer
    0]

              , [ Integer
    0, Integer
    0, Integer
    0,   Integer
    0, Integer
    0, Integer
    0,   Integer
    1, Integer
    0, Integer
    9]
              , [ Integer
    0, Integer
    2, Integer
    0,   Integer
    6, Integer
    0, Integer
    0,   Integer
    3, Integer
    5, Integer
    0]
              , [ Integer
    0, Integer
    5, Integer
    4,   Integer
    0, Integer
    0, Integer
    8,   Integer
    0, Integer
    7, Integer
    0] ]

    -- | The following is nefarious according to
    -- <http://haskell.org/haskellwiki/Sudoku>
    puzzle6 :: Puzzle
    puzzle6 :: Puzzle
    puzzle6 = [ [Integer
    0, Integer
    0, Integer
    0,   Integer
    0, Integer
    6, Integer
    0,   Integer
    0, Integer
    8, Integer
    0]
              , [Integer
    0, Integer
    2, Integer
    0,   Integer
    0, Integer
    0, Integer
    0,   Integer
    0, Integer
    0, Integer
    0]
              , [Integer
    0, Integer
    0, Integer
    1,   Integer
    0, Integer
    0, Integer
    0,   Integer
    0, Integer
    0, Integer
    0]

              , [Integer
    0, Integer
    7, Integer
    0,   Integer
    0, Integer
    0, Integer
    0,   Integer
    1, Integer
    0, Integer
    2]
              , [Integer
    5, Integer
    0, Integer
    0,   Integer
    0, Integer
    3, Integer
    0,   Integer
    0, Integer
    0, Integer
    0]
              , [Integer
    0, Integer
    0, Integer
    0,   Integer
    0, Integer
    0, Integer
    0,   Integer
    4, Integer
    0, Integer
    0]

              , [Integer
    0, Integer
    0, Integer
    4,   Integer
    2, Integer
    0, Integer
    1,   Integer
    0, Integer
    0, Integer
    0]
              , [Integer
    3, Integer
    0, Integer
    0,   Integer
    7, Integer
    0, Integer
    0,   Integer
    6, Integer
    0, Integer
    0]
              , [Integer
    0, Integer
    0, Integer
    0,   Integer
    0, Integer
    0, Integer
    0,   Integer
    0, Integer
    5, Integer
    0] ]

    -- | Solve them all, this takes a fraction of a second to run for each case
    allPuzzles :: IO ()
    allPuzzles :: IO ()
    allPuzzles = (Puzzle -> IO ()) -> [Puzzle] -> IO ()
    forall (t :: * -> *) (m :: * -> *) a b.
    (Foldable t, Monad m) =>
    (a -> m b) -> t a -> m ()
    mapM_ Puzzle -> IO ()
    sudoku [Puzzle
    puzzle1, Puzzle
    puzzle2, Puzzle
    puzzle3, Puzzle
    puzzle4, Puzzle
    puzzle5, Puzzle
    puzzle6]