سؤال

أحاول كتابة الدعامة التي تغير سودوكو ثم يتحقق مما إذا كان لا يزال ساري المفعول.

ومع ذلك، لست متأكدا من كيفية استخدام "OneOf" -Function بشكل صحيح. هل تستطيع أن تعطيني بعض التلميحات من فضلك

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

فيما يلي بعض المعلومات أكثر ...

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]

لقد كافأت بهذه الدعامة لمدة 3 ساعات الآن، لذا فإن أي أفكار هي موضع ترحيب!

هل كانت مفيدة؟

المحلول

ما كنت أقود فيه في هو أن لديك خلط النوع. يسمى، aBlank ليس Pos, ، ولكن Gen Pos, ، وبالتالي update su aBlank aCandidate لا معنى له! في الواقع، ما تريد هو وسيلة لتوليد سودوكو جديد نظرا لسودوكو الأولي؛ وبعبارة أخرى وظيفة

similarSudoku :: Sudoku -> Gen Sudoku

الآن يمكننا كتابة ذلك:

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)

أو حتى أبسط:

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

والممتلكات تبدو وكأنها

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

لأن هناك حالات

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

Sudoku -> Gen Bool يكون Testable كذلك (على افتراض instance Arbitrary Sudoku).

نصائح أخرى

على مدونتي، كتبت الفضقاء بسيطة محاكاة. مع اختبارات QuickCheck التي تستخدم oneof لتوليد لفات مثيرة للاهتمام.

قل لدينا سودوكو بسيطة للغاية من صف واحد:

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

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

لا يجب أن يكون لسودوكو السوبر بسيطة القيم المتكررة:

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

قد تولد سوبر سودوكو بسيطة مع

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)

ال trace هل هناك لإظهار المجالس التي تم إنشاؤها عشوائيا:

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

يبدو أن aBlank :: Gen Pos التي لا تتطابق مع الطريقة التي يستخدمها كحجة من candidates :: Sudoku -> Pos -> [Int].

لقد كنت أبحث من خلال هنا لإيجاد طريقة لتحويل Gen a ل a والتي من شأنها أن تسمح لك باستخدامها مع المرشحين. أفضل ما يمكن أن أرى هو generate وظيفة.

قل لي إذا كنت أفتقد شيئا ...

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top