La pregunta ha cambiado, por lo tanto, esta respuesta contiene diferentes versiones, con y sin una ruta cerrada.
Perl, ruta abierta, 69 bytes
print"@$_$/"for sort{$$a[0]<=>$$b[0]||$$a[1]<=>$$b[1]}map{[/\S+/g]}<>
Cada punto se espera en STDIN como línea, con las coordenadas separadas por espacios en blanco.
Se admite cualquier formato de número que Perl interprete como número (incluidos los números de coma flotante).
Ejemplo:
0 0
4 4
0 4
4 0
-2 1
2 -2
2 4
3.21 .56
.035e2 -7.8
0 2
Salida:
-2 1
0 0
0 2
0 4
2 -2
2 4
3.21 .56
.035e2 -7.8
4 0
4 4
Sin golf:
print "@$_$/" for # print output line
sort { # sort function for two points $a and $b
$$a[0] <=> $$b[0] # compare x part
|| $$a[1] <=> $$b[1] # compare y part, if x parts are identical
}
map { [/\S+/g] } # convert input line to point as array reference
<> # read input lines
Variantes de circuito
En la versión de la primera pregunta, había una conexión entre el último y el primer punto para hacer un circuito.
El centro no es un punto existente, 253 bytes
Esta variante puede fallar, si el centro es uno de los puntos, vea el ejemplo 3.
Ediciones:
En su respuesta, swish notó que los puntos deben centrarse alrededor del origen para garantizar un circuito libre de cruz:
- La ordenación necesita coordenadas transformadas.
- La representación de cadena original de los números debe mantenerse para la salida.
Corrección de errores: el caso especial para el eje x negativo había incluido el eje x positivo.
print"$$_[2] $$_[3]$/"for sort{($X,$Y)=@$a;($x,$y)=@$b;(!$X&&!$Y?-1:0)||!$x&&!$y||!$Y&&!$y&&$X<0&&$x<0&&$X<=>$x||atan2($Y,$X)<=>atan2($y,$x)||$X**2+$Y**2<=>$x**2+$y**2}map{[$$_[0]-$M/$n,$$_[1]-$N/$n,@$_]}map{$n++;$M+=$$_[0];$N+=$$_[1];$_}map{[/\S+/g]}<>
Ejemplo 1:
4 4
-2 0
2 0
1 1
4 0
-2 -2
-3 -1
1 -2
3 0
2 -4
0 0
-1 -2
3 3
-3 0
2 3
-5 1
-6 -1
Salida 1:
0 0
-6 -1
-3 -1
-2 -2
-1 -2
1 -2
2 -4
2 0
3 0
4 0
1 1
3 3
4 4
2 3
-5 1
-3 0
-2 0
Ejemplo 2
Prueba de representación de números y transformación de coordenadas.
.9e1 9
7 7.0
8.5 06
7.77 9.45
Salida 2:
7 7.0
8.5 06
.9e1 9
7.77 9.45
Sin golf:
print "$$_[2] $$_[3]$/" for sort { # print sorted points
($X, $Y) = @$a; # ($X, $Y) is first point $a
($x, $y) = @$b; # ($x, $y) is second point $b
(!$X && !$Y ? -1 : 0) || # origin comes first, test for $a
!$x && !$y || # origin comes first, test for $b
!$Y && !$y && $X < 0 && $x < 0 && $X <=> $x ||
# points on the negative x-axis are sorted in reverse order
atan2($Y, $X) <=> atan2($y, $x) ||
# sort by angles; the slope y/x would be an alternative,
# then the x-axis needs special treatment
$X**2 + $Y**2 <=> $x**2 + $y**2
# the (quadratic) length is the final sort criteria
}
map { [ # make tuple with transformed and original coordinates
# the center ($M/$n, $N/$n) is the new origin
$$_[0] - $M/$n, # transformed x value
$$_[1] - $N/$n, # transformed y value
@$_ # original coordinates
] }
map {
$n++; # $n is number of points
$M += $$_[0]; # $M is sum of x values
$N += $$_[1]; # $N is sum of y values
$_ # pass orignal coordinates through
}
map { # make tuple with point coordinates
[ /\S+/g ] # from non-whitespace in input line
}
<> # read input lines
Sin restricción, 325 bytes
print"$$_[2] $$_[3]$/"for sort{($X,$Y)=@$a;($x,$y)=@$b;atan2($Y,$X)<=>atan2($y,$x)||$X**2+$Y**2<=>$x**2+$y**2}map{[$$_[0]-$O/9,$$_[1]-$P/9,$$_[2],$$_[3]]}map{$O=$$_[0]if$$_[0]>0&&($O>$$_[0]||!$O);$P=$$_[1]if$$_[1]>0&&($P>$$_[1]||!$P);[@$_]}map{[$$_[0]-$M/$n,$$_[1]-$N/$n,@$_]}map{$n++;$M+=$$_[0];$N+=$$_[1];$_}map{[/\S+/g]}<>
En la versión anterior, el centro se coloca al principio y los últimos puntos en el eje negativo se ordenan en orden inverso para volver a cruzarse al centro nuevamente. Sin embargo, esto no es suficiente, porque los últimos puntos podrían estar en una línea diferente. Así, el siguiente ejemplo 3 fallaría.
Esto se soluciona moviendo el origen centrado un poco hacia arriba y hacia la derecha. Debido al centrado, debe haber al menos un punto con valor x positivo y un punto con valor y positivo. Por lo tanto, se toman los mínimos de los valores positivos x e y y se reducen a un noveno (medio o tercero podría ser suficiente). Este punto no puede ser uno de los puntos existentes y se convierte en el nuevo origen.
Los tratamientos especiales del origen y el eje x negativo se pueden eliminar, porque hay algún punto que se encuentra en el nuevo origen.
Ejemplo 3
-2 -2
-1 -1
-2 2
-1 1
2 -2
1 -1
2 2
1 1
0 0
Salida 3:
0 0
-1 -1
-2 -2
1 -1
2 -2
1 1
2 2
-2 2
-1 1
El ejemplo 1 ahora está ordenado de manera diferente:
Sin golf:
print "$$_[2] $$_[3]$/" for sort { # print sorted points
($X, $Y) = @$a; # ($X, $Y) is first point $a
($x, $y) = @$b; # ($x, $y) is second point $b
atan2($Y, $X) <=> atan2($y, $x) ||
# sort by angles; the slope y/x would be an alternative,
# then the x-axis needs special treatment
$X**2 + $Y**2 <=> $x**2 + $y**2
# the (quadratic) length is the final sort criteria
}
map { [ # make tuple with transformed coordinates
$$_[0] - $O/9, $$_[1] - $P/9, # new transformed coordinate
$$_[2], $$_[3] # keep original coordinate
] }
map {
# get the minimum positive x and y values
$O = $$_[0] if $$_[0] > 0 && ($O > $$_[0] || !$O);
$P = $$_[1] if $$_[1] > 0 && ($P > $$_[1] || !$P);
[ @$_ ] # pass tuple through
}
map { [ # make tuple with transformed and original coordinates
# the center ($M/$n, $N/$n) is the new origin
$$_[0] - $M/$n, # transformed x value
$$_[1] - $N/$n, # transformed y value
@$_ # original coordinates
] }
map {
$n++; # $n is number of points
$M += $$_[0]; # $M is sum of x values
$N += $$_[1]; # $N is sum of y values
$_ # pass orignal coordinates through
}
map { # make tuple with point coordinates
[ /\S+/g ] # from non-whitespace in input line
}
<> # read input lines