@@ -139,19 +139,17 @@ module Sudoku where
139
139
-- * C1
140
140
-- | cell generates an arbitrary cell in a Sudoku
141
141
cell :: Gen (Cell )
142
- cell = frequency [(4 , elements [Just n | n <- [1 .. 9 ]]),(9 ,elements [Nothing ])]
142
+ cell = frequency [(4 , elements [Just n | n <- [1 .. 9 ]]),(5 ,elements [Nothing ])]
143
143
144
144
-- * C2
145
145
-- | an instance for generating Arbitrary Sudokus
146
146
instance Arbitrary Sudoku where
147
147
arbitrary = Sudoku <$> (vectorOf 9 $ vectorOf 9 cell)
148
148
149
- -- hint: get to know the QuickCheck function vectorOf
150
149
-- * C3
151
150
prop_Sudoku :: Sudoku -> Bool
152
151
prop_Sudoku sud = isSudoku sud
153
152
154
- -- hint: this definition is simple!
155
153
------------------------------------------------------------------------------
156
154
type Block = [Cell ] -- a Row is also a Cell
157
155
-- * D1
@@ -231,24 +229,28 @@ module Sudoku where
231
229
where (head , _: tail ) = splitAt i list
232
230
233
231
232
+ -- | Checks that !!= operator work as intended
234
233
prop_bangBangEquals_correct :: [Maybe Int ] -> (Int ,(Maybe Int )) -> Bool
235
234
prop_bangBangEquals_correct list (i,v) | length list == 0 = (list !!= (0 ,v)) == []
236
235
| list !! i' == v = list == list !!= (i',v)
237
236
| otherwise = list /= list !!= (i',v)
238
237
where i' = if abs i >= length list then mod i $ length list else abs i
239
238
240
239
-- * E3
240
+ -- | Updates a given sudoku with a given value at a given position
241
241
update :: Sudoku -> Pos -> Cell -> Sudoku
242
242
update (Sudoku sud) (r,c) val = Sudoku (head ++ [upDatedRow] ++ tail )
243
243
where upDatedRow = (sud !! r) !!= (c,val)
244
- (head , _: tail ) = splitAt r sud
245
-
244
+ (head , _: tail ) = splitAt r sud
245
+
246
+ -- | Checks that function update work as intended
246
247
prop_update_updated :: Sudoku -> Pos -> Cell -> Bool
247
248
prop_update_updated s (i,j) c | c == takeCell (rows s) p' = s == update s p' c
248
249
| otherwise = s /= update s p' c
249
- where p' = if abs i > 8 || abs j > 8 then (mod i 8 , mod j 8 ) else (abs i, abs j)
250
+ where p' = if abs i > 8 || abs j > 8 then (mod i 8 , mod j 8 ) else (abs i, abs j) -- Could maybe have restricted (i,j) with a property test instead
250
251
------------------------------------------------------------------------------
251
252
-- * F1
253
+ -- | Produces one solution (if there is one) for a given sudoku
252
254
solve :: Sudoku -> Maybe Sudoku
253
255
solve sudoku = if length solution == 0 then Nothing else Just $ head solution
254
256
where solution = take 1 $ solve' sudoku $ blanks sudoku
@@ -260,21 +262,26 @@ module Sudoku where
260
262
| otherwise = filter (\ x -> isOkay x && isFilled x) solution
261
263
where solution = concat [solve' (update sudoku (head blank) (Just c)) (drop 1 blank) | c <- [1 .. 9 ]]
262
264
263
- -- * F2 reads a sudoku from a file, solves it and prints the solution if found
265
+ -- * F2
266
+ -- | Reads a sudoku from a file, solves it and prints the solution if found
264
267
readAndSolve :: FilePath -> IO ()
265
268
readAndSolve file = do
266
269
sud <- readSudoku file
267
270
let solved = solve sud
268
271
if solved == Nothing then putStr " No solution found\n " else printSudoku (fromJust $ solve sud)
269
272
270
- -- * F3 checks wheter the first sudoku is a solution to the second sudoku
273
+ -- * F3
274
+ -- | Checks whether the first sudoku is a solution to the second sudoku
271
275
isSolutionOf :: Sudoku -> Sudoku -> Bool
272
276
isSolutionOf s1 s2 = isSudoku s1 && isOkay s1 && isFilled s1 && containsAll
273
277
where containsAll = all (\ (x1,x2) -> x1 == x2) $ filter (\ (c1,c2) -> c2 /= Nothing ) $ zip (concat $ rows s1) (concat $ rows s2)
274
278
275
279
-- * F4
276
- prop_SolveSound :: Sudoku -> Bool
277
- prop_SolveSound sudoku = all (\ y -> isSolutionOf y sudoku) (solve' sudoku (blanks sudoku)) -- ==> isSudoku sudoku
278
- -- all (\y -> isSolutionOf y sudoku) (filter (\x -> isOkay x && isFilled x && isSudoku x) (solve' sudoku (blanks sudoku))) -- ==> isSudoku sudoku && isOkay sudoku
279
-
280
- fewerChecks prop = quickCheckWith stdArgs{maxSuccess= 40 } prop
280
+ -- | Tests if all solutions to a sudoku is a valid solution
281
+ prop_SolveSound :: Sudoku -> Property
282
+ prop_SolveSound sudoku = isSudoku sudoku && isOkay sudoku ==> solveSound (solve sudoku) sudoku
283
+ where solveSound :: Maybe Sudoku -> Sudoku -> Bool
284
+ solveSound (Just sudoku) sud = isSolutionOf (fromJust $ Just sudoku) sud
285
+ solveSound Nothing _ = False
286
+
287
+ fewerChecks prop = quickCheckWith stdArgs{maxSuccess= 30 } prop
0 commit comments