查找添加到数字的一个和两个的组合

时间:2016-10-18 21:21:54

标签: python-3.x math combinations permutation

我正在努力获得添加一个和两个以达到数字的所有可能的组合和排列。例如,您可以通过添加1 + 1 + 22 + 2 + 1等来达到5 目标:返回由1&2和2组成的所有列表的列表,其中元素的总和等于参数
我的代码赢了0,1和2指出
例如:

3: [1,1,1],[1,2],[2,1] 
4: [1,1,1,1],[1,2,1],[2,1,1],[1,1,2],[2,2] 

我已经找到了一种方法,但它只能工作到7,因为它不会找到中间的'组合(不是最多的1或2个,只是平均数量)  我的功能没有找到任何排列,它只是组合。

def findsum(x):
    numbers = []
    numOfOnes= x - 2
    numbers.append([1]*x) # all ones
    numbers.append([1] * numOfOnes + [2]) #all ones and a two
    if x % 2 == 0:
        numOfTwos = int((x - 2)/2)
        numbers.append([2]*(int(x/2))) # all twos
        if x >= 6:
            numbers.append([2] * numOfTwos+ [1,1]) #all twos and 2 ones

    else:
        numOfTwos = int((x - 1)/2)
        numbers.append([2] * numOfTwos+ [1])

    return numbers  

使用方法:     print(findsum(6))

# if number is greater that 7, won't get middle combination. Ex:
# [1,1,1,2,2] = 7 #doesn't have max 1's or 2's, , so won't be found in my algo
# [1,1,2,2,1,1] = 8 #doesn't have max 1's or 2's, so won't be found in my algo.

3 个答案:

答案 0 :(得分:1)

你所追求的是整数compositions - 特别是只包含1和2的作文。

因为这个problem对于Fibonacci序列是related,所以可能的解决方案在结构上与Fibonacci算法相似。这是一个递归版本:

def f_rec(n):
    assert n >= 0

    if n == 0:
        return [[]]
    elif n == 1:
        return [[1]]
    else:
        return [[1] + composition for composition in f_rec(n - 1)] \
             + [[2] + composition for composition in f_rec(n - 2)]

说明:让F(n) = n的所有成分仅由1和2组成。每个作文必须以1或2开头。

如果n的合成以1开头,则必须后跟n - 1的合成。如果它以2开头,则必须后跟n - 2的组合。因此,n的所有成分都是1,然后是n - 1的所有成分,或者是n - 2的所有成分,这正是这里的递归情况& #34;说"

这是一个基本的迭代版本:

def f_iter(n):
    assert n >= 0

    a, b = [[]], [[1]]

    for _ in range(n):
        a, b = b, [[1] + c for c in b] + [[2] + c for c in a]

    return a

对于迭代版本,我们从基本情况开始:a设置为0的所有组合(只有一个:空组合),b设置为全部在每次迭代中,ab都是"向前移动"一步到位。因此,经过一次迭代,a := F(1)b := F(2),然后是a := F(2)b := F(3),依此类推。

假设a := F(k)b := F(k + 1)a的下一个值应为F(k + 1),这只是b的当前值。要查找b的下一个值,请注意:

  • 如果您为k + 1的合成添加1,则会得到k + 2的合成。
  • 如果您为k的合成添加2,那么您也会得到k + 2的合成。
  • 事实上,这些是构成k + 2组合的唯一方法,因为我们只能使用1和2。

因此,b的新值F(k + 2)为1加上bF(k + 1))的所有旧值,加上所有的a旧值F(k)n)。

重复此a := F(n)次,最后得到b := F(n + 1)Fibonacci(n+1)

但请注意,由于结果的长度等于.red-box{ background-color:red; width:400px; height:400px; position:absolute; left:0; right:0; top:0; bottom:0; margin:auto; } .black-box{ background-color:black; width:200px; height:200px; position:absolute; top:0; bottom:0; left:0; right:0; margin:auto; ,因此上述两个函数都因为无法快速使用而无法使用。

答案 1 :(得分:0)

不需要一些复杂的代码来做到这一点。

我的功能:

def findsum(x) :
    base = [1]*x

    i = 0
    baseMax = ''
    while i < x :
        try :
            baseMax += str(base[i] + base[i+1])
        except IndexError :
            baseMax += str(base[i])
        i += 2

    baseList = []
    for i, n in enumerate(baseMax) :
        if n == '2' :
            baseList.append(baseMax[:i].replace('2', '11') + '1'*2 + baseMax[i+1:])
    baseList.append(baseMax)

    from itertools import permutations
    results = set()
    for n in baseList :
        if n.count('1') and n.count('2') :
            for p in sorted(permutations(n, len(n))) :
                results.add(''.join(list(p)))
        else :
            results.add(n)
    return sorted(results, key=int)

print(findsum(7))
# ['1222', '2122', '2212', '2221', '11122',
# '11212', '11221', '12112', '12121', '12211',
# '21112', '21121', '21211', '22111', '111112',
# '111121', '111211', '112111', '121111', '211111',
# '1111111']

答案 2 :(得分:0)

import math
import itertools
def findCombos(n):
    max2s = math.floor(n/2)

    min1s = n - max2s

    sets = []
    #each set includes [numOfTwos,numOfOnes]
    for x in range(max2s+1):
        sets.append([x,n-(x*2)])
    #creates sets of numberOfOnes and numberOfTwos
    numsets = []
    allsets = []
    for x in sets:
        numsets.append(x[0] * [2] + x[1] * [1])
    #changes set to number form , [2,3] >> [2,2,1,1,1]
    for eachset in numsets:
        if 1 in eachset and 2 in eachset:
            #if can be permutated(has 2 different numbers)
            y = set(itertools.permutations(eachset))
            #y is all the permutations for that set of numbers
            for z in y:
                #for each tuple in the list of tuples, append it
                allsets.append(z)
        else:
            #otherwise just append the list as a tuple
            allsets.append(tuple(eachset))
    return allsets

<强>用法:
print(findCombos(7))
输出:
[[(1, 1, 1, 1, 1, 1, 1), (1, 1, 1, 1, 1, 2), (1, 2, 1, 1, 1, 1), (1, 1, 1, 2, 1, 1), (1, 1, 2, 1, 1, 1), (2, 1, 1, 1, 1, 1), (1, 1, 1, 1, 2, 1), (1, 2, 1, 1, 2), (2, 1, 1, 1, 2), (2, 1, 2, 1, 1), (2, 1, 1, 2, 1), (1, 1, 2, 1, 2), (1, 1, 1, 2, 2), (1, 2, 2, 1, 1), (1, 2, 1, 2, 1), (1, 1, 2, 2, 1), (2, 2, 1, 1, 1), (2, 2, 1, 2), (2, 1, 2, 2), (2, 2, 2, 1), (1, 2, 2, 2)]