17
\$\begingroup\$

Today (or tomorrow, depending on your timezone, by the time of posting) is the birthday of the great mathematician and physicist Leonhard Euler. To celebrate his birthday, this challenge is about one of his theorems in geometry.

For a triangle, we define its incircle to be the largest circle inside the triangle and its circumcircle to be the circle that passes through all of the traingle's vertices.

Consider a triangle in a plane, we plot the center of its incircle I (sometimes called incenter) and the center of its circumcircle O (sometimes called circumcenter). Let \$r\$ be the radius of the incircle, \$R\$ be the radius of circumcircle, \$d\$ be the distance between I and O. Euler's theorem in geometry states that \$d^2=R(R-2r)\$.

The challenge

In the spirit of this theorem, your task, is for a triangle given by the lengths of its three sides, output \$d\$ (the distance between incenter I and circumcenter O described above).

  • Your code needs to take only the length of the three sides of triangle and output \$d\$. Inputs and outputs can be in any reasonable format.
  • The absolute error or relative error from your output and correct answer must be no greater than \$10^{-2}\$.
  • It's guaranteed that the three side lengths are positive integers and can form a non-degenerate triangle.
  • Standard loopholes are forbidden.

Since this is a , the shortest code in bytes wins!

Examples

In the samples, the outputs are rounded to 3 decimal places. You, however, are free to round them to more decimal places.

[a,b,c]       -> d
[2,3,4]       -> 1.265
[3,4,5]       -> 1.118
[3,5,7]       -> 3.055
[7,9,10]      -> 1.507
[8,8,8]       -> 0.000
[123,234,345] -> 309.109

List of sample inputs:

[[2,3,4],[3,4,5],[3,5,7],[7,9,10],[8,8,8],[123,234,345]]

\$\endgroup\$
0

9 Answers 9

13
\$\begingroup\$

JavaScript (ES7),  80 74 66  65 bytes

(a,b,c)=>(s=a+b+c,(p=a*b*c/s)*p/4*(s/=2)/(s-a)/(s-b)/(s-c)-p)**.5

Try it online!

How?

This is derived from:

  • The semiperimeter \$s\$ of the triangle:

    $$s=\frac{a+b+c}{2}$$

  • The circumradius \$R\$ of the triangle:

    $$R=\frac{abc}{4\sqrt{s(s-a)(s-b)(s-c)}}$$

  • The product of the inradius \$r\$ and the circumradius:

    $$rR=\frac{abc}{2(a+b+c)}=\frac{abc}{4s}$$

  • Euler's theorem:

    $$d=\sqrt{R(R-2r)}=\sqrt{R^2-2rR}=\sqrt{R^2-\frac{abc}{2s}}$$

\$\endgroup\$
3
  • \$\begingroup\$ Clever... using the perimeter at first, and then halving it. \$\endgroup\$ Commented Apr 15, 2020 at 5:55
  • \$\begingroup\$ 62 bytes \$\endgroup\$
    – newbie
    Commented Apr 15, 2020 at 6:35
  • 1
    \$\begingroup\$ @newbie Nice! But I think I'll leave this one unchanged, since the shorter version has already been posted by Tim Pederick. \$\endgroup\$
    – Arnauld
    Commented Apr 15, 2020 at 7:49
8
\$\begingroup\$

Python 3, 66 bytes

This formerly took advantage of the new assignment expressions ("walrus operator") introduced in Python 3.8. Thanks to commentors, I've taken that out, so it works on previous versions too!

lambda a,b,c:((a*b*c/(b+c-a)/(a+c-b)/(a+b-c)-1)*a*b*c/(a+b+c))**.5

Try it online!

It's based on the same calculations described in Arnauld's answer, but using the perimeter \$p\$ instead of the semiperimeter \$s\$: $$ \begin{aligned}\\ p&=a+b+c\\ &=2s \end{aligned}\\ \therefore d=\sqrt{R^2-\frac{abc}{p}}\\ \text{and } R^2=\frac{\left(abc\right)^2}{p(p-2a)(p-2b)(p-2c)} $$

The grand total savings of this rearrangement is... two bytes.

Factoring \$p\$ out and expanding the terms in the denominator means I don't have to store \$p\$, saving another three bytes. I also stored the product \$abc\$ in a variable \$m\$, which saved some bytes at first... but it could later be factored out, turning the brackets-and-walrus into a liability, not a savings! Here's the final formula: \begin{aligned} d&=\sqrt{\frac{\left(abc\right)^2}{p(p-2a)(p-2b)(p-2c)}-\frac{abc}{p}}\\ &=\sqrt{\left(\frac{abc}{(b+c-a)(a+c-b)(a+b-c)}-1\right)\frac{abc}{p}} \end{aligned}

\$\endgroup\$
5
  • \$\begingroup\$ 70 bytes \$\endgroup\$ Commented Apr 15, 2020 at 6:04
  • \$\begingroup\$ @dingledooper: Thanks! I'd just realised the same thing myself: storing \$m\$ meant that I could multiply by it instead of squaring, saving a byte. \$\endgroup\$ Commented Apr 15, 2020 at 6:10
  • \$\begingroup\$ Actually... 66 bytes \$\endgroup\$
    – newbie
    Commented Apr 15, 2020 at 6:34
  • \$\begingroup\$ @newbie And here I thought factoring out \$m\$ wouldn't save anything... I hadn't realised that it meant being able to drop a pair of parentheses. Thanks! \$\endgroup\$ Commented Apr 15, 2020 at 7:25
  • \$\begingroup\$ @dingledooper: facepalm Thanks. Done. \$\endgroup\$ Commented Apr 16, 2020 at 5:13
4
\$\begingroup\$

Charcoal, 31 18 bytes

I₂∕×⊖∕ΠθΠ⁻Σθ⊗θΠθΣθ

Try it online! Link is to verbose version of code. Takes input as a vector of doubles and outputs a double. Explanation:

$$ \begin{align}d &=\sqrt{R(R-2r)}\\ &=\sqrt{R^2-2Rr}\\ &=\sqrt{\left(\frac{abc}{4\Delta}\right)^2-\frac{abc}{2s}}\\ &=\sqrt{\frac{(abc)^2}{16\Delta^2}-\frac{abc}{2s}}\\ &=\sqrt{\frac{(abc)^2}{2s(2s-2a)(2s-2b)(2s-2c)}-\frac{abc}{2s}}\\ &=\sqrt{\frac{abc}{2s}\left(\frac{abc}{(2s-2a)(2s-2b)(2s-2c)}-1\right)}\\ \end{align} $$

where \$ 2s=a+b+c \$ and \$ \Delta=\sqrt{s(s-a)(s-b)(s-c)} \$.

            ⊗θ      `[2a, 2b, 2c]`
         ⁻Σθ        Vectorised subtract from `a+b+c`
        Π           Take the product
     ∕Πθ            Divide `abc` by that
    ⊖               Decrement
   ×          Πθ    Multiply by `abc`
  ∕             Σθ  Divide by `a+b+c`
 ₂                  Take the square root
I                   Cast to string
                    Implicitly print
\$\endgroup\$
4
\$\begingroup\$

05AB1E, 23 22 21 20 15 14 bytes

PDIϮPt/<*IO/t

-5 bytes porting @Neil's Charcoal answer, so make sure to upvote him!!
-1 byte thanks to @Grimmy.

Try it online or verify all test cases.

Explanation:

P              # Take the product of the (implicit) input-list
               #  [a,b,c] → abc
 D             # Duplicate it
  Iœ           # Get all permutations of the input-triplet
               #  [a,b,c] → [[a,b,c],[a,c,b],[b,a,c],[b,c,a],[c,a,b],[c,b,a]]
    Æ          # Reduce each by subtracting:
               #  → [a-b-c,a-c-b,b-a-c,b-c-a,c-a-b,c-b-a]
     P         # Take the product of that
               #  → (a-b-c)(a-c-b)(b-a-c)(b-c-a)(c-a-b)(c-b-a)
               #   → (a-b-c)²*(b-a-c)²*(c-a-b)²
      t        # Take the square-root
               #  → sqrt((a-b-c)²*(b-a-c)²*(c-a-b)²)
       /       # Divide the initially duplicated product by it
               #  → abc/(sqrt((a-b-c)²*(b-a-c)²*(c-a-b)²))
        <      # Decrease it by 1
               #  → abc/(sqrt((a-b-c)²*(b-a-c)²*(c-a-b)²))-1
         *     # Multiply it by the initial product
               #  → abc(abc/(sqrt((a-b-c)²*(b-a-c)²*(c-a-b)²))-1)
          IO/  # Divide it by the input-sum
               #  → abc(abc/(sqrt((a-b-c)²*(b-a-c)²*(c-a-b)²))-1)/(a+b+c)
             t # And take the square-root of that
               #  → sqrt(abc(abc/(sqrt((a-b-c)²*(b-a-c)²*(c-a-b)²))-1)/(a+b+c))
               # (after which it is output implicitly as result)

Or as a single formula:

$$d=\sqrt{\frac{abc\left(\frac{abc}{\sqrt{(a-b-c)^2\times(b-a-c)^2\times(c-a-b)^2}}-1\right)}{a+b+c}}$$

\$\endgroup\$
8
  • 1
    \$\begingroup\$ My attempt to port the formula I came up with clocks in at 17 bytes, which is bad, since it's only 18 in Charcoal... \$\endgroup\$
    – Neil
    Commented Apr 14, 2020 at 15:57
  • \$\begingroup\$ @Neil Nice approach! I got it down to 15 bytes porting your answer. Was about to go eat dinner, so will update it afterwards. :) \$\endgroup\$ Commented Apr 14, 2020 at 16:04
  • 1
    \$\begingroup\$ @Neil You're not the first one who couldn't find ·; I see answers overlooking it so many times for some reason.. I personally never really use the info.txt but use the wiki Commands page instead (although it is lacking some new builtins every now and then..) Btw, using the x we could still end up at 15 bytes: PDIxsOαP/<*IO/t. ;) \$\endgroup\$ Commented Apr 14, 2020 at 17:53
  • 2
    \$\begingroup\$ It doesn't help that one says a * 2 and the other says 2 * a... \$\endgroup\$
    – Neil
    Commented Apr 14, 2020 at 18:53
  • 1
    \$\begingroup\$ IOI·-P => IœÆPt for -1 (verify all) \$\endgroup\$
    – Grimmy
    Commented Apr 23, 2020 at 10:28
3
\$\begingroup\$

Java 8, 67 bytes

(a,b,c)->Math.sqrt(a*b*c*(a*b*c/(b+c-a)/(a+c-b)/(a+b-c)-1)/(a+b+c))

Try it online.

Not much to say. Uses the same formula as in @TimPederick's Python answer, which was based on @Arnauld's JavaScript answer, but which uses a rather similar formula as @Neil's Charcoal answer.

$$d=\sqrt{\frac{abc\left(abc\div(b+c-a)\div(a+c-b)\div(a+b-c)-1\right)}{a+b+c}}$$

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

Io, 87 bytes

Port of Arnauld's answer.

method(a,b,c,((y :=b*a*c/(z :=((b+c-a)*(c+a-b)*(a+b-c)/(x :=a+b+c))**.5)/x)*(y-z))**.5)

Try it online!

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

C (gcc), 76 72 bytes

Saved 4 bytes thanks to ceilingcat!!!

#define f(a,b,c)sqrt(a*b*c*(a*b*c/(0.+b+c-a)/(a+c-b)/(a+b-c)-1)/(a+b+c))

Try it online!

Port of Kevin Cruijssen's Java answer.

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

APL (Dyalog Unicode), 22 bytes

.5*⍨×/÷+/÷¯1+⊢×.÷+/-+⍨

Try it online!

Yet another port of Tim Pederick's Python answer.

$$ \begin{align} d&=\sqrt{\left(\frac{abc}{(b+c-a)(a+c-b)(a+b-c)}-1\right)\frac{abc}{a+b+c}} \\ &=\sqrt{\frac{abc}{\frac{a+b+c}{\frac{abc}{(b+c-a)(a+c-b)(a+b-c)}-1}}} \end{align} $$

Kind of ugly, but this is precisely what the code does. Requires ⎕DIV←1, i.e. division by 0 gives 0 (otherwise a=b=c case will throw an error).

How it works

.5*⍨×/÷+/÷¯1+⊢×.÷+/-+⍨  ⍝ Input: a 3-length vector [a b c]
                 +/-+⍨  ⍝ (a+b+c) - [2a, 2b, 2c] = [b+c-a, c+a-b, a+b-c]
             ⊢×.÷       ⍝ product([a,b,c] ÷ above)
          ¯1+           ⍝ above minus 1
    ×/÷+/÷  ⍝ product(a,b,c) ÷ (sum(a,b,c) ÷ above)
.5*⍨        ⍝ square root
\$\endgroup\$
0
\$\begingroup\$

Forth (gforth), 90 bytes

: f dup 2over * * s>f fdup 3. do dup 2over - - s>f f/ rot loop 1e f- f* + + s>f f/ fsqrt ;

Try it online!

Port of Kevin Cruijssen's Java answer. Since the inputs are positive integers, it takes the input from the data stack and returns the result through the FP stack.

A separate FP stack makes the task a bit easier, but having to work through three alternating sums explicitly is definitely a pain.

In order to copy top three elements, I used dup 2over which converts a b c into a b c c a b. Thankfully I didn't need exactly "3dup" because addition + and multiplication * are commutative, and alternating sums (c - (a - b)) are calculated for all three rotations (abc, bca, cab).

: f ( a b c -- f:result )
  dup 2over * * s>f fdup  ( a b c ) ( f: prod prod )
  3. do dup 2over - - s>f f/ rot loop  ( a b c ) ( f: prod prod/rots )
  1e f- f* + + s>f f/ fsqrt
;
\$\endgroup\$

Your Answer

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

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