Frage

Ich versuche, eine Stütze zu schreiben, die ein Sudoku ändert und überprüft dann, ob es noch gültig ist.

Ich bin aber nicht sicher, wie die „oneof“ -Funktion richtig zu verwenden. Können Sie mir einige Hinweise geben, bitte?

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)]

Hier sind einige weitere Informationen ...

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]

Ich habe mit dieser Stütze für 3 Stunden struggeled jetzt, so sind alle Ideen willkommen!

War es hilfreich?

Lösung

Was ich hinaus wollte, ist, dass Sie eine Art Mix-up haben. Und zwar ist aBlank kein Pos, sondern ein Gen Pos, so update su aBlank aCandidate macht keinen Sinn! In der Tat, was Sie wollen, ist eine Möglichkeit, ein neues Sudoku zu einem ersten Sudoku zu erzeugen; mit anderen Worten eine Funktion

similarSudoku :: Sudoku -> Gen Sudoku

Jetzt können wir es schreiben:

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)

oder noch einfacher:

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

Und die Eigenschaft sieht aus wie

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

Da gibt es Fälle

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

Sudoku -> Gen Bool ist Testable als auch (unter der Annahme instance Arbitrary Sudoku).

Andere Tipps

Auf meinem Blog, schrieb ich einen einfachen Craps Simulator rel="nofollow mit Quick Check-Tests, die verwendet werden oneof interessante Rollen zu erzeugen.

Sagen wir ein super-einfaches Sudoku eine einzelne Zeile haben:

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

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

Kein super-einfache Sudoku haben sollten Werte wiederholt:

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

Sie können ein super-einfaches Sudoku mit

erzeugen
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)

Die trace ist es, die zufällig generierten Bretter zu zeigen:

*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.

Es scheint, dass aBlank :: Gen Pos, das nicht die Art und Weise paßt es als Argument von candidates :: Sudoku -> Pos -> [Int] verwendet wird.

Ich habe mich durch hier ein finden Weg Gen a zu a umzuwandeln, die Sie mit den Kandidaten zu verwenden, erlauben würden. Das Beste, was ich sehen konnte, ist die generate Funktion.

Sag mir, wenn ich etwas fehle ...

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top