Un besoin très courant dans les classes d'algorithmes et l'informatique en général est d'itérer dans 4 directions sur une grille ou une matrice (comme dans BFS ou DFS). Cela semble souvent entraîner beaucoup de code maladroit et verbeux avec beaucoup d'arithmétique et de comparaisons dans les boucles. J'ai vu de nombreuses approches différentes à ce sujet, mais je ne peux pas me départir du sentiment qu'il existe une façon plus concise de le faire.
Le défi est d'écrire une fonction pure qui, étant donné la largeur et la hauteur d'un plan fini n, m
originaire d'un point (0,0)
, et les coordonnées (x,y)
qui peuvent représenter n'importe quel point valide dans ce plan, renvoie un objet itérable de tous les points dans le plan qui sont dans 4 directions adjacent à (x,y)
.
Le but est de définir cette fonction en aussi peu d'octets que possible.
Quelques exemples pour illustrer une entrée / sortie valide:
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)]
Et voici un exemple (celui-ci en Python) d'une fonction qui remplit les conditions:
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
L'exemple ci-dessus a défini une fonction nommée, mais les fonctions anonymes sont également acceptables.
Les entrées n, m, x, y
sont toutes des entiers 32 bits non signés dans les plages suivantes:
n > 0
m > 0
0 <= x < m
0 <= y < n
La sortie doit prendre la forme d'un itérable (cependant votre langue de choix le définit) de paires (x, y).
Précisions supplémentaires:
Les nombres complexes (et autres représentations / sérialisations) sont OK tant que le consommateur de l'itérable peut accéder x
et en y
tant qu'entiers ne connaissant que leur emplacement.
Les index non basés sur zéro sont acceptables, mais uniquement si la langue de choix est une langue non indexée sur zéro. Si le langage utilise un mélange de systèmes de numérotation, choisissez par défaut le système de numérotation de la structure de données la plus couramment utilisée pour représenter une matrice. Si ce sont encore tous des concepts étrangers dans la langue donnée, tout indice de départ est acceptable.
(x,y)
lui - même est dans le rectangle, non?Réponses:
Python 2 , 66 octets
Essayez-le en ligne!
Répertorie les quatre voisins, puis utilise le découpage de liste pour supprimer ceux qui sont hors limites.
Python 2 , 71 octets
Essayez-le en ligne!
Au lieu de vérifier lequel des quatre voisins sont entrants, nous le faisons plus lentement pour vérifier tous les points entrants pour ceux qui sont voisins, c'est-à-dire que la distance euclidienne est exactement à 1
(x,y)
. Nous utilisons également l' astuce div-mod classique pour parcourir une grille , ce qui évite d'écrire deux boucles commefor i in range(m)for j in range(n)
.J'ai essayé d'utiliser une arithmétique complexe pour écrire la condition de distance, mais cela s'est avéré plus long à écrire
abs((k/n-x)*1j+k%n-y)==1
.Python 2 , 70 octets
Essayez-le en ligne!
la source
Octave , 90 octets
Cela utilise une approche géométrique: d'abord, nous créons une matrice de zéros de la taille souhaitée, et définissons a
1
à l'emplacement souhaité. Puis on convolue avec le noyauce qui produit une nouvelle matrice de la même taille avec celles aux 4 voisins du point d'origine. Nous avons ensuite
find()
les indices des entrées non nulles de cette nouvelle matrice.Essayez-le en ligne!
la convolution est la clé du succès.
la source
Wolfram Language (Mathematica) , 42 octets
Essayez-le en ligne!
1-indexé (qui suit la convention de Mathematica pour l'indexation). Prend l'entrée comme
{x,y}, {m,n}
.pour les E / S indexées 0, 45 octets :
Essayez-le en ligne!
la source
JavaScript (ES6), 74 octets
Approche ennuyeuse.
Essayez-le en ligne!
JavaScript (Node.js) , 74 octets
Moins ennuyeux mais tout aussi long. Prend l'entrée comme
([h,w,x,y])
.Essayez-le en ligne!
JavaScript (V8) , 67 octets
Si toutes les méthodes de sortie standard étaient autorisées, nous pourrions simplement imprimer les coordonnées valides avec:
Essayez-le en ligne!
la source
Gelée ,
1312 octetsUn lien dyadique acceptant une liste de deux (0 indexées) entiers sur la gauche,
[row, column]
et deux entiers sur le côté droit[height, width]
, ce qui donne une liste de listes de nombres entiers,[[adjacent_row_1, adjacent_column_1], ...]
.Essayez-le en ligne!
Comment?
la source
ḶṚƬ
parṬ€
.2ḶṚƬNƬẎ
renvoie[[0, 1], [1, 0], [0, -1], [-1, 0]]
, tandis que2Ṭ€NƬẎ
renvoie[[1], [0, 1], [-1], [0, -1]]
, et, puisque les singletons sont enveloppés,+
ne vectorise qu'avec le premier élément de⁸
pour ceux-ci, ils agissent donc comme si leur deuxième élément était0
(l'identité additive). Par conséquent, seul l'ordre de la sortie peut changer.Perl 6 ,
5649 octets-7 octets grâce à nwellnhof!
Essayez-le en ligne!
Supprime les éléments hors limites en vérifiant si, lorsqu'il est divisé par les limites du tableau, il est compris entre 0 et 1. Prend l'entrée et la sortie via des nombres complexes où la partie réelle est la
x
coordonnée et l'imaginaire est lay
. Vous pouvez les extraire via les fonctions.im
et.re
.la source
div
cela ne semble pas fonctionner pourNum
s(*.reals>>.Int Zdiv@^b).none
ou(*.reals Z/@^b)>>.Int.none
fonctionnerait mais l'Int-cast semble trop coûteux.J ,
302928 octetsEssayez-le en ligne!
Comment:
m
xn
arg en une grille de nombres complexesj./&i./
j./
1=|@-
#~&,
+.@
la source
C # (Visual C # Interactive Compiler) , 91 octets
Essayez-le en ligne!
Alternativement:
Essayez-le en ligne!
la source
Fusain , 29 octets
Essayez-le en ligne! Le lien est vers la version détaillée du code. Prend les entrées dans l'ordre x, y, largeur, hauteur. Explication:
Imprimez un
#
à l'emplacement prévu.Faites une boucle sur le rectangle donné.
Aller à la position actuelle.
S'il y a un adjacent,
#
enregistrez la position.Sortez les positions découvertes à la fin de la boucle.
Réponse ennuyeuse:
Essayez-le en ligne! Le lien est vers la version détaillée du code. Fonctionne en trouvant mathématiquement les positions adjacentes.
la source
Haskell, 62 octets
En utilisant
Essayez-le en ligne!
Approche ennuyeuse: 81 octets
la source