Allineamento su griglie triangolari


18

Le griglie esagonali sono diventate recentemente una svolta abbastanza popolare per le sfide relative ai dati bidimensionali. Tuttavia, sembra che finora le altrettanto interessanti griglie triangolari siano state in gran parte trascurate. Vorrei correggerlo con una sfida piuttosto semplice.

Innanzitutto, come possiamo rappresentare una griglia triangolare? Considera il seguente esempio (ignora il diagramma giusto per ora):

inserisci qui la descrizione dell'immagine inserisci qui la descrizione dell'immagine

Le celle cadono ordinatamente su una griglia regolare (la differenza rispetto a una griglia normale è solo le celle considerate adiacenti):

1234567
89abcde
fghijkl
mnopqrs

Ora, come mostra il diagramma a destra, una griglia triangolare ha tre assi principali: uno orizzontale e due diagonali.

Evidenziando questi nella griglia ASCII:

AVAVAVA
VAabcAV
fVAiAVl
mnVAVrs

La sfida

Ti viene data una stringa rettangolare che rappresenta una griglia triangolare (dove l'angolo in alto a sinistra è un triangolo rivolto verso l'alto). La maggior parte delle celle sarà ., ma esattamente due celle saranno #, ad esempio:

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

Determina se i due #sono allineati lungo uno dei tre assi della griglia (ovvero se si trovano su una singola riga in una delle tre direzioni evidenziate sopra). Per questo esempio, la risposta è "no".

È possibile scrivere un programma o una funzione, prendendo l'input tramite STDIN (o l'alternativa più vicina), l'argomento della riga di comando o l'argomento della funzione e producendo il risultato tramite STDOUT (o l'alternativa più vicina), il valore di ritorno della funzione o il parametro della funzione (out).

L'input può essere una singola stringa delimitata da avanzamenti di riga o altri caratteri utili o un elenco di stringhe. È possibile utilizzare due caratteri ASCII stampabili (coerenti) al posto di .e #.

L'output dovrebbe essere un valore veritiero se le celle evidenziate sono allineate e un valore errato in caso contrario.

Si applicano le regole standard del .

Casi test

Griglie sincere:

.#..#.

#
#

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

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

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

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

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

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

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

Griglie Falsy:

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

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

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

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

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

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

Risposte:


3

Lumache , 40 39 byte

\#{z|=(ul.ul.`,l~a~)(l.a3|.a|d.ea5}.,\#
\# ,, incontro '#'
{
  z | ,, O girare in qualsiasi direzione ottinilare o fare tutte le altre cose prima del}
  = (,, Se questa affermazione ha esito positivo, la cella iniziale è un "triangolo rivolto verso l'alto"
    ul.ul.```, vai su una cella verso l'alto o a sinistra due volte, un numero qualsiasi di volte.
              ,, Questo avrebbe dovuto essere più corto di un byte con ul`2 o ul`2 +? ma
              ,, l'analisi di `è buggy.
    l ~ a ~ ,, Verifica che siamo nella cella in alto a sinistra abbinando i limiti fuori campo a sinistra e poi a nord-est
  )
  (l.a3 | ,, Spostati a sinistra una volta, quindi imposta la direzione verso nord-ovest; oppure
    .a | ,, Spostati a destra (la direzione iniziale) una volta, quindi imposta la direzione verso nord-est; o
    d.ea5 ,, scorri verso il basso una volta, quindi imposta la direzione verso nord-ovest o nord-est
}
. ,, Corrisponde a qualsiasi numero di caratteri arbitrari (muovendosi nella direzione corrente)
\# ,, incontro '#'

2

CJam, 47 byte

Bene, ora che esiste una soluzione più breve, non mi sento più male a condividere la mia. :) (Principalmente per dimostrare che ciò non è particolarmente difficile, anche se non si dispone di un linguaggio di corrispondenza dei motivi 2D ...)

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

Questo utilizza spazi al posto di #e davvero qualsiasi altra cosa per ..

Esegui tutti i casi di test online.

Odio davvero la duplicazione, P::+Xf|P::-Xf|ma finora non ho trovato nulla per liberarmene.

Spiegazione

Non continuare a leggere se vuoi trovare una soluzione per te stesso.

Innanzitutto, la parte noiosa: ottenere le due coppie di coordinate dei due spazi nella griglia di input:

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.

Ora la parte interessante è come determinare se tali coordinate sono allineate o meno. Il mio codice calcola separatamente tutti e tre gli assi:

  • L'asse orizzontale è banale. Controlla se le coordinate verticali corrispondono.
  • Diamo un'occhiata alla diagonale nord-est. Nella griglia ASCII, ci sono sempre due antidiagonali che appartengono a ciascuna diagonale tri-griglia:

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

    Possiamo identificare l'antidiagonale corrente sommando le coordinate xe y:

    01234567
    12345678
    23456789
    

    Quindi vorremmo 0e 1appartenere alla stessa diagonale, così come 2e 3, 4e 5e così via. Ciò significa che, una volta ottenuto il nostro indice anti-diagonale, vogliamo arrotondare al numero dispari successivo. In altre parole, prendiamo l'OR bit a bit con 1. (Potremmo anche arrotondare al prossimo numero pari per AND bit a bit -2ma è più costoso nel codice.)

  • Ora le diagonali sud-orientali:

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

    Per dare un indice diagonali, si sottrae il xdalle ycoordinate (che rappresentano i numeri negativi come lettere):

    0abcdefg
    10abcdef
    210abcde
    

    In questo caso, vorremmo 0e 1apparteniamo alla stessa diagonale, così come -1e -2, oe 2e 3. Quindi, ancora una volta, vogliamo arrotondare al prossimo numero dispari.

Ecco il codice per questo:

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.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.