не могу вернуть данные из функции
как получить на выходе функции subset1 и subset2 если они равны согласно коду я это возвращаю здесь
if sum(subset1) == sum(subset2):
return subset1, subset2
однако из за рекурсии я не знаю как это получит на выходе выполнения всех рекурсий данной функции. Единственный вариант который знаю я это ловить как исключении, но это как то не особо изящно
def find_two_equal_subset(subset1, subset2=None,):
if not subset2:
for i, item in enumerate(subset1):
find_two_equal_subset(subset1[:i] + subset1[i + 1:], [item])
else:
if sum(subset1) == sum(subset2):
return subset1, subset2
for i, item in enumerate(subset1):
set = find_two_equal_subset(subset1[:i] + subset1[i + 1:], subset2 + [item])
print(find_two_equal_subset([15, 5, 20, 10, 35, 15, 10]))
Ответы (2 шт):
В Питоне есть редкая особенность: он умеет возвращать несколько результатов. Я не про return a, b а про yield, который "возвращает" результат, но продолжает выполнение функции. Функция становится генератором, который вызывается в цикле или может быть переделан в список. Почитайте также про yield from:
def find_two_equal_subset(subset1, subset2=None,):
if not subset2:
for i, item in enumerate(subset1):
yield from find_two_equal_subset(subset1[:i] + subset1[i + 1:], [item])
else:
if sum(subset1) == sum(subset2):
yield subset1, subset2
for i, item in enumerate(subset1):
yield from find_two_equal_subset(subset1[:i] + subset1[i + 1:], subset2 + [item])
for a, b in find_two_equal_subset([15, 5, 20, 10, 35, 15, 10]):
print(a, b)
Вашу функцию можно упростить совместив ветки if и else:
def find_two_equal_subset(subset1, subset2=[]):
if sum(subset1) == sum(subset2):
yield subset1, subset2
for i, item in enumerate(subset1):
yield from find_two_equal_subset(subset1[:i] + subset1[i + 1:], subset2 + [item])
for a, b in find_two_equal_subset([15, 5, 20, 10, 35, 15, 10]):
print(a, b)
Второй аргумент - деталь реализации. Спрячем её:
def find_two_equal_subset(set_):
def find_two_equal_subset(subset1, subset2):
if sum(subset1) == sum(subset2):
yield subset1, subset2
for i, item in enumerate(subset1):
yield from find_two_equal_subset(subset1[:i] + subset1[i + 1:], subset2 + [item])
return find_two_equal_subset(set_, [])
for a, b in find_two_equal_subset([15, 5, 20, 10, 35, 15, 10]):
print(a, b)
Исходный вариант порождает одни и те же пары множеств много раз. Рекурсию можно было бы поправить, но она не нужна. itertools.product умеет перебирать подмножества нерекурсивно:
import itertools
def find_two_equal_subset(set_):
def subset(p, j):
return (a for a, i in zip(set_, p) if i == j)
for p in itertools.product((0, 1), repeat=len(set_)):
if sum(subset(p, 0)) == sum(subset(p, 1)):
yield list(subset(p, 0)), list(subset(p, 1))
for a, b in find_two_equal_subset([15, 5, 20, 10, 35, 15, 10]):
print(a, b)
Если нужен только один вариант можно обойтись без рекурсии, c помощью сортировки и цикла. Сортировка помогает поровну распределить значения. Цикл раскидывает значения по сабсетам в зависимости от того который из них меньше.
не на всех наборах данных работает
def find_two_equal_subset(set):
subset1=[]
subset2=[]
for n in sorted(set, reverse=True):
if sum(subset1) < sum(subset2):
subset1.append(n)
else:
subset2.append(n)
if (sum(subset1) == sum(subset2)):
return sum(subset1), sum(subset2)
Этот и другие варианты решения можно посмотреть тут