Compute height of Bowl Pile Bowl Pile Height

The goal of this puzzle is to compute the height of a stack of bowls.



A bowl is defined to be a radially symmetric device without thickness.
Its silhouette shape is an even polynomial. The stack is described by a list of radii, each associated with an even polynomial, given as input as a list of coefficients (e.g. the list 3.1 4.2 represents the polynomial \$3.1x^2+4.2x^4\$).

The polynomial may have arbitrary degree. For simplicity, the height of the pile is defined as the altitude of the center of the top-most bowl (see plot of Example 3 for an illustration).

Test cases are in the format radius:coeff1 coeff2 ...: each line starts with a float number representing the radius of the bowl, followed by a colon and a space-separated list containing the coefficients for the even powers, starting with power 2 (zero constant part is implied). For example, the line 2.3:3.1 4.2 describes a bowl of radius 2.3 and the shape-polynomial 3.1 * x^2 + 4.2 * x^4.

Example 1

42:3.141


describes a pile of zero height since a single bowl has no height.

Example 2

1:1 2
1.2:5
1:3


describes a pile of height 2.0 (see plot).



Example 3

1:1.0
0.6:0.2
0.6:0.4
1.4:0.2
0.4:0 10


describes a pile of height 0.8 (see green arrow in the plot).



This is code golf, so the shortest code wins.

I have reference code.

Edit:

The reference implementation relies on a library to compute the roots of polynomials.
You may do that as well but you don't need to.
Since the reference implementation is only a (quite good) numerical approximation, I will accept any code which produces correct results within common floating-point tolerances.

The idea counts. I don't care if there are small erros \$&lt;\varepsilon\$.


Another variant of this puzzle is to minimize the height by reordering the bowls. I'm not sure if there's a fast solution (I guess it's NP-hard). If anyone has a better idea (or can prove NP-completeness), please tell me!
Jelly, 54 53 bytes

J×$ÆrAƑƇ«⁹;⁹*€J{ḋ⁸ŻṀ
Œcz€0ḢṂç@I0;ⱮFƲƲ€ṚṁL’R€Ɗ;+Ṁ¥¥ƒ0Ṁ


Try it online!

A monadic link that takes as its argument the list of bowls from top to bottom in the format [[b1_radius, b1_coef1, ...], [b2_radius, b2_coef1, ...]] and returns the y position of the bottom of the top bowl.

Now correctly handles bowls which meet at places other than the minimal radius.

Explanation

Helper link: takes as left argument l the differences in coefficients of the polynomials representing the bowls from 1 upwards, and its right argument r the minimum radius; returns the maximum y value where the two bowls meet

  $                   | Following as a monad:
J                     | - Sequence from 1..&lt;len(l)&gt;
 ×                    | - Multiply (by l)
   Ær                 | Roots of polynomial
     AƑƇ              | Keep only those invariant when passed through absolute function (excludes negative, imaginary and complex numbers)
        «⁹            | Min of these filtered roots and r
          ;⁹          | Concatenate r to the list
            *€        | Each root/radius to the power of:
              J{      | - Sequence from 1..&lt;len(l)&gt;
                ḋ⁸    | Dot product with l
                  Ż   | Prepend zero
                   Ṁ  | Maximum


Main link, takes a bowl pile as its argument and returns y value of base of top bowl

Œc                               | Combinations length 2
  z€0                            | Transpose each using 0 as a filler
               Ʋ€                | For each one, do the following as a monad:
     Ḣ                           | - Take the head (the radii)     
      Ṃ                          | - Minimum
       ç@     Ʋ                  | - Call the helper link with this (min radius) as right argument and the following as left argument:
         I                       |   - Increments (difference between second and first polynomial for each coefficient)
          0;Ɱ                    |   - Prepend each with a zero (odd coefficients are all zero)
             F                   |   - Flatten
                 Ṛ               | Reverse
                  ṁ    Ɗ         | Mould to the following as a monad:
                   L             | Length
                    ’            | Decrease by 1
                     R€          | Range of each (e.g. [1],[1,2],[1,2,3],[1,2,3,4]
                            ¥ƒ0  | Reduce using the following as a dyad and starting with 0
                        ;  ¥     | - Concatenate the following as a dyad
                         +       |   - Add
                          Ṁ      |   - Take the maximum
                               Ṁ | Finally take the overall maximum


Python reference

Finally, here’s a TIO version of the Python reference that @pasbi included for the main problem.  It reads from stdin.