Uma necessidade muito comum nas classes de algoritmos e ciência da computação em geral é iterar de forma quadridirecional em uma grade ou matriz (como no BFS ou DFS). Isso geralmente resulta em muitos códigos desajeitados e detalhados, com muita aritmética e comparações em loops. Eu já vi muitas abordagens diferentes disso, mas não posso deixar de pensar que há uma maneira mais concisa de fazer isso.
O desafio é escrever uma função pura que, dada a largura e a altura de um plano finito com n, m
origem no ponto (0,0)
, e as coordenadas (x,y)
que podem representar qualquer ponto válido dentro desse plano, retorne um objeto iterável de todos os pontos no plano que sejam de direção 4 adjacente a (x,y)
.
O objetivo é definir essa função no menor número possível de bytes.
Alguns exemplos para ajudar a ilustrar entrada / saída 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)]
E aqui está um exemplo (este em Python) de uma função que satisfaz as condições:
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
O exemplo acima definiu uma função nomeada, mas funções anônimas também são aceitáveis.
As entradas n, m, x, y
são todos números inteiros de 32 bits não assinados dentro dos seguintes intervalos:
n > 0
m > 0
0 <= x < m
0 <= y < n
A saída deve assumir a forma de um iterável (no entanto, seu idioma de escolha define isso) de pares (x, y).
Esclarecimentos adicionais:
Números complexos (e outras representações / serializações) são válidos desde que o consumidor do iterável possa acessar x
e y
como números inteiros sabendo apenas sua localização.
Índices que não sejam baseados em zero são aceitáveis, mas apenas se o idioma de escolha for um idioma que não seja zero. Se o idioma usar uma combinação de sistemas de numeração, use como padrão o sistema de numeração da estrutura de dados mais comumente usado para representar uma matriz. Se esses ainda são todos conceitos estranhos no idioma especificado, qualquer índice inicial é aceitável.
(x,y)
ele está no retângulo, certo?Respostas:
Python 2 , 66 bytes
Experimente online!
Lista os quatro vizinhos e usa o fatiamento de lista para remover aqueles que estão fora dos limites.
Python 2 , 71 bytes
Experimente online!
Em vez de verificar qual dos quatro vizinhos está dentro dos limites, fazemos isso da maneira mais lenta de verificar todos os pontos dentro dos limites daqueles que são vizinhos, ou seja, com a distância euclidiana exatamente a 1
(x,y)
. Também usamos o clássico truque div-mod para iterar sobre uma grade , economizando a necessidade de escrever dois loops comofor i in range(m)for j in range(n)
.Tentei usar aritmética complexa para escrever a condição de distância, mas ficou mais tempo para escrever
abs((k/n-x)*1j+k%n-y)==1
.Python 2 , 70 bytes
Experimente online!
fonte
Oitava , 90 bytes
Isso usa uma abordagem geométrica: primeiro criamos uma matriz de zeros do tamanho desejado e configuramos
1
a no local desejado. Então nós convolvemos com o kernelque produz uma nova matriz do mesmo tamanho com as dos 4 vizinhos do ponto original. Então nós
find()
os índices das entradas diferentes de zero desta nova matriz.Experimente online!
convolução é a chave para o sucesso.
fonte
Wolfram Language (Mathematica) , 42 bytes
Experimente online!
Indexado a 1 (que segue a convenção do Mathematica para indexação). Toma entrada como
{x,y}, {m,n}
.para E / S indexada em 0, 45 bytes :
Experimente online!
fonte
JavaScript (ES6), 74 bytes
Abordagem chata.
Experimente online!
JavaScript (Node.js) , 74 bytes
Menos chato, mas tão longo. Toma entrada como
([h,w,x,y])
.Experimente online!
JavaScript (V8) , 67 bytes
Se todos os métodos de saída padrão fossem permitidos, poderíamos simplesmente imprimir as coordenadas válidas com:
Experimente online!
fonte
Geléia ,
1312 bytesUm link diádico que aceita uma lista de dois números inteiros (indexados 0) à esquerda
[row, column]
e dois inteiros à direita[height, width]
, que produz uma lista de listas de números inteiros[[adjacent_row_1, adjacent_column_1], ...]
,.Experimente online!
Quão?
fonte
ḶṚƬ
porṬ€
.2ḶṚƬNƬẎ
retorna[[0, 1], [1, 0], [0, -1], [-1, 0]]
, enquanto2Ṭ€NƬẎ
retorna[[1], [0, 1], [-1], [0, -1]]
e, como os singletons são agrupados,+
somente vetoriza com o primeiro elemento de⁸
para esses, então eles agem como se seu segundo elemento fosse0
(a identidade aditiva). Como resultado, apenas a ordem da saída pode mudar.Perl 6 ,
5649 bytes-7 bytes graças ao nwellnhof!
Experimente online!
Remove os elementos fora dos limites, verificando se, quando dividido pelos limites da matriz, está entre 0 e 1. Obtém entrada e saída através de números complexos, onde a parte real é a
x
coordenada e o imaginário é oy
. Você pode extraí-los através das funções.im
e.re
.fonte
div
não parece trabalho paraNum
s(*.reals>>.Int Zdiv@^b).none
ou(*.reals Z/@^b)>>.Int.none
funcionaria, mas o elenco interno parece muito caro.J ,
302928 bytesExperimente online!
Quão:
m
xn
arg em uma grade de números complexosj./&i./
j./
1=|@-
#~&,
+.@
fonte
C # (compilador interativo do Visual C #) , 91 bytes
Experimente online!
Alternativamente:
Experimente online!
fonte
Carvão , 29 bytes
Experimente online! Link é a versão detalhada do código. Recebe entradas na ordem x, y, largura, altura. Explicação:
Imprima a
#
na posição fornecida.Faça um loop sobre o retângulo especificado.
Salte para a posição atual.
Se houver um adjacente
#
, salve a posição.Saída as posições descobertas no final do loop.
Resposta chata:
Experimente online! Link é a versão detalhada do código. Funciona encontrando as posições adjacentes matematicamente.
fonte
Haskell, 62 bytes
Usando
Experimente online!
Abordagem chata: 81 bytes
fonte