在列表中生成总计为0的随机唯一数字

时间:2019-06-24 03:50:31

标签: python

问题是,例如,我需要生成总共N个数字才能获得总和0。如果N = 4,则应生成[1、0,-3、2]或[-2、1,-4、5]。

到目前为止,这是我的代码,它生成一个随机的int,其总和为N的值,并且它是列表中值的随机总数。

from random import randint

def solution(N):
    values = []
    while 1 <= N <= 100:
         value = randint(1, N)
         values.append(value)
         N = N - value
    return values

print(solution(3))

5 个答案:

答案 0 :(得分:2)

您可以使用5,然后简单地将最后一个值设为前三个值之和的负值:

random.sample

例如,它将输出:

import random
N=4
l = random.sample(range(-10, 10), k=3)
print(l + [-sum(l)])

哪个:

[-5, 1, -8, 12]

礼物:

print(sum([-5, 1, -8, 12]))

答案 1 :(得分:1)

这不能完全确保最终数字是唯一的,但是它不太可能已经存在于列表中。

def gen_unique_zero_sum_list(num_members):
    ret = []
    for i in range(int(num_members) - 1):
        candidate = random.randint(-100, 100)
        while candidate in ret:
            candidate = random.randint(-100, 100)
        ret.append(candidate)
    ret.append(-sum(ret))
    return ret

以上解决方案不能确保唯一性的事实困扰着我。这是应确保唯一性的增强版本:

def gen_unique_zero_sum_list(num_members, min=-100, max=100):
    if int(num_members) < 1:
        raise ValueError
    ret = []
    # populate as many as we can randomly
    for i in range(0, int(num_members) - 2, 1):
        candidate = random.randint(min, max)
        while candidate in ret:
            candidate = random.randint(min, max)
        ret.append(candidate)
    if int(num_members) > 1:
        while len(ret) < int(num_members):
            # at this point we could get a forced duplicate
            candidate = random.randint(min, max)
            while candidate in ret:
                candidate = random.randint(min, max)
            final = -(sum(ret) + candidate)
            if final in ret or final == candidate:
                # we would have a duplicate, force two new numbers
                continue
            ret.append(candidate)
            ret.append(final)
    else:
        # this will always be zero, by definition
        ret.append(-sum(ret))
    return ret

答案 2 :(得分:1)

解决此问题的一种选择是递归。我们可以从低到高的范围生成列表的第一个值,将其添加到列表中,然后通过函数进行返回,但是现在只有有限的选项(由于唯一性),直到我们到达一个点为止剩下。到那时,我们要么成功找到列表,要么失败了,以前的递归级别将在可能起作用的较早索引处搜索其他值。另一种可能性是没有可能的列表(例如,从低到高均为正,选项在最后一个点之前用完),在这种情况下,我们的函数将返回None。

import random


def foo(n, low, high):
    """Helper function for recursive function"""

    def rbar(arr):
        """Recursive function to create a 'random' list of n integers
        between low and high (exclusive) such that the sum of the list is 0
        and the entries of the list are unique."""

        # if one spot left check if -sum(arr) in arr
        if len(arr) == n-1:
            if -sum(arr) not in arr and -sum(arr) in range(low, high):
                    return arr + [-sum(arr)]

        # if more than one spot then generate the next possible values
        # and try to get to a full list of size n with those
        else:
            # loop through shuffled options (randomness here)
            options = [x for x in range(low, high) if x not in arr]

            for opt in random.sample(options, len(options)):
                # if recursively going through function produces a list then return it
                if rbar(arr + [opt]) is not None:
                    return rbar(arr + [opt])

            # if nothing worked then return None
            return


    if n==0:
        return []
    elif n==1 and 0 in range(low, high):
        return [0]
    elif n==1 and 0 not in range(low, high):
        return None
    else:
        return rbar([])


k = foo(4, -10, 10)

if k is not None:
    print("List: {}, Sum:{}".format(k, sum(k)))
else:
    print(None)

答案 3 :(得分:1)

最简单的解决方案是将 1, 2, 3 ... N-1 包含在数组中,数组的最后一个元素是前面元素的总和乘以 -1:

function findSet(N) {

  var sum = 0;
  var r = [];

  if (N === 1) {
     r[0] = 0;
  } else {
     for (var i = 1; i < N; i++) {
        r[i - 1] = i;
        sum += i;
     }
     
     r[N - 1] = -sum;
  }
  
  return r;
}

function printArray(a) {
  console.log('[' + a.join(',') + ']');
}

printArray(findSet(1));
printArray(findSet(2));
printArray(findSet(3));
printArray(findSet(4));
printArray(findSet(5));

它们不是随机的,但至少是唯一的 ;) 并且解决方案很快。

答案 4 :(得分:0)

def solution(N):
    l = random.sample(range(-10, 10), k=(N-1))
    return (l + [-sum(l)])

试试这个。