在Swift中生成强力球选择的单线程?

vac*_*ama 9 ruby swift

随着美国本周大量的15亿美元彩票,我在Ruby中编写了一个函数来制作强力球.在Powerball中,您可以从范围中选择5个数字1..69(没有重复项),并从该范围中选择1个数字1..26.

这就是我想出的:

def pball
    Array(1..69).shuffle[0..4].sort + [rand(1..26)]
end
Run Code Online (Sandbox Code Playgroud)

它的工作原理是创建一个从1到69的整数数组,对该数组进行混洗,选择前5个数字,对它们进行排序,最后添加1到26之间的数字.

要在Swift中执行此操作需要更多的工作,因为Swift没有内置shuffle方法Array.

这是我的尝试:

func pball() -> [Int] {
    let arr = Array(1...69).map{($0, drand48())}.sort{$0.1 < $1.1}.map{$0.0}[0...4].sort()
    return arr + [Int(arc4random_uniform(26) + 1)]
}
Run Code Online (Sandbox Code Playgroud)

由于没有shuffle方法,因此可以通过[Int]在范围内创建with值来实现1...69.然后它map用于创建[(Int, Double)]一个元组对数组,其中包含数字和Double范围内的随机数0.0 ..< 1.0.然后,它使用Double值对此数组进行排序,并使用秒map返回[Int],然后使用切片[0...4]提取前5个数字并对sort()它们进行排序.

在第二行中,它在范围中附加一个数字1...26.我尝试将其添加到第一行,但Swift给出了错误:

表达太复杂,无法在合理的时间内解决; 考虑将表达式分解为不同的子表达式.

任何人都可以建议如何将其转换为1行功能?也许有更好的方法来选择5个数字1...69.

Leo*_*bus 6

Xcode 8.3•Swift 3.1

import GameKit 

var powerballNumbers: [Int] {
    return (GKRandomSource.sharedRandom().arrayByShufflingObjects(in: Array(1...69)) as! [Int])[0..<5].sorted() + [Int(arc4random_uniform(26) + 1)]
}

powerballNumbers   // [5, 9, 62, 65, 69, 2]
Run Code Online (Sandbox Code Playgroud)

Swift 2.x

import GameKit 

var powerballNumbers: [Int] {
    return (GKRandomSource.sharedRandom().arrayByShufflingObjectsInArray(Array(1...69)) as! [Int])[0...4].sort() + [Int(arc4random_uniform(26).successor())]
}

powerballNumbers   // [21, 37, 39, 42, 65, 23]
Run Code Online (Sandbox Code Playgroud)


mat*_*att 5

我没有发现"单线"概念非常引人注目.有些语言适合它; 别人不这样做.我建议给Swift一个shuffle方法开始:

extension Array {
    mutating func shuffle () {
        for var i = self.count - 1; i != 0; i-- {
            let ix1 = i
            let ix2 = Int(arc4random_uniform(UInt32(i+1)))
            (self[ix1], self[ix2]) = (self[ix2], self[ix1])
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但是由于我做了这个mutating,我们仍然需要不止一行来表达整个操作,因为我们必须var引用我们的起始数组:

var arr = Array(1...69)
(1...4).forEach {_ in arr.shuffle()}
let result = Array(arr[0..<5]) + [Int(arc4random_uniform(26)) + 1]
Run Code Online (Sandbox Code Playgroud)

如果你真的坚持单行,并且你不计算实现所需的代码shuffle,那么你可以通过定义shuffle更多这样的方式来实现它,尽管效率较低:

extension Array {
    func shuffle () -> [Element] {
        var arr = self
        for var i = arr.count - 1; i != 0; i-- {
            let ix1 = i
            let ix2 = Int(arc4random_uniform(UInt32(i+1)))
            (arr[ix1], arr[ix2]) = (arr[ix2], arr[ix1])
        }
        return arr
    }
}
Run Code Online (Sandbox Code Playgroud)

这是你的单行:

let result = Array(1...69).shuffle().shuffle().shuffle().shuffle()[0..<5] + [Int(arc4random_uniform(26)) + 1]
Run Code Online (Sandbox Code Playgroud)

但是哎呀,我省略了你的排序.如果没有出现"太复杂"的错误,我不知道如何做到这一点; 为了解决这个问题,我不得不把它分成两行:

var result = Array(1...69).shuffle().shuffle().shuffle().shuffle()[0..<5].sort(<)
result.append(Int(arc4random_uniform(26)) + 1)
Run Code Online (Sandbox Code Playgroud)

  • 我理解你对"一线"概念的感受.在这种情况下,更多的是学术练习,看看可以做什么和应该做什么. (5认同)
  • @LeoDabus是的,我知道,我并不期待那样.或者丢失C型for循环.或者其他很多东西.:( (2认同)

vac*_*ama 3

Xcode 10 \xe2\x80\xa2 斯威夫特 4.2

\n

Swift 现在添加了shuffled()ClosedRangerandom(in:)现在Int可以在一行中轻松完成此操作:

\n
func pball() -> [Int] {\n    return (1...69).shuffled().prefix(5).sorted() + [Int.random(in: 1...26)]\n}\n
Run Code Online (Sandbox Code Playgroud)\n

进一步修饰:

\n

由于 的返回类型pball()Int可以在方法调用中推断出random。另外,.prefix(5)也可以替换为[...4]. 最后,return可以从一行函数中省略:

\n
func pball() -> [Int] {\n    (1...69).shuffled()[...4].sorted() + [.random(in: 1...26)]\n}\n
Run Code Online (Sandbox Code Playgroud)\n