список произведений элементов
Прошу помощи у сообщества, задача простейшая, но решить никак не получается.
Дано Список чисел, пусть будет [1, 2, 3, 4]
необходимо получить список, в котором каждый элемент равен произведению всех остальных элементов списка: [24, 12, 8, 6] - в случае с примером.
у меня получилось решить задачу для суммы:
a = [1, 2, 3, 4]
print([sum(a) - i for i in a])
как мне сделать для того, что бы получить произведения?
def product(a):
pr = 1
for i in a:
pr *= i
return pr
ans = [int(product(a)/i) for i in a]
print(ans)
Ответы (2 шт):
В вашем коде я вижу три недостатка:
много раз вычисляется
product, что делает ваше решение квадратичным по сложности, а можно уложиться в линейное время;int(... / ...)теряет точность, переводя целые (которые в Питоне не ограничены) в вещественные (у которых 53 бита точности). Вот пример:
[9007199254740993, 9007199254740991] -> [9007199254740991, 9007199254740992]
- неправильно обрабатываются нули в списке.
Возможное решение всех этих проблем ниже.
Код из вопроса int(... / ...) позволяет предположить что в списке только целые.
Наивное решение которое использует свежий Питон (3.8 и выше):
def naive_partial_products(a):
# если Питон не свежий, то вычислите произведение так
# p = functools.reduce(operator.mul, a, 1)
p = math.prod(a)
return [p // v for v in a]
Это короткое быстрое решение, которое хорошо работает пока в массиве нет нулей. Если нули есть, надо разбирать случаи. Если ноль один, то в ответе все нули кроме одного элемента. Если нулей больше одного, то в ответе одни нули.
Кроме нулей надо внимательно проследить как обрабатываются короткие массивы.
После учёта все возможностей получается такой симпатичный монстрик:
import math
def partial_products(a):
zc = a.count(0)
if zc > 1:
return [0] * len(a)
p = math.prod(v for v in a if v != 0)
if zc == 0:
return [p // v for v in a]
return [p if v == 0 else 0 for v in a]
def check(a):
print(f'{a} -> {partial_products(a)}')
check([])
check([0])
check([0, 0])
check([0, 0, 0])
check([10])
check([0, 10])
check([1, 2, 3, 4])
check([0, 1, 2, 3, 4])
check([0, 0, 1, 2, 3, 4])
$ python partial-products.py [] -> [] [0] -> [1] [0, 0] -> [0, 0] [0, 0, 0] -> [0, 0, 0] [10] -> [1] [0, 10] -> [10, 0] [1, 2, 3, 4] -> [24, 12, 8, 6] [0, 1, 2, 3, 4] -> [24, 0, 0, 0, 0] [0, 0, 1, 2, 3, 4] -> [0, 0, 0, 0, 0, 0]
import math
print([math.prod(a[:i] + a[i + 1:]) for i in range(len(a))])
так есть гуд?
import math
a = [0, 0, 1, 2, 3, 4]
temp_p = math.prod(a)
temp_i = a.count(0)
if temp_p == 0 and temp_i == 1:
i = a.index(0)
print([0] * i + [math.prod(a[:i] + a[i + 1:])] + [0] * (len(a) - i - 1))
elif temp_i > 1:
print([0] * len(a))
else:
print([temp_p // i for i in a])