16
\$\begingroup\$

The challenge:

Given four coordinates, each in x y form, your job is to find out whether or not the given coordinates form a rectangle, and output a truthy/falsey.

Rules:

  • For the sake of simplicity, squares, lines (two identical pairs of coordinates) or dots (all four of the coordinates are the same) are all counted as rectangles

  • Coordinates for rectangles can be given in any order, for example this:

A----B
|    |
D----C

and this:

A---B
|   |
|   |
|   |
C---D

are both rectangles.

  • Rectangles can be rotated, so they won't always be parallel to x and y axis.

  • You may take input in any form you like as long as the order for each coordinate is not mixed: [x,x,x,x,y,y,y,y] is not acceptable, where as [x,y,x,y,x,y,x,y] or [(x,y),(x,y),(x,y),(x,y)] is fine.

  • Complex numbers are a valid form of input

  • This is codegolf, so lowest byte count wins.

Test cases:

[0,2, 3,2, 3,0, 0,0]      Truthy
[3,5, 2,0, 0,2, 5,3]      Truthy
[6,3, 3,5, 0,2, 3,0]      Falsy
[1,4, 5,2, 4,0, 0,2]      Truthy
[0,0, 0,0, 3,2, 4,0]      Falsy
[1,1, 1,1, 1,1, 1,1]      Truthy
[1,4, 100,1, 100,1, 1,4]  Truthy
\$\endgroup\$
  • 5
    \$\begingroup\$ Is [6,3,3,5,0,2,2,0] really a rectangle? \$\endgroup\$ – xnor Apr 5 at 9:45
  • 1
    \$\begingroup\$ @Arnauld Good point, spacing it better does make the rectnagles clearer. It looks like the second test case actually has the issue that the points are in the wrong order, making a self-crossing shape. \$\endgroup\$ – xnor Apr 5 at 11:49
  • 6
    \$\begingroup\$ @SurculoseSputum I'm understanding it the other way, that the "Coordinates should not be treated like this figure:" means we should always interpret input points as being in cyclic order, so that the second test case wouldn't be a rectangle. I've VTC'ed as unclear. \$\endgroup\$ – xnor Apr 5 at 12:34
  • 1
    \$\begingroup\$ @Noodle9 fully approve of your edit, thank you! \$\endgroup\$ – Dion Apr 5 at 17:13
  • 2
    \$\begingroup\$ @MitchellSpector, yep \$\endgroup\$ – Dion Apr 5 at 17:34
23
\$\begingroup\$

Python 3, 88 \$\cdots\$ 54 43 bytes

lambda l:len({abs(sum(l)/4-z)for z in l})<2

Try it online!

How

Calculates the distances from the quadrilateral's centre of mass to all of its vertices and tests if they're equal.

Input The four vertices as a sequence of complex numbers in any order.
Output True/False

| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ Oh, I see, that's clever. That should work then in the "in any order" interpretation of the challenge. \$\endgroup\$ – xnor Apr 5 at 16:46
  • 2
    \$\begingroup\$ A nice solution! \$\endgroup\$ – Mitchell Spector Apr 5 at 16:50
  • 8
    \$\begingroup\$ Here's an argument that convinced me only a rectangle passes your test. Consider the circle on which four points lie. Its center must be the points' center of mass. One way to "average" the four points is to take the midpoint between two points and then midpoint between the other two points, and take the midpoint between those midpoints. To get the center of the circle at the end, the two midpoints must be opposite each inside the circle. (cont'd) \$\endgroup\$ – xnor Apr 5 at 17:06
  • 7
    \$\begingroup\$ (continuing) Draw the segment between the two midpoints. We can obtain the pair of points on the circle producing a midpoint by drawing the perpendicular to that segment and intersecting it with the circle. In fact, this the only such of pair of points on the circle. Doing so for both midpoints, we find that central segment is now perpendicular to two equal-length segments whose endpoints are the four corners, so they form a rectangle. (This was all probably confusing without a drawing...) \$\endgroup\$ – xnor Apr 5 at 17:08
  • 1
    \$\begingroup\$ Diagram \$\endgroup\$ – xnor Apr 5 at 23:11
8
\$\begingroup\$

Jelly, 6 bytes

A port of Noodle9's Python answer with a slight adjustment for golfing purposes.

×4_SAE

A monadic Link accepting a list of four complex numbers which yields 1 if they form a rectangle or 0 if not.

Try it online! Or see the test-suite.

How?

Checks that all four coordinates are equidistant from the centre of mass of the uniform density quadrilateral.

×4_SAE - Link: list of complex numbers, C
 4     - literal four
×      - (C) multiply (4) (vectorises across C)
   S   - sum (of C)
  _    - (C×4) subtract (sum(C)) (vectorises across C×4)
    A  - absolute value (vectorises)
     E - all equal?

Note this still works given an equilateral triangle with a repeated coordinate (it would skew the centre of mass toward the repeated coordinate).


The equivalent change to Noodle9's program would be:

lambda l:len({abs(z*4-sum(l))for z in l})<2
| improve this answer | |
\$\endgroup\$
2
\$\begingroup\$

05AB1E, 11 bytes

Port of Noodle9's Python answer. 05AB1E doesn't have complex numbers, so it ends up a bit long.

εIøO4/-}nOË

Try it online!

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

Python 3, 115 108 107 bytes

This solution finds if any permutation of A,B,C,D results in a rectangle. Output is correct for all test cases except test case 3 which is not a rectangle due to corners not equal to 90 degrees.

lambda a,b,c,d:g(a,b,c,d)+g(a,c,b,d)+g(a,b,d,c)
g=lambda a,b,c,d:b+d-a-c==((b-a)*(d-a).conjugate()).real==0

Try it online!

Input: 4 complex numbers representing the 4 coordinates.
Output: a positive integer if input is a rectangle, or 0 if input is not.

105 bytes if output can be 0 for rectangle, and non-zero for non-rectangle.

lambda a,b,c,d:g(a,b,c,d)*g(a,c,b,d)*g(a,b,d,c)
g=lambda a,b,c,d:b+d-a-c or((b-a)*(d-a).conjugate()).real
| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

APL2: 33 bytes

Yet another port of Noddle9's answer, this time in APL2.

Prerequisites:

  1. This is code is ⎕IO-dependant since it uses Partition with axis. This example in ⎕IO=0
  2. The list of coordinates is stored in variable C.

D≡⌽D←↑+/(M-+/¨.25×M←⊂[1]⍉4 2⍴C)*2

The result is either 1 for true or 0 for false.

An example

If C is the vector 3,5,2,0,0,2,5,3 or rather 3 5 2 0 0 2 5 3, then the first thing that happens is that 4 2⍴C turns it into a 4x2 matrix:

3 5
2 0
0 2
5 3

Then transposes that matrix and ⊂[1] turns it into a vector of 2 vectors (x & y). This is stored as M: ((3 2 0 5)(5 0 2 3)).

Next M is multiplied with 0.25 and summed element-wise: (this is what +/¨ does)

(2.5 2.5).

Now we subtract this from M and square the differences: (M- ...)*2 (yes, * is "power"). We now have: (0.25 0.25 6.25 6.25)(6.25 6.25 0.25 0.25).

This is summed by the +/ outside the brackets and we get ((6.5 6.5 6.5 6.5)). Sadly we have a 4-element vector inside another structure so we have to "spend" a character to remove the outer shell: .

The inner vector is assigned to variable D. Finally we use to compare D to its reverse ⌽D thereby checking if all items are equal.

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

Ruby, 44 bytes

Input is an array of 4 complex numbers, again.

->l{l.map{|z|(l.sum/4.0-z).abs}.uniq.size<2}

Try it online!

Port of @Noodle9's Python answer.

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

Bash + GNU utilities, 77 bytes

cat>t;join -j3 t t|xargs -I% dc -e%sDsClD-d*sqlC-d*lq+p|sort|uniq -c|grep 2\ 

(There's a space at the end, after the backslash.)

Try it online!

Or try the entire test suite online.

The input is in the form:

x1 y1
x2 y2
x3 y3
x4 y4

(with a newline after each point).

The output is the exit code: 0 for falsey, 1 for truthy.


Here's how it works (there are no complex numbers available in bash):

  1. The join computes all the pairs of points. There are 4 points, so there are 16 pairs of points. (This includes each pair in both orders, and it even includes pairs where the two points are the same.)

  2. The xargs command uses dc to compute the square of the distance between each pair of points. We now have a list of all the squares of the distances between pairs of the points.

  3. Now, sort|uniq -c computes how many times each value appears in the list of squared distances.

  4. The original four points form a rectangle iff no value appears exactly twice in the list.

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

APL (Dyalog Unicode), 25 bytes

{1=≢∪|⍵-+/⍵÷4}

Try it online!

input: complex numbers.

distances from centre of gravity must match.

| improve this 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.