TransWikia.com

Are they collinear?

Code Golf Asked by Mukundan314 on October 27, 2021

Task

Write a program/function that when given three 2d points in cartesian coordinates as input outputs a truthy value if they are collinear otherwise a falsey value

Three points are said to be collinear if there exists a straight line that passes through all the points

You may assume that the coordinates of the three points are integers and that the three points are distinct.

Scoring

This is so shortest bytes wins

Sample Testcases

(1, 1), (2, 2), (3, 3) -> Truthy
(1, 1), (2, 2), (10, 10) -> Truthy
(10, 1), (10, 2), (10, 3) -> Truthy
(1, 10), (2, 10), (3, 10) -> Truthy
(1, 1), (2, 2), (3, 4) -> Falsey
(1, 1), (2, 0), (2, 2) -> Falsey
(-5, 70), (2, 0), (-1, 30) -> Truthy
(460, 2363), (1127, 2392), (-1334, 2285) -> Truthy
(-789, -215), (-753, -110), (518, -780) -> Falsey
(227816082, 4430300), (121709952, 3976855), (127369710, 4001042) -> Truthy
(641027, 3459466), (475989, 3458761), (-675960, 3453838) -> Falsey

19 Answers

Husk, 7 bytes

EẊoF/z-

Try it online!

Answered by Razetime on October 27, 2021

AWK, 45 bytes

{print!($2*$3+$4*$5+$6*$1-$1*$4-$2*$5-$3*$6)}

Try it online!

Near-identical to Rich Farmbrough's Perl answer, but the syntax seemed better-suited to AWK than Perl. Thanks Rich!

Answered by Dominic van Essen on October 27, 2021

Perl 5, 3562 bytes

sub d{($a,$b,$c,$d,$e,$f)=@_;$b*($c-$e)+$d*($e-$a)+$f*($a-$c)}

Try it online!

I've put the wrapping on as explained in the comments, and golfed the original "guts" down by picking out some common factors

$b*($c-$e)+$d*($e-$a)+$f*($a-$c)

(--First attempt --)

$b*$c+$d*$e+$f*$a-$a*$d-$c*$f-$e*$b

Try it online!

  • Not sure if this follows the rules (where are they?) for header and footer, as much trying out "tio" as anything.
  • This takes the test text as per the question and outputs the exact same text! In other words it's equivalent to while(<>){print}, provided you feed it a crib sheet. If you remove (or change) the answers from the input, it will supply them.

Answered by Rich Farmbrough on October 27, 2021

[Google Sheets], 27 bytes

=0=MDETERM({A1:B3,{1;1;1}})

Try it online!

Answered by Conor James Thomas Warford Hen on October 27, 2021

[Excel], 37 bytes

=0=MDETERM(A1:C3+{0,0,1;0,0,1;0,0,1})

Example: enter image description here

Answered by Conor James Thomas Warford Hen on October 27, 2021

C# (Visual C# Interactive Compiler), 39 bytes

(a,A,b,B,c,C)=>(b-a)/(B-A)==(c-a)/(C-A)

Try it online!

Answered by Netråm on October 27, 2021

R, 22 bytes

function(x)lm(1:3~x)$d

Try it online!

Finally a challenge which calls for lm!

The function lm performs linear regression. Here, we are using the input x as covariates, and 1 2 3 as observations (any vector of length 3 would do).

The output is an object with many components; of interest here is df.residual (which can be accessed with the unambiguous abbreviation $d), the residual degrees of freedom. This number corresponds to the number of observations minus the number of parameters being estimated. Now:

  • if the points are not collinear, the regression proceeds normally, estimating 3 parameters, so df.residual == 0.
  • if the points are collinear, there is an identifiability issue and only 2 parameters can be estimated (the last will be given as NA), so df.residual == 1.

Note that the final test case fails due to numerical precision issues.

Answered by Robin Ryder on October 27, 2021

Charcoal, 21 bytes

NθNηNζ⁼×⁻ηN⁻θN×⁻ηN⁻θζ

Try it online! Link is to verbose version of code. Takes input as six integers and outputs a Charcoal boolean, i.e. - for collinear, nothing if not. Uses @SurculoseSputum's original formula. Explanation:

Nθ                      Input `a`
  Nη                    Input `A`
    Nζ                  Input `b`
         η              `A`
        ⁻               Minus
          N             Input `B`
       ×                Multiplied by
            θ           `a`
           ⁻            Minus
             N          Input `c`
      ⁼                 Equals
                η       `A`
               ⁻        Minus
                 N      Input `C`
              ×         Multiplied by
                   θ    `a`
                  ⁻     Minus
                    ζ   `b`
                        Implicitly print

Answered by Neil on October 27, 2021

J, 13 7 bytes

0=-/ .*

Try it online!

Uses the determinant. J's generalized determinant u .v is defined for non-square matrices, still multiplying (*) each x value with the difference of the other two y values (-/), finally reducing that result (-/). -/ .* calculates the determinant, check if it is 0=.

Answered by xash on October 27, 2021

R, 27 bytes

function(m)!det(cbind(1,m))

Try it online!

Port of alephalpha's Octave answer.

Answered by Kirill L. on October 27, 2021

R, 49 bytes

function(p,q=p-p[,1])q[1,3]*q[2,2]==q[2,3]*q[1,2]

Try it online!

How?

  • Subtract first point from the other two:
  • if points are on a line, the line must now pass through (x=0,y=0)
  • so we check that the gradient=y/x is identical for both other points: y2/x2==y3/x3
  • but to avoid dividing by zero, we rearrange: y2x3==y3x2

Edit:

  • which, thanks to Kirill, alephalpha and Wikipedia, I've now discovered is simply the determinant of the matrix (x2,y2,x3,y3)
  • so, for only 29 bytes: function(p)!det(p[,-1]-p[,1])

Answered by Dominic van Essen on October 27, 2021

Jelly, 4 bytes

_ÆḊ¬

Try it online!

Takes the differences [(a-b), (a-c)] via automatic vectorization of a-[b-c] then checks if the determinant (ÆḊ) is 0 (¬).

Answered by fireflame241 on October 27, 2021

Wolfram Language (Mathematica), 20 19 bytes

Det@{#2-#,#3-#}==0&

Try it online!

Answered by att on October 27, 2021

Raku, 21 19 bytes

{!im [/] $^a X-@_:}

Try it online!

Takes input as three complex numbers and returns a boolean. Note that if the last and first points are identical (which is disallowed in the challenge spec), then the division operation would return NaN for dividing by zero, which boolifies to True for some reason, so this would fail.

Answered by Jo King on October 27, 2021

Octave, 21 bytes

Takes a matrix [x1, y1; x2, y2; x3, y3] as input.

@(a)~det([a,[1;1;1]])

Try it online!

Answered by alephalpha on October 27, 2021

APL (Dyalog Unicode), 9 8 bytes

0=11○÷.-

Try it online!

-1 byte thanks to @Jo King.

Takes one complex number (A) on the left, and two complex numbers (B and C) on the right. APL automatically maps scalars, so A - B C gives (A-B)(A-C). Then divide between the two ÷., and check if the result's imaginary part 11○ is zero 0=.

Uses ⎕DIV←1, so if division by zero would occur (because A=C), ÷ returns 0 instead, which obviously has imaginary part of zero, giving truthy as a result.

Answered by Bubbler on October 27, 2021

05AB1E, 18 17 27 21 bytes

-Dн_iIн¹нQë`s/Uн¹н-X*¹θ+IθQ

Try it online!

Verify All Test Cases!

-1 byte due to remembering implicit input exists and that variable assignment pops values

+10 due to bug fix regarding vertical lines :-(

-6 thanks to the wonderful @Kevin, who always manages to golf my 05AB1E answers! :D. Go and upvote his posts!

Explained

Before we even begin to look at the program, let's take a look at the maths needed to see if three points are collinear. Let our first point have co-ordinates $(x_1, y_1)$, our second point have co-ordinates $(x_2, y_2)$ and our third point have co-ordinates $(x_3, y_3)$.

If the three points are collinear, then point three will lie on the line formed by joining points one and two. In other words, $x_3$, when plugged into the equation formed by the line joining points 1 and 2, gives $y_3$.

"But what's the line between point 1 and 2?" I hear you ask. Well, we use the good old "point-graident" method to find the line's equation:

$$ y - y_1 = m(x - x_1), m = frac{y_2 - y_1}{x_2 - x_1}\ y - y_1 = frac{y_2 - y_1}{x_2 - x_1}(x - x_1) $$

Now, we add $y_1$ to both sides to get an equation where plugging in an x value gives a single y value:

$$ y = frac{y_2 - y_1}{x_2 - x_1}(x - x_1) + y_1 $$

Substituting $x$ for $x_3$ and $y$ for $y_3$ gives an equality that determines if three points are collinear.

Alright, time for the code (as explained by Kevin).

-                     "[x2-x1, y2-y1]"
 V                    "pop and store it in variable `Y`"
  ¹-                  "[x3-x1, y3-y1]"
    н                 "Pop and leave only x3-x1"
     Yн_i             "If x2-x1 from variable `Y` == 0:"
         _            " Check if the x3-x1 at the top == 0"
        ë             "Else:"
         Y`s/         " Divide (y2-y1) by (x2-x1) from variable `Y`"
             *        " Multiply it by the x3-x1 at the top"
              ¹θ+     " Add x1"
                 Q    " Check [x3 == this value, y3 == this value] with the implicit third input"
                  θ   " And only keep the last one: y3 == this value"

Answered by lyxal on October 27, 2021

Python 2, 39 bytes

lambda a,b,c:(a-b)*(a-c-(a-c)%1*2)%1==0

Try it online!

Input: the 3 points as 3 complex numbers
Output: True or False.

How

Let the 3 points be $(a,A), (b,B), (c,C)$

The 3 points are colinear iff $(a-b)*(A-C)=(A-B)*(a-c)$. Note that this formula doesn't have division, and thus won't have floating point issue. Consider the following complex multiplication: $$ big((a-b)+(A-B)ibig) * big((a-c)-(A-C)ibig)$$ The imaginary part of the result is: $$(a-c)(A-B)-(a-b)(A-C)$$ which must be $0$ for the 3 points to be colinear.

Let a, b, c be the complex representation of the 3 points, then the condition above is equivalent to:

t = (a-b) * (a-c).conjugate()
t.imag == 0

Instead of using imag and conjugate, we can take advantage of the fact that all points are integers. For a complex number t where both the real and imaginary parts are integers, t%1 gives the imaginary part of t. Thus:

t % 1 == t.imag * 1j
t - t % 1 * 2 == t.conjugate()

Old solution that doesn't use complex number

Python 3, 43 bytes

lambda a,A,b,B,c,C:(a-b)*(A-C)==(A-B)*(a-c)

Try it online!

Input: the 2 coordinates of the first point, then the 2nd point, then the 3rd point.
Output: True or False.


This should work theoretically, but doesn't because of floating point imprecision:

Python 3, 34 bytes

lambda a,b,c:((a-b)/(a-c)).imag==0

Try it online!

Input: 3 points, each represented by a complex number
Output: True or False.

Answered by Surculose Sputum on October 27, 2021

JavaScript (Node.js), 39 bytes

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

Try it online!

Accepts input as (x1, y1, x2, y2, x3, y3). Uses the shoelace formula to determine if the enclosed area is 0.

Explanation

The shoelace formula states that, the area of a polygon can be calculated using the coordinates of its vertices. Specifically, assuming the vertices are $P_1, P_2, cdots, P_n$ so that $P_1P_2, P_2P_3, cdots, P_{n-1}P_n, P_nP_1$ are the edges of the polygon, then the area $A$ can be calculated with

$$A=frac{1}{2}left|(x_1y_2+x_2 y_3+cdots+x_{n-1}y_n+x_ny_1)-(y_1x_2+y_2x_3 +cdots+y_{n-1}x_n+y_nx_1)right|$$

where $(x_n,y_n)$ are the coordinates of $P_n$.

Taking $n=3$, we have the formula for the area of a triangle with coordinates $(x_1,y_1)$, $(x_2,y_2)$ and $(x_3,y_3)$:

$$A=frac{1}{2}left|(x_1y_2+x_2y_3+x_3y_1)-(y_1x_2+y_2x_3+y_3x_1)right|$$

Three points are collinear if and only if the triangle constructed by these points has a zero area (otherwise, one of the points lies away from the line segment between the other two points, giving a non-zero area to the triangle). Since we only need to check whether the area is 0, the 1/2 and the absolute can be ignored. This boils down to checking whether

$$(x_1y_2+x_2y_3+x_3y_1)-(y_1x_2+y_2x_3+y_3x_1)=0$$

or after rearranging terms

$$x_1y_2+x_2y_3+x_3y_1=y_1x_2+y_2x_3+y_3x_1$$

Answered by Shieru Asakoto on October 27, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP