APL(Dyalog), 30
+/{(2-/⍵)≡2-/,⍳2 2}¨,∘.,⍨⍣2⊂¨⎕
Well, in most cases, readability and char count is proportional.
Sample Output
⎕: (0 0)(0 1)(1 0)(1 1)(0 2)(1 2)(2 2)(2 1)(2 0)4
Explaination
So, 4 points forms a unit square if and only if their relative positions are (1,1),(1,2),(2,1),(2,2){(2-/⍵)≡2-/,⍳2 2}
is a function that return 1 or 0 (true/false) given a set of 4 points as input based on whether they are in relative positions and sorted in the order (1,1),(1,2),(2,1),(2,2):⍳2 2
Generate a 2×2 matrix of the points (1,1),(1,2),(2,1),(2,2),
Unravel that matrix to an array of points2-/
Pair-wise subtraction reduce: (1,1) - (1,2) ; (1,2) - (2,1) ; (2,1) - (2,2), which gives the array [(0,-1),(-1,1),(0,-1)](2-/⍵)
Pair-wise subtraction reduce on the input≡
Check if the two arrays equal
The main program⎕
Takes input and evals it. Things like (0 0)(0 1)(1 0)(1 1)
evaluates to a nested array (Equivalent of [[0,0],[0,1],[1,0],[1,1]]
in JS)⊂¨
For every point (¨
), enclose it in a scalar (⊂
) ([[[0,0]],[[0,1]],[[1,0]],[[1,1]]]
)∘.,⍨⍣2
For every pair of elements of the array, concatenate them to form a new array. ([ [[0,0],[0,0]],[[0,0],[0,1]]...
) Repeat once. This gives all sets of 4 points that can be made using the given points. In some of these sets, the same point would be used multiple times, but these would not be unit squares so no need to waste keystrokes to remove them. (,
concatenates 2 arrays, ∘.
means "do that for every pair of elements", ⍨
means "use right operand as both left and right operands", and ⍣2
means "do this twice"),
As the previous operation would give a 4-dimensional array (note that nested arrays and multi-dimensional arrays are different things in APL), we have to unravel it to get an array of sets (of 4 points).¨
For each of the sets,{...}
execute the aforementioned function. The result would be an array of 0s and 1s indicating whether the set is a unit square. Note that because the function also check ordering, duplicates are eliminated.+/
Finally, sum resulting array to get the count.