Question

Je suis en train d'écrire un accessoire qui change un Sudoku et vérifie si elle est toujours valide.

Cependant, je ne suis pas sûr de savoir comment utiliser le -fonction « oneOf » correctement. Pouvez-vous me donner quelques conseils, s'il vous plaît?

prop_candidates :: Sudoku -> Bool
prop_candidates su = isSudoku newSu && isOkay newSu
    where
        newSu       = update su aBlank aCandidate
        aCandidate  = oneof [return x | x <- candidates su aBlank]
        aBlank      = oneof [return x | x <- (blanks su)]

Voici encore plus d'info ...

type Pos = (Int, Int)
update :: Sudoku -> Pos -> Maybe Int -> Sudoku
blanks :: Sudoku -> [Pos]
candidates :: Sudoku -> Pos -> [Int]
[return x | x <- (blanks example)] :: (Monad m) => [m Pos]

Je struggeled avec ce support pendant 3 heures maintenant, donc toutes les idées sont les bienvenues!

Était-ce utile?

La solution

Ce que je conduisais à est que vous avez un méli-mélo de type. A savoir, aBlank n'est pas un Pos, mais un Gen Pos, donc update su aBlank aCandidate n'a pas de sens! En fait, ce que vous voulez est un moyen de générer un nouveau donné un sudoku initial sudoku; autrement dit une fonction

similarSudoku :: Sudoku -> Gen Sudoku

Maintenant, nous pouvons écrire:

similarSudoku su = do aBlank <- elements (blanks su) 
                      -- simpler than oneOf [return x | x <- blanks su]
                      aCandidate <- elements (candidates su aBlank)
                      return (update su aBlank aCandidate)

ou encore plus simple:

similarSudoku su = liftM2 (update su) (elements (blanks su)) (elements (candidates su aBlank))

Et la propriété ressemble à

prop_similar :: Sudoku -> Gen Bool
prop_similar su = do newSu <- similarSudoku su
                     return (isSudoku newSu && isOkay newSu)

Comme il y a des cas

Testable Bool
Testable prop => Testable (Gen prop)
(Arbitrary a, Show a, Testable prop) => Testable (a -> prop)

Sudoku -> Gen Bool est Testable ainsi (en supposant instance Arbitrary Sudoku).

Autres conseils

Sur mon blog, je l'ai écrit un simple tests QuickCheck qui utilisent oneof pour générer des rouleaux intéressants.

Disons que nous avons un Sudoku super-simple d'une seule ligne:

module Main where
import Control.Monad
import Data.List
import Test.QuickCheck
import Debug.Trace

type Pos = Int
data Sudoku = Sudoku [Char] deriving (Show)

Pas de super-simple, Sudoku aurait des valeurs répétées:

prop_noRepeats :: Sudoku -> Bool
prop_noRepeats s@(Sudoku xs) =
  trace (show s) $ all ((==1) . length) $
                   filter ((/='.') . head) $
                   group $ sort xs

Vous pouvez générer un Sudoku super simple avec

instance Arbitrary Sudoku where
  arbitrary = sized board :: Gen Sudoku
    where board :: Int -> Gen Sudoku
          board 0 = Sudoku `liftM` shuffle values
          board n | n > 6 = resize 6 arbitrary
                  | otherwise =
                      do xs <- shuffle values
                         let removed = take n xs
                             dots = take n $ repeat '.'
                             remain = values \\ removed
                         ys <- shuffle $ dots ++ remain
                         return $ Sudoku ys

          values = ['1' .. '9']

          shuffle :: (Eq a) => [a] -> Gen [a]
          shuffle [] = return []
          shuffle xs = do x  <- oneof $ map return xs
                          ys <- shuffle $ delete x xs
                          return (x:ys)

Le trace est là pour montrer les cartes généré au hasard:

*Main> quickCheck prop_noRepeats 
Sudoku "629387451"
Sudoku "91.235786"
Sudoku "1423.6.95"
Sudoku "613.4..87"
Sudoku "6..5..894"
Sudoku "7.2..49.."
Sudoku "24....1.."
[...]
+++ OK, passed 100 tests.

il semble que aBlank :: Gen Pos qui ne correspond pas à la façon dont il est utilisé comme un argument de candidates :: Sudoku -> Pos -> [Int].

J'ai cherché par ici pour trouver un façon de convertir Gen a à a qui vous permettra de l'utiliser avec les candidats. Le mieux que je pouvais voir est la fonction generate.

Dites-moi si je me manque quelque chose ...

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top