Una formica può pronunciare parole camminando sul cubo?


10

Scrivi una funzione che accetta due parametri: un numero intero positivo n e un elenco di parole.

Dato un cubo di n -by- n -by- n unità, assegnare una lettera casuale (AZ) a ciascuna unità di superficie. (Per un cubo 3x3x3, ci sarebbero 9 unità di superficie su ogni faccia.)

Quindi determinare se è possibile per una formica che cammina lungo la superficie (con la capacità di incrociare le facce) di scrivere ciascuna delle parole fornite. Supponiamo che per scrivere una parola, le lettere debbano essere su / giù o sinistra / destra adiacenti, ma non necessariamente sulla stessa faccia. [ Modifica, per chiarezza: la formica può invertire il suo percorso e usare le lettere più di una volta. Ogni unità di superficie conta come un carattere, quindi per scrivere una parola con lettere ripetute (ad esempio "vedi") la formica dovrebbe visitare tre unità adiacenti.]

La funzione dovrebbe produrre due cose:

1) Ciascuna delle lettere su ciascuna faccia, in modo tale che la topologia possa essere dedotta. Ad esempio, per un cubo 2x2x2, un output accettabile sarebbe simile a:

   QW
   ER
TY OP UI
DF JK XC
   AS
   GH
   LZ
   VB

2) Ciascuna delle parole, insieme a un booleano che rappresenta se è possibile per la formica pronunciare la parola camminando lungo la superficie del cubo. Per esempio:

1 ask
0 practical
1 pure
0 full

Sfida bonus (non prenderà in considerazione il punteggio, solo per divertimento): Invece di n che rappresenta solo la dimensione del cubo, n rappresenta anche la dimensionalità della forma. Quindi, una n di 2 produrrebbe un quadrato di 2x2; una n di 3 produrrebbe un cubo 3x3x3; e una n di 4 produrrebbe un tesseract 4x4x4x4.


1
Penso che sia necessario fornire ulteriori specifiche su come dovrebbe essere prodotto il cubo. Ad esempio, tutte le lettere possono essere su una riga, purché sappiamo sempre come dovrebbero essere organizzate?
Maniglia della porta

1
Finché la topologia può essere dedotta, non voglio porre ulteriori limiti sul modo in cui le lettere vengono stampate. Il mio esempio multilinea nella descrizione era illustrativo, piuttosto che proscriptivo.
Jawns317,

3
Sembra che la formica sia in grado di cambiare direzione; questo dovrebbe essere dichiarato esplicitamente. Può fare una virata di 180 gradi e può usare la stessa lettera due volte di seguito? In altre parole, puoi trovare qwqo qqnel cubo di esempio?
Zgarb,

3
Inoltre, la formica può usare una lettera più di una volta?
lirtosiast,

1
Quali sono le regole per la distribuzione delle lettere casuali? Il tuo esempio non mostra lettere ripetute, ma con un semplice algoritmo in cui ogni lettera viene scelta indipendentemente da 26 possibilità, è altamente improbabile che si ripetano zero ripetizioni. Ovviamente con N> 2 ci dovranno essere ripetizioni. Dovresti specificarlo più chiaramente, nel caso in cui qualcuno provi un cubo con solo due lettere diverse distribuite casualmente sull'intero cubo.
Level River St,

Risposte:


3

Rubino, 272 byte

Due righe inutili vengono aggiunte al codice ai lati della funzione nidificata gper migliorare la leggibilità. Questi sono esclusi dal punteggio. f=Sono esclusi anche i caratteri che assegnano la funzione anonima a una variabile.

Il formato di output è 0o in 1base alla domanda anziché al nativo di Ruby truee false. Una nuova riga (anziché uno spazio) viene utilizzata per separare il booleano e la parola. La mia comprensione è che questa è un'interpretazione accettabile dei requisiti di output, ma in caso contrario, l'impatto sul conteggio dei byte sarebbe minore.

f=->n,l{c=''
x=[p=6*n,1,-p,-1]
(m=3*p*n).times{|i|c<<(5+i/n%6-i/n/p&6==6?65+rand(26):i%p==p-1?10:46)}
q=m+3*n
puts c

g=->w,i,d{w==''?$r=1:c[i]<?A?g[w,(i+x[d])%q,d^1]:w[0]==c[i]&&4.times{|j|g[w[1..-1],(i+x[j])%q,j^1]}}

l.each{|w|$r=0
m.times{|i|c[i]>?@&&g[w,i,0]}
puts $r,w}}

Produzione

Dopo circa 50 chiamate in questo modo:

f[4,['PPCG','CODE','GOLF','ANT','CAN','CUBE','WORD','WALK','SPELL']]

Alla fine ho ottenuto il seguente output con 2 hit. ANTè in basso a destra andando verso l'alto, e ANè condiviso da CAN, con il Cgiro avvolgente in alto a sinistra.

....KCAAXRHT...........
....ALRZXRKL...........
....NDDLCMCT...........
....ETQZHXQF...........
........FYYUSRZX.......
........CFNPAUVX.......
........ZTJVHZVQ.......
........AUWKGVMC.......
............XWKSDWVZ...
............DPLUVTZF...
............DMFJINRJ...
............ZRXJIAFT...
0
PPCG
0
CODE
0
GOLF
1
ANT
1
CAN
0
CUBE
0
WORD
0
WALK
0
SPELL

Spiegazione

Il particolare sviluppo del cubo selezionato, è stato scelto in parte per la sua facilità di disegno, ma principalmente per la sua facilità di ricerca.

I caratteri non alfabetici (i punti più la nuova riga alla fine di ogni riga) sono una parte importante del campo in cui si trova la formica che cammina.

La ricerca viene eseguita dalla funzione ricorsiva g, che è nidificata nella funzione f. Se la parola passata è una stringa vuota la ricerca è completa ed $rè impostata su 1. Se la formica si trova su un quadrato di lettere che corrisponde alla prima lettera della parola, la ricerca continua in tutte e quattro le direzioni: la funzione viene richiamata di nuovo con la parola abbreviata rimuovendo la sua prima lettera. In questo caso il parametro direction è ignorato. Lo spostamento viene effettuato chiamando ricorsivamente con l'indice della cella modificato dai valori in x.Il risultato dell'aggiunta viene preso come modulo della dimensione della griglia più una mezza linea aggiuntiva. Ciò significa che la linea di fondo si avvolge verso l'alto e viceversa, con l'offset orizzontale corretto.

Se la formica si trova su un quadrato senza lettere, deve zigzagare con un movimento di scala finché non trova un quadrato di lettere. Zizag andrà in direzione sud-est o nord-ovest. Questo è simulato da chiamate ricorsive con il dparametro XORed con 1 ogni volta per tenere traccia del suo movimento. Fino a quando non raggiunge la lettera successiva, non c'è accorciamento della parola di input. Convenientemente, questo può essere fatto con la stessa ricorsione usata quando stiamo cercando nell'area con le lettere. La differenza è che la ricorsione ha un solo ramo quando la formica si trova nell'area degli spazi bianchi, invece di 4 nell'area delle lettere.

Codice commentato

->n,l{                                   #n=square size, l=list of words to search
  c=''                                   #empty grid
  x=[p=6*n,1,-p,-1]                      #offsets for south, east, north, west. p is also number of characters per line
  (m=3*p*n).times{|i|                    #m=total cells in grid. for each cell
    c<<(5+i/n%6-i/n/p&6==6?              #apppend to c (according to the formula)
      65+rand(26):                       #either a random letter
      i%p==p-1?10:46)                    #or a "whitespace character" (newline, ASCII 10 or period, ASCII 46)
  }
  q=m+3*n                                #offset for vertical wraparound = grid size plus half a row.                           
  puts c                                 #print grid

  g=->w,i,d{                             #search function. w=word to search for, i=start index in grid, d=direction
    w==''?                               #if length zero, already found,
      $r=1:                              #so set flag to 1. Else
      c[i]<?A?                           #if grid cell is not a letter
        g[w,(i+x[d])%q,d^1]:             #recursively call from the cell in front, with the direction reflected in NW-SE axis
        w[0]==c[i]&&                     #else if the letter on the grid cell matches the start of the word
          4.times{|j|                    #for each direction (iterate 4 times, each time a different direction is "in front")
            g[w[1..-1],(i+x[j])%q,j^1]}  #recursively call from the cell in front. Chop first letter off word. 
   }                                       #Direction parameter is XORed (reflected in NW-SE axis) in case ant hits whitespace and has to zigzag.

   l.each{|w|                            #for each word in the list
     $r=0                                #set global variable $r to zero to act as a flag
     m.times{|i|c[i]>?@&&g[w,i,0]}       #call g from all cells in the grid that contain a letter 
     puts $r,w}                          #output flag value and word
}
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.