Как создать перетасованную последовательность с помощью ScalaCheck?

Я пытался создать перетасованные последовательности с помощью scalacheck. Scalacheck не предоставляет никакого генератора, чтобы сделать это напрямую, и я не смог найти простого ответа в Интернете. Немного подумав, ниже показано, как я это сделал. Я надеюсь, что другие найдут, если это будет полезно.


person Guillaume Chérel    schedule 11.06.2015    source источник
comment
SO - это не место для демонстрации ответов. Создайте суть в GitHub или что-то подобное.   -  person M.K.    schedule 11.06.2015
comment
@И.К. там: gist.github.com/guillaumecherel/4f0532a61db73f768242   -  person Guillaume Chérel    schedule 11.06.2015
comment
Вопросы с самостоятельными ответами можно — это просто не очень хороший пример. Вопрос должен быть сформулирован полностью, а ответ должен быть больше, чем большой кусок неуклюже отформатированного кода.   -  person Travis Brown    schedule 11.06.2015
comment
@TravisBrown Я отредактировал вопрос, чтобы четко изложить его, как вы предложили. Что касается кода, я не вижу, насколько неудобно форматирование. Во всех случаях я написал этот вопрос и ответ, потому что искал его и не мог найти. Любой, кто ищет его в будущем, может быть рад найти его в будущем. Это краткий, но правильный ответ на правильный вопрос, и поэтому он ценен. Мне минусы кажутся чрезмерными.   -  person Guillaume Chérel    schedule 13.06.2015


Ответы (2)


org.scalacheck.Gen.pick(n: Int, l: Iterable[T]): Gen[Seq[T]] выбирает n различных элемента из l в случайном порядке. Позвоните pick с помощью n = l.length, и вы сгенерируете случайным образом

person justinpc    schedule 28.11.2016
comment
Это не работает. Мне нужен список с целыми числами от 1 до n (также случайными) в случайном порядке, я написал следующий генератор, но он генерирует только числа в порядке возрастания: Gen.choose(0, 10).flatMap(len => Gen .pick(длина, от 1 до длины)) - person dzs; 07.06.2017
comment
В настоящее время он не выбирает в случайном порядке, см. эту проблему - person Valy Dia; 28.02.2019
comment
Ты прав. Я думаю, что лучшим решением было бы скопировать в массив и применить стандартный алгоритм случайной перестановки к массивам с использованием подкачки путем создания вектора [rand (длина), rand (длина - 1), rand (длина - 2),... ] индексов случайной замены с помощью scalacheck и использования этих индексов для замены последовательных элементов массива. Затем конвертируйте обратно в Seq. Я давно не смотрел на Scala. Хотите предложить это как решение? - person justinpc; 28.02.2019
comment
Кстати, это известно как перетасовка Кнута или Фишера-Йейтса: en. wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle - person justinpc; 28.02.2019

Вы можете использовать алгоритм перетасовки коллекций (например, в 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 будет поддерживать это).

person Marius Danila    schedule 19.01.2016