A recent code golf requested a way to determine if 4 points form a square. Factor may not be the shortest answer, but I thought I would contribute it anyway.
We require four unique points to be provided. We then use the distance formula to compute the distances between all pairs of points. For a square, there should be just two lengths (the side and the diagonal) not counting zero (the distance from a point to itself).
USING: kernel math math.combinatorics math.vectors sequences sets ; : square? ( seq -- ? ) members [ length 4 = ] [ 2 [ first2 v- [ sq ] map-sum ] map-combinations { 0 } diff length 2 = ] bi and ;
We can write some unit tests to make sure it works.
USE: tools.test [ 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
Since it's code golf (fewest characters possible), how might you make it shorter?
It's not possible to combine a point with itself, and all of them are different (due to initial members), therefore you can replace { 0 } diff by members... not so big gain, but still :)
ReplyDeleteApart from that... just use 1 character for word name and stack effect declaration elements ": s ( s -- ? )" :)
And of course removing cosmetic spaces and USING: vocab, since only function definition is requested, even if this would ofuscate de code
ReplyDelete"v- [ sq ] map-sum" is distance (from math.vectors)
ReplyDelete