Una necesidad muy común en las clases de algoritmos y la informática en general es iterar en 4 direcciones sobre una cuadrícula o matriz (como en BFS o DFS). Esto a menudo parece dar como resultado una gran cantidad de código torpe y detallado con mucha aritmética y comparaciones dentro de los bucles. He visto muchos enfoques diferentes para esto, pero no puedo evitar la sensación de que hay una forma más concisa de hacerlo.
El desafío es escribir una función pura que, dado el ancho y la altura de un plano finito que se n, m
origina en el punto (0,0)
, y las coordenadas (x,y)
que pueden representar cualquier punto válido dentro de ese plano, devuelva un objeto iterable de todos los puntos dentro del plano que sean 4 direcciones adyacente a (x,y)
.
El objetivo es definir esa función en la menor cantidad de bytes posible.
Algunos ejemplos para ayudar a ilustrar la entrada / salida válida:
n = 5 (y-axis), m = 3 (x-axis) (zero-based)
matrix = [
[A, B, C],
[D, E, F],
[G, H, I],
[J, K, L],
[M, N, O],
]
(x, y) => [valid iterable points]
E: (1, 1) => [(1, 0), (2, 1), (1, 2), (0, 1)]
A: (0, 0) => [(1, 0), (0, 1)]
L: (2, 3) => [(2, 2), (2, 4), (1, 3)]
N: (1, 4) => [(1, 3), (2, 4), (0, 4)]
n = 1 (y-axis), m = 1 (x-axis) (zero-based)
matrix = [
[A],
]
(x, y) => [valid iterable points]
A: (0, 0) => []
n = 2 (y-axis), m = 1 (x-axis) (zero-based)
matrix = [
[A],
[B],
]
(x, y) => [valid iterable points]
A: (0, 0) => [(0, 1)]
B: (0, 1) => [(0, 0)]
Y aquí hay un ejemplo (este en Python) de una función que satisface las condiciones:
def four_directions(x, y, n, m):
valid_coordinates = []
for xd, yd in [(1, 0), (0, 1), (-1, 0), (0, -1)]:
nx, ny = x + xd, y + yd
if 0 <= nx < m and 0 <= ny < n:
valid_coordinates.append((nx, ny))
return valid_coordinates
El ejemplo anterior definió una función con nombre, pero las funciones anónimas también son aceptables.
n, m, x, y
Todas las entradas son enteros de 32 bits sin signo dentro de los siguientes rangos:
n > 0
m > 0
0 <= x < m
0 <= y < n
La salida debe tomar la forma de un iterable (sin embargo, su lenguaje de elección define eso) de pares (x, y).
Aclaraciones adicionales:
Los números complejos (y otras representaciones / serializaciones) están bien siempre que el consumidor del iterable pueda acceder x
y y
como enteros conociendo solo su ubicación.
Los índices no basados en cero son aceptables, pero solo si el idioma de elección es un idioma no indexado en cero. Si el lenguaje usa una combinación de sistemas de numeración, el sistema de numeración de la estructura de datos más comúnmente usado para representar una matriz es el predeterminado. Si estos todavía son todos conceptos extraños en el idioma dado, cualquier índice inicial es aceptable.
(x,y)
está en el rectángulo, ¿verdad?Respuestas:
Python 2 , 66 bytes
Pruébalo en línea!
Enumera los cuatro vecinos, luego usa el corte de lista para eliminar aquellos que están fuera de los límites.
Python 2 , 71 bytes
Pruébalo en línea!
En lugar de verificar cuál de los cuatro vecinos está dentro de los límites, lo hacemos de la manera más lenta de verificar todos los puntos dentro de los límites para aquellos que son vecinos, es decir, tener una distancia euclidiana exactamente a 1 de
(x,y)
. También usamos el clásico truco div-mod para iterar sobre una cuadrícula , ahorrando la necesidad de escribir dos bucles comofor i in range(m)for j in range(n)
.Intenté usar aritmética compleja para escribir la condición de distancia, pero resultó más largo escribir
abs((k/n-x)*1j+k%n-y)==1
.Python 2 , 70 bytes
Pruébalo en línea!
fuente
Octava , 90 bytes
Esto utiliza un enfoque geométrico: primero creamos una matriz de ceros del tamaño deseado y establecemos
1
a en la ubicación deseada. Luego nos involucramos con el núcleoque produce una nueva matriz del mismo tamaño con unos en los 4 vecinos del punto original. Luego tenemos
find()
los índices de las entradas distintas de cero de esta nueva matriz.Pruébalo en línea!
la convolución es la clave del éxito.
fuente
Wolfram Language (Mathematica) , 42 bytes
Pruébalo en línea!
1-indexado (que sigue la convención de Mathematica para indexar). Toma entrada como
{x,y}, {m,n}
.para E / S indexadas a 0, 45 bytes :
Pruébalo en línea!
fuente
JavaScript (ES6), 74 bytes
Aburrido enfoque.
Pruébalo en línea!
JavaScript (Node.js) , 74 bytes
Menos aburrido pero igual de largo. Toma entrada como
([h,w,x,y])
.Pruébalo en línea!
JavaScript (V8) , 67 bytes
Si se permitieran todos los métodos de salida estándar, podríamos imprimir las coordenadas válidas con:
Pruébalo en línea!
fuente
Jalea ,
1312 bytesUn Enlace diádica aceptar una lista de dos números enteros (0 reajustables) a la izquierda,
[row, column]
y dos enteros por la derecha[height, width]
, lo que da una lista de listas de números enteros,[[adjacent_row_1, adjacent_column_1], ...]
.Pruébalo en línea!
¿Cómo?
fuente
ḶṚƬ
conṬ€
.2ḶṚƬNƬẎ
devuelve[[0, 1], [1, 0], [0, -1], [-1, 0]]
, mientras que2Ṭ€NƬẎ
devuelve[[1], [0, 1], [-1], [0, -1]]
, y, dado que los singletons están envueltos,+
solo se vectoriza con el primer elemento de⁸
for these, de modo que actúan como si su segundo elemento fuera0
(la identidad aditiva). Como resultado, solo puede cambiar el orden de la salida.Perl 6 ,
5649 bytes-7 bytes gracias a nwellnhof!
Pruébalo en línea!
Elimina los elementos fuera de los límites comprobando si cuando se divide entre los límites de la matriz está entre 0 y 1. Toma entrada y salida a través de números complejos donde la parte real es la
x
coordenada y el imaginario es ely
. Puede extraerlos a través de las funciones.im
y.re
.fuente
div
no parece funcionar paraNum
s(*.reals>>.Int Zdiv@^b).none
o(*.reals Z/@^b)>>.Int.none
funcionaría, pero el Int-cast parece demasiado costoso.J ,
302928 bytesPruébalo en línea!
Cómo:
m
xn
arg en una cuadrícula de números complejosj./&i./
j./
1=|@-
#~&,
+.@
fuente
C # (compilador interactivo de Visual C #) , 91 bytes
Pruébalo en línea!
Alternativamente:
Pruébalo en línea!
fuente
Carbón , 29 bytes
Pruébalo en línea! El enlace es a la versión detallada del código. Toma entradas en el orden x, y, ancho, alto. Explicación:
Imprima a
#
en la posición provista.Pase sobre el rectángulo dado.
Salta a la posición actual.
Si hay un adyacente
#
, guarde la posición.Salida de las posiciones descubiertas al final del bucle.
Respuesta aburrida:
Pruébalo en línea! El enlace es a la versión detallada del código. Funciona encontrando las posiciones adyacentes matemáticamente.
fuente
Haskell, 62 bytes
Utilizando
Pruébalo en línea!
Aburrido enfoque: 81 bytes
fuente