17
\$\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\$
10
  • 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, 2015 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, 2015 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, 2015 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, 2015 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, 2015 at 19:19

18 Answers 18

15
\$\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\$
2
  • 17
    \$\begingroup\$ I love how this uses a Built-in and is still longer than the cjam answer. \$\endgroup\$ Oct 14, 2015 at 16:14
  • 2
    \$\begingroup\$ @Carcigenicate the real problem is the Partition[t,2], which corresponds to the 2/ in CJam. ;) \$\endgroup\$ Oct 14, 2015 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\$
4
  • 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, 2015 at 17:52
  • \$\begingroup\$ @Mwr247 the challenge says The input will be a vector with six base 10 positive integers. \$\endgroup\$
    – edc65
    Oct 14, 2015 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, 2015 at 20:23
  • \$\begingroup\$ @Mwr247 now you're right \$\endgroup\$
    – edc65
    Oct 14, 2015 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\$
4
  • \$\begingroup\$ you dont need to make it runnable? \$\endgroup\$ Oct 14, 2015 at 15:24
  • 3
    \$\begingroup\$ The example just shows a function call, and that's a relatively normal default here. \$\endgroup\$
    – Geobits
    Oct 14, 2015 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\$ Oct 14, 2015 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, 2015 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\$
2
  • \$\begingroup\$ what does g do? \$\endgroup\$ Oct 14, 2015 at 22:40
  • \$\begingroup\$ @steveverrill Nothing, I'm just an idiot. Fixing... \$\endgroup\$
    – user42643
    Oct 14, 2015 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\$
3
  • \$\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, 2015 at 9:48
  • \$\begingroup\$ After that, you can replace <?php echo with <?=, saving another 7 bytes \$\endgroup\$
    – Martijn
    Oct 15, 2015 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\$ Oct 16, 2015 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\$
5
  • \$\begingroup\$ you can remove the 0 from 2.0 to leave 2. \$\endgroup\$
    – Blue
    Oct 14, 2015 at 17:36
  • \$\begingroup\$ Quite true, @muddyfish, thanks! \$\endgroup\$
    – Celeo
    Oct 14, 2015 at 17:38
  • \$\begingroup\$ Is this Python 2 or 3? Division works differently depending on the version... \$\endgroup\$
    – mbomb007
    Oct 14, 2015 at 18:42
  • \$\begingroup\$ Clarified, @mbomb007. \$\endgroup\$
    – Celeo
    Oct 14, 2015 at 18:46
  • 1
    \$\begingroup\$ You need an abs to make the answer positive. \$\endgroup\$
    – xnor
    Oct 14, 2015 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\$
1
  • \$\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, 2015 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\$
0
\$\begingroup\$

Jelly, 6 bytes

_ḢÆḊHA

Try it online!

Takes input as 3 pairs [a,b],[c,d],[e,f] as Jelly has no concept of variables

How it works

This implements the method outlined on Wikipedia that Dennis' answer uses, in that, the area of a triangle \$(0,0), (x,y), (v,w)\$ is

$$\frac12\left|\det\left[\begin{matrix} x & y \\ v & w \end{matrix}\right]\right|$$

and that, for an arbitrary triple of points \$(a,b),(c,d),(e,f)\$, we can translate them to form a triangle with a corner on the origin: \$(0,0),(c-a,d-b),(e-a,f-b)\$, so the area is

$$\frac12\left|\det\left[\begin{matrix} c-a & d-b \\ e-a & f-b \end{matrix}\right]\right|$$

_ḢÆḊHA - Main link. Takes [[a, b], [c, d], [e, f]] on the left
 Ḣ     - Remove [a,b] and yield it
_      - Vectorised subtraction from each of [[c, d], [e, f]] which yields
         [[c-a, d-b], [e-a, f-b]]
  ÆḊ   - Determinant
    H  - Halve
     A - Absolute value
\$\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.