29
\$\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 \$\text{UR}(\cdot)\$ to denote the ultraradical function. For example, \$\text{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\$

22 Answers 22

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\$
3
  • 9
    \$\begingroup\$ I keep wondering why Mathematica uses and instead of and \$\endgroup\$
    – Adám
    Sep 23, 2019 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, 2019 at 17:11
  • 7
    \$\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, 2019 at 17:39
8
\$\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\$
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\$
1
  • \$\begingroup\$ Would a linear search take less bytes? \$\endgroup\$
    – DELETE_ME
    Sep 23, 2019 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\$
2
  • \$\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, 2019 at 17:52
  • 1
    \$\begingroup\$ @Joel I've added a safer version. \$\endgroup\$
    – Arnauld
    Sep 23, 2019 at 18:25
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\$
2
  • \$\begingroup\$ This is very cool. Sadly J does not seem able to perform this inversion \$\endgroup\$
    – Jonah
    Sep 23, 2019 at 12:04
  • \$\begingroup\$ @dzaima Why didn't I see that‽ Thank you. \$\endgroup\$
    – Adám
    Sep 24, 2019 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\$
1
  • \$\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\$ Sep 23, 2019 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\$
4
  • 2
    \$\begingroup\$ 43 bytes \$\endgroup\$ Sep 23, 2019 at 10:14
  • \$\begingroup\$ @RobinRyder that’s sufficiently different that I think you should post your own answer. Thanks though! \$\endgroup\$ Sep 23, 2019 at 10:36
  • 1
    \$\begingroup\$ OK, thanks. Here it is. \$\endgroup\$ Sep 23, 2019 at 11:49
  • \$\begingroup\$ "Unfortunately", polyroot returns all complex roots ... Otherwise it would win. \$\endgroup\$
    – Roland
    Sep 25, 2019 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\$
4
  • \$\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\$ Sep 23, 2019 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\$ Sep 23, 2019 at 12:06
  • \$\begingroup\$ You can use an anonymous function: a->solve(X=-a,a,X^5+X+a). \$\endgroup\$
    – alephalpha
    Sep 23, 2019 at 12:46
  • \$\begingroup\$ Thanks @alephalpha. \$\endgroup\$ Sep 23, 2019 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\$
3
  • \$\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, 2019 at 19:44
  • \$\begingroup\$ cool! the last pair of [ ] seems unnecessary \$\endgroup\$
    – ngn
    Oct 9, 2019 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, 2019 at 20:05
1
\$\begingroup\$

Pari/GP, 24 bytes

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

Try it online!

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

Octave, 25 bytes

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

Try it online!

\$\endgroup\$
1
\$\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\$
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\$
2
  • \$\begingroup\$ Would something like x-=t=... work? \$\endgroup\$
    – DELETE_ME
    Sep 25, 2019 at 2:15
  • 1
    \$\begingroup\$ 82 bytes \$\endgroup\$
    – ceilingcat
    Sep 28, 2019 at 1:52
1
\$\begingroup\$

MMIX, 68 bytes (17 instrs)

(jelly-style xxd -g4)

00000000: e0043ff0 e0034014 79010001 3b01013f  ṭ¥?ṅṭ¤@Þy¢¡¢;¢¢?
00000010: e8013ff0 c1020100 10ff0202 10ffffff  ċ¢?ṅḊ£¢¡Ñ”££Ñ”””
00000020: 1001ff02 10ffff03 e4010020 04ffff04  Ñ¢”£Ñ””¤ỵ¢¡ ¥””¥
00000030: 06010100 140101ff 11020102 5b02fff6  ©¢¢¡Þ¢¢”×£¢£[£”ẇ
00000040: f8020000                             ẏ£¡¡

Disassembly

bringr  SETH  $4,#3FF0          // one = 1.
        SETH  $3,#4014          // five = 5.
        ZSNN  $1,$0,1           // x = (a neg? 0 : 1)
        SLU   $1,$1,63          // x <<= 63
        ORH   $1,#3FF0          // x |= 1. [now x = a neg? 1. : -1.]
0H      SET   $2,$1             // loop: px = x
        FMUL  $255,$2,$2        // t = px *. px
        FMUL  $255,$255,$255    // t = t *. t
        FMUL  $1,$255,$2        // x = t *. px
        FMUL  $255,$255,$3      // px = px *. five
        INCH  $1,#20            // x *.= 4. (bit trick: add two to exponent)
        FADD  $255,$255,$4      // t = t +. one
        FSUB  $1,$1,$0          // x = x -. a
        FDIV  $1,$1,$255        // x = x /. t
        FCMPE $2,$1,$2          // px = epsilon_comp(x, px)
        PBNZ  $2,0B             // iflikely(px) goto loop
        POP   2,0               // return x

I used WolframAlpha to simplify Newton's method for this. It said that \$\def\d{{\rm d}}x-{x^5+x+a\over{\d\over \d x}x^5+x+a}\$ simplified down to \$4x^5-a\over5x^4+1\$. The convergence test here is a builtin epsilon-convergence, so rE must be set by the calling function.

For faster convergence, change ORH $1,#3FF0 to

        SLU  $255,$0,1      // 3BFF0001 ;”¡¢ shift left to erase sign
        INCH $255,#8020     // E4FF8020 ỵ”⁰  unbias exponent
        PUT  rD,0           // F7010000 ẋ¢¡¡ prep dividend
        DIVU $2,$255,5      // 1F02FF05 þ£”¦ take approximate fifth root
        CSN  $2,$255,$255   // 6002FFFF `£”” and use that if we are >1
        INCH $2,#7FE0       // E4027FE0 ỵ£¶ṭ rebias exponent
        SRU  $255,$2,1      // 3FFF0201 ?”£¢ shift right again
        OR   $1,$1,$255     // C00101FF Ċ¢¢” or sign and guess
\$\endgroup\$
1
\$\begingroup\$

Excel (Insider Beta), 59 bytes

=h(a1,1)
h =LAMBDA(a,x,IF(a=x^5+x,x,h(a,(a/(x^5+x))^0.2*x))) in name manager

1 byte for name h in name manager, 49 bytes for formula for h, 9 bytes for calling h. Uses successive approximations using the 5th root of a/(x^0.5+x) times x. Initial call uses 1 for x.

\$\endgroup\$
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\$

TI-Basic (TI-83), 12 bytes

solve(X^5+X+Ans,X,0

TI-Basic (TI-89), 13* bytes

solve(x^5+x=-a,x)→f(a)

*Not completely sure how to score ti-89 programs/functions

\$\endgroup\$
-1
\$\begingroup\$

Scala, 74 bytes

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

Golfed version. Try it online!

def f(a:Double)={var x=a/5;(1 to 99).foreach{_=>x-=(a/(x*x*x*x+1)+x)/5};x}

Ungolfed version. Try it online!

import scala.math._

object Main {
  def main(args: Array[String]): Unit = {
    val f: Double => Double = a => {
      var x = a / 5
      (1 to 99).foreach { _ =>
        x -= (a / (x * x * x * x + 1) + x) / 5
      }
      x
    }

    val inputs = List(-100010.0, 0.0, 1.0, -1.0, exp(1), pow(2, 0.5), 1073741888.0)
    inputs.foreach { x =>
      println(s"%.9f --> %.9f".format(x, f(x)))
    }
  }
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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