g | x | w | all
Bytes Lang Time Link
034Dyalog APL250815T060852ZAaron
076Python110312T070028Zpaperhor
031Wolfram Language Mathematica190827T070910ZRoman
nanIts not exactly shortest190828T002749Zkot
141C gcc190420T082752Zceilingc
014Stax190621T143214Zrecursiv
071Python110311T063502Zuser932
049Python 2190420T051316Zxnor
008Jelly190420T031615Zlynn
066Mathematica130513T125632ZDavidC
nanPython130514T225748ZBrian Ca
066Python130514T125105ZReinstat
091Smalltalk Squeak 4.x flavour130503T170024Zaka.nice
145OCaml110311T165025Zbltxd
132OCaml + Batteries110315T190105ZMatí
033K110408T182227Zisawdron
107C#110311T181736Zuser965
nan110312T033216Zmrjbq7
159Clojure110311T085216ZMeikel
100Haskell110315T043859Zuser1027
nan110315T042039ZJagu
082PHP110314T122809Zarek
nanC# not exactly short. Abusing LINQ. Selects distinct twocombinations of points in the input110314T055744ZDaniel C
066GoRuby110313T110844ZNemo157
112JavaScript 1.8110311T200358Zecatmur
158PHP110310T225024ZKevin Br
042Python110311T002937Zgnibbler
144JavaScript110311T132539Zaaaaaaaa
1104Haskell110311T165035ZChris Ku
146Scala110311T164535ZGareth
028J110310T233035ZJ B
123Mathematica110311T145406Zuser503
106Smalltalk for110311T143954Zuser952
026J110311T082033ZEelvex
212Haskell110311T050353ZDan Burt
105Python110311T040844ZHoa Long

Dyalog APL, 34 chars

{∧/1 1 2∊(⊢÷∨/){+/⍺⍵*2}/¨⊃-/1 1⊂⍵}­⁡​‎‎⁡⁠⁢⁤⁣‏⁠‎⁡⁠⁢⁤⁤‏⁠‎⁡⁠⁣⁡⁡‏⁠‎⁡⁠⁣⁡⁢‏⁠‎⁡⁠⁣⁡⁣‏⁠‏​⁡⁠⁡‌⁢​‎‎⁡⁠⁢⁣⁤‏⁠‎⁡⁠⁢⁤⁡‏⁠‎⁡⁠⁢⁤⁢‏⁠‏​⁡⁠⁡‌⁣​‎‎⁡⁠⁢⁣⁣‏⁠‏​⁡⁠⁡‌⁤​‎‎⁡⁠⁢⁡⁢‏⁠⁠‎⁡⁠⁢⁣⁡‏⁠‎⁡⁠⁢⁣⁢‏⁠‏​⁡⁠⁡‌⁢⁡​‎‎⁡⁠⁢⁢⁡‏⁠‎⁡⁠⁢⁢⁢‏⁠‎⁡⁠⁢⁢⁣‏⁠‎⁡⁠⁢⁢⁤‏⁠‏​⁡⁠⁡‌⁢⁢​‎‎⁡⁠⁢⁡⁣‏⁠‎⁡⁠⁢⁡⁤‏⁠‏​⁡⁠⁡‌⁢⁣​‎‎⁡⁠⁣⁢‏⁠‎⁡⁠⁣⁣‏⁠‎⁡⁠⁣⁤‏⁠‎⁡⁠⁢⁡⁡‏⁠‏​⁡⁠⁡‌⁢⁤​‎‎⁡⁠⁤⁣‏⁠‎⁡⁠⁤⁤‏‏​⁡⁠⁡‌⁣⁡​‎‎⁡⁠⁤⁡‏⁠‎⁡⁠⁤⁢‏‏​⁡⁠⁡‌⁣⁢​‎‎⁡⁠⁤‏⁠‎⁡⁠⁢⁡‏⁠‎⁡⁠⁢⁢‏⁠‎⁡⁠⁢⁣‏⁠‎⁡⁠⁢⁤‏⁠‎⁡⁠⁣⁡‏‏​⁡⁠⁡‌⁣⁣​‎‎⁡⁠⁢‏⁠‎⁡⁠⁣‏‏​⁡⁠⁡‌­
                            1 1⊂⍵   # ‎⁡Split the input into head and tail
                         ⊃-/        # ‎⁢Subtract the head from each element of the tail and disclose
                        ¨           # ‎⁣For each of the results which is a pair of numbers
               {      }/            # ‎⁤Apply this between them to find their distance from the head
                  ⍺⍵*2              # ‎⁢⁡Square the left and right args
                +/                  # ‎⁢⁢and take their sum.  I don't have to then find the square root because I'm going to compare with the squared distance (2) later
         (⊢÷  )                     # ‎⁢⁣Normalize these numbers by dividing by
            ∨/                      # ‎⁢⁤the GCD
   1 1 2∊                           # ‎⁣⁢Check that the result, in any order, consists of a 1, a 1, and a 2
 ∧/                                 # ‎⁣⁣And-Over to ensure they were all present which implies they make a square
💎

Created with the help of Luminespire.

Python 176 90 76 bytes

def S(A):c=sum(A)/4.0;return set(A)==set((A[0]-c)*1j**i+c for i in range(4))

Function S takes a list of complex numbers as its input (A). If we know both the centre and one corner of a square, we can reconstruct the square by rotating the corner 90,180 and 270 degrees around the centre point (c). On the complex plane rotation by 90 degrees about the origin is done by multiplying the point by i. If our original shape and the reconstructed square have the same points then it must have been a square.

Wolfram Language (Mathematica), 32 31 bytes

Tr[#^2]==Tr[#^3]==0&[#-Mean@#]&

Try it online!

Takes a list of points represented by complex numbers, calculates the second and third central moment, and checks that both are zero.

Un-golfed:

S[p_] := Total[(p - Mean[p])^2] == Total[(p - Mean[p])^3] == 0

or

S[p_] := CentralMoment[p, 2] == CentralMoment[p, 3] == 0

proof

This criterion works on the entire complex plane, not just on the Gaussian integers.

  1. First, we note that the central moments do not change when the points are translated together. For a set of points

    P = Table[c + x[i] + I*y[i], {i, 4}]
    

    the central moments are all independent of c (that's why they are called central):

    {FreeQ[FullSimplify[CentralMoment[P, 2]], c], FreeQ[FullSimplify[CentralMoment[P, 3]], c]}
    (*    {True, True}    *)
    
  2. Second, the central moments have a simple dependence on overall complex scaling (scaling and rotation) of the set of points:

    P = Table[f * (x[i] + I*y[i]), {i, 4}];
    FullSimplify[CentralMoment[P, 2]]
    (*    f^2 * (...)    *)
    FullSimplify[CentralMoment[P, 3]]
    (*    f^3 * (...)    *)
    

    This means that if a central moment is zero, then scaling and/or rotating the set of points will keep the central moment equal to zero.

  3. Third, let's prove the criterion for a list of points where the first two points are fixed:

    P = {0, 1, x[3] + I*y[3], x[4] + I*y[4]};
    

    Under what conditions are the real and imaginary parts of the second and third central moments zero?

    C2 = CentralMoment[P, 2] // ReIm // ComplexExpand // FullSimplify;
    C3 = CentralMoment[P, 3] // ReIm // ComplexExpand // FullSimplify;
    Solve[Thread[Join[C2, C3] == 0], {x[3], y[3], x[4], y[4]}, Reals] // FullSimplify
    (*    {{x[3] -> 0, y[3] -> -1, x[4] -> 1, y[4] -> -1},
           {x[3] -> 0, y[3] -> 1, x[4] -> 1, y[4] -> 1},
           {x[3] -> 1/2, y[3] -> -1/2, x[4] -> 1/2, y[4] -> 1/2},
           {x[3] -> 1/2, y[3] -> 1/2, x[4] -> 1/2, y[4] -> -1/2},
           {x[3] -> 1, y[3] -> -1, x[4] -> 0, y[4] -> -1},
           {x[3] -> 1, y[3] -> 1, x[4] -> 0, y[4] -> 1}}    *)
    

    All of these six solutions represent squares: enter image description here Therefore, the only way that a list of points of the form {0, 1, x[3] + I*y[3], x[4] + I*y[4]} can have zero second and third central moments is when the four points form a square.

Due to the translation, rotation, and scaling properties demonstrated in points 1 and 2, this means that any time the second and third central moments are zero, we have a square in some translation/rotation/scaling state. ∎

generalization

The k-th central moment of a regular n-gon is zero if k is not divisible by n. Enough of these conditions must be combined to make up a sufficient criterion for detecting n-gons. For the case n=4 it was enough to detect zeros in k=2 and k=3; for detecting, e.g., hexagons (n=6) it may be necessary to check k=2,3,4,5 for zeros. I haven't proved the following, but suspect that it will detect any regular n-gon:

isregularngon[p_List] :=
  And @@ Table[PossibleZeroQ[CentralMoment[p, k]], {k, 2, Length[p] - 1}]

The code challenge is essentially this code specialized for length-4 lists.

Its not exactly shortest, but I dont think anyone proposed this strategy.

Scala, 152

def f(p:Seq[(Double,Double)])={p.map(b=>{math.sqrt(math.pow((p.map(_._1).sum/p.size)-b._1,2)+math.pow((p.map(_._2).sum/p.size)-b._2,2))}).toSet.size==1}

Basically we calculate average of all points across each axis to find presumably center of the square, and then validate that center has same distance from all points.

Properly formatted solution:

type Point = (Double, Double)
def isSquare(points: Seq[Point]): Boolean = {
  //finds center point along an axis
  def avg(axis: Seq[Double]): Double = {
    axis.sum / axis.size
  }

  //finds distance between 2 points
  def distance(a: Point, b: Point): Double = {
    val x = a._1 - b._1
    val y = a._2 - b._2
    math.sqrt((x * x) + (y * y))
  }

  //point in the center of square
  val center = (
    avg(points.map(_._1)),
    avg(points.map(_._2)))

  //find a set of distances from center to all points
  //and make sure only one is in the set
  points.map(distance(center, _)).toSet.size == 1
}

C (gcc), 159 141 bytes

g;f(a,e)_Complex*a,e;{e=(*a+a[1]+a[2]+a[3])/4;for(g=0;a[g]-=e,g<4&cabs(a[g])==cabs(*a)&!fmod(carg(a[g++])-carg(*a),atan(1)););return g>4;}

-18 thanks to @G.Sliepen.

Try it online!

After subtracting the center point, checks that the absolute values of each complex number are equal, and that all the arguments are equal modulo π/2.

Stax, 14 bytes

┐cÜ╦┤╖ó#┬├{%ì↔

Run and debug it

2S{M{:sJF+m square of the distance between each pair of points
:_          "reduce"; divide each by the gcd of the array
:*4=        does the product of the array equal 4?

Run this one

Python, 71 42

lambda A: len(set(A))==4 and len(set(abs(i-j)for i in A for j in A))==3

Update 1) to require 4 different points (would previously give false positives for repeated points - are there others?) 2) to define a function per spec

For a square, the vector between any two points must be 0 (the same point), a side, or a diagonal. So, the set of the magnitude of these vectors must have length 3.

# Accepts co-ordinates as sequences of complex numbers

SQUARES=[
 (0+0j,0+1j,1+1j,1+0j),  # standard square
 (0+0j,2+1j,3-1j,1-2j),  # non-axis-aligned square
 (0+0j,1+1j,0+1j,1+0j)   # different order
]

NONSQUARES=[
 (0+0j,0+2j,3+2j,3+0j),  # rectangle
 (0+0j,3+4j,8+4j,5+0j),  # rhombus
 (0+0j,0+1j,1+1j,0+0j),   # duplicated point
 (0+0j,1+60j,1+0j,1-60j)  # rhombus 2 (J B)
] 
 
test = "lambda A: len(set(A))==4 and len(set(abs(i-j)for i in A for j in A))==3"
assert len(test)==71

is_square=lambda A: len(set(A))==4 and len(set(abs(i-j)for i in A for j in A))==3    
    
for A in SQUARES:
    assert is_square(A)
    
for A in NONSQUARES:
    assert not is_square(A)

Python 2, 49 bytes

lambda l:all(1j*z+(1-1j)*sum(l)/4in l for z in l)

Try it online!

Takes a list of four complex numbers as input. Rotates each point 90 degrees around the average, and checks that each resulting point is in the original list.

Same length (though shorter in Python 3 using {*l}).

lambda l:{1j*z+(1-1j)*sum(l)/4for z in l}==set(l)

Try it online!

Jelly, 8 bytes

_Æm×ıḟƊṆ

Try it online!

Takes a list of complex numbers as a command line argument. Prints 1 or 0.

_Æm        Subtract mean of points from each point (i.e. center on 0)
   ×ıḟƊ    Rotate 90°, then compute set difference with original.
       Ṇ   Logical negation: if empty (i.e. sets are equal) then 1 else 0.

This seems like an enjoyable challenge to revive!

Mathematica 65 80 69 66

Checks that the number of distinct inter-point distances (not including distance from a point to itself) is 2 and the shorter of the two is not 0.

h = Length@# == 2 \[And] Min@# != 0 &[Union[EuclideanDistance @@@ Subsets[#, {2}]]] &;

Usage

h@{{0, 0}, {0, 1}, {1, 1}, {1, 0}}       (*standard square *)
h@{{0, 0}, {2, 1}, {3, -1}, {1, -2}}     (*non-axis aligned square *)
h@{{0, 0}, {1, 1}, {0, 1}, {1, 0}}       (*a different order *)

h@{{0, 0}, {0, 2}, {3, 2}, {3, 0}}       (* rectangle *)
h@{{0, 0}, {3, 4}, {8, 4}, {5, 0}}       (* rhombus   *)
h@{{0, 0}, {0, 0}, {1, 1}, {0, 0}}       (* only 2 distinct points *)
h@{{0, 0}, {0, 1}, {1, 1}, {0, 1}}       (* only 3 distinct points *)

True
True
True
False
False
False
False

N.B.: \[And] is a single character in Mathematica.

Python, 67 chars, complex and distance-based, and no false positives ...

S=lambda A:len(set(A))-1==len(set([abs(K-J)for K in A for J in A]))

(I hope;-).

The sqrt in abs() may cause some roundoff problems, but probably not - abs((K-J)**2) is more reliable but compresses domain as numbers can approach to within a few digits of double precision limits.

Combines Jagu's answer (len(set(Points))-1==len(set(distances)) - brilliant IMNSHO - which drops to 85 as outer pow(...,.5) calls are unnecessary, and (...)**2 is shorter anyway) and user932's (lambda instead of def).

Neither as elegant, nor as short, as paperhorse's rotation as modified by WolframH.

I had a solution that put only the squares of the side and diagonal lengths in the set L and tested "len(L)==2 and max(set(L))/2 in L" but it never went much below 90 chars.

Tests (all should print True):

print S([(0+1j),(1+0j),(0+0j),(1+1j)])
print S([(0+0j),(2+1j),(3-1j),(1-2j)])
print S([(0+0j),(1+1j),(0+1j),(1+0j)])
print S([(1000+1j),(-1+1000j),(1-1000j),(-1000-1j)])

print not S([(0+1j),(0-1j),(0+0j),(0+1j)])
print not S([(999+1j),(-1+1000j),(1-1000j),(-1000-1j)])
print not S([(0+1j),(1+0j),(0+0j),(0-1j)])
print not S([(0+0j),(0+2j),(3+2j),(3+0j)])
print not S([(0+0j),(3+4j),(8+4j),(5+0j)])
print not S([(0+0j),(0+0j),(1+1j),(0+0j)])
print not S([(0+0j),(0+0j),(1+0j),(0+1j)])

Python, 66

Improving paperhorse's answer from 76 to 66:

def U(A):c=sum(A)/4;d=A[0]-c;return{d+c,c-d,d*1j+c,c-d*1j}==set(A)

Smalltalk Squeak 4.x flavour, 91 char in the form of a block:

[:p||b|b:=Bag new.p do:[:x|p do:[:y|b add:(x dist:y)]].b valuesAndCounts asSet={4. 8}asSet]

Test it with:

{
"Example squares:"
    {0@ 0. 0@ 1. 1@ 1. 1@ 0}. " standard square"
    {0@ 0. 2@ 1. 3@ -1. 1@ -2}.  " non-axis-aligned square"
    {0@ 0. 1@ 1. 0@ 1. 1@ 0}. " different order"
"Example non-squares:"
    {0@ 0. 0@ 2. 3@ 2. 3@ 0}.  " rectangle"
    {0@ 0. 3@ 4. 8@ 4. 5@ 0}.  " rhombus"
    {0@ 0. 0@ 0. 1@ 1. 0@ 0}.  " only 2 distinct points"
    {0@ 0. 0@ 0. 1@ 0. 0@ 1}.   " only 3 distinct points"
}
collect:
[:p||b|b:=Bag new.p do:[:x|p do:[:y|b add:(x dist:y)]].b valuesAndCounts asSet={4. 8}asSet].

It's a variant of #(4 8 4)

A degenerated (0,0)*4 is not considered as a valid square.

OCaml, 145 164

let(%)(a,b)(c,d)=(c-a)*(c-a)+(d-b)*(d-b)
let t a b c d=a%b+a%c=b%c&&d%c+d%b=b%c&&a%b=a%c&&d%c=d%b
let q(a,b,c,d)=t a b c d||t a c d b||t a b d c

Run like this:

q ((0,0),(2,1),(3,-1),(1,-2))

Let's deobfuscate and explain a bit.

First we define a norm:

let norm (ax,ay) (bx,by) = (bx-ax)*(bx-ax)+(by-ay)*(by-ay)

You'll notice that there is no call to sqrt, it's not needed here.

let is_square_with_fixed_layout a b c d =
  (norm a b) + (norm a c) = norm b c
  && (norm d c) + (norm d b) = norm b c
  && norm a b = norm a c
  && norm d c = norm d b

Here a, b, c and d are points. We assume that these points are layed out like this:

a - b
| / |
c - d

If we have a square then all these conditions must hold:

Observe that the following always holds:

is_square_with_fixed_layout r s t u = is_square_with_fixed_layout r t s u

We will use that to simplify our test function below.

Since our input is not ordered, we also have to check all permutations. Without loss of generality we can avoid permuting the first point:

let is_square (a,b,c,d) =
  is_square_with_fixed_layout a b c d
  || is_square_with_fixed_layout a c b d
  || is_square_with_fixed_layout a c d b
  || is_square_with_fixed_layout a b d c
  || is_square_with_fixed_layout a d b c
  || is_square_with_fixed_layout a d c b

After simplification:

let is_square (a,b,c,d) =
  is_square_with_fixed_layout a b c d
  || is_square_with_fixed_layout a c d b
  || is_square_with_fixed_layout a b d c

Edit: followed M.Giovannini's advice.

OCaml + Batteries, 132 characters

let q l=match List.group(-)[?List:(x-z)*(x-z)+(y-t)*(y-t)|x,y<-List:l;z,t<-List:l;(x,y)<(z,t)?]with[[s;_;_;_];[d;_]]->2*s=d|_->false

(look, Ma, no spaces!) The list comprehension in q forms the list of squared norms for each distinct unordered pair of points. A square has four equal sides and two equal diagonals, the squared lengths of the latter being twice the squared lengths of the former. Since there aren't equilateral triangles in the integer lattice the test isn't really necessary, but I include it for completeness.

Tests:

q [(0,0);(0,1);(1,1);(1,0)] ;;
- : bool = true
q [(0,0);(2,1);(3,-1);(1,-2)] ;;
- : bool = true
q [(0,0);(1,1);(0,1);(1,0)] ;;
- : bool = true
q [(0,0);(0,2);(3,2);(3,0)] ;;
- : bool = false
q [(0,0);(3,4);(8,4);(5,0)] ;;
- : bool = false
q [(0,0);(0,0);(1,1);(0,0)] ;;
- : bool = false
q [(0,0);(0,0);(1,0);(0,1)] ;;
- : bool = false

K - 33

Translation of the J solution by J B:

{4 8 4~#:'=_sqrt+/'_sqr,/x-/:\:x}

K suffers here from its reserved words(_sqr and _sqrt).

Testing:

  f:{4 8 4~#:'=_sqrt+/'_sqr,/x-/:\:x}

  f (0 0;0 1;1 1;1 0)
1

  f 4 2#0 0 1 1 0 1 1 0
1

  f 4 2#0 0 3 4 8 4 5 0
0

C#, 107 characters

return p.Distinct().Count()==4&&
(from a in p from b in p select (a-b).LengthSquared).Distinct().Count()==3;

Where points is List of Vector3D containing the points.

Computes all distances squared between all points, and if there are exactly three distinct types (must be 0, some value a, and 2*a) and 4 distinct points then the points form a square.

Factor

An implementation in the Factor programming language:

USING: kernel math math.combinatorics math.vectors sequences sets ;

: square? ( seq -- ? )
    members [ length 4 = ] [
        2 [ first2 distance ] map-combinations
        { 0 } diff length 2 =
    ] bi and ;

And some unit tests:

[ t ] [
    {
        { { 0 0 } { 0 1 } { 1 1 } { 1 0 } }   ! standard square
        { { 0 0 } { 2 1 } { 3 -1 } { 1 -2 } } ! non-axis-aligned square
        { { 0 0 } { 1 1 } { 0 1 } { 1 0 } }   ! different order
        { { 0 0 } { 0 4 } { 2 2 } { -2 2 } }  ! rotated square
    } [ square? ] all?
] unit-test

[ f ] [
    {
        { { 0 0 } { 0 2 } { 3 2 } { 3 0 } }   ! rectangle
        { { 0 0 } { 3 4 } { 8 4 } { 5 0 } }   ! rhombus
        { { 0 0 } { 0 0 } { 1 1 } { 0 0 } }   ! only 2 distinct points
        { { 0 0 } { 0 0 } { 1 0 } { 0 1 } }   ! only 3 distinct points
    } [ square? ] any?
] unit-test

Clojure, 159 chars.

user=> (def squares
         [[[0,0] [0,1] [1,1]  [1,0]]   ; standard square
         [[0,0] [2,1] [3,-1] [1,-2]]  ; non-axis-aligned square
         [[0,0] [1,1] [0,1]  [1,0]]]) ; different order
#'user/squares
user=> (def non-squares
         [[[0,0] [0,2] [3,2] [3,0]]    ; rectangle
          [[0,0] [3,4] [8,4] [5,0]]])  ; rhombus
#'user/non-squares
user=> (defn norm
         [x y]
         (reduce + (map (comp #(* % %) -) x y)))
#'user/norm
user=> (defn square?
         [[a b c d]]
         (let [[x y z] (sort (map #(norm a %) [b c d]))]
           (and (= x y) (= z (* 2 x)))))
#'user/square?
user=> (every? square? squares)
true
user=> (not-any? square? non-squares)
true

Edit: To also explain a little bit.

(Note: the square rooting is not needed and hence in the code saved above.)

Haskell, 100 characters

Here's how I'd write the JB's J solution in Haskell. With no attempt made to damage readability by removing nonessential characters, it's about 132 characters:

import Data.List
d (x,y) (x',y') = (x-x')^2 + (y-y')^2
square xs = (== [4,8,4]) . map length . group . sort $ [d x y | x<-xs, y<-xs]

You can scrape it down a bit to 100 by removing excess spaces and renaming some things

import Data.List
d(x,y)(a,b)=(x-a)^2+(y-b)^2
s l=(==[4,8,4]).map length.group.sort$[d x y|x<-l,y<-l]

Let's use QuickCheck to ensure that it accepts arbitrary squares, with one vertex at (x,y) and edge vector (a,b):

prop_square (x,y) (a,b) = square [(x,y),(x+a,y+b),(x-b,y+a),(x+a-b,y+b+a)]

Trying it in ghci:

ghci> quickCheck prop_square
*** Failed! Falsifiable (after 1 test):  
(0,0)
(0,0)

Oh right, the empty square isn't considered a square here, so we'll revise our test:

prop_square (x,y) (a,b) =
   (a,b) /= (0,0) ==> square [(x,y),(x+a,y+b),(x-b,y+a),(x+a-b,y+b+a)]

And trying it again:

ghci> quickCheck prop_square
+++ OK, passed 100 tests.

Python 97 (without complex points)

def t(p):return len(set(p))-1==len(set([pow(pow(a-c,2)+pow(b-d,2),.5)for a,b in p for c,d in p]))

This will take lists of point tuples in [(x,y),(x,y),(x,y),(x,y)] in any order, and can handle duplicates, or the wrong number of points. It does NOT require complex points like the other python answers.

You can test it like this:

S1 = [(0,0),(1,0),(1,1),(0,1)]   # standard square
S2 = [(0,0),(2,1),(3,-1),(1,-2)] # non-axis-aligned square
S3 = [(0,0),(1,1),(0,1),(1,0)]   # different order
S4 = [(0,0),(2,2),(0,2),(2,0)]   #
S5 = [(0,0),(2,2),(0,2),(2,0),(0,0)] #Redundant points

B1 = [(0,0),(0,2),(3,2),(3,0)]  # rectangle
B2 = [(0,0),(3,4),(8,4),(5,0)]  # rhombus
B3 = [(0,0),(0,0),(1,1),(0,0)]  # only 2 distinct points
B4 = [(0,0),(0,0),(1,0),(0,1)]  # only 3 distinct points
B5 = [(1,1),(2,2),(3,3),(4,4)]  # Points on the same line
B6 = [(0,0),(2,2),(0,2)]        # Not enough points

def tests(f):
    assert(f(S1) == True)
    assert(f(S2) == True)
    assert(f(S3) == True)
    assert(f(S4) == True)
    assert(f(S5) == True)

    assert(f(B1) == False)
    assert(f(B2) == False)
    assert(f(B3) == False)
    assert(f(B4) == False)
    assert(f(B5) == False)
    assert(f(B6) == False)

def t(p):return len(set(p))-1==len(set([pow(pow(a-c,2)+pow(b-d,2),.5)for a,b in p for c,d in p]))

tests(t)

This will take a little explaining, but the overall idea is that there are only three distances between the points in a square (Side, Diagonal, Zero(point compared to itself)):

def t(p):return len(set(p))-1==len(set([pow(pow(a-c,2)+pow(b-d,2),.5)for a,b in p for c,d in p]))

To save code characters I am:

I fear someone can find a test case that breaks this. So please do and Ill correct. For instance the fact I just check for three distances, instead of doing an abs() and checking for side length and hypotenuse, seems like an error.

First time I've tried code golf. Be kind if I've broken any house rules.

PHP, 82 characters


//$x=array of x coordinates
//$y=array of respective y coordinates
/* bounding box of a square is also a square - check if Xmax-Xmin equals Ymax-Ymin */
function S($x,$y){sort($x);sort($y);return ($x[3]-$x[0]==$y[3]-$y[0])?true:false};

//Or even better (81 chars):
//$a=array of points - ((x1,y1), (x2,y2), (x3,y3), (x4,y4))
function S($a){sort($a);return (bool)($a[3][0]-$a[0][0]-abs($a[2][1]-$a[3][1]))};

C# -- not exactly short. Abusing LINQ. Selects distinct two-combinations of points in the input, calculates their distances, then verifies that exactly four of them are equal and that there is only one other distinct distance value. Point is a class with two double members, X and Y. Could easily be a Tuple, but meh.

var points = new List<Point>
             {
                 new Point( 0, 0 ), 
                 new Point( 3, 4 ), 
                 new Point( 8, 4 ), 
                 new Point( 5, 0 )
              };    
var distances = points.SelectMany(
    (value, index) => points.Skip(index + 1),
    (first, second) => new Tuple<Point, Point>(first, second)).Select(
        pointPair =>
        Math.Sqrt(Math.Pow(pointPair.Item2.X - pointPair.Item1.X, 2) +
                Math.Pow(pointPair.Item2.Y - pointPair.Item1.Y, 2)));
return
    distances.Any(
        d => distances.Where( p => p == d ).Count() == 4 &&
                distances.Where( p => p != d ).Distinct().Count() == 1 );

GoRuby - 66 characters

f=->a{z=12;a.pe(2).m{|k,l|(k-l).a}.so.go{|k|k}.a{|k,l|l.sz==z-=4}}

expanded:

f=->a{z=12;a.permutation(2).map{|k,l|(k-l).abs}.sort.group_by{|k|k}.all?{|k,l|l.size==(z-=4)}}

Same algorithm as J B's answer.

Test like:

p f[[Complex(0,0), Complex(0,1), Complex(1,1), Complex(1,0)]]

Outputs true for true and blank for false

JavaScript 1.8, 112 characters

Update: saved 2 characters by folding the array comprehensions together.

function i(s)(p=[],[(e=x-a,f=y-b,d=e*e+f*f,p[d]=~~p[d]+1)for each([a,b]in s)for each([x,y]in s)],/8,+4/.test(p))

Another reimplementation of J B's answer. Exploits JavaScript 1.7/1.8 features (expression closures, array comprehensions, destructuring assignment). Also abuses ~~ (double bitwise not operator) to coerce undefined to numeric, with array-to-string coercion and a regexp to check that the length counts are [4, 8, 4] (it assumes that exactly 4 points are passed). The abuse of the comma operator is an old obfuscated C trick.

Tests:

function assert(cond, x) { if (!cond) throw ["Assertion failure", x]; }

let text = "function i(s)(p=[],[(e=x-a,f=y-b,d=e*e+f*f,p[d]=~~p[d]+1)for each([a,b]in s)for each([x,y]in s)],/8,+4/.test(p))"
assert(text.length == 112);
assert(let (source = i.toSource()) (eval(text), source == i.toSource()));

// Example squares:
assert(i([[0,0],[0,1],[1,1],[1,0]]))    // standard square
assert(i([[0,0],[2,1],[3,-1],[1,-2]]))  // non-axis-aligned square
assert(i([[0,0],[1,1],[0,1],[1,0]]))    // different order

// Example non-squares:
assert(!i([[0,0],[0,2],[3,2],[3,0]]))  // rectangle
assert(!i([[0,0],[3,4],[8,4],[5,0]]))  // rhombus
assert(!i([[0,0],[0,0],[1,1],[0,0]]))  // only 2 distinct points
assert(!i([[0,0],[0,0],[1,0],[0,1]]))  // only 3 distinct points

// Degenerate square:
assert(!i([[0,0],[0,0],[0,0],[0,0]]))   // we reject this case

PHP, 161 158 characters

function S($a){for($b=4;--$b;)for($c=$b;$c--;){$e=$a[$c][0]-$a[$b][0];$f=$a[$c][1]-$a[$b][1];$d[$g++]=$e*$e+$f*$f;}sort($d);return$d[0]==$d[3]&&$d[4]==$d[5];}

Proof (1x1): http://codepad.viper-7.com/ZlBpOB

This is based off of eBuisness's JavaScript answer.

Python - 42 chars

Looks like its an improvement to use complex numbers for the points

len(set(abs(x-y)for x in A for y in A))==3

where A = [(11+13j), (14+12j), (13+9j), (10+10j)]

old answer:

from itertools import*
len(set((a-c)**2+(b-d)**2 for(a,b),(c,d)in combinations(A,2)))==2

Points are specified in any order as a list, eg

A = [(11, 13), (14, 12), (13, 9), (10, 10)]

JavaScript 144 characters

Mathematically equal to J Bs answer. It generates the 6 lengths and assert that the 2 greatest are equal and that the 4 smallest are equal. Input must be an array of arrays.

function F(a){d=[];g=0;for(b=4;--b;)for(c=b;c--;d[g++]=(e*e+f*f)/1e6)e=a[c][0]-a[b][0],f=a[c][1]-a[b][1];d.sort();return d[0]==d[3]&&d[4]==d[5]} //Compact function
testcases=[
[[0,0],[1,1],[1,0],[0,1]],
[[0,0],[999,999],[999,0],[0,999]],
[[0,0],[2,1],[3,-1],[1,-2]],
[[0,0],[0,2],[3,2],[3,0]],
[[0,0],[3,4],[8,4],[5,0]],
[[0,0],[0,0],[1,1],[0,0]],
[[0,0],[0,0],[1,0],[0,1]]
]
for(v=0;v<7;v++){
    document.write(F(testcases[v])+"<br>")
}

function G(a){ //Readable version
    d=[]
    g=0
    for(b=4;--b;){
        for(c=b;c--;){
            e=a[c][0]-a[b][0]
            f=a[c][1]-a[b][1]
            d[g++]=(e*e+f*f)/1e6 //The division tricks the sort algorithm to sort correctly by default method.
        }
    }
    d.sort()
    return (d[0]==d[3]&&d[4]==d[5])
}

Haskell, "wc -c" reports 110 characters. Does not check that the input has 4 elements.

import Data.List
k [a,b]=2*a==b
k _=0<1
h ((a,b):t)=map (\(c,d)->(a-c)^2+(b-d)^2) t++h t
h _=[]
j=k.nub.sort.h

I tested on

test1 = [(0,0),(3,4),(-4,3),(-1,7)] -- j test1 is True
test2 = [(0,0),(3,4),(-3,4),(0,8)]  -- j test2 is False

Scala (146 characters)

def s(l:List[List[Int]]){var r=Set(0.0);l map(a=>l map(b=>r+=(math.pow((b.head-a.head),2)+math.pow((b.last-a.last),2))));print(((r-0.0).size)==2)}

J, 28 17 25 27

J doesn't really have functions, but here's a monadic verb that takes a vector of points from the complex plane:

4 8 4-:#/.~&(/:~&:|&,&(-/~))

Method is a mix of Michael Spencer (work solely on inter-vertex lengths; but he's currently failing my rhombus2) and Eelvex's (check the sets' sizes) works. Reading right to left:

Demonstration:

   NB. give the verb a name for easier use
   f =: 4 8 4-:#/.~&(/:~&:|&,&(-/~))

   NB. standard square
   f 0 0j1 1j1 1
1

   NB. non-axis-aligned square
   f 0 2j1 3j_1 1j_2
1

   NB. different order
   f 0 1j1 0j1 1
1

   NB. rectangle
   f 0 0j2 3j2 3
0

   NB. rhombus 1
   f 0 3j4 8j4 5
0

   NB. rhombus 2
   f 0 1ad_60 1ad0 1ad60
0

For memory's sake, my previous method (required ordered vertices, but could detect regular polygons of any order):

*./&(={.)&(%1&|.)&(-1&|.)

See history for explanation and demo. The current method could probably be expanded to other polygons, that 4 8 4 does look a lot like a binomial distribution.

Mathematica, 123 characters (but you can do better):

Flatten[Table[x-y,{x,a},{y,a}],1]
Sort[DeleteDuplicates[Abs[Flatten[Table[c.d,{c,%},{d,%}]]]]]
%[[1]]==0&&%[[3]]/%[[2]]==2

Where 'a' is the input in Mathematica list form, eg: a={{0,0},{3,4},{8,4},{5,0}}

The key is to look at the dot products between all the vectors and note that they must have exactly three values: 0, x, and 2*x for some value of x. The dot product checks both perpendicularity AND length in one swell foop.

I know there are Mathematica shortcuts that can make this shorter, but I don't know what they are.

Smalltalk for 106 characters

s:=Set new.
p permutationsDo:[:e|s add:((e first - e second) dotProduct:(e first - e third))].
s size = 2

where p is a collection of points, e.g.

p := { 0@0. 2@1. 3@ -1. 1@ -2}. "twisted square"

I think the math is sound...

J, 31 29 27 26

3=[:#[:~.[:,([:+/*:@-)"1/~

checks if the 8 smallest distances between the points are the same. checks if there are exactly three kinds of distances between the points (zero, side length and diagonal length).

f 4 2 $ 0 0 2 1 3 _1 1 _2
1
f 4 2 $ 0 0 0 2 3 2 3 0
0

4 2 $ is a way of writing an array in J.

Haskell (212)

import Data.List;j=any f.permutations where f x=(all g(t x)&&s(map m(t x)));t x=zip3 x(drop 1$z x)(drop 2$z x);g(a,b,c)=l a c==sqrt 2*l a b;m(a,b,_)=l a b;s(x:y)=all(==x)y;l(m,n)(o,p)=sqrt$(o-m)^2+(n-p)^2;z=cycle

Naive first attempt. Checks the following two conditions for all permutations of the input list of points (where a given permutation represents, say, a clockwise ordering of the points):

Deobfuscated code and tests

j' = any satisfyBothConditions . permutations
          --f
    where satisfyBothConditions xs = all angleIs90 (transform xs) && 
                                     same (map findLength' (transform xs))
          --t
          transform xs = zip3 xs (drop 1 $ cycle xs) (drop 2 $ cycle xs)
          --g
          angleIs90 (a,b,c) = findLength a c == sqrt 2 * findLength a b
          --m
          findLength' (a,b,_) = findLength a b
          --s
          same (x:xs) = all (== x) xs
          --l
          findLength (x1,y1) (x2,y2) = sqrt $ (x2 - x1)^2 + (y2 - y1)^2


main = do print $ "These should be true"
          print $ j [(0,0),(0,1),(1,1),(1,0)]
          print $ j [(0,0),(2,1),(3,-1),(1,-2)]
          print $ j [(0,0),(1,1),(0,1),(1,0)]
          print $ "These should not"
          print $ j [(0,0),(0,2),(3,2),(3,0)]
          print $ j [(0,0),(3,4),(8,4),(5,0)]
          print $ "also testing j' just in case"
          print $ j' [(0,0),(0,1),(1,1),(1,0)]
          print $ j' [(0,0),(2,1),(3,-1),(1,-2)]
          print $ j' [(0,0),(1,1),(0,1),(1,0)]
          print $ j' [(0,0),(0,2),(3,2),(3,0)]
          print $ j' [(0,0),(3,4),(8,4),(5,0)]

Python (105)

Points are represented by (x,y) tuples. Points can be in any order and only accepts squares. Creates a list, s, of pairwise (non-zero) distances between the points. There should be 12 distances in total, in two unique groups.

def f(p):s=filter(None,[(x-z)**2+(y-w)**2for x,y in p for z,w in p]);return len(s)==12and len(set(s))==2