繁体   English   中英

Scala:在范围1到45中模拟乐透号码生成器

[英]Scala : simulate Lotto number generator in Range 1 to 45

以下是从1到45范围内模拟数字彩票的必要解决方案,每次我们生成数字n1时,该数字将从可能的数字集合中删除。

是否有可能以更实用的方式实现相同目标? 即使用地图,过滤等

def getNumbers :Array[Int] = {

        val range = 1 to 45
        var set = range.toSet

        var resultSet:Set[Int] = Set()
        var current: Int = 0

        while(resultSet.size <  5 ){
            current = Random.shuffle(set).head // pick the head of the shuffled set
            set -= current
            resultSet += current
        }

        resultSet.toArray
    }

“编辑”

示例从范围1到5中选择3个数字

Original Set is {1,2,3,4,5}
{1,2,3,4,5} shuffle(1) picked at random 3
{1,2,4,5}     shuffle(2) picked at random 2
{1,4,5}       shuffle(3) picked at random 4
original Set becomes {1,5}

numbers picked {3,2,4}

每个shuffle随机化一个不同的SET! =>不同的概率

我希望看到一个功能性的“方法”,5次洗牌而不是1次洗牌!

当然,这是可能的。 集合API拥有您需要的一切。 什么你要找的是take ,这会第一时间n集合的元素,还是一样多的元素集合有,如果有小于n

Random.shuffle(1 to 45).take(5).toArray

我和mz在一起,但如果你真的想要一个不断重新洗牌的功能形式,那么你想要这样的东西:

import scala.util.Random
import scala.annotation.tailrec

val initialSet = 1 to 45

def lottery(initialSet: Seq[Int], numbersPicked: Int): Set[Int] = {
  @tailrec
  def internalTailRec(setToUse: Seq[Int], picksLeft: Int, selection: Set[Int]):Set[Int]= {
    if(picksLeft == 0) selection
    else {
      val selected = Random.shuffle(setToUse).head
      internalTailRec(setToUse.filter(_ != selected), picksLeft - 1, selection ++ Set(selected))
    }
  }
  internalTailRec(initialSet, numbersPicked, Set())
}

lottery(initialSet, 5)

我也更喜欢@ mz的解决方案,并同意他关于概率的推理。 读取Random.shuffle的源代码可能是值得的。

每次迭代都会从range删除一个元素,并将其添加到累加器acc ,这与您的命令式方法类似,只是我们不会改变集合和计数器。

import scala.util.Random._
import scala.annotation.tailrec

def getNumbers(): Array[Int] = {
  val range = (1 to 45).toSeq
  @tailrec
  def getNumbersR(range: Seq[Int], acc: Array[Int], i: Int): Array[Int] = (i, range(nextInt(range.size))) match{
    case (i, x) if i < 5 => getNumbersR(range.filter(_ != x), x +: acc, i + 1)
    case (i, x)          => acc
  }
  getNumbersR(range, Array[Int](), 0)
}

scala> getNumbers
res78: Array[Int] = Array(4, 36, 41, 20, 14)

这将模拟您想要的行为:

画一个,剩下的重新洗牌数据,画一个等等。

import scala.util.Random
import scala.annotation.tailrec

def draw(count: Int, data: Set[Int]): Set[Int] = {

  @tailrec
  def drawRec( accum: Set[Int] ) : Set[Int] =  
    if (accum.size == count ) 
      accum
    else 
      drawRec( accum + Random.shuffle( (data -- accum).toList ).head )

  drawRec( Set() )      
}

scala> draw(5, (1 to 45).toSet)
res15: Set[Int] = Set(1, 41, 45, 17, 22)

scala> draw(5, (1 to 45).toSet)
res16: Set[Int] = Set(5, 24, 1, 6, 28)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM