2015-06-11 69 views
1

我一直在試圖用scalacheck生成混洗序列。 Scalacheck不提供任何生成器來直接執行此操作,而且我也無法在網上找到任何簡單的答案。經過一番思考,下面是我如何做到的。我希望別人會發現,如果有用。如何用ScalaCheck生成混洗序列?

+0

SO不是一個展示答案的地方。在GitHub或類似的東西中創建一個要點。 –

+0

@ I.K。有:https://gist.github.com/guillaumecherel/4f0532a61db73f768242 –

+2

自我回答的問題[很好](http://blog.stackoverflow.com/2011/07/its-ok-to-ask-and-answer - 你自己的問題/) - 這不是一個很好的例子。這個問題應該充分說明,答案應該不僅僅是一大塊格式不正確的代碼。 –

回答

2

org.scalacheck.Gen.pick(n: Int, l: Iterable[T]): Gen[Seq[T]]挑選n以隨機順序排列的不同元素l。撥打電話pickn = l.length,您將生成一個隨機

+0

這不起作用。我想要一個隨機順序爲1到n(也是隨機)的整數列表,我寫了下面的生成器,但它只是按升序生成數字:Gen.choose(0,10).flatMap(len => Gen .pick(len,1到len)) – dzs

0
def shuffle[T](s: Seq[T], prefix: Seq[T] = Vector()): Gen[Seq[T]] = 
    if (s.length == 0) Gen.const(prefix.toSeq) 
    else 
     Gen.choose(0, s.length - 1) 
     .flatMap { i => 
      shuffle(
      s.take(i) ++ s.takeRight(s.length - i - 1), 
      prefix :+ s(i)) } 
0

你可以使用一個收集混洗算法(如一個在scala.util.Random),以獲得更清晰的溶液:

/** 
* This represents a potential list shuffling. It 
* acts as a pure function - when applied to the 
* same list it always returns the same result 
*/ 
class Shuffling(seed: Int) { 
    def apply[T](xs: Seq[T]): Seq[T] = { 
    val r = new scala.util.Random(seed) 
    r.shuffle(xs) 
    } 
} 

import org.scalacheck.Arbitrary._ 
import org.scalacheck.Gen 

val shufflingGen: Gen[Shuffling] = arbitrary[Int].map(new Shuffling(_)) 

上述片段定義一shuffling - 一個可能的再列表的排序。它還定義了一個提供任意混洗實例的生成器。下面的例子顯示瞭如何使用洗牌重新排序一個整數範圍:

def shuffledRange(n: Int): Gen[Seq[Int]] = { 
    for { 
    shuffling <- shufflingGen 
    } yield shuffling(Range(0, n)) 
} 

似乎有些奇怪添加在Shuffling類的形式一層間接 - 我們也可以同樣適用Random.shuffle直接在列表中。這是因爲除了隱式隨機化Scalacheck已經在後臺執行 - 我們希望避免額外的隨機來源 - 洗牌過程中的隨機來源來自scalacheck生成器。

對此的一個好處是生成的病例的重複性(每當Scalacheck will support it)。