随着美国本周超过15亿美元的彩票,我在
Ruby中写了一个功能,让Powerball的选择.在
Powerball中,您可以从1..69(无重复)范围内选择5个数字,从1..26范围选择1个数字.
这是我想出来的:
def pball Array(1..69).shuffle[0..4].sort + [rand(1..26)] end
它通过创建从1到69的整数数组,重排数组,选择前5个数字,排序这些数组,最后添加1到26之间的数字.
为了做这个在Swift需要更多的工作,因为Swift没有内置的随机播放方法在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)] }
由于没有随机播放方法,它可以通过创建一个[Int],值范围为1 … 69.然后,它使用地图创建[(Int,Double)],包含数字的元组对数组和范围为0.0 ..< 1.0.然后使用Double值排序此数组,并使用第二个映射返回[Int],然后使用slice [0 ... 4]来提取前5个数字并排序sort()进行排序. 在第二行,它附加一个数字范围1 … 26.我尝试将其添加到第一行,但Swift给出了错误:
Expression was too complex to be solved in reasonable time; consider
breaking up the expression into distinct sub-expressions.
解决方法
为了其乐趣,Swift 3的非GameplayKit(长)单行,使用全局
sequence(state:next:)
功能从可变状态数组生成随机元素,而不是重排数组(尽管数值数组的变化是5次,所以一些额外的复制操作在这里…)
let powerballNumbers = Array(sequence(state: Array(1...69),next: { (s: inout [Int]) -> Int? in s.remove(at: Int(arc4random_uniform(UInt32(s.count))))}) .prefix(5).sorted()) + [Int(arc4random_uniform(26) + 1)]
…分解为可读性.
(可能在将来的Swift版本)
如果type inference weren’t broken inout
closure parameters(作为关闭的论据),我们可以将以上内容减少到:
let powerballNumbers = Array(sequence(state: Array(1...69),next: { $0.remove(at: Int(arc4random_uniform(UInt32($0.count)))) }) .prefix(5).sorted()) + [Int(arc4random_uniform(26) + 1)]
如果我们也允许以下扩展名
extension Int { var rand: Int { return Int(arc4random_uniform(UInt32(exactly: self) ?? 0)) } }
然后,我们可以继续减少一行:
let powerballNumbers = Array(sequence(state: Array(1...69),next: { $0.remove(at: $0.count.rand) }).prefix(5).sorted()) + [26.rand + 1]