sum-pyramid 0.0 → 0.0.1
raw patch · 9 files changed
+177/−142 lines, 9 filesdep ~basedep ~comfort-arraydep ~containers
Dependency ranges changed: base, comfort-array, containers, lapack, optparse-applicative, random
Files
- Makefile +1/−1
- puzzle.tex +2/−1
- src/Common.hs +28/−4
- src/LinearAlgebra.hs +29/−45
- src/Main.hs +35/−34
- src/UniqueLogic.hs +25/−28
- sum-pyramid.cabal +19/−7
- test/Test/LinearAlgebra.hs +14/−6
- test/Test/UniqueLogic.hs +24/−16
Makefile view
@@ -1,4 +1,4 @@-CABALOPTS :=+CABALOPTS := --disable-documentation .PHONY: all
puzzle.tex view
@@ -6,10 +6,11 @@ \usepackage{pict2e} \usepackage{color} -\newenvironment{puzzle}{\noindent\mbox{}\vfill}{\newpage}+\newenvironment{puzzle}{\noindent\mbox{}\vfill}{\vfill\newpage} \newcommand\puzzles{ \fontsize{36}{42}\selectfont+\linethickness{0.1em} \setlength{\unitlength}{2.1em} \input{mixed} %
src/Common.hs view
@@ -1,21 +1,45 @@+{-# LANGUAGE TypeFamilies #-} module Common where import qualified Data.Array.Comfort.Boxed as BoxedArray import qualified Data.Array.Comfort.Shape as Shape+import qualified Data.Set as Set import Data.Array.Comfort.Boxed (Array)+import Data.Map (Map)+import Data.Set (Set) +import qualified Combinatorics + data Op = Add | Mul deriving (Eq, Ord, Enum, Show) -sizeFromOps :: Array (Shape.LowerTriangular ShapeInt) op -> Int-sizeFromOps = succ . Shape.size . Shape.triangularSize . BoxedArray.shape+newtype ShapeOp = ShapeOp {shapeOpSize :: Int} +instance Shape.C ShapeOp where+ size (ShapeOp n) = max 0 $ n-1++instance Shape.Indexed ShapeOp where+ type Index ShapeOp = Int+ indices sh = take (Shape.size sh) [0..]+ unifiedOffset sh = Shape.unifiedOffset (Shape.ZeroBased (Shape.size sh))+++sizeFromOps :: Array (Shape.LowerTriangular ShapeOp) op -> Int+sizeFromOps = shapeOpSize . Shape.triangularSize . BoxedArray.shape++ type ShapeInt = Shape.ZeroBased Int type SolutionCheck a =- BoxedArray.Array (Shape.LowerTriangular ShapeInt) Op ->- [((Int,Int),a)] ->+ BoxedArray.Array (Shape.LowerTriangular ShapeOp) Op ->+ Map (Int,Int) a -> Bool+++allCellSelections :: Int -> [Set (Int, Int)]+allCellSelections n =+ map Set.fromList $ Combinatorics.tuples n $ Shape.indices $+ Shape.lowerTriangular $ Shape.ZeroBased n
src/LinearAlgebra.hs view
@@ -1,5 +1,7 @@ module LinearAlgebra where +import Common (allCellSelections)+ import qualified Numeric.LAPACK.Matrix.Triangular as Triangular import qualified Numeric.LAPACK.Matrix.Layout as Layout import qualified Numeric.LAPACK.Matrix as Matrix@@ -8,14 +10,14 @@ import Numeric.LAPACK.Matrix (ShapeInt, (#*|)) import Numeric.LAPACK.Format ((##)) -import qualified Combinatorics- import qualified Data.Array.Comfort.Boxed as BoxedArray import qualified Data.Array.Comfort.Storable as Array+import qualified Data.Array.Comfort.Bool as ComfortSet import qualified Data.Array.Comfort.Shape as Shape-import qualified Data.IntSet as IntSet-import qualified Data.Set as Set+import qualified Data.Map as Map import Data.Array.Comfort.Storable (Array)+import Data.Map (Map)+import Data.Set (Set) import Data.Foldable (for_) import Data.Tuple.HT (mapSnd)@@ -24,6 +26,7 @@ {- $setup >>> import qualified Data.Array.Comfort.Storable as Array+>>> import qualified Data.Map as Map >>> import Data.Tuple.HT (mapSnd) >>> >>> myRound :: Double -> Integer@@ -71,45 +74,43 @@ Matrix.fromRows (Shape.lowerTriangular shape) $ map (pyramid . Vector.unit shape) $ take n [0..] -addIndices :: [[Maybe a]] -> [((Int,Int), a)]-addIndices puzzle = do+addIndices :: [[Maybe a]] -> Map (Int,Int) a+addIndices puzzle = Map.fromList $ do (i, xs) <- zip [0..] puzzle (j, Just x) <- zip [0..] xs return ((i,j),x) {- |->>> mapSnd (map myRound . Array.toList) $ solve 3 [((0,0),8), ((2,0),1), ((2,2),3)]+>>> mapSnd (map myRound . Array.toList) $ solve 3 $ Map.fromList [((0,0),8), ((2,0),1), ((2,2),3)] (3,[8,3,5,1,2,3]) -} solve ::- Int -> [((Int,Int),Double)] ->+ Int -> Map (Int,Int) Double -> (Int, Array (Shape.LowerTriangular ShapeInt) Double) solve n indexed = let fullBasis = Matrix.transpose $ basis (Matrix.shapeInt n)- selected =- Matrix.takeRowArray- (BoxedArray.vectorFromList (map fst indexed))- fullBasis+ selected = Matrix.takeRowSet (Map.keysSet indexed) fullBasis in mapSnd ((fullBasis #*|) . Matrix.flattenColumn) (Singular.leastSquaresMinimumNormRCond 1e-5 selected $- Matrix.singleColumn Layout.ColumnMajor $- Vector.autoFromList (map snd indexed))+ Matrix.singleColumn Layout.ColumnMajor $ Array.fromMap indexed) -solvable :: Int -> [(Int,Int)] -> Bool+solvable :: Int -> Set (Int,Int) -> Bool solvable n = let shape = Matrix.shapeInt n fullBasis = basis shape in \ixs -> (n==) $ length $ takeWhile (1e-5<) $ Vector.toList $- (#*| Vector.one shape) $ Singular.values $- Matrix.takeColumnArray (BoxedArray.vectorFromList ixs) fullBasis+ (#*| Vector.one ixs) $ Singular.values $+ Matrix.takeColumnSet ixs fullBasis -solvables :: Int -> [[(Int,Int)]]+{- |+>>> map (length . solvables) [0..5]+[1,1,3,17,149,1824]+-}+solvables :: Int -> [Set (Int,Int)] solvables n = let check = solvable n- in filter check $- Combinatorics.tuples n $ Shape.indices $- Shape.lowerTriangular $ Matrix.shapeInt n+ in filter check $ allCellSelections n {- Check, whether a sum pyramid contains a sub-pyramid of size k@@ -117,27 +118,12 @@ If yes, then the pyramid has redundancies in a sub-pyramid and is not solvable. -}-wellcrowded :: Int -> [(Int,Int)] -> Bool+wellcrowded :: Int -> Set (Int,Int) -> Bool wellcrowded n ixs = let triShape = Shape.lowerTriangular $ Matrix.shapeInt n- set = Set.fromList ixs- countSubTriangle (i,j) k =- length $- filter (\(si,sj) -> Set.member (i+si,j+sj) set) $- Shape.indices $ Shape.lowerTriangular $ Matrix.shapeInt k- in and $ do- (i,j) <- Shape.indices triShape- k <- [0..n-i]- return $ countSubTriangle (i,j) k <= k--wellcrowdedIntSet :: Int -> [(Int,Int)] -> Bool-wellcrowdedIntSet n ixs =- let triShape = Shape.lowerTriangular $ Matrix.shapeInt n- set = IntSet.fromList $ map (Shape.offset triShape) ixs+ set = ComfortSet.fromSet triShape ixs countSubTriangle (i,j) k =- length $- filter (\(si,sj) ->- flip IntSet.member set $ Shape.offset triShape (i+si,j+sj)) $+ length $ filter (\(si,sj) -> ComfortSet.member (i+si,j+sj) set) $ Shape.indices $ Shape.lowerTriangular $ Matrix.shapeInt k in and $ do (i,j) <- Shape.indices triShape@@ -155,20 +141,18 @@ . * . * . . * -}-counterexamples :: Int -> [[(Int, Int)]]+counterexamples :: Int -> [Set (Int, Int)] counterexamples n = let check = solvable n- in filter (\ixs -> check ixs /= wellcrowded n ixs) $- Combinatorics.tuples n $ Shape.indices $- Shape.lowerTriangular $ Matrix.shapeInt n+ in filter (\ixs -> check ixs /= wellcrowded n ixs) $ allCellSelections n -boolMatrix :: Int -> [(Int, Int)] -> Matrix.Lower ShapeInt Float+boolMatrix :: Int -> Set (Int, Int) -> Matrix.Lower ShapeInt Float boolMatrix n ixs = Triangular.fromLowerRowMajor $ Array.fromAssociations 0 (Shape.lowerTriangular $ Matrix.shapeInt n)- (map (\ix -> (ix,1::Float)) ixs)+ (Map.toList $ Map.fromSet (const (1::Float)) ixs) test :: IO ()
src/Main.hs view
@@ -4,11 +4,9 @@ import qualified UniqueLogic as Logic import Common -import qualified Combinatorics- import qualified Control.Monad.Trans.Class as MT import qualified Control.Monad.Trans.State as MS-import Control.Monad (replicateM, join)+import Control.Monad (replicateM, join, guard) import Control.Applicative (pure, (<*>), (<|>)) import qualified System.Random as Random@@ -18,6 +16,7 @@ import qualified Data.Array.Comfort.Boxed as BoxedArray import qualified Data.Array.Comfort.Shape as Shape import qualified Data.List.HT as ListHT+import qualified Data.Map as Map import qualified Data.Set as Set import Data.Array.Comfort.Boxed (Array, (!)) import Data.Foldable (for_)@@ -47,7 +46,7 @@ Allowed -> Array ShapeInt Integer -> MS.State g- (Array (Shape.LowerTriangular ShapeInt) Op,+ (Array (Shape.LowerTriangular ShapeOp) Op, Array (Shape.LowerTriangular ShapeInt) Integer) pyramid allowed base = do let nextRow xs =@@ -71,10 +70,9 @@ else go ys0 let xs0 = BoxedArray.toList base let shape@(Shape.ZeroBased n) = BoxedArray.shape base- let shape1 = Shape.ZeroBased (n-1) (ops,xs) <- go xs0 return- (BoxedArray.fromList (Shape.lowerTriangular shape1) $+ (BoxedArray.fromList (Shape.lowerTriangular (ShapeOp n)) $ concat $ reverse ops, BoxedArray.fromList (Shape.lowerTriangular shape) $ concat $ reverse (xs0:xs))@@ -84,7 +82,7 @@ SolutionCheck Integer -> Allowed -> Int -> Integer -> MS.State g- (Array (Shape.LowerTriangular ShapeInt) Op,+ (Array (Shape.LowerTriangular ShapeOp) Op, Array (Shape.LowerTriangular ShapeInt) (Integer,Bool)) construct check allowed n maxV = do let shape = Shape.ZeroBased n@@ -95,7 +93,7 @@ selected <- MS.evalStateT (replicateM n pick) $ Set.fromList $ Shape.indices triShape- let puzzle = map (\ij -> (ij, pyr!ij)) selected+ let puzzle = Map.fromSet (pyr!) $ Set.fromList selected if check ops puzzle then return selected else go@@ -107,35 +105,39 @@ latexFromPuzzle :: String ->- Either Int (Array (Shape.LowerTriangular ShapeInt) Op) ->+ Either Int (Array (Shape.LowerTriangular ShapeOp) Op) -> Array (Shape.LowerTriangular ShapeInt) (Integer,Bool) -> [String]-latexFromPuzzle hidden mops xs =+latexFromPuzzle hiddenMacro mops xs = let n = either id sizeFromOps mops in printf "\\begin{picture}(%d,%d)" (2*n) n :- map (\(i,j) -> printf "\\put(%d,%d){\\framebox(2,1){}}" (n-1-i + 2*j) (n-i))- (Shape.indices $ Shape.lowerTriangular $ Shape.ZeroBased n) ++- (BoxedArray.toAssociations xs >>= \((i,j),(x,display)) ->- if null hidden && not display- then []- else- let cell :: String- cell =- if display- then printf "%d" x- else printf "\\%s{%d}" hidden x- in [printf "\\put(%d,%d){\\makebox(2,1)[c]{%s}}"- (n-1-i + 2*j) (n-i) cell]) +++ (take n [0..] >>= \i ->+ printf "\\put(%d,%d){\\line(0,-1){1}\\line(1,0){%d}\\line(0,-1){1}}"+ (n-1-i) (n-i) (2*i+2) :+ flip map (take (n-i-1) $ iterate (2+) (2+i)) (\j ->+ printf "\\put(%d,%d){\\line(0,1){1}}" j i)) +++ printf "\\put(0,0){\\line(1,0){%d}}" (2*n) :+ (do+ ((i,j),(x,display)) <- BoxedArray.toAssociations xs+ guard $ display || not (null hiddenMacro)+ let cell :: String+ cell =+ if display+ then printf "%d" x+ else printf "\\%s{%d}" hiddenMacro x+ [printf "\\put(%d,%d){\\makebox(2,1)[c]{%s}}" (n-1-i + 2*j) (n-i-1) cell])+ ++ (case mops of Left _ -> [] Right ops -> let half = 0.5 :: Double in BoxedArray.toAssociations ops >>= \((i,j),op) ->+ let h = n-i-1 in [printf "\\put(%d,%d){\\textcolor{white}{\\circle*{0.5}}}"- (n-i + 2*j) (n-i),- printf "\\put(%d,%d){\\circle{0.5}}" (n-i + 2*j) (n-i),+ (n-i + 2*j) h,+ printf "\\put(%d,%d){\\circle{0.5}}" (n-i + 2*j) h, printf "\\put(%.1f,%.1f){\\makebox(1,1)[c]{$%s$}}"- (fromIntegral (n-i + 2*j) - half) (fromIntegral (n-i) - half)+ (fromIntegral (n-i + 2*j) - half) (fromIntegral h - half) (case op of Add -> "+"; Mul -> "\\times{}")]) ++ "\\end{picture}" : []@@ -143,7 +145,7 @@ mainCreate :: (SolutionCheck Integer, (Allowed,Bool)) -> Int -> Int -> Integer -> String -> String -> IO ()-mainCreate (check,(allowed,displayOps)) n number maxV env hidden =+mainCreate (check,(allowed,displayOps)) n number maxV env hiddenMacro = putStr . unlines . concatMap ((if null env@@ -151,7 +153,7 @@ else (\pic -> printf "\\begin{%s}" env : pic ++ printf "\\end{%s}" env : []))- . uncurry (latexFromPuzzle hidden)+ . uncurry (latexFromPuzzle hiddenMacro) . mapFst (if displayOps then Right else const (Left n))) . MS.evalState (replicateM number $ construct check allowed n maxV) =<< Random.initStdGen@@ -163,10 +165,11 @@ <*> ( (OP.flag'- (\ops xs -> LinAlg.solvable (sizeFromOps ops) (map fst xs),+ (\ops xs ->+ LinAlg.solvable (sizeFromOps ops) (Map.keysSet xs), (Allowed {allowedAdd = True, allowedMul = False}, False)) $ OP.long "allow-gaps" <>- OP.help "Employ both addition and multiplication")+ OP.help "Puzzles maybe not be solvable step by step") <|> (fmap ((,) Logic.solvableMixed) $ (OP.flag'@@ -249,12 +252,10 @@ 573549 13604001 -}-mainCount :: (Int -> [(Int,Int)] -> Bool) -> IO ()+mainCount :: (Int -> Set (Int,Int) -> Bool) -> IO () mainCount check = for_ [0..] $ \n ->- print $ length $ filter (check n) $- Combinatorics.tuples n $ Shape.indices $- Shape.lowerTriangular $ Shape.ZeroBased n+ print $ length $ filter (check n) $ allCellSelections n commandCount :: OP.Mod OP.CommandFields (IO ()) commandCount =
src/UniqueLogic.hs view
@@ -6,23 +6,24 @@ import qualified UniqueLogic.ST.TF.System.Simple as Sys import qualified UniqueLogic.ST.TF.ZeroFractional as ZeroFrac -import qualified Combinatorics- import Control.Monad.ST (ST, runST) import qualified Data.Array.Comfort.Boxed as BoxedArray import qualified Data.Array.Comfort.Shape as Shape import qualified Data.Traversable as Trav import qualified Data.Foldable as Fold+import qualified Data.Map as Map import Data.Array.Comfort.Boxed ((!))+import Data.Map (Map)+import Data.Set (Set) import Data.Foldable (for_, traverse_) import Data.Maybe (isJust)-import Data.Tuple.HT (mapSnd) {- $setup >>> import qualified Data.Array.Comfort.Boxed as BoxedArray >>> import qualified Data.Array.Comfort.Shape as Shape+>>> import qualified Data.Map as Map >>> import Common -} @@ -32,11 +33,8 @@ system :: BoxedArray.Array- (Shape.LowerTriangular ShapeInt)- (Variable s a ->- Variable s a ->- Variable s a ->- System s ()) ->+ (Shape.LowerTriangular ShapeOp)+ (Variable s a -> Variable s a -> Variable s a -> System s ()) -> ST s (BoxedArray.Array (Shape.LowerTriangular ShapeInt) (Variable s a), System s ())@@ -55,40 +53,38 @@ {- |->>> solve 3 [((0,0),1), ((1,0),1), ((2,0),1::Integer)]+>>> solve 3 $ Map.fromList [((0,0),1), ((1,0),1), ((2,0),1::Integer)] BoxedArray...Triangular... 3... [Just 1,Just 1,Just 0,Just 1,Just 0,Just 0] ->>> solve 3 [((0,0),1), ((2,0),1), ((2,2),1::Integer)]+>>> solve 3 $ Map.fromList [((0,0),1), ((2,0),1), ((2,2),1::Integer)] BoxedArray...Triangular... 3... [Just 1,Nothing,Nothing,Just 1,Nothing,Just 1] -} solve :: (Num a) =>- Int -> [((Int,Int),a)] ->+ Int -> Map (Int,Int) a -> BoxedArray.Array (Shape.LowerTriangular ShapeInt) (Maybe a) solve n xs = runST (do (vars, sys) <- system $- BoxedArray.replicate- (Shape.lowerTriangular $ Shape.ZeroBased $ n-1)- Rule.add+ BoxedArray.replicate (Shape.lowerTriangular $ ShapeOp n) Rule.add Sys.solve $ do sys- for_ xs $ \(ij,x) ->+ for_ (Map.toList xs) $ \(ij,x) -> Rule.equ (vars!ij) =<< Sys.constant x traverse Sys.query vars) {- |->>> solveMixed (BoxedArray.fromList (Shape.lowerTriangular $ Shape.ZeroBased 1) [Mul]) [((0,0),0), ((1,1),0::Rational)]+>>> solveMixed (BoxedArray.fromList (Shape.lowerTriangular $ ShapeOp 2) [Mul]) (Map.fromList [((0,0),0), ((1,1),0::Rational)]) BoxedArray...Triangular... 2... [Just (0 % 1),Nothing,Just (0 % 1)]->>> solveMixed (BoxedArray.fromList (Shape.lowerTriangular $ Shape.ZeroBased 1) [Mul]) [((0,0),0), ((1,1),5::Rational)]+>>> solveMixed (BoxedArray.fromList (Shape.lowerTriangular $ ShapeOp 2) [Mul]) (Map.fromList [((0,0),0), ((1,1),5::Rational)]) BoxedArray...Triangular... 2... [Just (0 % 1),Just (0 % 1),Just (5 % 1)] -} solveMixed :: (ZeroFrac.C a) =>- BoxedArray.Array (Shape.LowerTriangular ShapeInt) Op ->- [((Int,Int),a)] ->+ BoxedArray.Array (Shape.LowerTriangular ShapeOp) Op ->+ Map (Int,Int) a -> BoxedArray.Array (Shape.LowerTriangular ShapeInt) (Maybe a) solveMixed ops xs = runST@@ -100,21 +96,22 @@ (vars, sys) <- system $ fmap rule ops Sys.solve $ do sys- for_ xs $ \(ij,x) ->+ for_ (Map.toList xs) $ \(ij,x) -> Rule.equ (vars!ij) =<< Sys.constant x traverse Sys.query vars) -solvable :: Int -> [(Int, Int)] -> Bool-solvable n = Fold.all isJust . solve n . map (\ij -> (ij, 0::Integer))+solvable :: Int -> Set (Int, Int) -> Bool+solvable n = Fold.all isJust . solve n . Map.fromSet (const (0::Integer)) -solvables :: Int -> [[(Int,Int)]]-solvables n =- filter (solvable n) $- Combinatorics.tuples n $ Shape.indices $- Shape.lowerTriangular $ Shape.ZeroBased n+{- |+>>> map (length . solvables) [0..5]+[1,1,3,16,122,1188]+-}+solvables :: Int -> [Set (Int,Int)]+solvables n = filter (solvable n) $ allCellSelections n solvableMixed :: SolutionCheck Integer solvableMixed ops puzzle =- Fold.all isJust $ solveMixed ops $ map (mapSnd toRational) puzzle+ Fold.all isJust $ solveMixed ops $ fmap toRational puzzle
sum-pyramid.cabal view
@@ -1,5 +1,5 @@ Name: sum-pyramid-Version: 0.0+Version: 0.0.1 Synopsis: Create Sum Pyramid (Additionstreppe) exercises Description: Create Sum Pyramid (Additionstreppe) exercises.@@ -7,6 +7,18 @@ and the program emits LaTeX code for puzzles. . > sum-pyramid create --size 5+ .+ > nix-shell --run "make puzzle.pdf"+ .+ You may also use multiplications (@--multiplication@),+ or both addition and multiplication (@--mixed@).+ In case of additions only,+ you may allow puzzles that are uniquely solvable,+ but possibly not step-by-step (@--allow-gaps@).+ You can also control via LaTeX macros+ whether and how unknown cells are displayed.+ .+ Example output: http://code.henning-thielemann.de/sum-pyramid/puzzle.pdf Homepage: https://hub.darcs.net/thielema/sum-pyramid License: BSD3 License-File: LICENSE@@ -21,7 +33,7 @@ puzzle.tex Source-Repository this- Tag: 0.0+ Tag: 0.0.1 Type: darcs Location: https://hub.darcs.net/thielema/sum-pyramid @@ -31,12 +43,12 @@ Executable sum-pyramid Build-Depends:- lapack >=0.5.1 && <0.6,+ lapack >=0.5.2 && <0.6, unique-logic-tf >=0.5.1 && <0.6, combinatorial >=0.1.1 && <0.2,- random >=1.2.1 && <1.3,- comfort-array >=0.5 && <0.6,- containers >=0.5.4 && <0.8,+ random >=1.2.1 && <1.4,+ comfort-array >=0.5.5 && <0.6,+ containers >=0.5.4 && <0.9, transformers >=0.3 && <0.7, shell-utility >=0.1 && <0.2, optparse-applicative >=0.11 && <0.19,@@ -63,7 +75,7 @@ containers, transformers, utility-ht,- base+ base >=4.5 && <5 Default-Language: Haskell2010 GHC-Options: -Wall Hs-Source-Dirs: src, test
test/Test/LinearAlgebra.hs view
@@ -1,5 +1,5 @@ -- Do not edit! Automatically created with doctest-extract from src/LinearAlgebra.hs-{-# LINE 25 "src/LinearAlgebra.hs" #-}+{-# LINE 27 "src/LinearAlgebra.hs" #-} module Test.LinearAlgebra where @@ -7,8 +7,9 @@ import Test.DocTest.Base import qualified Test.DocTest.Driver as DocTest -{-# LINE 26 "src/LinearAlgebra.hs" #-}+{-# LINE 28 "src/LinearAlgebra.hs" #-} import qualified Data.Array.Comfort.Storable as Array+import qualified Data.Map as Map import Data.Tuple.HT (mapSnd) myRound :: Double -> Integer@@ -16,10 +17,17 @@ test :: DocTest.T () test = do- DocTest.printPrefix "LinearAlgebra:81: "-{-# LINE 81 "src/LinearAlgebra.hs" #-}+ DocTest.printPrefix "LinearAlgebra:84: "+{-# LINE 84 "src/LinearAlgebra.hs" #-} DocTest.example(-{-# LINE 81 "src/LinearAlgebra.hs" #-}- mapSnd (map myRound . Array.toList) $ solve 3 [((0,0),8), ((2,0),1), ((2,2),3)]+{-# LINE 84 "src/LinearAlgebra.hs" #-}+ mapSnd (map myRound . Array.toList) $ solve 3 $ Map.fromList [((0,0),8), ((2,0),1), ((2,2),3)] ) [ExpectedLine [LineChunk "(3,[8,3,5,1,2,3])"]]+ DocTest.printPrefix "LinearAlgebra:107: "+{-# LINE 107 "src/LinearAlgebra.hs" #-}+ DocTest.example(+{-# LINE 107 "src/LinearAlgebra.hs" #-}+ map (length . solvables) [0..5]+ )+ [ExpectedLine [LineChunk "[1,1,3,17,149,1824]"]]
test/Test/UniqueLogic.hs view
@@ -10,35 +10,43 @@ {-# LINE 24 "src/UniqueLogic.hs" #-} import qualified Data.Array.Comfort.Boxed as BoxedArray import qualified Data.Array.Comfort.Shape as Shape+import qualified Data.Map as Map import Common test :: DocTest.T () test = do- DocTest.printPrefix "UniqueLogic:58: "-{-# LINE 58 "src/UniqueLogic.hs" #-}+ DocTest.printPrefix "UniqueLogic:56: "+{-# LINE 56 "src/UniqueLogic.hs" #-} DocTest.example(-{-# LINE 58 "src/UniqueLogic.hs" #-}- solve 3 [((0,0),1), ((1,0),1), ((2,0),1::Integer)]+{-# LINE 56 "src/UniqueLogic.hs" #-}+ solve 3 $ Map.fromList [((0,0),1), ((1,0),1), ((2,0),1::Integer)] ) [ExpectedLine [LineChunk "BoxedArray",WildCardChunk,LineChunk "Triangular",WildCardChunk,LineChunk " 3",WildCardChunk,LineChunk " [Just 1,Just 1,Just 0,Just 1,Just 0,Just 0]"]]- DocTest.printPrefix "UniqueLogic:61: "-{-# LINE 61 "src/UniqueLogic.hs" #-}+ DocTest.printPrefix "UniqueLogic:59: "+{-# LINE 59 "src/UniqueLogic.hs" #-} DocTest.example(-{-# LINE 61 "src/UniqueLogic.hs" #-}- solve 3 [((0,0),1), ((2,0),1), ((2,2),1::Integer)]+{-# LINE 59 "src/UniqueLogic.hs" #-}+ solve 3 $ Map.fromList [((0,0),1), ((2,0),1), ((2,2),1::Integer)] ) [ExpectedLine [LineChunk "BoxedArray",WildCardChunk,LineChunk "Triangular",WildCardChunk,LineChunk " 3",WildCardChunk,LineChunk " [Just 1,Nothing,Nothing,Just 1,Nothing,Just 1]"]]- DocTest.printPrefix "UniqueLogic:83: "-{-# LINE 83 "src/UniqueLogic.hs" #-}+ DocTest.printPrefix "UniqueLogic:79: "+{-# LINE 79 "src/UniqueLogic.hs" #-} DocTest.example(-{-# LINE 83 "src/UniqueLogic.hs" #-}- solveMixed (BoxedArray.fromList (Shape.lowerTriangular $ Shape.ZeroBased 1) [Mul]) [((0,0),0), ((1,1),0::Rational)]+{-# LINE 79 "src/UniqueLogic.hs" #-}+ solveMixed (BoxedArray.fromList (Shape.lowerTriangular $ ShapeOp 2) [Mul]) (Map.fromList [((0,0),0), ((1,1),0::Rational)]) ) [ExpectedLine [LineChunk "BoxedArray",WildCardChunk,LineChunk "Triangular",WildCardChunk,LineChunk " 2",WildCardChunk,LineChunk " [Just (0 % 1),Nothing,Just (0 % 1)]"]]- DocTest.printPrefix "UniqueLogic:85: "-{-# LINE 85 "src/UniqueLogic.hs" #-}+ DocTest.printPrefix "UniqueLogic:81: "+{-# LINE 81 "src/UniqueLogic.hs" #-} DocTest.example(-{-# LINE 85 "src/UniqueLogic.hs" #-}- solveMixed (BoxedArray.fromList (Shape.lowerTriangular $ Shape.ZeroBased 1) [Mul]) [((0,0),0), ((1,1),5::Rational)]+{-# LINE 81 "src/UniqueLogic.hs" #-}+ solveMixed (BoxedArray.fromList (Shape.lowerTriangular $ ShapeOp 2) [Mul]) (Map.fromList [((0,0),0), ((1,1),5::Rational)]) ) [ExpectedLine [LineChunk "BoxedArray",WildCardChunk,LineChunk "Triangular",WildCardChunk,LineChunk " 2",WildCardChunk,LineChunk " [Just (0 % 1),Just (0 % 1),Just (5 % 1)]"]]+ DocTest.printPrefix "UniqueLogic:108: "+{-# LINE 108 "src/UniqueLogic.hs" #-}+ DocTest.example(+{-# LINE 108 "src/UniqueLogic.hs" #-}+ map (length . solvables) [0..5]+ )+ [ExpectedLine [LineChunk "[1,1,3,16,122,1188]"]]