15
\$\begingroup\$

Specs

  1. You have a cubic 3D space x,y,z of size S integer units, such as 0 <= x,y,z <= S.
  2. You get from default input methods an array of points P represented as x,y,z integer coordinates, in any reasonable format as you like, for example: [x1,y1,z1],[x2,y2,z2],[x3,y3,z3] ... [xn,yn,zn].
  3. All the P values will be in the above said cubic 3D space, such as 0 <= x,y,z <= S.
  4. The possible total number of P will be 1 <= P <= S3.
  5. You also get as input the x,y,z integer coordinates of the base point B and the 3D cube size S.

Task

Your goal is to output, in your preferred format, the points P sorted by the linear (Euclidean) distance from the base point B.

Rules

  1. If you find more than one point P that are equidistant from B you must output all of the equidistant P's in your preferred order.
  2. It is possible that a point P will coincide with B, so that their distance is 0, you must output that point.
  3. This is a challenge, so the shortest code wins.
  4. Standard loopholes are forbidden.
  5. Code explanations are appreciated.

Test cases

Input:
S (size), [B (base point x,y,z)], [P1 (x,y,z)], [P2], [P3], [P4], [P5], [...], [Pn]
10, [5,5,5], [0,0,0], [10,10,10], [2,0,8], [10,3,1], [4,4,5], [5,5,5], [5,5,4]

Output:
[5,5,5], [5,5,4], [4,4,5], [2,0,8], [10,3,1], [0,0,0], [10,10,10]

- - -

Input:
5, [2, 3, 3], [3, 0, 4], [5, 0, 3], [0, 2, 4], [0, 3, 5], [4, 2, 1], [2, 2, 2], [3, 1, 2], [3, 1, 0], [1, 3, 2], [2, 3, 1], [3, 1, 5], [4, 0, 0], [4, 3, 1], [0, 5, 5], [1, 5, 1], [3, 1, 4], [2, 2, 2], [0, 2, 5], [3, 3, 5], [3, 3, 0], [5, 4, 5], [4, 1, 3], [5, 1, 1], [3, 5, 3], [1, 5, 3], [0, 5, 2], [4, 3, 3], [2, 1, 1], [3, 3, 0], [5, 0, 4], [1, 5, 2], [4, 2, 3], [4, 2, 1], [2, 5, 5], [3, 4, 0], [3, 0, 2], [2, 3, 2], [3, 5, 1], [5, 1, 0], [2, 4, 3], [1, 0, 5], [0, 2, 5], [3, 4, 4], [2, 4, 0], [0, 1, 5], [0, 5, 4], [1, 5, 1], [2, 1, 0], [1, 3, 4], [2, 2, 2], [4, 2, 4], [5, 5, 4], [4, 4, 0], [0, 4, 1], [2, 0, 3], [3, 1, 5], [4, 4, 0], [2, 5, 1], [1, 2, 4], [4, 3, 1], [0, 2, 4], [4, 5, 2], [2, 0, 1], [0, 0, 2], [4, 1, 0], [5, 4, 3], [2, 5, 2], [5, 4, 4], [4, 4, 3], [5, 5, 1], [4, 0, 2], [1, 3, 5], [4, 2, 0], [0, 3, 1], [2, 2, 0], [0, 4, 5], [3, 2, 0], [0, 2, 1], [1, 2, 2], [2, 5, 3], [5, 5, 2], [5, 2, 4], [4, 5, 5], [2, 1, 2], [5, 4, 3], [4, 5, 4], [2, 3, 1], [4, 4, 4], [3, 0, 0], [2, 4, 5], [4, 3, 3], [3, 5, 3], [4, 0, 0], [1, 1, 1], [3, 1, 3], [2, 5, 5], [0, 0, 5], [2, 0, 2], [1, 0, 3], [3, 1, 4], [1, 2, 5], [4, 1, 3], [1, 4, 5], [3, 1, 4], [3, 5, 1], [5, 1, 4], [1, 0, 4], [2, 2, 0], [5, 2, 1], [0, 5, 3], [2, 1, 1], [0, 3, 0], [4, 5, 5], [3, 4, 2], [5, 3, 3], [3, 1, 1], [4, 0, 1], [5, 0, 5], [5, 0, 4], [1, 4, 3], [5, 4, 2], [5, 4, 0], [5, 1, 0], [0, 0, 1], [5, 3, 0]

Output:
[2, 4, 3], [2, 3, 2], [1, 3, 4], [1, 3, 2], [2, 2, 2], [1, 4, 3], [2, 2, 2], [2, 2, 2], [1, 2, 2], [3, 4, 2], [1, 2, 4], [3, 4, 4], [2, 5, 3], [4, 3, 3], [2, 3, 1], [4, 3, 3], [2, 3, 1], [1, 3, 5], [4, 4, 3], [2, 5, 2], [3, 1, 3], [1, 5, 3], [4, 2, 3], [2, 1, 2], [3, 5, 3], [2, 4, 5], [3, 3, 5], [3, 5, 3], [3, 1, 4], [0, 2, 4], [0, 2, 4], [1, 2, 5], [3, 1, 2], [3, 1, 4], [3, 1, 4], [4, 2, 4], [1, 4, 5], [4, 4, 4], [1, 5, 2], [4, 3, 1], [0, 5, 3], [2, 1, 1], [4, 1, 3], [4, 3, 1], [2, 5, 5], [0, 3, 5], [4, 1, 3], [2, 5, 1], [2, 1, 1], [0, 3, 1], [2, 5, 5], [1, 1, 1], [0, 4, 5], [4, 5, 4], [4, 5, 2], [0, 2, 1], [1, 5, 1], [5, 3, 3], [0, 5, 2], [3, 5, 1], [3, 5, 1], [0, 2, 5], [1, 5, 1], [4, 2, 1], [3, 1, 5], [3, 1, 1], [0, 2, 5], [4, 2, 1], [0, 5, 4], [0, 4, 1], [2, 0, 3], [3, 1, 5], [2, 4, 0], [2, 2, 0], [2, 0, 2], [3, 3, 0], [3, 3, 0], [5, 4, 3], [1, 0, 3], [5, 4, 3], [2, 2, 0], [3, 0, 2], [5, 4, 4], [5, 4, 2], [1, 0, 4], [3, 0, 4], [5, 2, 4], [3, 2, 0], [3, 4, 0], [0, 1, 5], [0, 5, 5], [4, 5, 5], [4, 5, 5], [0, 3, 0], [2, 0, 1], [2, 1, 0], [4, 4, 0], [5, 1, 4], [5, 5, 4], [5, 2, 1], [3, 1, 0], [5, 4, 5], [4, 4, 0], [1, 0, 5], [4, 2, 0], [0, 0, 2], [4, 0, 2], [5, 5, 2], [4, 1, 0], [5, 5, 1], [0, 0, 1], [5, 1, 1], [4, 0, 1], [0, 0, 5], [5, 0, 3], [5, 3, 0], [5, 4, 0], [3, 0, 0], [5, 0, 4], [5, 0, 4], [5, 1, 0], [4, 0, 0], [4, 0, 0], [5, 0, 5], [5, 1, 0]

- - -

Input:
10, [1, 9, 4], [4, 6, 2], [7, 5, 3], [10, 5, 2], [9, 8, 9], [10, 5, 10], [1, 5, 4], [8, 1, 1], [8, 6, 9], [10, 4, 1], [3, 4, 10], [4, 7, 0], [7, 10, 9], [5, 7, 3], [6, 7, 9], [5, 1, 4], [4, 3, 8], [4, 4, 9], [6, 9, 3], [8, 2, 6], [3, 5, 1], [0, 9, 0], [8, 4, 3], [0, 1, 1], [6, 7, 6], [4, 6, 10], [3, 9, 10], [8, 3, 1], [10, 1, 1], [9, 10, 6], [2, 3, 9], [10, 5, 0], [3, 2, 1], [10, 2, 7], [8, 4, 9], [5, 2, 4], [0, 8, 9], [10, 1, 6], [0, 8, 10], [5, 10, 1], [7, 4, 5], [4, 5, 2], [0, 2, 0], [8, 3, 3], [6, 6, 6], [3, 0, 2], [0, 1, 1], [10, 10, 8], [6, 2, 8], [8, 8, 6], [5, 4, 7], [10, 7, 4], [0, 9, 2], [1, 6, 6], [8, 5, 9], [3, 7, 4], [5, 6, 6], [3, 1, 1], [10, 4, 5], [1, 5, 7], [8, 6, 6], [4, 3, 7], [2, 1, 0], [6, 4, 2], [0, 7, 8], [8, 3, 6], [9, 2, 0], [1, 3, 8], [4, 4, 6], [5, 8, 9], [9, 4, 4], [0, 7, 3], [8, 3, 4], [6, 7, 9], [8, 7, 0], [0, 7, 7], [8, 10, 10], [10, 2, 5], [6, 9, 5], [6, 2, 7], [0, 9, 6], [1, 4, 1], [4, 3, 1], [5, 7, 3], [9, 6, 8], [4, 1, 7], [4, 0, 8], [3, 4, 7], [2, 3, 6], [0, 0, 7], [5, 3, 6], [7, 3, 4], [6, 7, 8], [3, 7, 9], [1, 9, 10], [2, 1, 2], [2, 8, 2], [0, 3, 0], [1, 1, 9], [3, 5, 2], [10, 5, 3], [5, 2, 9], [6, 9, 0], [9, 5, 0], [7, 1, 10], [3, 3, 8], [2, 5, 1], [3, 10, 10], [6, 2, 2], [10, 7, 2], [4, 3, 1], [4, 2, 1], [4, 2, 8], [6, 8, 5], [3, 10, 0], [1, 1, 7], [6, 9, 6], [6, 2, 4], [5, 5, 7], [5, 4, 5], [9, 8, 1], [9, 8, 1], [0, 10, 6], [1, 1, 9], [3, 8, 8], [3, 1, 5], [5, 7, 4], [4, 3, 6], [5, 4, 7], [6, 0, 8], [7, 8, 1], [9, 8, 4], [2, 10, 0], [3, 4, 5], [9, 3, 10], [7, 4, 1], [2, 1, 9], [10, 8, 1], [10, 3, 7], [2, 0, 6], [3, 8, 4], [10, 0, 2], [9, 9, 10], [8, 9, 5], [4, 10, 2], [8, 3, 4], [4, 2, 10], [9, 1, 6], [6, 1, 3], [4, 1, 3], [2, 9, 0], [5, 6, 5], [8, 8, 3], [5, 5, 0], [7, 6, 9], [1, 1, 5], [3, 0, 4], [1, 10, 6], [8, 0, 2], [0, 7, 3], [8, 9, 8], [2, 1, 8], [3, 1, 10], [4, 5, 9], [7, 6, 10], [3, 6, 10], [5, 9, 8], [9, 3, 3], [2, 2, 3], [9, 9, 0], [7, 2, 2], [0, 0, 9], [8, 7, 4], [9, 2, 9], [0, 6, 4], [9, 4, 3], [10, 1, 3], [5, 9, 10], [5, 10, 6], [6, 3, 10], 

Output: 
[1, 10, 6], [3, 8, 4], [0, 9, 6], [0, 9, 2], [2, 8, 2], [0, 7, 3], [0, 7, 3], [0, 10, 6], [3, 7, 4], [0, 6, 4], [1, 6, 6], [0, 7, 7], [4, 10, 2], [1, 5, 4], [0, 9, 0], [2, 9, 0], [2, 10, 0], [5, 7, 4], [5, 7, 3], [5, 10, 6], [5, 7, 3], [0, 7, 8], [3, 10, 0], [3, 8, 8], [4, 6, 2], [3, 5, 2], [1, 5, 7], [5, 10, 1], [6, 9, 3], [6, 9, 5], [5, 6, 5], [2, 5, 1], [0, 8, 9], [6, 8, 5], [5, 6, 6], [6, 9, 6], [4, 5, 2], [4, 7, 0], [3, 5, 1], [3, 4, 5], [5, 9, 8], [6, 7, 6], [3, 7, 9], [1, 4, 1], [1, 9, 10], [4, 4, 6], [0, 8, 10], [6, 6, 6], [3, 4, 7], [3, 9, 10], [5, 5, 7], [3, 10, 10], [2, 3, 6], [6, 9, 0], [5, 8, 9], [5, 4, 5], [6, 7, 8], [7, 8, 1], [5, 5, 0], [4, 3, 6], [3, 6, 10], [8, 9, 5], [5, 4, 7], [4, 5, 9], [5, 4, 7], [2, 2, 3], [8, 8, 3], [1, 3, 8], [5, 9, 10], [0, 3, 0], [7, 5, 3], [8, 7, 4], [4, 3, 1], [8, 8, 6], [6, 4, 2], [4, 3, 7], [6, 7, 9], [4, 6, 10], [4, 3, 1], [6, 7, 9], [3, 3, 8], [5, 3, 6], [4, 4, 9], [4, 3, 8], [8, 6, 6], [3, 2, 1], [7, 4, 5], [7, 10, 9], [2, 3, 9], [5, 2, 4], [1, 1, 5], [3, 4, 10], [8, 9, 8], [9, 8, 4], [0, 2, 0], [4, 2, 1], [3, 1, 5], [2, 1, 2], [8, 7, 0], [9, 10, 6], [7, 4, 1], [7, 6, 9], [7, 3, 4], [1, 1, 7], [0, 1, 1], [4, 2, 8], [9, 8, 1], [0, 1, 1], [4, 1, 3], [6, 2, 4], [9, 8, 1], [8, 4, 3], [3, 1, 1], [6, 2, 2], [5, 1, 4], [9, 9, 0], [7, 6, 10], [2, 1, 0], [2, 1, 8], [4, 1, 7], [8, 6, 9], [6, 2, 7], [8, 3, 4], [8, 3, 4], [10, 7, 4], [3, 0, 4], [8, 3, 3], [8, 10, 10], [2, 0, 6], [9, 6, 8], [10, 7, 2], [1, 1, 9], [8, 3, 6], [1, 1, 9], [7, 2, 2], [3, 0, 2], [9, 4, 4], [8, 5, 9], [2, 1, 9], [6, 1, 3], [6, 2, 8], [5, 2, 9], [9, 4, 3], [9, 8, 9], [0, 0, 7], [10, 8, 1], [4, 2, 10], [8, 3, 1], [9, 5, 0], [6, 3, 10], [10, 10, 8], [10, 5, 3], [8, 4, 9], [9, 9, 10], [10, 5, 2], [9, 3, 3], [8, 2, 6], [3, 1, 10], [4, 0, 8], [0, 0, 9], [10, 4, 5], [10, 5, 0], [10, 4, 1], [8, 1, 1], [6, 0, 8], [10, 3, 7], [9, 2, 0], [10, 2, 5], [9, 1, 6], [10, 5, 10], [8, 0, 2], [9, 3, 10], [7, 1, 10], [9, 2, 9], [10, 2, 7], [10, 1, 3], [10, 1, 6], [10, 1, 1], [10, 0, 2]

- - -

Input:
10000, [8452, 3160, 6109], [7172, 5052, 4795], [9789, 4033, 2952], [8242, 213, 3835], [177, 7083, 908], [3788, 3129, 3018], [9060, 464, 2701], [6537, 8698, 291], [9048, 3860, 6099], [4600, 2696, 4854], [2319, 3278, 9825]

Output:
[9048, 3860, 6099], [7172, 5052, 4795], [9789, 4033, 2952], [8242, 213, 3835], [4600, 2696, 4854], [9060, 464, 2701], [3788, 3129, 3018], [2319, 3278, 9825], [6537, 8698, 291], [177, 7083, 908]
\$\endgroup\$
  • 1
    \$\begingroup\$ Is it really necessary to take S as a parameter? \$\endgroup\$ – Cristian Lupascu Sep 12 '17 at 9:45
  • \$\begingroup\$ @GolfWolf if you don't need it, don't take it. \$\endgroup\$ – Mario Sep 12 '17 at 9:55
  • 2
    \$\begingroup\$ I'd strongly recommend specifying which kind of metric you want us to be using. Some people use Euclidean metric (ρ = √[(x₁-x₂)²+(y₁-y₂)²+(z₁-z₂)²]), others use Manhattan metric (ρ = |x₁-x₂| + |y₁-y₂| + |z₁-z₂|). In my opinion everyone should be using the same metric. \$\endgroup\$ – Ramillies Sep 12 '17 at 13:11
  • 4
    \$\begingroup\$ @Ramillies: The challenge specifies linear distance which in my mind is Euclidean. I wouldn't call Manhattan linear, but I agree that specifying specifically which metric to use should make it harder to misunderstand the challenge. \$\endgroup\$ – Emigna Sep 12 '17 at 13:38
  • 1
    \$\begingroup\$ Don't say linear, say Euclidean. \$\endgroup\$ – Lyndon White Sep 14 '17 at 8:26

17 Answers 17

11
\$\begingroup\$

05AB1E, 4 bytes

ΣαnO

Try it online!

Explanation

Σ        # sort by
   O     # sum of
  n      # square of
 α       # absolute difference between current value and second input
\$\endgroup\$
  • \$\begingroup\$ Why do you need n? \$\endgroup\$ – Erik the Outgolfer Sep 12 '17 at 12:07
  • \$\begingroup\$ @EriktheOutgolfer: Maybe this small example can show the difference between squaring and not. \$\endgroup\$ – Emigna Sep 12 '17 at 12:29
  • \$\begingroup\$ So, is everybody doing it wrong or everybody doing it right? \$\endgroup\$ – Erik the Outgolfer Sep 12 '17 at 12:31
  • \$\begingroup\$ @EriktheOutgolfer: I haven't checked all answers, but most seem to be correct. \$\endgroup\$ – Emigna Sep 12 '17 at 12:34
  • \$\begingroup\$ Many answers don't square, that's why I asked, since they are using exactly the same algorithm. \$\endgroup\$ – Erik the Outgolfer Sep 12 '17 at 12:38
6
\$\begingroup\$

JavaScript (ES6), 71 bytes

(b,a,g=a=>a.reduce((d,c,i)=>d+(c-=b[i])*c,0))=>a.sort((b,a)=>g(b)-g(a))
\$\endgroup\$
  • \$\begingroup\$ I think you can save a byte by using currying and moving definition of g inside sort. \$\endgroup\$ – user72349 Sep 12 '17 at 12:46
  • 1
    \$\begingroup\$ @ThePirateBay: Neil doesn't do currying! \$\endgroup\$ – Shaggy Sep 12 '17 at 21:51
6
\$\begingroup\$

Haskell, 54 52 bytes

import Data.List
f o=sortOn(sum.map(^2).zipWith(-)o)

Try it online!

I don't need the size of the space. sum.map(^2).zipWith(-)o computes the distance from a point to o : (xo-xp)^2+(yo-yp)^2+(zo-zp)^2. The points are simply sorted on the distance to o.

EDIT: "if you don't need it, don't take it" saved 2 bytes.

\$\endgroup\$
2
\$\begingroup\$

Java 8, 194 + 31 214 169 163 123 112 106 + 19 109 103 bytes

B->P->P.sort(java.util.Comparator.comparing(p->{int d=0,i=0;while(i<3)d+=(d=p[i]-B[i++])*d;return d;}))

Try it online!

\$\endgroup\$
  • \$\begingroup\$ Wrong results : base=[2,3,3], points=[4,3,3],[1,3,4]. Your result is [4,3,3], [1,3,4], while the correct result is [1,3,4],[4,3,3]. \$\endgroup\$ – Olivier Grégoire Sep 12 '17 at 12:45
  • \$\begingroup\$ @OlivierGrégoire Oops, fixed \$\endgroup\$ – Roberto Graham Sep 12 '17 at 12:54
  • \$\begingroup\$ Fix + golf: b->l->{l.sort(java.util.Comparator.comparing(p->{int d=0,i=3;for(;i-->0;)d+=(b[i]-p[i])*(b[i]-p[i]);return d;}));} (114 bytes), assuming a List<int[]> as parameter instead of int[][]. \$\endgroup\$ – Olivier Grégoire Sep 12 '17 at 12:54
  • 1
    \$\begingroup\$ Oh, pow does work in += without cast, not in most other cases. Nice to know! \$\endgroup\$ – Olivier Grégoire Sep 12 '17 at 13:38
  • \$\begingroup\$ 103 bytes: B->P->P.sort(java.util.Comparator.comparing(p->{int d=0,i=0;while(i<3)d+=(d=p[i]-B[i++])*d;return d;})) \$\endgroup\$ – Nevay Sep 13 '17 at 10:05
2
\$\begingroup\$

MATL, 7 bytes

yZP&SY)

Inputs are: 3-column matrix with points as rows, and 3-column vector with base point.

Try it at MATL Online!

Explanation

y   % Implicitly take two inputs: 3-column matrix and 3-row vector. Duplicate the first
    % STACK: input 1 (matrix), input 2 (vector), input 1 (matrix)
ZP  % Euclidean distance between rows of top two elements in stack
    % STACK: input 1 (matrix), distances (vector)
&S  % Sort and push the indices of the sorting (not the sorted values)
    % STACK: input 1 (matrix), indices (vector)
Y)  % Use as row indices. Implicitly display
    % STACK: final result (matrix)
\$\endgroup\$
5
\$\begingroup\$

Python 3, 68 64 bytes

-4 bytes thanks to @Ramillies

def f(b,l):l.sort(key=lambda p:sum((a-b)**2for a,b in zip(b,p)))

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Perl 6, 35 bytes (33 characters)

{@^b;@^p.sort:{[+] ($_ Z- @b)»²}}

Try it online!

Explanation: This takes a list with the coordinates of the base point (called @b), then a list of lists with coordinates of the other points (called @p). In a block, you can use them on the fly using the ^ symbol. Each of the ^'d variables corresponds to one argument. (They're sorted alphabetically, so @^b is the 1st argument and @^p the 2nd.) After one use of this symbol, you can use the variable normally.

The statement @^b is there just to say that the block will take the base point argument, which is used only inside the sorting block. (Otherwise it would refer to the argument of the sorting block.) The method .sort may take one argument. If it's a block taking 1 argument (like here), the array is sorted according to the values of that function. The block itself just takes each point in turn and zips it with minus (Z-) with the base point coordinates. Then we square all the elements in the list with »² and sum them using [+].

As an added bonus, this will work with float coordinates as well, and in any dimension (as long as you, obviously, supply the same number of coordinates for all the points, it does the right thing).


This is no longer valid. I leave it here just for fun.

Perl 6, 24 bytes — only a joke!

{@^b;@^p.sort:{$_!~~@b}}

Try it online!

Since the OP doesn't state which metric shall be used, this submission chooses to use the discrete metric. In this metric, the distance between two points is 0 if they are identical, and 1 if they are not. It's easy to check that this is indeed a metric (if ρ(A,B) is distance from A to B, we require that 1) ρ(A,B) = 0 iff A = B, 2) ρ(A,B) = ρ(B,A), 3) ρ(A,B) + ρ(B,C) ≥ ρ(A,C) ("triangle inequality")).

It could be probably golfed a lot more, but I don't mean it seriously.

\$\endgroup\$
  • \$\begingroup\$ Doesn't work for <5 5 5>,(<5 5 10>,<6 5 5>). Lists don't sort by their sum, but by element-wise comparison. You need a sum somewhere. \$\endgroup\$ – nwellnhof Sep 12 '17 at 13:38
  • \$\begingroup\$ @nwellnhof, many thanks. I don't know what I was thinking... Will fix shortly. \$\endgroup\$ – Ramillies Sep 12 '17 at 17:03
1
\$\begingroup\$

Pyth, 6 bytes

o.a,vz

Try it online: Demonstration

Explanation:

o.a,vzNQ   implicit variables at the end
o      Q   order the points from the first input line by:
 .a           the euclidean distance between
      N       the point
   ,          and
    vz        the point from the second input line
\$\endgroup\$
  • 1
    \$\begingroup\$ Herokuapp says: Bad Request: Request Line is too large (7005 > 4094). You should make your test suite smaller in order to fit the maximum link size. \$\endgroup\$ – Mr. Xcoder Sep 12 '17 at 11:47
  • \$\begingroup\$ @Mr.Xcoder Thanks. I fixed it. \$\endgroup\$ – Jakube Sep 12 '17 at 12:03
3
\$\begingroup\$

Mathematica, 24 bytes

xN@Norm[#-x]&//SortBy

Takes input in the format f[B][P].

We have to use 4 bytes on x to make the nested function. The precedence of  (\[Function]) and // works out nicely so that the expression is equivalent to this:

Function[x, SortBy[N@Norm[# - x]&] ]

We need N because by default, Mathematica sorts by expression structure instead of by value:

Sort[{1, Sqrt@2, 2}]
{1, 2, Sqrt[2]}

SortBy[N][{1, Sqrt@2, 2}]
{1, Sqrt[2], 2}
\$\endgroup\$
3
\$\begingroup\$

Japt, 10 9 bytes

-1 byte thanks to @Shaggy

ñ_íaV m²x

Takes points as an array of three-item arrays and the base point an a single array, in that order. Does not take the size argument.

Try it online! or run the huge test case with -R to output one x,y,z per line.

Explanation

ñ_            Sort the input array as if each item were mapped through the function...
  í V         Pair the x,y,z in the current item with those in the base point, V
   a          Take the absolute different from each pair
      m²      Square each of the 3 differences
        x     Sum those squares
              Sorted array is implicitly returned
\$\endgroup\$
  • \$\begingroup\$ Nice :) I was down to 11 bytes before work got in the way! \$\endgroup\$ – Shaggy Sep 12 '17 at 11:58
  • \$\begingroup\$ Looks like this should work for 9 bytes, but it needs some more testing. EDIT: Both versions fail on the 2nd & 3rd test cases. \$\endgroup\$ – Shaggy Sep 12 '17 at 12:00
  • \$\begingroup\$ @Shaggy I never realized í could take it's arguments in reverse, that's pretty nice. I too think it should work; I'll run some of the other test cases and edit when I'm back to a computer. \$\endgroup\$ – Justin Mariner Sep 12 '17 at 12:07
  • \$\begingroup\$ Note: - or n would also work in place of a. \$\endgroup\$ – Shaggy Sep 13 '17 at 10:53
2
\$\begingroup\$

Jelly, 5 bytes

Saved 1 byte, thanks to Leaky Nun.

ạ²SðÞ

Try it online!

Explanation

ạ²SðÞ

    Þ - Sort by key function.
ạ     - Absolute difference with the elements in the second input list.
 ²    - Square. Vectorizes.
  S   - Sum.
   ð  - Starts a separate dyadic chain.
      - Output implicitly.
\$\endgroup\$
  • \$\begingroup\$ Save a byte with ạS¥Þ (didn't notice your answer before posting mine). \$\endgroup\$ – Erik the Outgolfer Sep 12 '17 at 12:06
  • \$\begingroup\$ Hmm...I think you will have to go back to 5 bytes since I found that you need to square: ạ²SµÞ \$\endgroup\$ – Erik the Outgolfer Sep 12 '17 at 12:42
  • \$\begingroup\$ @EriktheOutgolfer I think I fixed it now. Not sure though \$\endgroup\$ – Mr. Xcoder Sep 12 '17 at 13:13
  • \$\begingroup\$ You need to square before summing (vectorize), not after. \$\endgroup\$ – Erik the Outgolfer Sep 12 '17 at 13:24
  • \$\begingroup\$ @EriktheOutgolfer Should be ok now \$\endgroup\$ – Mr. Xcoder Sep 12 '17 at 13:27
4
\$\begingroup\$

R, 56 40 bytes

-16 bytes thanks to flodel for suggesting a different input format

function(P,B)P[,order(colSums((P-B)^2))]

Try it online!

Takes P as a 3xn matrix of points, i.e., each column is a point; output is in the same format.

Use the helper function g to transform the list of points P from the test cases into the appropriate R format.

\$\endgroup\$
  • 1
    \$\begingroup\$ Maybe replace the sapply() with colSums((t(P)-B)^2), where the input P would be a matrix? \$\endgroup\$ – flodel Sep 13 '17 at 1:15
  • \$\begingroup\$ @flodel if I'm going to do that, I may as well take P as a 3xn matrix and just do colSums((P-B)^2) instead! \$\endgroup\$ – Giuseppe Sep 13 '17 at 13:24
3
\$\begingroup\$

C# (.NET Core), 68 57 53 + 23 18 bytes

-11 bytes thanks to Emigna

B=>P=>P.OrderBy(p=>p.Zip(B,(x,y)=>(x-y)*(x-y)).Sum())

Byte count also includes

using System.Linq;

Try it online!

Points are treated as collections of ints. Explanation:

B => P =>                          // Take the base point and a collection of points to sort
    P.OrderBy(p =>                 // Order the points by:
        p.Zip(B, (x, y) =>         //     Take each point and combine it with the base:
            (x - y) * (x - y)      //         Take each dimension and measure their distance squared
        ).Sum()                    //     Sum of the distances in each dimension together
    )
\$\endgroup\$
3
\$\begingroup\$

JavaScript (ES6), 72 71 bytes

This one is not shorter than Neil's answer, but I thought I would post it anyway to demonstrate the use of Math.hypot(), which was introduced in ES6.

Takes input in currying syntax (p)(a), where p = [ x,y,z ] is the base point and a is the array of other points.

p=>a=>a.sort((a,b)=>(g=a=>Math.hypot(...a.map((v,i)=>v-p[i])))(a)-g(b))

let f =

p=>a=>a.sort((a,b)=>(g=a=>Math.hypot(...a.map((v,i)=>v-p[i])))(a)-g(b))

console.log(JSON.stringify(f([5, 5, 5])([[0, 0, 0], [10, 10, 10], [2, 0, 8], [10, 3, 1], [4, 4, 5], [5, 5, 5], [5, 5, 4]])))

console.log(JSON.stringify(f([2, 3, 3])([[3, 0, 4], [5, 0, 3], [0, 2, 4], [0, 3, 5], [4, 2, 1], [2, 2, 2], [3, 1, 2], [3, 1, 0], [1, 3, 2], [2, 3, 1], [3, 1, 5], [4, 0, 0], [4, 3, 1], [0, 5, 5], [1, 5, 1], [3, 1, 4], [2, 2, 2], [0, 2, 5], [3, 3, 5], [3, 3, 0], [5, 4, 5], [4, 1, 3], [5, 1, 1], [3, 5, 3], [1, 5, 3], [0, 5, 2], [4, 3, 3], [2, 1, 1], [3, 3, 0], [5, 0, 4], [1, 5, 2], [4, 2, 3], [4, 2, 1], [2, 5, 5], [3, 4, 0], [3, 0, 2], [2, 3, 2], [3, 5, 1], [5, 1, 0], [2, 4, 3], [1, 0, 5], [0, 2, 5], [3, 4, 4], [2, 4, 0], [0, 1, 5], [0, 5, 4], [1, 5, 1], [2, 1, 0], [1, 3, 4], [2, 2, 2], [4, 2, 4], [5, 5, 4], [4, 4, 0], [0, 4, 1], [2, 0, 3], [3, 1, 5], [4, 4, 0], [2, 5, 1], [1, 2, 4], [4, 3, 1], [0, 2, 4], [4, 5, 2], [2, 0, 1], [0, 0, 2], [4, 1, 0], [5, 4, 3], [2, 5, 2], [5, 4, 4], [4, 4, 3], [5, 5, 1], [4, 0, 2], [1, 3, 5], [4, 2, 0], [0, 3, 1], [2, 2, 0], [0, 4, 5], [3, 2, 0], [0, 2, 1], [1, 2, 2], [2, 5, 3], [5, 5, 2], [5, 2, 4], [4, 5, 5], [2, 1, 2], [5, 4, 3], [4, 5, 4], [2, 3, 1], [4, 4, 4], [3, 0, 0], [2, 4, 5], [4, 3, 3], [3, 5, 3], [4, 0, 0], [1, 1, 1], [3, 1, 3], [2, 5, 5], [0, 0, 5], [2, 0, 2], [1, 0, 3], [3, 1, 4], [1, 2, 5], [4, 1, 3], [1, 4, 5], [3, 1, 4], [3, 5, 1], [5, 1, 4], [1, 0, 4], [2, 2, 0], [5, 2, 1], [0, 5, 3], [2, 1, 1], [0, 3, 0], [4, 5, 5], [3, 4, 2], [5, 3, 3], [3, 1, 1], [4, 0, 1], [5, 0, 5], [5, 0, 4], [1, 4, 3], [5, 4, 2], [5, 4, 0], [5, 1, 0], [0, 0, 1], [5, 3, 0]])))

console.log(JSON.stringify(f([1, 9, 4])([[4, 6, 2], [7, 5, 3], [10, 5, 2], [9, 8, 9], [10, 5, 10], [1, 5, 4], [8, 1, 1], [8, 6, 9], [10, 4, 1], [3, 4, 10], [4, 7, 0], [7, 10, 9], [5, 7, 3], [6, 7, 9], [5, 1, 4], [4, 3, 8], [4, 4, 9], [6, 9, 3], [8, 2, 6], [3, 5, 1], [0, 9, 0], [8, 4, 3], [0, 1, 1], [6, 7, 6], [4, 6, 10], [3, 9, 10], [8, 3, 1], [10, 1, 1], [9, 10, 6], [2, 3, 9], [10, 5, 0], [3, 2, 1], [10, 2, 7], [8, 4, 9], [5, 2, 4], [0, 8, 9], [10, 1, 6], [0, 8, 10], [5, 10, 1], [7, 4, 5], [4, 5, 2], [0, 2, 0], [8, 3, 3], [6, 6, 6], [3, 0, 2], [0, 1, 1], [10, 10, 8], [6, 2, 8], [8, 8, 6], [5, 4, 7], [10, 7, 4], [0, 9, 2], [1, 6, 6], [8, 5, 9], [3, 7, 4], [5, 6, 6], [3, 1, 1], [10, 4, 5], [1, 5, 7], [8, 6, 6], [4, 3, 7], [2, 1, 0], [6, 4, 2], [0, 7, 8], [8, 3, 6], [9, 2, 0], [1, 3, 8], [4, 4, 6], [5, 8, 9], [9, 4, 4], [0, 7, 3], [8, 3, 4], [6, 7, 9], [8, 7, 0], [0, 7, 7], [8, 10, 10], [10, 2, 5], [6, 9, 5], [6, 2, 7], [0, 9, 6], [1, 4, 1], [4, 3, 1], [5, 7, 3], [9, 6, 8], [4, 1, 7], [4, 0, 8], [3, 4, 7], [2, 3, 6], [0, 0, 7], [5, 3, 6], [7, 3, 4], [6, 7, 8], [3, 7, 9], [1, 9, 10], [2, 1, 2], [2, 8, 2], [0, 3, 0], [1, 1, 9], [3, 5, 2], [10, 5, 3], [5, 2, 9], [6, 9, 0], [9, 5, 0], [7, 1, 10], [3, 3, 8], [2, 5, 1], [3, 10, 10], [6, 2, 2], [10, 7, 2], [4, 3, 1], [4, 2, 1], [4, 2, 8], [6, 8, 5], [3, 10, 0], [1, 1, 7], [6, 9, 6], [6, 2, 4], [5, 5, 7], [5, 4, 5], [9, 8, 1], [9, 8, 1], [0, 10, 6], [1, 1, 9], [3, 8, 8], [3, 1, 5], [5, 7, 4], [4, 3, 6], [5, 4, 7], [6, 0, 8], [7, 8, 1], [9, 8, 4], [2, 10, 0], [3, 4, 5], [9, 3, 10], [7, 4, 1], [2, 1, 9], [10, 8, 1], [10, 3, 7], [2, 0, 6], [3, 8, 4], [10, 0, 2], [9, 9, 10], [8, 9, 5], [4, 10, 2], [8, 3, 4], [4, 2, 10], [9, 1, 6], [6, 1, 3], [4, 1, 3], [2, 9, 0], [5, 6, 5], [8, 8, 3], [5, 5, 0], [7, 6, 9], [1, 1, 5], [3, 0, 4], [1, 10, 6], [8, 0, 2], [0, 7, 3], [8, 9, 8], [2, 1, 8], [3, 1, 10], [4, 5, 9], [7, 6, 10], [3, 6, 10], [5, 9, 8], [9, 3, 3], [2, 2, 3], [9, 9, 0], [7, 2, 2], [0, 0, 9], [8, 7, 4], [9, 2, 9], [0, 6, 4], [9, 4, 3], [10, 1, 3], [5, 9, 10], [5, 10, 6], [6, 3, 10]])))

console.log(JSON.stringify(f([8452, 3160, 6109])([[7172, 5052, 4795], [9789, 4033, 2952], [8242, 213, 3835], [177, 7083, 908], [3788, 3129, 3018], [9060, 464, 2701], [6537, 8698, 291], [9048, 3860, 6099], [4600, 2696, 4854], [2319, 3278, 9825]])))

\$\endgroup\$
3
\$\begingroup\$

k, 14 bytes

{y@<+/x*x-:+y}

Try it online!

{            } /function(x,y)
           +y  /transpose y
        x-:    /w[j,i] = x[j] - y[j,i]
      x*       /w[j,i]*w[j,i]
    +/         /v[i] = sum over all j: w[j,i]
   <           /indices to sort by
 y@            /rearrange list of points by indices

Also, this works for n dimensions, and is not limited to 3.

\$\endgroup\$
2
\$\begingroup\$

Kotlin 1.1, 58 bytes

{t,i->i.sortedBy{it.zip(t).map{(f,s)->(f-s)*(f-s)}.sum()}}

Beautified

// t is the target, i is the list of inputs
{ t, i ->
    // Sort the inputs by the distance
    i.sortedBy {
        // For each dimension
        it.zip(t)
            // Calculate the square of the distance
            .map { (f, s) -> (f - s) * (f - s) }
            // Add up the squares
            .sum()
    }
}

Test

var f: (List<Int>, List<List<Int>>) -> List<List<Int>> =
{t,i->i.sortedBy{it.zip(t).map{(f,s)->(f-s)*(f-s)}.sum()}}

data class TestData(val target: List<Int>, val input: List<List<Int>>, val output: List<List<Int>>)

fun main(args: Array<String>) {
    val items = listOf(
            TestData(listOf(5, 5, 5),
                    listOf(listOf(0, 0, 0), listOf(10, 10, 10), listOf(2, 0, 8), listOf(10, 3, 1), listOf(4, 4, 5), listOf(5, 5, 5), listOf(5, 5, 4)),
                    listOf(listOf(5, 5, 5), listOf(5, 5, 4), listOf(4, 4, 5), listOf(2, 0, 8), listOf(10, 3, 1), listOf(0, 0, 0), listOf(10, 10, 10))
            ),
            TestData(listOf(8452, 3160, 6109),
                    listOf(listOf(7172, 5052, 4795), listOf(9789, 4033, 2952), listOf(8242, 213, 3835), listOf(177, 7083, 908), listOf(3788, 3129, 3018), listOf(9060, 464, 2701), listOf(6537, 8698, 291), listOf(9048, 3860, 6099), listOf(4600, 2696, 4854), listOf(2319, 3278, 9825)),
                    listOf(listOf(9048, 3860, 6099), listOf(7172, 5052, 4795), listOf(9789, 4033, 2952), listOf(8242, 213, 3835), listOf(4600, 2696, 4854), listOf(9060, 464, 2701), listOf(3788, 3129, 3018), listOf(2319, 3278, 9825), listOf(6537, 8698, 291), listOf(177, 7083, 908))
            ))
    items.map { it to f(it.target, it.input) }.filter { it.first.output != it.second }.forEach {
        System.err.println(it.first.output)
        System.err.println(it.second)
        throw AssertionError(it.first)
    }
    println("Test Passed")
}
\$\endgroup\$
1
\$\begingroup\$

Perl 5, 90 bytes

sub v{$i=$t=0;$t+=($_-$p[$i++])**2for pop=~/\d+/g;$t}@p=<>=~/\d+/g;say sort{v($a)<=>v$b}<>

Try it online!

Input is newline separated list of points, with the first one being the base point and the last having a trailing newline. Brackets ([]) around the coordinates are optional.

\$\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.