24
\$\begingroup\$

What is the Ultraradical

The ultraradical, or the Bring radical, of a real number \$a\$ is defined as the only real root of the quintic equation \$x^5+x+a=0\$.

Here we use \$UR(\cdot)\$ to denote the ultraradical function. For example, \$UR(-100010)=10\$, since \$10^5+10-100010=0\$.

Challenge

Write a full program or a function, that takes a real number as input, and returns or outputs its ultraradical.

Requirements

No standard loopholes are allowed. The results for the test cases below must be accurate to at least 6 significant digits, but in general the program should calculate the corresponding values for any valid real number inputs.

Test Cases

9 decimal places rounded towards 0 are given for reference. Explanation is added for some of the test cases.

 a                         | UR(a)
---------------------------+---------------------
             0             |   0.000 000 000        # 0
             1             |  -0.754 877 (666)      # UR(a) < 0 when a > 0
            -1             |   0.754 877 (666)      # UR(a) > 0 when a < 0
             1.414 213 562 |  -0.881 616 (566)      # UR(sqrt(2))
            -2.718 281 828 |   1.100 93(2 665)      # UR(-e)
             3.141 592 653 |  -1.147 96(5 385)      # UR(pi)
            -9.515 716 566 |   1.515 71(6 566)      # 5th root of 8, fractional parts should match
            10             |  -1.533 01(2 798)
          -100             |   2.499 20(3 570)
         1 000             |  -3.977 89(9 393)
      -100 010             |  10.000 0(00 000)      # a = (-10)^5 + (-10)
 1 073 741 888             | -64.000 0(00 000)      # a = 64^5 + 64

Winning Criteria

The shortest valid submission in every language wins.

\$\endgroup\$

18 Answers 18

12
\$\begingroup\$

Wolfram Language (Mathematica), 20 bytes

Root[xx^5+x+#,1]&

Try it online!

Still a built-in, but at least it isn't UltraRadical.

(the character is displayed like |-> in Mathematica, similar to => in JS)

\$\endgroup\$
  • 9
    \$\begingroup\$ I keep wondering why Mathematica uses and instead of and \$\endgroup\$ – Adám Sep 23 at 12:19
  • 2
    \$\begingroup\$ @Adám am I supposed to just see squares for the first two, or am I missing some kind of font... \$\endgroup\$ – mbrig Sep 24 at 17:11
  • 6
    \$\begingroup\$ @mbrig Just squares. That's my point. Mathematica uses characters in the Private Use Areas even though Unicode does have most of them. \$\endgroup\$ – Adám Sep 24 at 17:39
8
\$\begingroup\$

Python 3.8 (pre-release), 60 bytes

f=lambda n,x=0:x!=(a:=x-(x**5+x+n)/(5*x**4+1))and f(n,a)or a

Try it online!

Newton iteration method. \$ x' = x - \frac {f(x)} {f'(x)} = x - \frac {x^5+x+n} {5x^4+1}\$

While using \$ \frac {4x^5-n} {5x^4+1} \$ is mathematically equivalent, it makes the program loop forever.


Other approach:

Python 3.8 (pre-release), 102 bytes

lambda x:a(x,-x*x-1,x*x+1)
a=lambda x,l,r:r<l+1e-9and l or(m:=(l+r)/2)**5+m+x>0and a(x,l,m)or a(x,m,r)

Try it online!

Binary search, given that the function x^5+x+a is increasing. Set the bounds to -abs(x) and abs(x) is enough but -x*x-1 and x*x+1 is shorter.

BTW Python's recursion limit is a bit too low so it's necessary to have 1e-9, and the := is called the walrus operator.

\$\endgroup\$
  • \$\begingroup\$ Would a linear search take less bytes? \$\endgroup\$ – user202729 Sep 23 at 2:57
8
\$\begingroup\$

JavaScript (ES7), 44 bytes

A safer version using the same formula as below but with a fixed number of iterations.

n=>(i=1e3,g=x=>i--?g(.8*x-n/(5*x**4+5)):x)``

Try it online!


JavaScript (ES7),  43  42 bytes

Newton's method, using \$5x^4+5\$ as an approximation of \$f'(x)=5x^4+1\$.

n=>(g=x=>x-(x-=(x+n/(x**4+1))/5)?g(x):x)``

Try it online!

How?

We start with \$x_0=0\$ and recursively compute:

$$x_{k+1}=x_k-\frac{{x_k}^5+x_k+n}{5{x_k}^4+5}=x_k-\frac{x_k+\frac{n}{{x_k}^4+1}}{5}$$

until \$x_k-x_{k+1}\$ is insignificant.

\$\endgroup\$
  • \$\begingroup\$ Since comparing equivalence of floating numbers is inaccurate, I am not sure whether the termination of the program can be guaranteed for every possible input (the Python 3 answer below already experienced issues when attempting to shorten the formula). \$\endgroup\$ – Joel Sep 23 at 17:52
  • 1
    \$\begingroup\$ @Joel I've added a safer version. \$\endgroup\$ – Arnauld Sep 23 at 18:25
7
\$\begingroup\$

Jelly, 8 bytes

;17B¤ÆrḢ

Try it online!

How it works:

  • Constructs the list [a, 1, 0, 0, 0, 1] by prepending a to the binary representation of 17. Why this list? Because it corresponds to the coefficients we are looking for:

    [a, 1, 0, 0, 0, 1] -> P(x) := a + 1*x^1 + 0*x^2 + 0*x^3 + 0*x^4 + 1*x^5 = a + x + x^5
    
  • Then, Ær is a built-in that solves the polynomial equation P(x) = 0, given a list of coefficients (what we constructed earlier).

  • We are only interested in the real solution, so we take the first entry in the list of solutions with .

\$\endgroup\$
6
\$\begingroup\$

APL (Dyalog Unicode), 11 10 bytesSBCS

-1 thanks to dzaima

Anonymous tacit prefix function.

(--*∘5)⍣¯1

Try it online!

()⍣¯1 apply the following tacit function negative one time:

- the negated argument

- minus

*∘5 the argument raised to the power of 5

In essence, this asks: Which \$x\$ do I need to feed to \$f(x)=-x-x^5\$ such that the result becomes \$y\$.

\$\endgroup\$
  • \$\begingroup\$ This is very cool. Sadly J does not seem able to perform this inversion \$\endgroup\$ – Jonah Sep 23 at 12:04
  • \$\begingroup\$ @dzaima Why didn't I see that‽ Thank you. \$\endgroup\$ – Adám Sep 24 at 11:31
5
\$\begingroup\$

R, 43 bytes

function(a)nlm(function(x)abs(x^5+x+a),a)$e

Try it online!

nlm is an optimization function, so this searches for the minimum of the function \$x\mapsto |x^5+x+a|\$, i.e. the only zero. The second parameter of nlm is the initialization point. Interestingly, initializing at 0 fails for the last test case (presumably because of numerical precision), but initializing at a (which isn't even the right sign) succeeds.

\$\endgroup\$
  • \$\begingroup\$ @TheSimpliFire Mathematically, it is equivalent, but numerically, it isn't: using the square instead of the absolute value leads to the wrong value for large input. (Try it online.) \$\endgroup\$ – Robin Ryder Sep 23 at 15:42
4
\$\begingroup\$

R, 56 bytes

function(x)(y=polyroot(c(x,1,0,0,0,1)))[abs(Im(y))<1e-9]

Try it online!

Thanks to @Roland for pointing out polyroot. I have also realised my previous answer picked a complex root for zero or negative \$a\$ so now rewritten using polyroot and filtering complex roots.

\$\endgroup\$
  • 2
    \$\begingroup\$ 43 bytes \$\endgroup\$ – Robin Ryder Sep 23 at 10:14
  • \$\begingroup\$ @RobinRyder that’s sufficiently different that I think you should post your own answer. Thanks though! \$\endgroup\$ – Nick Kennedy Sep 23 at 10:36
  • 1
    \$\begingroup\$ OK, thanks. Here it is. \$\endgroup\$ – Robin Ryder Sep 23 at 11:49
  • \$\begingroup\$ "Unfortunately", polyroot returns all complex roots ... Otherwise it would win. \$\endgroup\$ – Roland Sep 25 at 15:17
3
\$\begingroup\$

J, 14 bytes

{:@;@p.@,#:@17

Try it online!

J has a built in for solving polynomials... p.

The final 4 test cases timeout on TIO, but in theory are still correct.

how

The polynomial coefficients for J's builtin are taken as a numeric list, with the coefficient for x^0 first. This means the list is:

a 1 0 0 0 1

1 0 0 0 1 is 17 in binary, so we represent it as #:@17, then append the input ,, then apply p., then unbox the results with raze ;, then take the last element {:

\$\endgroup\$
3
\$\begingroup\$

Ruby, 53 41 bytes

->a{x=a/=5;99.times{x-=a/(x**4+1)+x/5};x}

Try it online!

Using Newton-Raphson with a fixed number of iterations, and the same approximation trick as Arnauld

\$\endgroup\$
2
\$\begingroup\$

Pari/GP, 34 32 26 24 bytes

a->-solve(X=0,a,a-X-X^5)

Try it online!

\$\endgroup\$
  • \$\begingroup\$ Nice answer, but out of curiosity: why does s(-100010) result in -8.090... - 5.877...*I instead of just 10? Is this a limitation of the language for large test cases? PS: You can save 2 bytes changing both 0.2 to .2. :) \$\endgroup\$ – Kevin Cruijssen Sep 23 at 11:31
  • \$\begingroup\$ Thanks for the tip @KevinCruijssen. The issue is actually for the whole of \$\Bbb R^-\$, but please see the workaround :) \$\endgroup\$ – TheSimpliFire Sep 23 at 12:06
  • \$\begingroup\$ You can use an anonymous function: a->solve(X=-a,a,X^5+X+a). \$\endgroup\$ – alephalpha Sep 23 at 12:46
  • \$\begingroup\$ Thanks @alephalpha. \$\endgroup\$ – TheSimpliFire Sep 23 at 13:03
2
\$\begingroup\$

05AB1E, 12 bytes

ΔyIy4m>/+5/-

Try it online!

Newton's method.

\$\endgroup\$
2
\$\begingroup\$

k4, 33 31 bytes

{{y-(x+y+*/5#y)%5+5*/4#y}[x]/x}

newton-raphson computed iteratively until a number is converged on

edit: -2 thanks to ngn!


whoops, got this all wrong...

K (oK), 10 bytes

{-x+*/5#x}
\$\endgroup\$
  • \$\begingroup\$ @ngn lol, that was careless... updated but now in k4 as i'm too lazy to do it in ngn/k or oK :) \$\endgroup\$ – scrawl Oct 9 at 19:44
  • \$\begingroup\$ cool! the last pair of [ ] seems unnecessary \$\endgroup\$ – ngn Oct 9 at 19:49
  • \$\begingroup\$ hmm, you're right. i've encountered strange behaviour before where over/converge results in an infinite loop because of extraneous/omitted (one or the other, i forget) brackets. that's why i left them in but i should have checked. thanks! \$\endgroup\$ – scrawl Oct 9 at 20:05
1
\$\begingroup\$

Pari/GP, 24 bytes

a->polrootsreal(x^5+x+a)

Try it online!

\$\endgroup\$
  • \$\begingroup\$ Nice, didn't know that solve has an analogue \$\endgroup\$ – TheSimpliFire Sep 23 at 13:20
1
\$\begingroup\$

C,118b/96b

#include<math.h>
double ur(double a){double x=a,t=1;while(fabs(t)>1e-6){t=x*x*x*x;t=(x*t+x+a)/(5*t+1);x-=t;}return x;}

118 bytes with original function name and with some extra accuracy (double). With bit hacks may be better, but unportable.

96 bytes with fixed iterations.

double ur(double a){double x=a,t;for(int k=0;k<99;k++){t=x*x*x*x;x=(4*x*t-a)/(5*t+1);}return x;}

Actually, our function is so good we can use better adaptations of Newton's method. Much faster and practical implementation (150 bytes) would be

#include<math.h>
double ur(double a){double x=a/5,f=1,t;while(fabs(f)>1e-6){t=x*x*x*x;f=(t*(5*t*x+5*a+6*x)+a+x)/(15*t*t-10*a*x*x*x+1);x-=f;}return x;}

I checked it works, but I'm too lazy to find out how much more fast it would be. Should be at least one more order faster as Newton's.

\$\endgroup\$
  • \$\begingroup\$ Would something like x-=t=... work? \$\endgroup\$ – user202729 Sep 25 at 2:15
  • 1
    \$\begingroup\$ 82 bytes \$\endgroup\$ – ceilingcat Sep 28 at 1:52
0
\$\begingroup\$

Clean, 61 60 bytes

import StdEnv
$a=iter 99(\x=(3.0*x^5.0-a)/inc(4.0*x^4.0))0.0

Try it online!

Newton's method, first implemented in user202729's answer.

Clean, 124 bytes

import StdEnv
$a= ?a(~a)with@x=abs(x^5.0+x+a);?u v|u-d==u=u|v+d==v=v= ?(u+if(@u< @v)0.0d)(v-if(@u> @v)0.0d)where d=(v-u)/3E1

Try it online!

A "binary" search, narrowing the search area to the upper or lower 99.6% of the range between the high and low bounds at each iteration instead of 50%.

\$\endgroup\$
0
\$\begingroup\$

Python 3 + sympy, 72 bytes

lambda y:float(sympy.poly("x**5+x+"+str(y)).all_roots()[0])
import sympy

Try it online!

\$\endgroup\$
0
\$\begingroup\$

Octave, 25 bytes

@(a)fzero(@(x)x^5+x+a,-a)

Try it online!

\$\endgroup\$
0
\$\begingroup\$

Maplesoft Maple, 23 bytes

f:=a->fsolve(x^5+x+a=0)

Unfortunately, there is no online Maple compiler/calculator out there AFAIK. But the code is pretty straightforward.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.