Apple Swift - 通过重复生成组合 [英] Apple Swift - Generate combinations with repetition

查看:168
本文介绍了Apple Swift - 通过重复生成组合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



有关重复组合的详细解释可以在附近找到本页底部: http://www.mathsisfun.com/combinatorics/combinations-permutations。 html



简而言之,顺序无关紧要,我们可以重复

n =我们选择的一组内容



r =我们选择的事物的数量

我想创建一个函数,它将生成一个嵌套数组,其中包含所有n和r(小)值重复的组合。



如果有n = 3件事情可供选择,我们选择r = 2。

  n = [0,1,2] 
r = 2

函数 combos(n:[0,1,2],r:2)的结果是:

 结果= [
[0,0],
[0,1],
[0,2],
[1,1],
[1,2],
[2,2]
]

//我们不需要[1, 0],[2,0]等,因为订单无关紧要

在许多编程语言中这样做: http://rosettacode.org/wi ki / Combinations_with_repetitions



以下是PHP示例。这是最简单的,并返回一个数组,这是我想要的:

$ p $ 函数组合($ arr,$ k) {
if($ k == 0){
return array(array());


if(count($ arr)== 0){
return array();
}

$ head = $ arr [0];

$ combos = array();
$ subcombos = combos($ arr,$ k-1);
foreach($ subcomos as $ subcombo){
array_unshift($ subcombo,$ head);
$ combos [] = $ subcombo;
}
array_shift($ arr);
$ combos = array_merge($ combos,combos($ arr,$ k));
返回$ combos;

$ / code>

这是我将Swift函数移植到目前为止的地方:

  func combos(var array:[Int],k:Int) - > AnyObject {//  - >阵列<阵列<诠释>> {
如果k == 0 {
return [[]]
}

如果array.isEmpty {
return []
}

让head = array [0]

var combos = [[]]
var subcombos:[Array< Int>] = combos(array,k- 1)//错误:'(@Ivalue [Int],$ T5) - > $ T $'与subcombo中的[NSArray]'
不一样{
var sub = subcombo
sub.insert(head,atIndex:0)
combos.append (sub)
}
array.removeAtIndex(0)
combos + = combos(array,k)// error:'(@Ivalue [Int],Int) - > $ T5'与'[NSArray]'

返回连击
}


$不一样b $ b

大多数情况下,我似乎遇到了各种变量的类型声明和天气这些都是可变的或不可变的问题。



我尝试过更多显式的,不太明确的类型声明,但我设法实现的是稍微不同的错误消息。



如果有人会解释我的位置,我将不胜感激出错了,为什么?



非常感谢: - )

解决方案

您可以通过将循环写为

  var sub = subcombo  >为subcombo子组合{
ret.append([head] + subcombo)
}

使用 map()函数可以进一步简化:

  func combos< T>(var array:Array< T> ;, k:Int) - >阵列<阵列< T>> {
如果k == 0 {
return [[]]
}

如果array.isEmpty {
return []
}

let head = [array [0]]
let subcombos = combos(array,k:k - 1)
var ret = subcombos.map {head + $ 0}
array.removeAtIndex(0)
ret + = combos(array,k:k)

return ret
}






更新Swift 4:


$ (元素:ArraySlice< T> ;, k:Int) - > [[T]] {
如果k == 0 {
return [[]]
}

guard let first = elements.first else {
返回[]
}

let head = [first]
let subcombos = combos(elements:elements,k:k - 1)
var ret = subcombos .map {head + $ 0}
ret + = combos(elements:elements.dropFirst(),k:k)

return ret
}

元素组合< T>(元素:数组< T> ;, k:Int) - > [b]
return combos(elements:ArraySlice(elements),k:k)
}



现在将array slices 传递给递归调用,以避免
创建许多临时数组。



<例如:

  print(combos(elements:[1,2,3],k:2))
// [[1,1],[1,2],[1,3],[2,2],[2,3],[3,3]]


I'm trying to generate a nested array containing all combinations with repetition in Apple's Swift programming language.

An detailed explanation of combinations with repetition can be found near the bottom of this page: http://www.mathsisfun.com/combinatorics/combinations-permutations.html

Briefly; order does not matter, and we can repeat

n = the set of things we are choosing form

r = the number of things we are choosing

I want to create a function that will generate a nested array containing all combinations with repetition for any (small) values of n and r.

If there are n=3 things to choose from, and we choose r=2 of them.

n = [0, 1, 2]
r = 2

The result of the function combos(n: [0, 1, 2], r: 2) would be:

result = [
  [0, 0],
  [0, 1],  
  [0, 2],
  [1, 1],
  [1, 2],
  [2, 2]
]

// we don't need [1, 0], [2, 0] etc. because "order does not matter"

There are examples for doing this in many programming languages here: http://rosettacode.org/wiki/Combinations_with_repetitions

Here's the PHP example. It is one of the simplest and returns an array, which is what I want:

function combos($arr, $k) {
    if ($k == 0) {
        return array(array());
    }

    if (count($arr) == 0) {
        return array();
    }

    $head = $arr[0];

    $combos = array();
    $subcombos = combos($arr, $k-1);
    foreach ($subcombos as $subcombo) {
        array_unshift($subcombo, $head);
        $combos[] = $subcombo;
    }
    array_shift($arr);
    $combos = array_merge($combos, combos($arr, $k));
    return $combos;
}

Here's where I've got so far with porting the function to Swift:

func combos(var array: [Int], k: Int) -> AnyObject { // -> Array<Array<Int>> {
    if k == 0 {
        return [[]]
    }

    if array.isEmpty {
        return []
    }

    let head = array[0]

    var combos = [[]]
    var subcombos: [Array<Int>] = combos(array, k-1)    // error: '(@Ivalue [Int], $T5) -> $T6' is not identical to '[NSArray]'
    for subcombo in subcombos {
        var sub = subcombo
        sub.insert(head, atIndex: 0)
        combos.append(sub)
    }
    array.removeAtIndex(0)
    combos += combos(array, k)    // error: '(@Ivalue [Int], Int) -> $T5' is not identical to '[NSArray]'

    return combos
}

Mostly I seem to be having problems with the type declarations of the various variables and weather these are mutable or immutable.

I've tried being more explicit and less explicit with the type declarations but all I'm managed to achieve are slightly different error messages.

I would be most grateful if someone would explain where I'm going wrong and why?

Many thanks :-)

解决方案

You can get rid of var sub = subcombo by writing the loop as

for subcombo in subcombos {
    ret.append([head] + subcombo)
}

This can be further simplified using the map() function:

func combos<T>(var array: Array<T>, k: Int) -> Array<Array<T>> {
    if k == 0 {
        return [[]]
    }

    if array.isEmpty {
        return []
    }

    let head = [array[0]]
    let subcombos = combos(array, k: k - 1)
    var ret = subcombos.map {head + $0}
    array.removeAtIndex(0)
    ret += combos(array, k: k)

    return ret
}


Update for Swift 4:

func combos<T>(elements: ArraySlice<T>, k: Int) -> [[T]] {
    if k == 0 {
        return [[]]
    }

    guard let first = elements.first else {
        return []
    }

    let head = [first]
    let subcombos = combos(elements: elements, k: k - 1)
    var ret = subcombos.map { head + $0 }
    ret += combos(elements: elements.dropFirst(), k: k)

    return ret
}

func combos<T>(elements: Array<T>, k: Int) -> [[T]] {
    return combos(elements: ArraySlice(elements), k: k)
}

Now array slices are passed to the recursive calls to avoid the creation of many temporary arrays.

Example:

print(combos(elements: [1, 2, 3], k: 2))
// [[1, 1], [1, 2], [1, 3], [2, 2], [2, 3], [3, 3]]

这篇关于Apple Swift - 通过重复生成组合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆