Domanda

Sto cercando di scrivere un puntello che cambia un sudoku e poi controlla se è ancora valido.

Tuttavia, non sono sicuro di come utilizzare il "oneof" -funzione correttamente. Potete darmi qualche suggerimento, per favore?

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

Qui ci sono alcuni più 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]

Ho struggeled con questo puntello per 3 ore, in modo che tutte le idee sono benvenute!

È stato utile?

Soluzione

Quello che mi stavo guidando a è che avete un tipo di mix-up. Vale a dire, non è un aBlank Pos, ma un Gen Pos, quindi update su aBlank aCandidate non ha senso! In realtà, ciò che si vuole è un modo per generare un nuovo sudoku dato un sudoku iniziale; in altre parole una funzione

similarSudoku :: Sudoku -> Gen Sudoku

Ora possiamo scrivere:

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)

o ancora più semplice:

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

E la proprietà si presenta come

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

Dato che ci sono casi

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

Sudoku -> Gen Bool è Testable così (supponendo instance Arbitrary Sudoku).

Altri suggerimenti

Sul mio blog, ho scritto un semplice craps simulatore con test QuickCheck che utilizzano oneof generare rotoli interessanti.

Supponiamo di avere un super-semplice Sudoku di una singola riga:

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

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

Nessun super-Simple Sudoku avrebbe dovuto ripetuto valori:

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

Si potrebbe generare un super-semplice Sudoku con

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)

Il trace è lì per mostrare le schede generati casualmente:

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

sembra che aBlank :: Gen Pos, che non corrisponde al modo in cui viene utilizzato come argomento di candidates :: Sudoku -> Pos -> [Int].

Ho cercato attraverso qui per trovare un modo per convertire Gen a a a che permetterebbe di usarlo con i candidati. Il meglio che ho potuto vedere è la funzione generate.

Dimmi se mi manca qualcosa ...

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top