Alignement sur les grilles triangulaires

18

Récemment, les grilles hexagonales sont devenues une variante assez populaire des défis concernant les données bidimensionnelles. Cependant, il semble que les grilles triangulaires tout aussi intéressantes aient été largement négligées jusqu'à présent. Je voudrais rectifier cela avec un défi assez simple.

Tout d'abord, comment représenter une grille triangulaire? Prenons l'exemple suivant (ignorez le bon diagramme pour l'instant):

entrez la description de l'image ici entrez la description de l'image ici

Les cellules tombent proprement sur une grille régulière (la différence avec une grille régulière étant uniquement les cellules considérées comme adjacentes):

1234567
89abcde
fghijkl
mnopqrs

Maintenant, comme le montre le diagramme de droite, une grille triangulaire a trois axes principaux: un horizontal et deux diagonaux.

Soulignant ces derniers dans la grille ASCII:

AVAVAVA
VAabcAV
fVAiAVl
mnVAVrs

Le défi

Vous obtenez une chaîne rectangulaire représentant une grille triangulaire (où le coin supérieur gauche est un triangle pointant vers le haut). La plupart des cellules avec be ., mais exactement deux cellules seront #, par exemple:

....#
.#...
.....

Déterminez si les deux #sont alignés le long de l'un des trois axes de la grille (c'est-à-dire s'ils se trouvent sur une seule ligne dans l'une des trois directions mises en évidence ci-dessus). Pour cet exemple, la réponse est "non".

Vous pouvez écrire un programme ou une fonction, en prenant une entrée via STDIN (ou l'alternative la plus proche), un argument de ligne de commande ou un argument de fonction et en sortant le résultat via STDOUT (ou l'alternative la plus proche), la valeur de retour de la fonction ou le paramètre de la fonction (out).

L'entrée peut être une chaîne unique délimitée par des sauts de ligne ou un autre caractère pratique, ou une liste de chaînes. Vous pouvez utiliser deux caractères ASCII imprimables (cohérents) à la place de .et #.

La sortie doit être une valeur véridique si les cellules en surbrillance sont alignées et une valeur fausse dans le cas contraire.

Les règles de standard s'appliquent.

Cas de test

Véritables grilles:

.#..#.

#
#

...........
...#.......
...........
...........
...........
.......#...
...........

...........
.......#...
...........
...........
...........
...#.......
...........

.#.........
...........
...........
...........
...........
.......#...
...........

...........
...#.......
...........
...........
...........
...........
.......#...

.........#.
...........
...........
...........
...........
...#.......
...........

...........
.......#...
...........
...........
...........
...........
...#.......

...........
.#.....#...
...........
...........
...........

Grilles de falsification:

#.....
.....#

.....#
#.....

...#.......
...........
...........
...........
...........
.......#...
...........

...........
...#.......
...........
...........
...........
...........
.........#.

.......#...
...........
...........
...........
...........
...#.......
...........

...........
.......#...
...........
...........
...........
...........
.#.........
Martin Ender
la source

Réponses:

3

Escargots , 40 39 octets

\#{z|=(ul.ul.`,l~a~)(l.a3|.a|d.ea5}.,\#
\# ,, rencontre '#'
{
  z | ,, Soit tournez dans n'importe quelle direction octinilaire, soit faites toutes les autres choses avant}
  = (,, Si cette assertion réussit, la cellule de départ est un "triangle pointant vers le haut"
    ul.ul.`, ,, Montez une cellule vers le haut ou vers la gauche deux fois, autant de fois que vous le souhaitez.
              ,, Cela aurait dû être un octet plus court avec ul.`2, ou ul.`2 +? mais
              ,, l'analyse de `est boguée.
    l ~ a ~ ,, Vérifiez que nous sommes sur la cellule en haut à gauche en faisant correspondre les limites à gauche puis au nord-est
  )
  (l.a3 | ,, Déplacez-vous une fois vers la gauche, puis définissez la direction vers le nord-ouest; ou
    .a | ,, Déplacez-vous une fois vers la droite (la direction initiale), puis définissez la direction vers le nord-est; ou
    d.ea5 ,, Descendez une fois, puis définissez la direction au nord-ouest ou au nord-est
}
., ,, Correspond à n'importe quel nombre de caractères arbitraires (se déplaçant dans la direction actuelle)
\# ,, rencontre '#'
feersum
la source
2

CJam, 47 octets

Eh bien, maintenant qu'il existe une solution plus courte, je ne me sens plus mal de partager la mienne. :) (Surtout pour montrer que ce n'est pas particulièrement difficile, même si vous n'avez pas de langage de correspondance de motifs 2D ...)

qN%:eeee::f+:~{S&},2f<:P0f=P::+Xf|P::-Xf|]::=:|

Cela utilise des espaces à la place de #et vraiment n'importe quoi d'autre pour ..

Exécutez tous les cas de test en ligne.

Je déteste vraiment la duplication P::+Xf|P::-Xf|mais jusqu'à présent, je n'ai rien trouvé pour m'en débarrasser.

Explication

Ne continuez pas à lire si vous voulez trouver une solution pour vous-même.

Tout d'abord, la partie ennuyeuse: obtenir les deux paires de coordonnées des deux espaces dans la grille d'entrée:

qN%   e# Read input and split into lines.
:ee   e# Enumerate the characters in each line. I.e. turn each character 'x into a pair
      e# [N 'x] where N is its horizontal 0-based index.
ee    e# Enumerate the lines themselves, turning each line [...] into [M [...]] where M
      e# is its vertical 0-based index.
::f+  e# This distributes the vertical index over the individual lines, by prepending it
      e# to each pair in that line. So now we've got a 2-D array, where each character 'x
      e# has been turned into [M N 'x].
:~    e# Flatten the outermost dimension, so that we have a flat list of characters with
      e# their coordinates.
{S&}, e# Filter only those lists that contain a space.
2f<   e# Truncate the two results to only their first two elements.
:P    e# Store the result in P.

Maintenant, la partie intéressante est de savoir si ces coordonnées sont alignées ou non. Mon code calcule les trois axes séparément:

  • L'axe horizontal est trivial. Vérifiez si les coordonnées verticales correspondent.
  • Regardons la diagonale nord-est. Dans la grille ASCII, il y a toujours deux antidiagonales qui appartiennent à chaque diagonale tri-grille:

    ....AV..
    ...AV...
    ..AV....
    

    Nous pouvons identifier l'antidiagonale actuelle en additionnant les coordonnées xet y:

    01234567
    12345678
    23456789
    

    Nous voudrions donc 0et 1appartenir à la même diagonale, ainsi que 2et 3, 4et 5et ainsi de suite. Cela signifie qu'une fois que nous avons notre indice anti-diagonal, nous voulons arrondir au prochain nombre impair. En d'autres termes, nous prenons le OR au niveau du bit avec 1. (Nous pourrions également arrondir au nombre pair suivant par ET au niveau du bit avec -2mais c'est plus cher en code.)

  • Maintenant les diagonales sud-est:

    .VA.....
    ..VA....
    ...VA...
    

    Afin de donner un indice aux diagonales, nous soustrayons la xde la ycoordonnée (représentant les nombres négatifs sous forme de lettres):

    0abcdefg
    10abcdef
    210abcde
    

    Dans ce cas, nous voulons 0et 1appartenir à la même diagonale, ainsi que -1et -2, ou 2et 3. Donc, encore une fois, nous voulons arrondir au prochain nombre impair.

Voici le code pour cela:

0f=  e# The coordinates are still on the stack. Replace each with its vertical coordinate
     e# to check for the horizontal axis.
P    e# Push the coordinates again.
::+  e# Sum each pair to get an anti-diagonal index.
Xf|  e# OR each index with 1 to round up to the next odd number.
P    e# Push the coordinates again.
::-  e# In each pair, subtract the horizontal coordinate from the vertical, to
     e# get a diagonal index.
Xf|  e# OR each index with 1.
]    e# Wrap all three index pairs in an array.
::=  e# Check equality for each pair.
:|   e# Fold bitwise OR over the results to check if at least one pair of indices
     e# was equal.
Martin Ender
la source