2

我一直在尝试使用 scalacheck 生成洗牌序列。Scalacheck 没有提供任何生成器来直接完成,我在网上找不到任何简单的答案。经过一番思考,下面是我的做法。我希望其他人会发现是否有用。

4

3 回答 3

3

您可以使用集合改组算法(例如 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- 一个可能的列表重新排序。它还定义了一个提供任意改组实例的生成器。以下示例显示了如何使用 shuffle 对一系列整数进行重新排序:

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

以类的形式添加一层间接性可能看起来很奇怪Shuffling——我们也可以Random.shuffle直接在列表上应用。这是因为除了隐式随机化 Scalacheck 已经在后台执行之外,我们还希望避免额外的随机源 - 改组中的随机源来自 scalacheck 生成器。

这样做的一个好处是生成案例的可重复性(只要 Scalacheck支持它)。

于 2016-01-19T17:24:42.733 回答
2

org.scalacheck.Gen.pick(n: Int, l: Iterable[T]): Gen[Seq[T]]以随机顺序从中挑选n不同的元素。用l调用,你会随机生成一个pickn = l.length

于 2016-11-28T10:30:52.337 回答
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)) }
于 2015-06-11T09:58:52.257 回答