*** Nova polynomial from roots*** 

This kata is from a series on polynomial handling. ( [#1](http://www.codewars.com/kata/nova-polynomial-1-add-1)   [#2](http://www.codewars.com/kata/570eb07e127ad107270005fe)  [#3](http://www.codewars.com/kata/5714041e8807940ff3001140 )   [#4](http://www.codewars.com/kata/571a2e2df24bdfd4e20001f5))

Consider a polynomial in a list where each element in the list element corresponds to the factors. The factor order is the position in the list. The first element is the zero order factor (the constant).

p = [a0, a1, a2, a3] signifies the polynomial a0 + a1x + a2x^2 + a3*x^3

In this kata create the polynomial from a list of roots:

[r0, r1 ,r2, r3 ]

p = (x-r0)(x-r1)(x-r2)(x-r3)

note: no roots should return the identity polynomial.

```python 
poly_from_roots([4]) = [-4, 1]
poly_from_roots([0, 0, 0, 0] ) = [0, 0, 0, 0, 1]
poly_from_roots([]) = [1]
```
The first katas of this series is preloaded in the code and can be used: [poly_add](http://www.codewars.com/kata/570eb07e127ad107270005fe) [poly_multiply](http://www.codewars.com/kata/570eb07e127ad107270005fe)

Difficulty: EASY
Starter code: def poly_from_roots(r):
	

Solutions:
import numpy

def poly_from_roots(r):
	return list(reversed(numpy.poly(tuple(r)))) if len(r) > 0 else [1]


from collections import Counter
from itertools import product
from functools import reduce
from operator import mul

class P(Counter):

	def __mul__(self, other):
		m = P()
		for ((ao, av), (bo, bv)) in product(self.items(), other.items()):
			m[ao + bo] += av * bv
		return m

def poly_from_roots(roots):
	result = reduce(mul, (P({0: -r, 1: 1}) for r in roots), P({0: 1}))
	return [result[i] for i in range(len(roots) + 1)]


from numpy.polynomial import polynomial as P

def poly_from_roots(r):
	return P.polyfromroots(r).tolist()


def poly_from_roots(r):
	lst = [1]
	while r:
		v = -r.pop()
		lst.append(0)
		lst = [1 if i == len(lst) - 1 else x * v + lst[i - 1] for (i, x) in enumerate(lst)]
	return lst


from functools import reduce
from itertools import combinations

def poly_from_roots(r):
	return [sum((reduce(lambda x, y: -x * y, c, 1) for c in combinations(r, i))) for i in range(len(r), -1, -1)]


def poly_multiply(p1, p2):
	answer = [0] * (len(p1) + len(p2) - 1)
	for (i, coeff1) in enumerate(p1):
		for (j, coeff2) in enumerate(p2):
			answer[i + j] += coeff1 * coeff2
	return [] if all((coeff == 0 for coeff in answer)) else answer

def poly_from_roots(r):
	if not r:
		return [1]
	parts = [[-root, 1] for root in r]
	answer = parts[0]
	for part in parts[1:]:
		answer = poly_multiply(answer, part)
	return answer


from numpy import poly
poly_from_roots = lambda r: list(reversed(poly(r))) if len(r) else [1]


from itertools import combinations
from functools import reduce
from operator import mul

def poly_from_roots(r):
	res = []
	for p in range(len(r) + 1):
		factor = sum((reduce(mul, [v for v in k], 1) for k in combinations(r, p)))
		res.append(-factor if p % 2 else factor)
	return res[::-1]