Steht dieses Wort auf der Pinnwand?

38

Einführung

Nachdem Sie einen Tag lang getrunken und die Weltmeisterschaft beobachtet haben, setzen Sie sich, um ein Freundschaftsspiel zu spielen. Die Stimmung steigt, weil Sie beschuldigt werden, Zeit mit unsinnigen Worten zu verschwenden, die nicht einmal auf dem Brett stehen! Möglicherweise sehen Sie doppelt, aber Sie denken sicherlich klar genug, um ein Programm zu schreiben, das überprüft, ob Ihre Worte auf der Tafel stehen.

Deine Aufgabe

Schreiben Sie ein Programm, ein Skript oder eine Funktion, die eine Boggle-Tafel und ein Wort als Eingabe verwendet und True zurückgibt, wenn sich das Wort auf der Tafel befindet, und False, wenn das Wort nicht auf der Tafel steht.

Die Eingabe erfolgt in Form von sechs getrennten \nZeilen. Die ersten fünf Zeilen bestehen aus dem 5x5-Block und enthalten jeweils fünf Großbuchstaben. Die sechste Zeile enthält das betreffende Wort, auch in Großbuchstaben.

Beispieleingabe:

AJNES
TNFTR
LSAIL
UDNEX
EQGMM
DAFTER

Die Ausgabe kann alles sein, was in der Programmiersprache Ihrer Wahl eindeutig "Wahr" oder "Falsch" bedeutet und die Standardkonventionen "Null", "Null" und "Leer" für "Falsch" einhält.

Beispielausgabe für obige Eingabe:

1

I / O-Richtlinien

  • Die Eingabe kann von stdin gelesen und die Ausgabe auf stdout beantwortet werden.

Oder

  • Die Eingabe kann ein einzelnes Zeichenfolgenargument für eine Funktion sein und answer der Rückgabewert dieser Funktion.

Boggle-Regeln

  • Ein Wort ist 'auf dem Brett', wenn Sie das Wort über einen Pfad aufeinanderfolgender, benachbarter, sich nicht wiederholender Kacheln auf dem Brett konstruieren können.
  • Eine Kachel wird neben den acht Kacheln betrachtet, die sie umgeben (diagonale Pfade sind zulässig). Die Kacheln am Rand der Tafel grenzen an nur fünf Kacheln. Fliesen in der Ecke grenzen an nur drei.
  • Aufeinanderfolgende Buchstaben im Wort müssen nebeneinander stehen, der ith Buchstabe im Wort muss neben dem i-1th und i+1th stehen.
  • Ein Buchstabe kann in einem Wort mehr als einmal vorkommen, Sie können jedoch nicht mehr als einmal pro Wort dasselbe Quadrat auf der Schalttafel verwenden.
  • Die online boggle Seite wordsplay.net kann nützlich sein, wenn Sie noch nie boggle gespielt haben, aber ein Gefühl für diese Regeln bekommen möchten.

Im Gegensatz zu normalen Boggle:

  • Sie müssen sich NICHT darum sorgen, dass das Wort ein gültiges englisches Wort ist.
  • Es wird KEINE Queinzelne Fliese geben.
  • Das fragliche Wort kann eine beliebige Länge> 0 haben

Beispiel

Im Vorstand von

AJNES
TNFTR
LSAIL
UDNEX
EQGMM

Diese Wörter sollten True zurückgeben: FATE, DATING, STANDS, LIFTS.

Diese Wörter sollten False zurückgeben: SADDEN, SULTANS, EXIST, SUEDE, QUEST

Dies ist eine Code-Golf-Herausforderung, also gewinnt der kürzeste Code!

turbulencetoo
quelle
Wickelt sich das Board? Ich kann mich nicht erinnern
Claudiu
Nein, es schließt nicht, ich habe die Klarstellung über die Nachbarschaft aktualisiert, um dies zu reflektieren.
turbulencetoo
Kann sich der Weg diagonal kreuzen?
Martin Ender
@ m.buettner Yep
turbulencetoo
Boggle ist normalerweise ein 4x4-Board.
mbomb007

Antworten:

11

GolfScript, 74 Zeichen

:^n%5>)]){{^@==}+29,\,{{+}+1$/}%\;}/{:s$..&=[s{.@-\}*;]1567`{7&.~)}%-!&},,

Die Eingabe muss auf STDIN erfolgen. Gibt die Anzahl der gültigen Pfade auf der Karte aus, dh 0für keine und für eine positive Zahl (true).

Sie können das Beispiel online testen .

Code mit einigen Kommentaren:

:^              # assign the input to variable ^
n%              # split at newlines
5>              # truncate array such that [WORD] remains
)])             # prepares [[]] and WORD on the stack

# the following loop generates all possible paths (valid and invalid ones)
# by looking up all index combinations which yield the correct word
{               # loop over all characters
  {^@==}+29,\,  # get all indices of current character in the board
  {{+}+1$/}%\;  # append any index to all lists in the result set
}/              # end loop

# filter the results list for valid paths
{               # {...}, -> apply filter
  :s            # save path to variable s
  $..&=         # check if all numbers in path are unique
  [s{.@-\}*;]   # calculate differences along the path
  1567`{7&.~)}% # generate the array [1 -1 5 -5 6 -6 7 -7] of valid
                # differences
  -!            # check if all differences were valid
  &             # are both conditions fulfilled?
},              # end of filter block

,               # count the number of remaining paths
Howard
quelle
12

Javascript (E6) 137 160 175 190

Weniger als 2 * Golfscript. Moralischer Sieg ...

F=a=>[...a].some((e,p,b)=>(Q=(p,n)=>p>29||b[p]!=b[n]||(b.r|=!b[++n])||(b[p]=b[n+~[1,5,6,7].map(q=>Q(p+q,n)|Q(p-q,n),b[p]=0)]))(p,30)&b.r)

Neuorganisation des Golf-Codes bearbeiten . Wieder und wieder

Ungolfed Letzte Version, etwas schwierig zu folgen

F = a => 
  [...a] // input string to array, 30 chars of board then the target word
  .some ( // use some to scan the board, return true when found
      (e,p,b)=> // params to callback: element, position, complete array 
      (         // NB array b has no .r property, so use it for return value (it's undefined at start) 
        Q = (p,n) =>         // Scan function, p=position in board, n=nth char of target word
          p > 29 ||          // Chaek if going outside the board to the target word
          b[p] != b[n] ||    // if invalid char at current position, return
          (b.r |= !b[++n]) ||  // if at end of target, set r to 1 and return (also increment n )
          (                  // else... (NB next tree lines are coalesced in golfed code)
            b[p] = 0,        // remove current char (to avoid reusing) 
            [1,5,6,7].map( q => Q(p+q,n)|Q(p-q,n)), // recursive call for + - 1,5,6,7
            b[p] = b[n-1]    // put current char into array again 
          )
      )(p,30) & b.r // initial position 0 in target word is 30 in the array
  ) 

Ungolfed Erste Version, sollte klarer sein

F = a => (
  b = a.split('\n'),
  w = b.pop(),
  r = 0,
  Q = (p, n) => 
    (r |= !w[n]) || 
    (
      b[p] = 0,
      [1,5,6,7,-1,-5,-6,-7].map( q => b[q+=p]==w[n] && Q(q,n+1)),
      b[p] = w[n-1]
    ),
  b = [...b+''],
  b.map((e, p) => e==w[0] && Q(p,1)),
  r
)

Verwendung

F("AJNES\nTNFTR\nLSAIL\nUDNEX\nEQGMM\nLIFTS\nDAFTER")

Prüfung

['DAFTER', 'STANDS', 'LIFTS', 'FATE', 'DATING' ,
 'SADDEN','SULTANS', 'EXIST', 'SUEDE', 'QUEST']
.map(w => [w, F("AJNES\nTNFTR\nLSAIL\nUDNEX\nEQGMM\n" +w)])

Ausgabe:

[["DAFTER", true], ["STANDS", true], ["LIFTS", true], ["FATE", true], ["DATING", true], 
["SADDEN", false], ["SULTANS", false], ["EXIST", false], ["SUEDE", false], ["QUEST", false]]
edc65
quelle
1
Einige kleinere Optimierungen:F=a=>(b=a.split('\n'),w=b.pop(Q=(p,n)=>((R|=!w[n])||(b[p]=0)||[1,5,6,7,-1,-5,-6,-7].map(q=>b[q+=p]==w[n]&&Q(q,n+1,b[q]=w[n])))),[Q(~~p,1)for(p in b=[...b.join(R=0)])if(b[p]==w[0])],R)
nderscore
Soll es w = a.pop()(Golf) oder w = b.pop()(ungolf, Linie 2) sein? (wahrscheinlich das letztere, denke ich)
hlt
@androyd Ich habe den älteren Code aus Gründen der Übersichtlichkeit nach der Umstrukturierung unbenutzt gelassen. Aber es ist nicht 100% synchron. Ich werde versuchen zu klären
edc65
Meine böse, hast nicht gesehen, dass du es geändert hast, a=a.pop()anstatt b=a.pop()...
hlt
4

Python, 207 204 203

g=raw_input
r=range
b=''.join(g()for _ in r(5))
w=g()
s=lambda b,w,i:0<=i<25and(not w or(b[i]==w[0])*any(s(b[:i]+'_'+b[i+1:],w[1:],i+j+k*5-6)for j in r(3)for k in r(3)))
print any(s(b,w,i)for i in r(25))

Durch Ersetzen ... (b[i]==w[0])*any ...durch wird ... b[i]==w[0]and any ...die Leistung auf Kosten von 2 Zeichen erheblich verbessert.

Pappschachtel
quelle
1
Sie können Leerzeichen entfernen, wenn sie zwischen Zahlen und Befehlen stehen. 0<=i<25and
Siehe auch
3

J - 75 Zeichen

Eugh, dieser sieht böse aus. Und nicht einmal mit Golfscript zu binden! Dies ist eine Funktion, deren einziges Argument ein String ist. Sie können ein beliebiges Trennzeichen mit einem Zeichen verwenden, solange es am Ende jeder Zeile steht, einschließlich des letzten.

+/@([:*/"1^:2(2(=*)@-/\>@~.)S:1)@{@(((<@#:i.)5 5)<@#~&,"2{:=/&:>}:)@(<;._2)

Eine Erklärung folgt. Beachten Sie, dass die Funktion in fünf verschiedene Teile der obersten Ebene unterteilt werden kann, die jeweils durch ein @Trennzeichen voneinander getrennt sind. Daher werden diese Teile von rechts nach links getrennt behandelt.

  • (<;._2)- Dies teilt die Zeilen in Zeilenumbrüche / Trennzeichen auf. Dabei wird das Zeichen am Ende der Zeichenfolge als das Zeichen verwendet, auf das aufgeteilt werden soll. Wir packen alles in Kästchen ( <), da wir sonst einige Auffüllprobleme bekommen, wenn J uns das Ergebnis zurückgibt.

  • (((<@#:i.)5 5)<@#~&,"2{:=/&:>}:) - Erstellen Sie für jeden Buchstaben im zu überprüfenden Wort eine Liste von Indizes in der Boggle-Tafel, in der sich dieser Buchstabe befindet.

    • {:ist das letzte geteilte Stück (das zu überprüfende Wort) und }:ist alles andere als das letzte (das Boggle-Brett).

    • &:>öffnet die Kästchen, die wir zuvor erstellt haben, mit dem nützlichen Nebenprodukt der Umwandlung }:in ein 2D-Array von Zeichen. =/Dann wird für jeden Buchstaben im Wort eine Kopie dieses Boggle-Boards erstellt und die Positionen in boolesche Werte umgewandelt, je nachdem, ob der Buchstabe im Board mit dem Buchstaben im Wort übereinstimmt.

    • ((<@#:i.)5 5)ist eine kurze Möglichkeit, ein 5x5-Array von Indizes auszudrücken. x#:yis konvertiert yin ein Array der Basisdarstellung x. (Na ja, fast. Die Wahrheit ist komplexer, aber das funktioniert für unsere Zwecke.)

    • <@#~&,"2- Sammeln Sie für die resultierende boolesche Matrix jedes Buchstabens alle entsprechend wahren Indizes zusammen. "2Lässt alles an den richtigen Ergebnissen arbeiten, #~&,führt die Auswahl durch und <@sammelt jedes Ergebnis in einer Box, um sich auf den nächsten Schritt vorzubereiten.

  • {- Dieses Verb, das monadisch verwendet wird, heißt Catalog und verwendet eine Liste von Feldern als Argument. Es kombiniert die Innenseiten jeder Box auf jede mögliche Weise. So würde zB ein Katalog auf einigen Feldern mit den Zeichenfolgen "AB" und "abc" die Ergebnisse "Aa", "Ab", "Ac", "Ba", "Bb", "Bc" ergeben.

    Wenn Sie dies in unserer Liste mit Indexlisten in der Box ausführen, können Sie alle möglichen Indexkombinationen erstellen. Dies kann eine große Menge sein, wenn das Wort lang ist und es viele wiederholte Buchstaben gibt, aber auch leer, wenn sich kein Buchstabe auf der Tafel befindet. Wir bemerken auch, dass wir Kacheln in einigen dieser Pfade wiederverwenden: Wir werden das später erklären.

  • ([:*/"1^:2(2(=*)@-/\>@~.)S:1) - Hier überprüfen wir jeden Pfad, um festzustellen, ob er gültig ist.

    • (...)S:1Wendet das (...)auf jeden Pfad an und sammelt die Ergebnisse in einer flachen Liste. Dies ist von entscheidender Bedeutung, da das Ergebnis {ein mehrdimensionales Array ist und wir uns nicht um die Struktur dieses Arrays kümmern, sondern nur um dessen Inhalt in jeder Box.

    • 2(=*)@-/\>Gibt eine 1, wenn jede Koordinate jedes Index höchstens eine von der darauf folgenden entfernt ist, und ansonsten eine 0. Die 2und die /\sind dafür paarweise verantwortlich.

    • */"1^:2logische UNDs diese alle zusammen am Ende. Das [:Teil ist eine strukturelle Sache in J, mach dir keine Sorgen.

    • Das Hinzufügen @~.zu >ist eine clevere Möglichkeit, Pfade mit wiederholten Eingaben auszuschließen. ~.Nimmt die eindeutigen Elemente einer Liste, so dass die Liste gekürzt wird, wenn sie sich selbst überschneidet, und kürzere Listen werden automatisch mit Nullen aufgefüllt, wenn sie zusammengesetzt werden, wie die Art und Weise, wie die Ergebnisse kombiniert werden, wenn sie herauskommen S:. Dies ist letztendlich kürzer als das explizite Ausschließen von sich überschneidenden Pfaden.

  • +/- Zum Schluss addieren wir einfach alles zusammen. Das Ergebnis ist die Anzahl der gültigen Pfade, die das Wort auf der Tafel ergeben, wobei 0 keine Pfade bedeutet, dh dieses Wort befindet sich nicht auf der Tafel. Für die Kosten eines Zeichens können wir +./stattdessen schreiben (alles logisch ODER-verknüpft), was explizit eine boolesche 1 oder 0 ergibt.

Hier sind einige Beispielläufe. Sie können den J-Interpreter unter jsoftware.com oder online unter tryj.tk herunterladen .

   NB. the  0 : 0 ... )  thing is how you do multiline strings in J
   +/@([:*/"1^:2(2(=*)@-/\>@~.)S:1)@{@(((<@#:i.)5 5)<@#~&,"2{:=/&:>}:)@(<;._2) 0 : 0
AJNES
TNFTR
LSAIL
UDNEX
EQGMM
DAFTER
)
1
   b =: +/@([:*/"1^:2(2(=*)@-/\>@~.)S:1)@{@(((<@#:i.)5 5)<@#~&,"2{:=/&:>}:)@(<;._2)
   b 'AJNES TNFTR LSAIL UDNEX EQGMM FATE '    NB. any separator will do
1
   b 'AJNES TNFTR LSAIL UDNEX EQGMM SADDEN '  NB. not on the board
0
   b 'AJNES TNFTR LSAIL UDNEX EQGMM SANDS '   NB. self-intersecting path
0
   b 'AJNES TNFTR LSAIL UDNEX EQGMM MEND '    NB. multiple paths
2
algorithmshark
quelle
1
+1 für die Details. Ich würde gerne mehr Antworten wie diese sehen!
edc65
2

Prolog - 315

r(L):-get_char(C),(C='\n',!,L=[];r(T),L=[C|T]).
b(0,[]):-!.
b(N,[R|T]):-M is N-1,r(R),b(M,T).
d(-1). d(0). d(1).
d([A,B],[C,D]):-d(X),C is A+X,d(Y),D is B+Y.
f([L|W],B,P,U):-P=[X,Y],nth(Y,B,R),nth(X,R,L),\+member(P,U),(W=[];d(P,Q),f(W,B,Q,[P|U])).
m:-b(5,B),r(W),f(W,B,_,[]),write(t);write(f).
:-initialization(m).

Ich dachte, dass Prolog eine gute Sprache für diese ist, mit der eingebauten Rückverfolgungsunterstützung, aber ich denke, es ist mehr behindert, wenn für fast jeden berechneten Wert eine Variable benötigt wird.

Getestet mit GNU Prolog; sollte mit ISO Prolog kompatibel sein.

Ungolfed:

get_line(Line) :-
    get_char(C),
    (   C='\n', !, Line=[]
    ;   get_line(Tail), Line=[C|Tail]
    ).

% The cut prevents recursion to help_get_board(-1, MoreRows)
% (and golfs one character shorter than putting N>0 in the second rule).
help_get_board(0, []) :- !.
help_get_board(N, [Row|Tail]) :-
    M is N-1, get_line(Row), help_get_board(M, Tail).

% The golfed version doesn't define an equivalent to get_board/1.
% help_get_board(5,Board) is used directly instead.
get_board(Board) :- help_get_board(5,Board).

small(-1). small(0). small(1).
step([X1,Y1],[X2,Y2]) :-
    small(DX), X2 is X1+DX,
    small(DY), Y2 is Y1+DY.

% The golfed version doesn't define an equivalent to letter_at/3.
% See find_word/4.
letter_at([X,Y], Letter, Board) :-
    nth(Y, Board, Row),
    nth(X, Row, Letter).

find_word([Letter|Word], Board, Pos1, Used) :-
%    letter_at(Pos1, Letter, Board),  % "inlined" to next three lines:
    ( Pos1 = [X,Y],
      nth(Y, Board, Row),
      nth(X, Row, Letter) ),
    \+member(Pos1, Used),
    (   Word=[]
    ;
        step(Pos1, Pos2),
        find_word(Word, Board, Pos2, [Pos1|Used])
    ).

main :-
    get_board(Board),
    get_line(Word),
    % Begin at any position. Initially no positions are "Used".
    find_word(Word, Board, _, []).
aschepler
quelle