Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Nice work on this post. It was easy to follow your line of exploration and thinking. May I suggest a couple of simplifications.

The generator expression in the sum() just applies a one-argument function so it can be replaced with map(). And instead of computing a sign at each step, it is simpler and faster to negate the roots at the outset.

There actually is a combinations(..., 0) in Python, and it returns [()] which is consistent with math.comb(4, 0) returning 1. Also, prod([]) returns 1. Putting those facts together helps eliminate special case at the end point.

Here's the simplified code:

    from itertools import combinations
    from operator import neg
    from math import prod

    def coeffs_from_roots(roots):
        roots = list(map(neg, roots))
        return [
            sum(map(prod, combinations(roots, k)))
            for k in range(len(roots) + 1)
        ]



I'm not sure why I missed the combinations(..., 0), I'm pretty certain to have tested in a previous iteration (maybe because I wasn't using math.prod() initially); code and text adjusted.

For the map yeah I thought it wasn't recommended by Python style but I personally prefer it so I'm adopting that change as well.

For the sign change, your initial comment (before your edits) was proposing the (1, -1)[i & 1] trick, which I actually like better than negating all the roots. At least for clarity in understanding the blog post (which mentions the sign juggling), I think it's better to keep it that way. I added a link to your comment for anyone looking for further improvement.

Thanks for the all the suggestions :)




Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: