Czy mrówka może przeliterować słowa, chodząc po kostce?

10

Napisz funkcję, która przyjmuje dwa parametry: dodatnią liczbę całkowitą n i listę słów.

Biorąc pod uwagę sześcian n -przez- n -przez- n jednostek, przypisz losową literę (AZ) do każdej jednostki powierzchni. (W przypadku kostki 3x3x3 na każdej powierzchni będzie 9 jednostek powierzchni).

Następnie ustal, czy mrówka idąca po powierzchni (z możliwością krzyżowania twarzy) może przeliterować każde z podanych słów. Załóżmy, że aby przeliterować słowo, litery muszą znajdować się obok siebie w górę / w dół lub w lewo / w prawo, ale niekoniecznie na tej samej twarzy. [ Edytuj, dla jasności: Mrówka może odwrócić swoją ścieżkę i używać liter więcej niż jeden raz. Każda jednostka powierzchni liczy się jako jeden znak, więc aby przeliterować słowo powtarzającymi się literami (np. „Patrz”), mrówka musiałaby odwiedzić trzy sąsiednie jednostki.]

Funkcja powinna generować dwie rzeczy:

1) Każda z liter na każdej twarzy, w taki sposób, aby można było wywnioskować topologię. Na przykład dla kostki 2x2x2 akceptowalny wynik wygląda następująco:

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

2) Każde ze słów wraz z logiczną logiką określającą, czy mrówka może przeliterować słowo, idąc po powierzchni sześcianu. Na przykład:

1 ask
0 practical
1 pure
0 full

Bonusowe wyzwanie (nie będzie brane pod uwagę w ocenie, tylko dla zabawy): Zamiast n reprezentującego tylko rozmiar sześcianu, niech n reprezentuje również wymiar kształtu. Zatem n 2 będzie dawać kwadrat 2x2; an n 3 dałoby sześcian 3x3x3; a n n 4 dałoby wynik działania 4x4x4x4.

jawns317
źródło
1
Myślę, że musisz podać dodatkową specyfikację, w jaki sposób sześcian powinien być wyprowadzany. Na przykład, czy wszystkie litery mogą znajdować się w jednej linii, pod warunkiem, że zawsze wiemy, jak powinny być ułożone?
Klamka
1
Dopóki można wywnioskować topologię, nie chcę nakładać żadnych dodatkowych ograniczeń na sposób wyświetlania liter. Mój wielowierszowy przykład w opisie był raczej ilustracyjny niż opisowy.
jawns317
3
Wygląda na to, że mrówka może zmienić kierunek; należy to wyraźnie zaznaczyć. Czy potrafi wykonać obrót o 180 stopni i czy może użyć tej samej litery dwa razy z rzędu? Innymi słowy, czy możesz znaleźć qwqlub qqw przykładowej kostce?
Zgarb,
3
Ponadto, czy mrówka może użyć litery więcej niż raz?
lirtosiast,
1
Jakie są zasady dystrybucji losowych liter? Twój przykład nie pokazuje powtarzających się liter, ale z prostym algorytmem, w którym każda litera jest wybierana niezależnie z 26 możliwości, prawdopodobieństwo zerowego powtórzenia jest bardzo mało prawdopodobne. Oczywiście przy N> 2 trzeba będzie powtórzyć. Powinieneś to sprecyzować, na wypadek, gdyby ktoś spróbował kostki z tylko dwiema różnymi literami rozmieszczonymi losowo na całej kostce.
Level River St

Odpowiedzi:

3

Rubinowy, 272 bajtów

Dwie niepotrzebne nowe znaki są dodawane do kodu po obu stronach funkcji zagnieżdżonej, gaby poprawić czytelność. Są one wyłączone z wyniku. Znaki f=przypisujące funkcję anonimową do zmiennej są również wykluczone.

Format wyjściowy to 0lub 1na pytanie zamiast natywnego truei Ruby false. Nowa linia (zamiast spacji) służy do oddzielenia wartości logicznej i słowa. Rozumiem, że jest to akceptowalna interpretacja wymagań wyjściowych, ale jeśli nie, wpływ na liczbę bajtów byłby niewielki.

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}}

Wynik

Po około 50 takich połączeniach:

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

W końcu otrzymałem następujący wynik z 2 trafieniami. ANTjest w prawym dolnym rogu i idzie w górę, i ANjest udostępniany przez CAN, z Crundy owijania do góry po lewej stronie.

....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

Wyjaśnienie

Konkretne rozwinięcie wybranego sześcianu zostało wybrane częściowo ze względu na łatwość rysowania, ale głównie ze względu na łatwość wyszukiwania.

Znaki inne niż alfabet (kropki plus znak nowej linii na końcu każdej linii) są ważną częścią pola, na którym mrówka może chodzić.

Wyszukiwanie jest wykonywane przez funkcję rekurencyjną g, która jest zagnieżdżona w funkcji f. Jeśli przekazane słowo jest pustym ciągiem, wyszukiwanie jest zakończone i $rustawione na 1. Jeśli mrówka znajduje się na kwadracie, który odpowiada pierwszej literze słowa, wyszukiwanie jest kontynuowane we wszystkich czterech kierunkach: funkcja jest wywoływana ponownie ze słowem skróconym przez usunięcie pierwszej litery. W takim przypadku parametr kierunku jest ignorowany. Przenoszenie odbywa się poprzez rekurencyjne wywoływanie z indeksem komórki zmienionym o wartości w x.Wynik dodawania jest brany modulo do wielkości siatki plus dodatkowa połowa linii. Oznacza to, że dolna linia zawija się do góry i odwrotnie, z prawidłowym przesunięciem w poziomie.

Jeśli mrówka znajduje się na kwadracie innym niż litera, musi poruszać się zygzakiem po schodach, aż znajdzie kwadrat z literą. Będzie zygzakiem w kierunku południowo-wschodnim lub północno-zachodnim. Jest to symulowane przez wywołania rekurencyjne z dparametrem XORed z 1 za każdym razem, aby śledzić jej ruch. Dopóki nie dojdzie do kwadratu z następną literą, słowo wejściowe nie ulega skróceniu. Dogodnie można tego dokonać za pomocą tej samej rekurencji, co w przypadku wyszukiwania w obszarze z literami. Różnica polega na tym, że rekursja ma tylko jedną gałąź, gdy mrówka znajduje się w obszarze białych znaków, a nie 4 w obszarze litery.

Skomentowany kod

->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
}
Level River St
źródło