Нужно найти 4 числа из списка, сумма которых будет равна заданной "sum_"

def find_four(nums, sum_):
    if len(nums) < 4:
        return
    i = 0
    i2 = 1
    i3 = 2
    i4 = 3
    while True:
        num_sum = nums[i] + nums[i2] + nums[i3] + nums[i4]
        if num_sum == sum_:
            return [nums[i], nums[i2], nums[i3], nums[i4]]
        elif i == len(nums) - 4:
            return
        elif i2 == len(nums) - 3:
            i += 1
        elif i3 == len(nums) - 2:
            i2 += 1
        elif i4 == len(nums) - 1:
            i3 += 1
        elif i4 != len(nums):
            i4 += 1

Мой код хорошо работает с некоторыми списками, такими как: find_four([1, 1, 1, 5, 1, 5, 7], 10) или { { Х1 } } . Но с некоторыми это не работает, например find_four([7, 5, 1, 4, 1, 6, 2], 11) (нужно напечатать 7, 1, 1, 2) Что случилось ?? :(

3
Lorrain 31 Авг 2017 в 20:41

5 ответов

Лучший ответ

Вам, вероятно, следует отсортировать nums перед тем, как обрабатывать его частями по 4, как вы делаете.

def find_four(nums, sum_):
    if len(nums) < 4:
        return
    nums = sorted(nums)  # Sort nums here
    i = 0
    i2 = 1
    i3 = 2
    i4 = 3
    while True:
        num_sum = nums[i] + nums[i2] + nums[i3] + nums[i4]
        if num_sum == sum_:
            return [nums[i], nums[i2], nums[i3], nums[i4]]
        elif i == len(nums) - 4:
            return
        elif i2 == len(nums) - 3:
            i += 1
        elif i3 == len(nums) - 2:
            i2 += 1
        elif i4 == len(nums) - 1:
            i3 += 1
        elif i4 != len(nums):
            i4 += 1

Это произведет для 7, 1, 1, 2 для find_four([7, 5, 1, 4, 1, 6, 2], 11). Обратите внимание, что порядок чисел не будет сохранен.

2
Cuber 31 Авг 2017 в 23:14

Просто используйте itertools.combinations. Ниже код вернет все пары, из которых суммация равна sum_. Я устанавливаю combinations, чтобы взять 4 числа, передавая 4 по умолчанию в аргументе. Вы можете чередовать количество чисел, используемых для расчета суммы, изменяя цель.

import itertools
from itertools import combinations
def find_four(nums, sum_,target=4):
    return([pair for pair in itertools.combinations(nums,target) if sum(pair) == sum_])

nums=[1,2,3,4,1,5,6,7,8,9,10,11,12]

Пример:-

>>> find_four([1,2,3,4,1,5,6,7,8,9,10,11,12],10)
[(1, 2, 3, 4), (1, 2, 1, 6), (1, 3, 1, 5), (2, 3, 4, 1)]
>>>find_four([1,2,3,4,1,5,6,7,8,9,10,11,12],10,3)
[(1, 2, 7), (1, 3, 6), (1, 4, 5), (1, 1, 8), (2, 3, 5), (2, 1, 7), (3, 1, 6), (4, 1, 5)]
1
Vineet Jain 2 Сен 2017 в 15:41

Вы можете сделать это проще, используя 4 цикла

def find_four(arr, sum_):
    for i in range(len(arr)):
        for j in range(i + 1, len(arr)):
            for t in range(j + 1, len(arr)):
                for k in range(t + 1, len(arr)):
                    if arr[i] + arr[j] + arr[t] + arr[k] == sum_:
                        return [arr[i],arr[j],arr[t],arr[k]]
    return []

Ввод

find_four([1, 1, 1, 5, 1, 5, 7], 10)
find_four([4, 6, 1, 4, 1, 6, 2], 13)
find_four([7, 5, 1, 4, 1, 6, 2], 11)

Вывод

[1, 1, 1, 7]
[4, 6, 1, 2]
[7, 1, 1, 2]
0
Vladyslav 31 Авг 2017 в 17:57

Нет причин для вложенных циклов.

import itertools
import operator as op
from functools import reduce

def find_N(nums, target, N=4):
    for combo in list(itertools.combinations(nums, N)):
        if reduce(op.add, combo) == target:
            return combo
    return []

>>> find_N([1,2,3,4,5,6,7,8], target=10)
(1, 2, 3, 4)

>>> find_N([1,2,3,4,5,6,7,8], target=10, N=3)
(1, 2, 7)

>>> find_N([1,2,3,4,5,6,7,8], target=10, N=2)
(2, 8)

Наблюдения:

  • Многие вещи предварительно встроены в Python, используйте их вместо воссоздания колеса
  • Обобщение это хорошо. Вы не хотите менять свою функцию, если N меняется с 4
  • sum не является именем звуковой переменной, так как оно перекрывает встроенную функцию этого имени
5
Chris Johnson 31 Авг 2017 в 18:57

Я заметил, что каждая коллекция чисел в вопросе представляет собой bag или multiset , а не набор. То есть каждая коллекция содержит хотя бы одно повторение одного из своих членов. Это гарантированно имеет место, может быть более уместно вычислять все мультимножественные комбинации и тем самым избегать обработки повторных комбинаций.

>>> from sympy.utilities.iterables import multiset_combinations
>>> def find_four(nums, sum_):
...     for c in multiset_combinations(nums, 4):
...         if sum(c) == sum_:
...             return c
...     return {}
... 
>>> find_four([1, 1, 1, 5, 1, 5, 7], 10)
[1, 1, 1, 7]
>>> find_four([4, 6, 1, 4, 1, 6, 2], 13)
[1, 2, 4, 6]
>>> find_four([7, 5, 1, 4, 1, 6, 2], 11)
[1, 1, 2, 7]
0
Bill Bell 31 Авг 2017 в 19:26