33
\$\begingroup\$

Given three sidelengths of a triangle, evaluate its aspect ratio AR given the following formula:

enter image description here

where

enter image description here

The closer to equilaterality a triangle is, the closer to 1 its aspect ratio is. The aspect ratio is bigger or equal to 1 for valid triangles.

Inputs

The input is three real positive numbers which can be encapsulated in a list or anything similar if need be.

Your program must output the same value no matter what the order in which the three sidelengths are inputted is.

Those three numbers will always be valid sidelengths of a triangle (degenerate triangles like one with sidelengths 1, 1 and 2 will not be given as input). You need not worry about floating point inaccuracies when values become extremely close to a degenerate triangle (e.g. it is acceptable that your program would error division by 0 for input [1, 1, 1.9999999999999999]).

The input can be given through STDIN, as a function argument, or anything similar.

Outputs

The output is a real number bigger or equal to 1 with the standard accuracy that is acceptable in your language.

The output may be printed to STDOUT, returned from a function, or anything similar.

Test cases

Inputs                   Output

  1      1      1         1
  3      4      5         1.25
 42     42   3.14         ≈ 6.9476
 14      6     12         1.575
  6     12     14         1.575
0.5    0.6    0.7         ≈ 1.09375

Scoring

This is , so the shortest answer in bytes wins.

\$\endgroup\$
  • \$\begingroup\$ should s be (a+b+c)/3 ? \$\endgroup\$ – costrom Nov 28 '16 at 16:06
  • 3
    \$\begingroup\$ @costrom No, the formula is correct. s is the semiperimeter of the triangle. your formula would be undefined for an equilateral triangle. \$\endgroup\$ – Fatalize Nov 28 '16 at 17:10
  • \$\begingroup\$ Can I just get floats for input or do I need to get integers as well? \$\endgroup\$ – Erik the Outgolfer Nov 29 '16 at 13:35
  • \$\begingroup\$ @ErikGolferエリックゴルファー It is acceptable to input 42.0 instead of 42. \$\endgroup\$ – Fatalize Nov 29 '16 at 13:37
  • \$\begingroup\$ @Fatalize Thanks. Also, can the inputs all be 0? \$\endgroup\$ – Erik the Outgolfer Nov 29 '16 at 13:39

41 Answers 41

19
\$\begingroup\$

Jelly, 6 bytes

This answer is based on Emigna's 05AB1E answer. Many thanks to Dennis and Lynn for their help in figuring this answer out. Golfing suggestions welcome! Try it online!

S_Ḥ⁸÷P

Ungolfing

           Implicit argument [a, b, c].
S          Take the sum, a+b+c or 2*s
  Ḥ        Take the double, [2*a, 2*b, 2*c].
 _         Vectorized subtract, giving us [2*(s-a), 2*(s-b), 2*(s-c)].
   ⁸÷      Vectorized divide the initial left argument, the input [a, b, c],
             by [2*(s-a), 2*(s-b), 2*(s-c)].
     P     Take the product giving us the aspect ratio, abc/8(s-a)(s-b)(s-c).
\$\endgroup\$
  • 4
    \$\begingroup\$ 6 bytes and you still want golfing suggestions? :-D \$\endgroup\$ – Luis Mendo Nov 27 '16 at 16:58
  • 1
    \$\begingroup\$ @LuisMendo If it's at all possible, sure :D \$\endgroup\$ – Sherlock9 Nov 27 '16 at 17:01
  • 1
    \$\begingroup\$ “Push” isn’t quite correct terminology; Jelly isn’t stack-based. Rather, ⁸÷ gets muched off the chain as a unit, and should be read as divide the initial left argument by this, or something. \$\endgroup\$ – Lynn Nov 27 '16 at 17:28
  • 1
    \$\begingroup\$ @Lynn I'm been golfing Actually for several months now. Stack-based terminology is firmly wedged in my brain :D Should be fixed now. \$\endgroup\$ – Sherlock9 Nov 27 '16 at 17:32
56
+250
\$\begingroup\$

Jelly, 7 bytes

SH_÷@HP

Try it online!

Explanation

enter image description here

Let’s read this chain:

  • The implicit argument is a list [a, b, c].

  • First we read S. This takes the sum: a + b + c.

  • Then, we read H. This halves it: (a + b + c)/2. (This is s.)

  • Then, we read a dyad _ (subtract), followed by another dyad. This is a hook: it lacks a right argument, so it receives the argument to this chain, [a, b, c], giving us [s-a, s-b, s-c]. (This is the fifth chain pattern in the table here.)

  • Then, we read the dyad-monad pair ÷@H. This is a fork: ÷@ is division with the arguments flipped, and H is halve, so our working value gets Half the argument to this chain ÷’d by it. This vectorizes; we’re left with [(a/2)/(s-a), (b/2)/(s-b), (c/2)/(s-c)]. (This is the second chain pattern in the table here.)

  • Finally, we take the product with P, getting us abc/(8(s-a)(s-b)(s-c)).

View a tree-like graph of how the links fit together.

\$\endgroup\$
  • 8
    \$\begingroup\$ The images look great! Nice touch! \$\endgroup\$ – DavidC Nov 27 '16 at 13:10
  • 2
    \$\begingroup\$ I made the top image smaller myself, and turned the second one into a link (no pun intended). \$\endgroup\$ – Lynn Nov 27 '16 at 14:06
  • \$\begingroup\$ I saw the image and immediately thought, "Nice one, Lynn!" before looking at who posted it ;-) \$\endgroup\$ – ETHproductions Nov 28 '16 at 0:24
  • 7
    \$\begingroup\$ Best explanation I've seen of a Jelly program. I still don't understand, but closer! \$\endgroup\$ – Sparr Nov 30 '16 at 7:45
  • \$\begingroup\$ I ran the sample against the test-case ´6.0,12.0,14.0` and it gave `-0.8888888888888888´ instead of 1.575 as shown in the test-cases. Is it a problem with the test-cases or your code? \$\endgroup\$ – MBaas Dec 1 '16 at 4:18
13
\$\begingroup\$

Jelly, 6 bytes

S÷_2Pİ

Try it online!

How it works

S÷_2Pİ  Main link. Argument: [a, b, c]

S       Sum; compute 2s := a + b + c.
 ÷      Divide; yield [2s ÷ a, 2s ÷ b, 2s ÷ c].
  _2    Subtract 2; yield [2s ÷ a - 2, 2s ÷ b - 2, 2s ÷ c - 2].
    P   Product; yield (2s ÷ a - 2)(2s ÷ b - 2)(2s ÷ c - 2).
     İ  Invert; yield 1 ÷ (2s ÷ a - 2)(2s ÷ b - 2)(2s ÷ c - 2).
\$\endgroup\$
  • \$\begingroup\$ Ahh, and I tried to use ³⁴⁵ as arguments... \$\endgroup\$ – Erik the Outgolfer Nov 29 '16 at 13:10
11
\$\begingroup\$

JavaScript, 38 bytes

This is a (curried) lambda:

a=>b=>c=>a*b*c/(b+c-a)/(a+c-b)/(a+b-c)

(If you assign it to a variable f you'd need to call it like f(3)(4)(5))

\$\endgroup\$
  • \$\begingroup\$ Beat me to it by a few seconds :) Mind explaining how the formula works similarly to the one provided by the question? \$\endgroup\$ – Cows quack Nov 27 '16 at 11:21
  • \$\begingroup\$ @KritixiLithos Just plug in s = 1/2(a+b+c) into the formula and simplify :D (e.g. s-a = .5*b+.5*c-.5*a, and the three factors of .5 cancel with 8) \$\endgroup\$ – flawr Nov 27 '16 at 11:22
  • 5
    \$\begingroup\$ (a,b,c)=> is the same length, and costs less bytes to call ;) \$\endgroup\$ – ETHproductions Nov 28 '16 at 0:25
  • 4
    \$\begingroup\$ But I love curry :D \$\endgroup\$ – flawr Nov 28 '16 at 10:21
9
\$\begingroup\$

MATL, 8 7 bytes

tsGE-/p

Try it online!

Explanation

Let's use input [3 4 5] as an example

t    % Take input implicitly. Duplicate
     % STACK: [3 4 5], [3 4 5]
s    % Sum of array
     % STACK: [3 4 5], 12
G    % Push input again
     % STACK: [3 4 5], 12, [3 4 5]
E    % Multiply by 2, element-wise
     % STACK: [3 4 5], 12, [6 8 10]
-    % Subtract, element-wise
     % STACK: [3 4 5], [6 4 2]
/    % Divide, element-wise
     % STACK: [0.5 1 2.5]
p    % Product of array. Implicitly display
     % STACK: 1.25
\$\endgroup\$
9
\$\begingroup\$

05AB1E, 11 7 bytes

05AB1E uses CP-1252 encoding.

O¹·-¹/P

Try it online!

Explanation

O         # sum input
 ¹        # push input again
  ·       # multiply by 2
   -      # subtract from sum
    ¹/    # divide by input
      P   # product
\$\endgroup\$
8
\$\begingroup\$

R, 34 29 bytes

x=scan();prod(x/(sum(x)-2*x))

Reads input from stdin and store as the R-vector x. Then make use of R's vectorization to form the denominator.

\$\endgroup\$
7
\$\begingroup\$

Haskell, 36 bytes

This defines the function # which takes three arguments.

(a#b)c=a*b*c/(b+c-a)/(a+c-b)/(a+b-c)

You have to call it as follows: (3#4)5

A little bit longer but perhaps more golfable:

p=product
f v=p v/p((sum v-).(2*)<$>v)
\$\endgroup\$
6
\$\begingroup\$

MATLAB, 64 38 25 bytes

This is an anyonmous function that implements the formula as provided:

@(v)prod(v./(sum(v)-2*v))

It assumes the input to be a list of three values e.g. [3,4,5]. This example is used in following explanation:

             sum(v)        = 3+4+5 = 12
             sum(v)-2*v    = 12 - 2*[3,4,5] = 12 - [6,8,10] = [6,4,2]
         v./(sum(v)-2*v))  = [3,4,5] ./ [6,4,2] = [0.5,1,2.5]
    prod(v./(sum(v)-2*v))  = 0.5 * 1 * 2.5 = 1.25
\$\endgroup\$
6
\$\begingroup\$

Mathematica, 20 bytes

1##&@@(#/(Tr@#-2#))&

Takes input as a list of three values, which is referred to as # inside the function. Tr@ is the shortest way to sum a list (to get 2s) and 1##&@@(...) multiplies the three factors i/(2s-2i) for i in a, b, c.

If the inputs are integers or rational numbers, you'll get an exact result.

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

Python 3, 42 bytes

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

Try It Online!

\$\endgroup\$
5
\$\begingroup\$

OCaml, 51 bytes

fun a b c->a*.b*.c/.(b+.c-.a)/.(a+.c-.b)/.(a+.b-.c)

Yay, separate operators for floats...

\$\endgroup\$
5
\$\begingroup\$

Wonder, 48 bytes

@@@prod[#0#1#2/1- +#1#0#2/1- +#2#0#1/1- +#2#1#0]

RIP

Usage:

(((@@@prod[#0#1#2/1* * - +#1#0#2- +#2#0#1- +#2#1#0])3)4)5

Explanation

Function calls are costly in Wonder when compared to infix operators in other languages. Because of this, I contained all the terms in an array and got the product of the result instead of multiplying every single term. The code would be equivalent to something like:

(a,b,c)=>product([a,b,c,1/(b+c-a),1/(a+c-b),1/(a+b-c)])
\$\endgroup\$
  • 1
    \$\begingroup\$ Hmm, why "RIP"? \$\endgroup\$ – Luis Mendo Nov 27 '16 at 17:04
  • \$\begingroup\$ It's much longer than necessary/expected \$\endgroup\$ – Mama Fun Roll Nov 27 '16 at 20:16
5
\$\begingroup\$

Actually, 10 8 bytes

This answer is based on Dennis's excellent Jelly answer. Golfing suggestions welcome! Try it online!

;Σ♀/♂¬πì

Ungolfing

     Implicit input [a, b, c].
;    Duplicate [a, b, c].
Σ    sum() to get twice the semiperimeter, 2*s.
♀/   Vectorized divide 2*s by [a, b, c] to get [2*s/a, 2*s/b, 2*s/c].
♂¬   Vectorized subtract 2 to get [2*s/a-2, 2*s/b-2, 2*s/c-2].
π    Get the product of the above to get 8*(s/a-1)*(s/b-1)*(s/c-1).
     This is the same as 8(s-a)(s-b)(s-c)/abc.
ì    Invert to get the aspect ratio, abc/8(s-a)(s-b)(s-c).
     Implicit return.
\$\endgroup\$
5
\$\begingroup\$

Minecraft 1.8, 1607 bytes + 85 blocks = 1692 blytes

Warning: Not golfed. Golfed will take up to 1/3 less blytes.

Here is a commented screenshot:

enter image description here

  • The inputs are a, b, and c,and the output is fin

  • fin, and all other variables in Minecraft are integers, so the standard Minecraft accuracy is 0 decimal points

  • The green border: the command blocks on the left will activate after the ones on the right, which are just variable initializations.

  • The lever (grey-brown rectangle in the down right) is the contraption trigger

  • It takes up so much because of the way Minecraft handles variables. A very simplified overview:

    • /scoreboard objectives add name dummy creates a new variable named "name"

    • /scoreboard players set @p name number sets the variable name to number. Number must be a real number, not a variable.

    • /scoreboard players operation @p name += @p name2 increments name by name2. name2 must be a variable, not a number.

      • -=, /=, *=, = and more can be used instead += to decrement, multiply, divide, etc.
  • I'm not going to post all the 43 commands here. It would help golfing this, but would also help drive me crazy copypasting

  • If 1.9 command blocks would be used, the solution would (at least) use 42 blocks less. If one-letter variables would be used, almost 200 bytes would be saved.

\$\endgroup\$
4
\$\begingroup\$

Java, 38 bytes

(a,b,c)->a*b*c/(b+c-a)/(a-b+c)/(a+b-c)

Testing and ungolfed

public class Pcg101234 {
  interface F {
    double f(double a, double b, double c);
  }
  public static void main(String[] args) {
    F f = (a,b,c)->a*b*c/(b+c-a)/(a-b+c)/(a+b-c);

    System.out.println(f.f(1,1,1));
    System.out.println(f.f(3,4,5));
    System.out.println(f.f(42,42,3.14));
    System.out.println(f.f(14,6,12));
    System.out.println(f.f(6,12,14));
    System.out.println(f.f(0.5,0.6,0.7));
  }
}

Test it!

Output

1.0
1.25
6.947606226693615
1.575
1.575
1.09375
\$\endgroup\$
  • \$\begingroup\$ I feel like (a,b,c) is kinda cheating here, because it contains no type information. IMO the implicit lambda interface (in your case F) should count in the total byte sum. \$\endgroup\$ – F. George Nov 27 '16 at 18:51
  • 4
    \$\begingroup\$ @mEQ5aNLrK3lqs3kfSa5HbvsTWe0nIu Lambdas are heavily recommended. Also, most of the Java 8 entries work like that without any remarks. If you disagree and consider I cheated, I invite you to ask formally in meta if this notation is accepted or not. Meanwhile, I align on previous Java 8 answers. \$\endgroup\$ – Olivier Grégoire Nov 27 '16 at 19:01
4
\$\begingroup\$

Jellyfish, 17 16 bytes

Thanks to Zgarb for saving 1 byte.

p%/*-)/+i
    2%

Try it online!

Explanation

This is based on the same reciprocal formula as Dennis's answer.

In more traditional functional notation, the above program reads as follows:

print(
  1 / fold(
    multiply,
    fold(add, i) / i - 2
  )
)

Where i is the input list. Note that fold(multiply, ...) just computes the product and fold(add, ...) the sum, so we can further simplify this to:

print(1 / product(sum(i) / i - 2))

The sum(i) / i is implemented via the hook )/+ which defines a new unary function to do both steps at once.

\$\endgroup\$
  • \$\begingroup\$ Save a byte with a hook. \$\endgroup\$ – Zgarb Nov 29 '16 at 14:02
4
\$\begingroup\$

Dyalog APL, 10 9 bytes

×/⊢÷+/-+⍨

This is an anonymous function train (an atop of a fork of a fork of a fork), meaning that every sub-function is applied to the argument, inside the following structure:

 ┌─┴─┐          
×/ ┌─┼───┐      
   ⊢ ÷ ┌─┼──┐  
      +/ - +⍨

TryAPL online!

×/ the product of

the arguments

÷ divided by

+/ the sum of the arguments

- minus

+⍨ the arguments doubled (lit. added to themselves)

Mathematical background.

ngn shaved a byte.

\$\endgroup\$
  • \$\begingroup\$ Hi Adám, pls. remind me to ask you about ´⊢´ next week if I forget it :-) \$\endgroup\$ – MBaas Dec 1 '16 at 4:11
  • \$\begingroup\$ I dunno how the "background" link supposedly pertains to this answer because I see no algorithm there at all. Also, can you add some info about order of operations? I've tried to reproduce this answer in a few different languages with varying order of operations but I always get an answer different from that in the question. \$\endgroup\$ – cat Dec 3 '16 at 13:02
  • \$\begingroup\$ @cat Well, it wasn't intended to give the algorithm, only to explain what the aspect ratio is, as there is no such page on Wikipedia. APL is right-to-left, meaning that every function takes whatever is on its right as argument. Therefore, it can be read from left to right as in the explanation. \$\endgroup\$ – Adám Dec 4 '16 at 9:34
3
\$\begingroup\$

2sable, 6 bytes

A port of Dennis' Jelly answer.

Os/ÍPz

Uses the CP-1252 encoding. Try it online!

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

dc, 49 bytes

5k?dsa?dsb?dsc++2/sslalblc**lsla-lslb-lslc-8***/p

A direct implementation of the formula given. Prompts for the three inputs upon invocation on three separate lines and outputs a floating-point value with 5 digits after the decimal point to the next line.

Explanation

5k                                                # Set the output precision to 5 digits after the decimal
  ?dsa                                            # Prompt for first input value on first line, duplicate it, and then store it in register `a`
      ?dsb                                        # Prompt for second input, duplicate it, and store it in register `b`
          ?dsc                                    # Prompt for third input, duplicate it, and store it in register `c`
              ++2/ss                              # Sum up the 3 values on the main stack, then divide sum by 2 and store the result in register `s`
                    lalblc**                      # Copy all three values from registers `a`,`b`,`c` onto the main stack, find their product, and push result to top of main stack
                            lsla-                 # Copy value from register `s` onto main stack, subtract register `a`'s value from it, and push result to main stack
                                 lslb-            # Copy value from register `s` onto main stack, subtract register `b`'s value from it, and push result to main stack
                                      lslc-       # Copy value from register `s` onto main stack, subtract register `c`'s value from it, and push result to main stack
                                           8***   # Find the product of the top three values and 8 and then push the result to main stack
                                               /p # Divide the second to top value (a*b*c) by the top of stack value (8*(s-a)*(s-b)*(s-c)), push the result to the main stack, and then output the result to STDOUT
\$\endgroup\$
3
\$\begingroup\$

TI-Basic, 11 bytes

Input should be in the form of a list, like {A B C}.

prod(Ans)/prod(sum(Ans)-2Ans

Maybe this visual will help (remember that 2s = a+b+c):

      abc                    abc                   abc                prod(Ans)
---------------- = --------------------- = ------------------- = -------------------
8(s-a)(s-b)(s-c)   (2s-2a)(2s-2b)(2s-2c)   (a+b+c)(1-2{a,b,c})   prod(sum(Ans)-2Ans)
\$\endgroup\$
2
\$\begingroup\$

Perl 6, 44 bytes

->\a,\b,\c{a*b*c/(b+c -a)/(a+c -b)/(a+b -c)}
\$\endgroup\$
2
\$\begingroup\$

Python, 55 bytes

def f(x,y,z):s=x+y+z;return 1/((s/x-2)*(s/y-2)*(s/z-2))

Credit to Dennis. I just ported. In Python, a much-neglected language.

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

Forth, 83 bytes

Assumes the floating point parameters start on the floating point stack. Leaves the result on the floating point stack. Using the stack for params/returning is the standard for Forth.

: p 3 fpick ;
: T p p p ;
: f 0 s>f T f- f+ f- T f+ f- f* T f- f- f* 1/f f* f* f* ;

Try it online - contains all test cases

Uses the formula a*b*c * 1/ ( -(a+b-c) * -(b+c-a) * (a+c-b) ). Pretty much the entire program is using only the floating point stack. The exception is the 3 in 3 fpick. This program requires an interpreter that supports fpick (Ideone works, repl.it doesn't).

Explanation: slightly less golfed

\ 3 fpick takes the 3rd element (0-indexed) and pushes a copy
\ Used to copy parameters on the stack over another number 'x' ( a b c x -> a b c x a b c )
: f3p 3 fpick 3 fpick 3 fpick ;

: f                     \ define a function f
0 s>f f3p f- f+ f-      \ push a zero, copy params, compute 0-(a+b-c)
                        \ the zero allows me to copy (I need an 'x' to jump over)
f3p f+ f- f*            \ copy params and compute -(b+c-a), multiply by previous result
                        \ the negatives miraculously cancel
f3p f- f- f*            \ copy and compute (a+c-b), multiply by previous result
1/f f* f* f* ;          \ take the reciprocal and multiply by a*b*c
                        \ the result is left on the floating point stack
\$\endgroup\$
2
\$\begingroup\$

ised: 19 bytes

@*$1/@*{@+$1-2.*$1}

Call it as ised --l 'inputfile.txt' '@*$1/@*{@+$1-2.*$1}' where inputfile.txt can be a file with space separated array, or - to receive from pipe/stdin.

Unicode version (same bytecount but 3 chars less):

Π$1/Π{Σ$1-2.*$1}

Unfortunately, ised wastes a lot of chars for its input argument syntax.

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

vba, 76

Function r(a,b,c)
s=(a+b+c)/2:r=(a*b*c)/(8*(s-a)*(s-b)*(s-c))
End Function

Call with

?r(3,4,5)

or in excel with

=r(5,12,13)

\$\endgroup\$
  • \$\begingroup\$ You'd save 6 bytes with @SuperJedi224 's algorithm: Public Function r(a,b,c):r=a*b*c/(b+c-a)/(a-b+c)/(a+b-c):End Function \$\endgroup\$ – steenbergh Nov 30 '16 at 15:26
2
\$\begingroup\$

C#, 82 bytes

void ar(double a,double b,double c)=>Console.Write(a*b*c/(b+c-a)/(a+c-b)/(a+b-c));

Usage:

ar(42, 42, 3.14);
\$\endgroup\$
2
\$\begingroup\$

Pyke, 12 bytes

1QFQsR/tt)B/

Try it here!

Well, BlueEyedBeast, you had your chance. I used a good algorithm here.

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

k, 19 bytes

{(*/x)%8*/-x-+/x%2}

Evaluates right to left - Divide the list x by 2, sum the result and subtract it from original x. Neg the answer and get the product of the result and 8. The result is the denominator, the numerator is the product of the list.

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

Lua, 45 bytes

a,b,c=...print(a*b*c/(b+c-a)/(a+c-b)/(a+b-c))

Heavily based on the JavaScript answer.

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