16
\$\begingroup\$

Another easy challenge for you.

Your task

Write a program or function that takes the input, which contains 3 pairs of x- and y-coordinates and calculates the area of the triangle formed inside them. For those who can't remember how to calculate it, you can find it here.

Example:

1,2,4,2,3,7       # input as x1,y1,x2,y2,x3,y3
7.5               # output

See it at Wolfram Alpha

Some considerations:

  • The input will be six base 10 positive integers.
  • You may assume the input is in any reasonable format.
  • The points will always form a valid triangle.
  • You can assume the input is already stored in a variable such as t.
  • The shortest code in bytes wins!

Edit: To avoid any confusion I've simplificated how the input should be dealt without jeopardizing any of the current codes.

Remember that the your program/function must output a valid area, so it can't give a negative number as output

\$\endgroup\$
  • 1
    \$\begingroup\$ Re: your edit. Does that mean that I can have an actual array of pairs (e.g., [[1, 2], [4, 2], [3, 7]]) in T? \$\endgroup\$ – Dennis Oct 14 '15 at 21:07
  • 4
    \$\begingroup\$ I'm still confused. The post still says both "3 pairs" and "six ... integers". Note that removing either one would invalidate some answers. \$\endgroup\$ – xnor Oct 14 '15 at 21:08
  • 1
    \$\begingroup\$ I don't like seeing a question change after posting and answer. But this time I can save 2 more bytes, so it's all right \$\endgroup\$ – edc65 Oct 14 '15 at 21:37
  • 1
    \$\begingroup\$ If we can take them in as three pairs, can we take them in as a multidimensional array? That is, [1 2;4 2;3 7] (using Julia syntax)? \$\endgroup\$ – Glen O Oct 15 '15 at 5:16
  • 2
    \$\begingroup\$ @YiminRong The area of a triangle cannot be negative by definition. It does not matter what order the points are in. \$\endgroup\$ – Rainbolt Oct 15 '15 at 19:19

17 Answers 17

16
\$\begingroup\$

CJam, 18 16 bytes

T(f.-~(+.*:-z.5*

Try it online in the CJam interpreter.

Idea

As mentioned on Wikipedia, the area of the triangle [[0 0] [x y] [z w]] can be calculated as |det([[x y] [z w]])| / 2 = |xw-yz| / 2.

For a generic triangle [[a b] [c d] [e f]], we can translate its first vertex to the origin, thus obtaining the triangle [[0 0] [c-a d-b] [e-a f-b]], whose area can be calculated by the above formula.

Code

T                  e# Push T.
                   e# [[a b] [c d] [e f]]
   (               e# Shift out the first pair.
                   e# [[c d] [e f]] [a b]
    f.-            e# For [c d] and [e f], perform vectorized
                   e# subtraction with [a b].
                   e# [[c-a d-b] [e-a f-b]]
       ~           e# Dump the array on the stack.
                   e# [c-a d-b] [e-a f-b]
        (+         e# Shift and append. Rotates the second array.
                   e# [c-a d-b] [f-b e-a]
          .*       e# Vectorized product.
                   e# [(c-a)(f-b) (d-b)(e-a)]
            :-     e# Reduce by subtraction.
                   e# (c-a)(f-b) - (d-b)(e-a)
              z    e# Apply absolute value.
                   e# |(c-a)(f-b) - (d-b)(e-a)|
               .5* e# Multiply by 0.5.
                   e# |(c-a)(f-b) - (d-b)(e-a)| / 2
\$\endgroup\$
10
\$\begingroup\$

Mathematica, 27 bytes

Area@Polygon@Partition[t,2]
\$\endgroup\$
  • 17
    \$\begingroup\$ I love how this uses a Built-in and is still longer than the cjam answer. \$\endgroup\$ – Carcigenicate Oct 14 '15 at 16:14
  • 2
    \$\begingroup\$ @Carcigenicate the real problem is the Partition[t,2], which corresponds to the 2/ in CJam. ;) \$\endgroup\$ – Martin Ender Oct 14 '15 at 21:33
10
\$\begingroup\$

JavaScript (ES6) 42 .44.

Edit Input format changed, I can save 2 bytes

An anonymous function that take the array as a parameter and returns the calculated value.

(a,b,c,d,e,f)=>(a*(d-f)+c*(f-b)+e*(b-d))/2

Test running the snippet below in an EcmaScript 6 compliant browser.

f=(a,b,c,d,e,f)=>(a*(d-f)+c*(f-b)+e*(b-d))/2

function test()
{
  var v=I.value.match(/\d+/g)
  I.value = v
  R.innerHTML=f(...v)
}
<input id=I onchange="test()"><button onclick="test()">-></button><span id=R></span>

\$\endgroup\$
  • 1
    \$\begingroup\$ Couldn't you just take the values as standard parameters and save yourself 2 characters on creating the array? \$\endgroup\$ – Mwr247 Oct 14 '15 at 17:52
  • \$\begingroup\$ @Mwr247 the challenge says The input will be a vector with six base 10 positive integers. \$\endgroup\$ – edc65 Oct 14 '15 at 19:50
  • \$\begingroup\$ Aha. I had initially interpreted that as meaning each pair makes up a coordinate vector (such as the Wolfram example), as opposed to the input itself being limited to an array, and as such could use other formats. Makes more sense now. \$\endgroup\$ – Mwr247 Oct 14 '15 at 20:23
  • \$\begingroup\$ @Mwr247 now you're right \$\endgroup\$ – edc65 Oct 14 '15 at 21:34
8
\$\begingroup\$

Julia, 32 bytes

abs(det(t[1:2].-t[[3 5;4 6]]))/2

Constructs a matrix of the appropriate terms of a cross product, uses det to get the resulting value, takes absolute value to deal with negatives, and then divides by 2 because it's a triangle and not a parallelogram.

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

Matlab/Octave, 26 bytes

I did not know about this built in so far=)

polyarea(t(1:2:5),t(2:2:6))
\$\endgroup\$
6
\$\begingroup\$

Java, 79 88 bytes

float f(int[]a){return Math.abs(a[0]*(a[3]-a[5])+a[2]*(a[5]-a[1])+a[4]*(a[1]-a[3]))/2f;}

Just uses the basic formula, nothing special.

Edit: Forgot to take the absolute value :(

\$\endgroup\$
  • \$\begingroup\$ you dont need to make it runnable? \$\endgroup\$ – downrep_nation Oct 14 '15 at 15:24
  • 3
    \$\begingroup\$ The example just shows a function call, and that's a relatively normal default here. \$\endgroup\$ – Geobits Oct 14 '15 at 15:25
  • 2
    \$\begingroup\$ Per the question, •You can assume the input is already stored in a variable such as 't'. So, return(t[0]*(t[3]... should suffice, no? \$\endgroup\$ – AdmBorkBork Oct 14 '15 at 15:29
  • \$\begingroup\$ @TimmyD Feels shady doing it, but it would bring it down to 62 bytes. Hmmm.... I'm going to leave it as is, for now at least. \$\endgroup\$ – Geobits Oct 14 '15 at 15:31
5
\$\begingroup\$

Minkolang 0.8, 34 bytes

ndndn0g-n1g-n0g-n0g-1R*1R*-$~2$:N.

Anyone want some egg-n0g?

Explanation

Very straightforward. Uses the formula |(x2-x1)(y3-y1) - (x3-x1)(y2-y1)|/2.

nd      x1, x1
nd      x1, x1, y1, y1
n0g-    x1, y1, y1, x2-x1
n1g-    x1, y1, x2-x1, y2-y1
n0g-    y1, x2-x1, y2-y1, x3-x1
n0g-    x2-x1, y2-y1, x3-x1, y3-y1
1R*     y3-y1, x2-x1, (y2-y1)(x3-x1)
1R*     (y2-y1)(x3-x1), (y3-y1)(x2-x1)
-       (y2-y1)(x3-x1) - (y3-y1)(x2-x1)
$~      |(y2-y1)(x3-x1) - (y3-y1)(x2-x1)|
2$:     |(y2-y1)(x3-x1) - (y3-y1)(x2-x1)|/2 (float division)
N.      Output as integer and quit.
\$\endgroup\$
3
\$\begingroup\$

JayScript, 58 bytes

Declares an anonymous function:

function(a,b,c,d,e,f){return (a*(d-f)+c*(f-b)+e*(b-d))/2};

Example:

var nFunct = function(a,b,c,d,e,f){return (a*(d-f)+c*(f-b)+e*(b-d))/2};
print(nFunct(1,2,4,2,3,7));
\$\endgroup\$
  • \$\begingroup\$ what does g do? \$\endgroup\$ – Level River St Oct 14 '15 at 22:40
  • \$\begingroup\$ @steveverrill Nothing, I'm just an idiot. Fixing... \$\endgroup\$ – mınxomaτ Oct 14 '15 at 22:48
3
\$\begingroup\$

Ruby, 45

->a,b,p,q,x,y{((a-x)*(q-y)-(p-x)*(b-y)).abs/2}
\$\endgroup\$
3
\$\begingroup\$

PHP – 68 88 89 bytes

Thanks to Martjin for some great pointers!

<?=.5*abs(($t[1]-$t[5])*($t[4]-$t[2])-($t[1]-$t[3])*($t[6]-$t[2]))?>

To use it, create a file area.php with this content, the extra line meets the assume the data is saved in a variable t part of the specs, and the ␍ at the end adds a carriage return so the output is nice and separated:

<?php $t = $argv; ?>
<?=.5*abs(($t[1]-$t[5])*($t[4]-$t[2])-($t[1]-$t[3])*($t[6]-$t[2]))?>
␍

Then provide the coordinates on the command line as x₁ y₁ x₂ y₂ x₃ y₃, e.g.

$ php area.php 1 2 4 2 3 7
7.5
\$\endgroup\$
  • \$\begingroup\$ "You can assume the input is already stored in a variable such as t." $a -> $t, remove $a=$argv; saving 9 bytes \$\endgroup\$ – Martijn Oct 15 '15 at 9:48
  • \$\begingroup\$ After that, you can replace <?php echo with <?=, saving another 7 bytes \$\endgroup\$ – Martijn Oct 15 '15 at 9:52
  • \$\begingroup\$ You can say that this is PHP4.1, with register_globals=On in your php.ini file (default). Read more at php.net/manual/en/security.globals.php \$\endgroup\$ – Ismael Miguel Oct 16 '15 at 1:07
2
\$\begingroup\$

Pyth, 34 30 bytes

KCcQ2c.asm*@hKd-@eKhd@eKtdU3 2

Try it online.

Works by calculating abs(a*(d-f) + c*(f-b) + e*(b-d))/2 from input a,b,c,d,e,f.

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

R, 37 bytes

cat(abs(det(rbind(matrix(t,2),1))/2))

Converts the vector of coordinates into a matrix and tacks on a row of 1's.
Calculates the determinant and divides by 2.
Returns the absolute result. If the order was always clockwise the abs would not be required.

> t = c(1,2,4,2,3,7)
> cat(det(rbind(matrix(t,2),1))/2)
7.5
\$\endgroup\$
2
\$\begingroup\$

Python 2, 48 47 50 bytes

Very simple; follows the standard equation:

lambda a,b,c,d,e,f:abs(a*(d-f)+c*(f-b)+e*(b-d))/2.

The other, similarly simple approaches are longer:

def a(a,b,c,d,e,f):return abs(a*(d-f)+c*(f-b)+e*(b-d))/2. # 57
lambda t:abs(t[0]*(t[3]-t[5])+t[2]*(t[5]-t[1])+t[4]*(t[1]-t[3]))/2. # 67
def a(t):return abs(t[0]*(t[3]-t[5])+t[2]*(t[5]-t[1])+t[4]*(t[1]-t[3]))/2. # 74

Python's access to a determinate function is through numpy.

Thanks to muddyfish for 1 byte and xnor for catching an error.

\$\endgroup\$
  • \$\begingroup\$ you can remove the 0 from 2.0 to leave 2. \$\endgroup\$ – Blue Oct 14 '15 at 17:36
  • \$\begingroup\$ Quite true, @muddyfish, thanks! \$\endgroup\$ – Celeo Oct 14 '15 at 17:38
  • \$\begingroup\$ Is this Python 2 or 3? Division works differently depending on the version... \$\endgroup\$ – mbomb007 Oct 14 '15 at 18:42
  • \$\begingroup\$ Clarified, @mbomb007. \$\endgroup\$ – Celeo Oct 14 '15 at 18:46
  • 1
    \$\begingroup\$ You need an abs to make the answer positive. \$\endgroup\$ – xnor Oct 14 '15 at 20:56
2
\$\begingroup\$

PHP, 77

Based on @Yimin Rong's answer, I felt I could improve upon it by a few bytes by using list() rather than straight $argv to abbreviate some variables. Also echo doesn't need a space if there is delimiter between echo and the thing being echoed.

echo$variable;, echo(4+2);, and echo'some string'; are equally valid whereas echofunction($variable) confuses PHP.

On the other hand, I also added abs() to be mathematically accurate, since some combinations of vertices yielded "negative area"

list($t,$a,$b,$c,$d,$e,$f)=$argv;echo.5*abs(($a-$e)*($d-$b)-($a-$c)*($f-$b));

You can run it via CLI

php -r "list($t,$a,$b,$c,$d,$e,$f)=$argv;echo.5*abs(($a-$e)*($d-$b)-($a-$c)*($f-$b));" 1 2 4 2 3 7
7.5
\$\endgroup\$
2
\$\begingroup\$

AWK – 51 42 bytes

AWK has no built-in abs so using sqrt(x^2) to substitute.

{print sqrt((($1-$5)*($4-$2)-($1-$3)*($6-$2))^2)/2}

Save as area.awk and use as echo x₁ y₁ x₂ y₂ x₃ y₃ | awk -f area.awk, e.g.

$ echo 1 2 4 2 3 7 | awk -f area.awk
7.5
\$\endgroup\$
1
\$\begingroup\$

PowerShell, 70 Bytes

[math]::Abs(($t[0]-$t[4])*($t[3]-$t[1])-($t[0]-$t[2])*($t[5]-$t[1]))/2

Uses the same standard formula as other solutions. Per the question, assumes the array is pre-populated, e.g. $t=(1,2,4,2,3,7). But ooof, does the $ and [] syntax kill this one...

\$\endgroup\$
  • \$\begingroup\$ Your comment about the penalty from using $ and [] inspired me to try an AWK solution which, by length, is not uncompetitive! \$\endgroup\$ – user15259 Oct 14 '15 at 16:22
1
\$\begingroup\$

dc, 52 bytes

Assumes the input is in register t as: x1 y1 x2 y2 x3 y3 with x1 at the top of t's stack.

1kLtLtsaLtsbLtdscLtltrlalclbltla-*sd-*se-*leld++2/p

1 2 4 2 3 7stStStStStSt #puts coordinates into register t (closest thing dc has to variables) 1kLtLtsaLtsbLtdscLtltrlalclbltla-*sd-*se-*leld++2/p 7.5

This uses the following formula for area:

(x1(y2-y3) + x2(y3-y1) + x3(y1 - y2))/2

And for a quick breakdown of the process:

  • 1k Lt Lt sa Lt sb Lt d sc Lt lt r: set decimal precision to 1 place, move parts of the stack in t to the main stack and move various parts of the main stack to other registers for storage (d duplicates the top of main stack, r reverses the top two elements of main stack, L/l move/copy from the given register to main, s moves top of main stack to the given register)

    Main: y3 x3 y2 x1

    a: y1, b: x2, c: y2, t: y3

  • la lc lb lt la: copy the top of the stacks in registers a, c, b, t, and a to the main stack in that order

    Main: y1 y3 x2 y2 y1 y3 x3 y2 x1

    a: y1, b: x2, c: y2, t: y3

  • - * sd: calculate ((y3-y1)*x2) and put result in d (registers a, b, c, and t are no longer used so I'll drop them from the list of stacks now)

    Main: y2 y1 y3 x3 y2 x1

    d:((y3-y1)*x2)

  • - * se - *: compute ((y1-y2)*y3) and ((y2-x3)*x1); store the former in e and leave the latter on the main stack

    Main: ((y2-x3)*x1)

    d:((y3-y1)*x2), e:((y1-y2)*y3)

  • le ld + +: copy top of register e and d to the main stack, calculate sum of top 2 stack values (pushing result back to main stack) twice

    Main: (((y3-y1)*x2)+((y1-y2)*y3)+((y2-x3)*x1))

    d:((y3-y1)*x2), e:((y1-y2)*y3)

  • 2 /: push 2 onto main stack, divide 2nd values on stack by the 1st (d and e are no longer used, dropping them from list of stacks)

    Main: (((y3-y1)*x2)+((y1-y2)*y3)+((y2-x3)*x1))/2

Rearranging the value on the stack we can see it's equivalent to the formula at the top of this explanation: (x1(y2-y3) + x2(y3-y1) + x3(y1 - y2))/2

  • p: Print top of main stack to output.
\$\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.