Puzzle di ricerca di parole


29

Dato un testo rettangolare come un puzzle di ricerca di parole e una stringa di ricerca, determinare se il testo contiene la stringa di ricerca. La stringa di ricerca può apparire:

  • orizzontalmente, verticalmente o diagonalmente
  • avanti o indietro

È possibile scrivere una funzione o un programma e prendere due stringhe come input tramite argomento della funzione, ARGV o STDIN. L'output dovrebbe essere un risultato veritiero o falso che può essere restituito dalla funzione o scritto su STDOUT.

Supponiamo che il testo conterrà caratteri ASCII stampabili arbitrari (codici esadecimali da 20 a 7E) e caratteri di interruzione di riga. Le lettere fanno distinzione tra maiuscole e minuscole. Si può presumere che il testo di input sia rettangolare, ovvero che tutte le linee abbiano la stessa lunghezza. Puoi decidere se l'input termina con una riga finale o meno (se è importante per l'invio).

Questo è il codice golf, vince la risposta più breve (in byte).

Esempi

Usando questa griglia dall'articolo di Wikipedia sulle ricerche di parole come primo input:

WVERTICALL
ROOAFFLSAB
ACRILIATOA
NDODKONWDC
DRKESOODDK
OEEPZEGLIW
MSIIHOAERA
ALRKRRIRER
KODIDEDRCD
HELWSLEUTH

le seguenti stringhe di ricerca dovrebbero produrre rispettivamente risultati di verità o falsa:

Truthy: RANDOM, VERTICAL, HORIZONTAL, WORDSEARCH, WIKIPEDIA, TAIL
Falsy:  WordSearch, CODEGOLF, UNICORN

In alternativa, usando questo testo di input

Lorem ipsum dolor sit amet consectetu
r adipisicing elit sed do eiusmod tem
por incididunt ut labore et dolore ma
gna aliqua. Ut enim ad minim veniam, 
quis nostrud exercitation ullamco lab
oris nisi ut aliquip ex ea commodo co
nsequat. Duis aute irure dolor in rep
rehenderit in voluptate velit esse ci
llum dolore eu fugiat nulla pariatur.

Otteniamo i seguenti risultati di ricerca (usando le virgolette ora, perché ci sono spazi in alcune stringhe di ricerca):

Truthy: "Lorem", "mine", "uma bop", "tuetdod", "snol,a", "texas", "pii.d  v", "vexta"
Falsy:  "lorem", "wordsearch", "pii.d v", "mute"

Risposte:


7

CJam, 46 37 byte

qN%{_zW%__,N**2$2$+,)/z\}4*]:+N*eas#)

Legge la griglia da STDIN e la parola come argomento della riga di comando. Stampa numeri interi positivi per le corrispondenze e 0 per le non corrispondenze.

Al costo di due byte extra, entrambe le stringhe (word, linefeed, grid) possono essere lette da STDIN:

qN%(\{_zW%__,N**2$2$+,)/z\}4*](\:+N*\#)

Puoi provare questa versione online con l' interprete CJam .

Esempio di esecuzione

$ for W in Lorem mine uma\ bop tuetdod snol,a texas pii.d\ \ v vexta WordSearch CODEGOLF UNICORN; do echo -e "$(cjam wordsearch.cjam "$W" < grid)\t$W"; done
1       Lorem
3085    mine
2055    uma bop
5142    tuetdod
3878    snol,a
1426    texas
5371    pii.d  v
2536    vexta
0       WordSearch
0       CODEGOLF
0       UNICORN

sfondo

Supponiamo che l'input sia la seguente griglia:

ABCD
EFGH
IJKL

Dividendo agli avanzamenti di riga, otteniamo il seguente array:

A := [
         "ABCD"
         "EFGH"
         "IJKL"
     ]

Questo riguarda le parole orientali (parole che vanno da sinistra a destra).

Ora, uniamo gli elementi Adell'utilizzo di una stringa di len(A)avanzamenti di riga come separatore:

"ABCD⏎⏎⏎EFGH⏎⏎⏎IJKL"

Quindi, tagliamo la stringa risultante in blocchi di lunghezza len(A) + len(A[0]) + 1:

[
    "ABCD⏎⏎⏎E"
    "FGH⏎⏎⏎IJ"
    "KL"
]

Se "comprimiamo" l'array (trasponiamo righe e colonne), otteniamo:

[
    "AFK"
    "BGL"
    "CH"
    "D⏎"
    "⏎⏎"
    "⏎⏎"
    "I⏎"
    "EJ"
]

Questo copre le parole del sud-est.

Se comprimiamo A e invertiamo l'ordine delle righe del risultato, otteniamo:

[
    "DHL"
    "CGK"
    "BFJ"
    "AEI"
]

Questo riguarda il Sud e - dopo aver ripetuto il processo per le diagonali - le parole del Sud Ovest.

Zipping e reverse di nuovo, otteniamo:

[
    "LKJI"
    "HGFE"
    "DCBA"
]

Questo riguarda l'Ovest e - dopo aver ripetuto il processo per le diagonali - le parole del Nord Ovest.

Ancora una volta zippando e invertendo, otteniamo:

[
    "IEA"
    "JFB"
    "KGC"
    "LHD"
]

Questo riguarda il Nord e - dopo aver ripetuto il processo per le diagonali - le parole del Nord Est.

Come funziona

Il codice funziona come spiegato nella sezione precedente, con due differenze minori:

  • Si zip e si inverte una volta all'inizio.
  • Calcola len(A) + len(A[0])come len(A + zip(A)).

Infine, unisce tutte le righe di tutti gli array generati utilizzando gli avanzamenti di riga come separatori e cerca la parola nella stringa risultante.

qN%                                   " A := split(input(),'\n')                          ";
   {                    }4*           " Do 4 times:                                       ";
    _zW%                              "   B := reverse(zip(A))                            ";
        __,N**                        "   C := B.join(len(B) * '\n')                      ";
              2$2$+,)/z               "   D := zip(C.chunks(len(A + B) + 1))              ";
                       \              "   A := B                                          ";
                           ]          " Collect all values of A and D in an array R.      ";
                            :+        " R := flatten(R)                                   ";
                              N*      " R := R.join('\n')                                 ";
                                eas   " I := flatten(ARGV)                                ";
                                   #) " print R.index(I) + 1                              ";

7

Java: 183 211 321

boolean s(char[]w,char[]s){int j,z,a=s.length,i=a*9,f=1,q=0;for(;s[q++]>10;);for(;i-->0;)for(j=w.length,z=i/9;i%9!=4&j-->0&z>=0&z<a&&s[z]==w[j];z+=q*(i/3%3)+i%3-q-1)f*=j;return f==0;}

Una forza bruta di base. Non c'è molto altro da dire, immagino. L'ingresso è il primo ago e il secondo pagliaio. Presuppone che la griglia sia terminata da newline .

Una versione leggermente più leggibile con test case mostrato:

public class WordSearch {
    static String grid = "WVERTICALL\nROOAFFLSAB\nACRILIATOA\nNDODKONWDC\nDRKESOODDK\nOEEPZEGLIW\nMSIIHOAERA\nALRKRRIRER\nKODIDEDRCD\nHELWSLEUTH";
    static String search = "RANDOM";

    public static void main(String[] args) {
        System.out.println(new WordSearch().s(search.toCharArray(),grid.toCharArray()));
    }

    boolean s(char[]w,char[]s){
        int j,z,a=s.length,i=a*9,f=1,q=0;
        for(;s[q++]>10;);
        for(;i-->0;)
            for(j=w.length,z=i/9;
                i%9!=4&j-->0&z>=0&z<a&&s[z]==w[j];
                z+=q*(i/3%3)+i%3-q-1)
                f*=j;
        return f==0;
    }
}

if(e<1)return 1>0;potrebbe essere return e<1;vero?
FryAmTheEggman,

@FryAmTheEggman No, sarebbe tornato dopo aver trovato il primo errore, quindi non avrebbe cercato nell'intera griglia.
Geobits,

1
Ah scusa, mi sono perso un po 'lì dentro; _;
FryAmTheEggman,

4
Il fuori due cicli for potrebbe essere crollato in un unico posto in modo che faresti i=a*9,e for(;i-->0;)poi z=i/9;e i%a!=4&e così via?
Sarà il

1
Wow, è così simile al mio. E l'ho guardato solo dopo che avevo già iniziato. Non ho preso tempo per vedere come funziona. +1.
Level River St,

6

JavaScript (E6) 111 116

Ricerca della forza bruta per ogni personaggio in ogni direzione - il più possibile il golf

F=(b,w)=>
  [1,-1,r=b.search('\n'),-r,++r,-r,++r,-r].some(d=>
    [...b].some((_,p)=>
      [...w].every(c=>c==b[p+=d],p-=d)
    )
  )

Test nella console FireFox / Firebug

;["RANDOM", "VERTICAL", "HORIZONTAL", "WORDSEARCH", "WIKIPEDIA", "TAIL",
"WordSearch", "CODEGOLF", "UNICORN"]
.forEach(w=>console.log('\n'+ w +' -> '+
  F("WVERTICALL\nROOAFFLSAB\nACRILIATOA\nNDODKONWDC\nDRKESOODDK\nOEEPZEGLIW\nMSIIHOAERA\nALRKRRIRER\nKODIDEDRCD\nHELWSLEUTH",w)))

Produzione

RANDOM -> true
VERTICAL -> true
HORIZONTAL -> true
WORDSEARCH -> true
WIKIPEDIA -> true
TAIL -> true
WordSearch -> false
CODEGOLF -> false
UNICORN -> false

5

Python, 175

Non molto ispirato, ma qui va:

def s(h,n):
 l=h.find('\n')+2;h+='\n'*l;L=i=len(h)
 while i>0:
  i-=1
  for d in[-l,1-l,2-l,-1,1,l-2,l-1,l]:
    j=i;m=len(n)
    for c in n:m-=c==h[j%L];j+=d
    if m<1:i=-1
 return-i

Il primo argomento è il pagliaio, il secondo è l'ago.


Penso che puoi salvare 6 caratteri usando h,n=input()e print. Inoltre, funziona con input non quadrati? (m = len (n)? Ammetto di non aver compreso appieno quello che stai facendo, quindi potrei sbagliarmi completamente!)
FryAmTheEggman,

@FryAmTheEggman: Sì, funziona con input non quadrati.
Ell

1
Alcune ottimizzazioni Python standard: while i>0a while i:(poiché inon può mai diventare negativo), if m<1:i=-1a i-=m<1.
xnor,

1
@xnor Penso che potresti aver letto male if m<1:i=-1perché if m<1:i-=1nessuno di questi funzionerà perché si sta impostando iin modo negativo.
FryAmTheEggman,

@FryAmTheEggman Oh, sì, l'ho totalmente frainteso.
xnor,

5

Bash + coreutils, 214 169 byte

r()(tee >(rev) $@)
t()(eval paste -d'"\0"' `sed 's/.*/<(fold -1<<<"&")/'`)
d()(while IFS= read l;do echo "$a$l";a+=_;done|t)
r<<<"$2"|r >(d) >(r|t) >(r|d)|r|grep -q "$1"

Usi 3 trasformano funzioni r, te dper invertire, trasposizione e spostamento diagonale, in tutte le combinazioni necessarie.

Aggiornamento: la rfunzione ora produce output invertiti e non invertiti per maggiore golfiness

Immissione tramite argomenti della riga di comando: stringa di ricerca, seguita da un blocco di ricerca di parole rettangolare (separato da nuova riga).

L'output è un codice di stato di uscita della shell idiomaticamente corretto - 0 che significa VERO e 1 che significa FALSO.

Produzione:

$ for w in "Lorem" "mine" "uma bop" "tuetdod" "snol,a" "texas" "pii.d  v" "vexta" ; do ./ws.sh "$w" "Lorem ipsum dolor sit amet consectetu
r adipisicing elit sed do eiusmod tem
por incididunt ut labore et dolore ma
gna aliqua. Ut enim ad minim veniam, 
quis nostrud exercitation ullamco lab
oris nisi ut aliquip ex ea commodo co
nsequat. Duis aute irure dolor in rep
rehenderit in voluptate velit esse ci
llum dolore eu fugiat nulla pariatur."; echo $?; done
0
0
0
0
0
0
0
0
$ for w in WordSearch CODEGOLF UNICORN ; do ./ws.sh "$w" "Lorem ipsum dolor sit amet consectetu
r adipisicing elit sed do eiusmod tem
por incididunt ut labore et dolore ma
gna aliqua. Ut enim ad minim veniam, 
quis nostrud exercitation ullamco lab
oris nisi ut aliquip ex ea commodo co
nsequat. Duis aute irure dolor in rep
rehenderit in voluptate velit esse ci
llum dolore eu fugiat nulla pariatur."; echo $?; done
1
1
1
$ 

1. Stavo per suggerire T()(tee >(r) $@), ma è ancora meglio. 2. Non credo di aver mai visto prima quella sintassi della funzione. 3. Considerando la verità su stringhe non vuote e false su stringhe vuote, penso che tu possa ometterlo -q.
Dennis,

Se si definisce r()(tee >(rev) $@), r<<<"$2"|r >(d) >(r|t) >(r|d)|r|grep "$1"dovrebbe funzionare anche.
Dennis,

Non ho testato nient'altro, ma i due casi di test nella domanda hanno verificato quando ho provato.
Dennis,

@Dennis Nice - sì, ora funziona. Ho controllato con Martin: vuole -qche rimanga.
Trauma digitale,

5

C, 163

f(char*h,char*n){int i,j,d,p,y=0,l=strlen(h),w=strchr(h,10)-h+1;for(i=l*9;i--;y+=d&&!n[j]){p=i/9;d=i%9/3*w-w+i%3-1;for(j=0;p>=0&p<l&h[p]==n[j];j++)p+=d;}return y;}

Nessun riarrangiamento della griglia, provo semplicemente ogni lettera iniziale in ogni direzione e cammino fino a quando non corro dalla griglia o trovo una discrepanza.

Approfitto del fatto che una stringa C termina in un byte zero. Poiché non ci sono zero byte nella griglia, ci sarà SEMPRE una discrepanza. Ma se la discrepanza si verifica sul byte zero sappiamo che abbiamo trovato la fine della stringa da cercare e la registriamo come una corrispondenza.

Ungolfed in un programma di test

char h[]="WVERTICALL\nROOAFFLSAB\nACRILIATOA\nNDODKONWDC\nDRKESOODDK\nOEEPZEGLIW\nMSIIHOAERA\nALRKRRIRER\nKODIDEDRCD\nHELWSLEUTH\n";

f(char*h,char*n){                                   //haystack,needle
  int i,j,d,p,y=0,l=strlen(h),w=strchr(h,10)-h+1;   //l=length of whole grid. w=width of row, including terminal newline ASCII 10
  for(i=l*9;i--;){                                  //for each start letter and direction
    p=i/9;                                          //pointer to start letter
    d=i%9/3*w-w+i%3-1;                              //9 possible values of direction vector {-w,0,w}+{-1,0,1}
    for(j=0;p>=0&p<l&h[p]==n[j];j++)p+=d;           //walk p in the direction defined by d until we walk off the top or bottom of the grid or a mismatch is fount
    y+=d&&!n[j];                                    //if we got all the way to the terminal 0, record it as a hit. If d=0, don't record as this is an invalid direction.
  }
  return y;   
}

main(int c, char**v){
  printf("%d",f(h,v[1]));  
}

Produzione

Si noti che la funzione restituirà il numero totale di incidenze della stringa cercata nella griglia. Pertanto OD, restituisce 6. Se non viene rilevata alcuna incidenza, viene restituito 0, che è l'unico valore errato in C. La modifica in y|=d*!n[j]salverebbe un carattere ma perderebbe questa funzionalità.

$ ./a UNICORN
0

$ ./a CODEGOLF
0

$ ./a WordSearch
0

$ ./a RANDOM
1

$ ./a WORDSEARCH
1

$ ./a VERTICAL
1

$ ./a HORIZONTAL
1

$ ./a WIKIPEDIA
1

$ ./a TAIL
1

$ ./a OD
6

5

C # - 218 197 186 byte

Funzione C # che accetta 2 stringhe, prima la parola da cercare, più tardi la griglia con avanzamenti di riga ( \n) tra le righe. Le cose stanno diventando disperate ora ... così disperate che la mia modifica precedente non ha funzionato!

Codice golfizzato:

bool F(string D,string S){int l=S.Length,i=l*13,r,p;for(S+="\n";i-->l*5;i=r<0?r:i)for(r=D.Length,p=i%l;p>-1&p<l&r-->0&&D[r]==S[p];p+=(S.IndexOf('\n')+1)*(i/l%9/3-1)+i/l%3-1);return i<0;}

Meno golfato con codice di prova:

class P
{
    static void Main()
    {
        System.Console.WriteLine(new P().F(System.Console.ReadLine(),System.Console.In.ReadToEnd())?"Truthy":"Falsy"); // because why not
    }

    bool F(string D,string S)
    {
        int l=S.Length,i=l*13,r,p;

        for(S+="\n";i-->l*5;i=r<0?r:i) // for each cell/direction
            for(r=D.Length,p=i%l;p>-1&p<l&r-->0&&D[r]==S[p];p+=(S.IndexOf('\n')+1)*(i/l%9/3-1)+i/l%3-1); // test against string (backwards)

        return i<0;
    }
}

4

Haskell - 173

Invece di cercare direttamente sulla griglia, trasformo la griglia in diversi modi e abbino la parola a ciascuna riga della nuova griglia.

Per esempio,

G1    G2    G3       G4   G5

abcd  aA1   abcd     a..  ..1
ABCD  bB2   .ABCD    bA.  .A2
1234  cC3   ..1234   cB1  aB3
      dD4            dC2  bC4
                      D3  cD
                       4  d

Cerca la parola in ogni riga di G1, G2, G4 e G5, quindi abbiamo finito. Nota che G3 non viene utilizzato, lo inserisco qui solo a scopo illustrativo.

Un'idea simile viene applicata per cercare avanti e indietro: basta cercare la parola originale e la parola invertita.

Quindi ora abbiamo cercato 8 direzioni. Ecco il codice, la cui correttezza è stata verificata da un altro script .

import Data.List
v=reverse
t=transpose
y=any
d r=zipWith(++)(scanr(\_->('\n':))[]r)r
g r w=y(y$y((==w).take(length w)).tails)[r,t r,t.d$r,t.d.v$r]
f r w=y(g(lines r))[w,v w]

La funzione fè ciò che vogliamo e il suo argomento rè la stringa del rettangolo, wè la parola da cercare.


4

Python 2 - 246 259 275 308 298 297 294 313 322

w,s=input()
r=range
d='\n'
I=''.join
w=w.split(d)
t,u=len(w),len(w[0])
v=d.join([I(x)for x in zip(*w)]+[d]+[I([w[i+j][i]for i in r(min(u,t-j))])+d+I([w[i][i+j]for i in r(min(t,u-j))])for j in r(max(t,u))]+[d]+w)
print s in v or s[::-1]in v

Grazie a Will per l'aiuto nella gestione della stampa e nella definizione del join.

Grazie alla ferrovia sotterranea per avermi ricordato correttamente gli spazi del golf; p

Risolto il problema con partite errate grazie all'utilizzo di ',' come delimitatore.

Apparentemente il modo migliore per giocare a golf è aggiungere tonnellate di scorrimento orizzontale.

Ingresso come spazio bianco botto di fine riga linee tra virgolette delimitato: "WVERTICALL \ nROOAFFLSAB \ nACRILIATOA \ nNDODKONWDC \ nDRKESOODDK \ nOEEPZEGLIW \ nMSIIHOAERA \ nALRKRRIRER \ nKODIDEDRCD \ nHELWSLEUTH", "RANDOM"


1
L=len;J=''.joinecc e print any(s in(v,d,w,r...))? Stavo seguendo le stesse linee quando ti ho visto pubblicato :)
Will,

@Will Grazie per l'aiuto! Definire len costa tanti caratteri quanti ne risparmia e non sono sicuro di come definire l'unione in modo ottimale (alcuni hanno delle virgole), quindi lo farò tra poco.
FryAmTheEggman,

Ovunque tu abbia )o ]seguito da uno spazio, puoi eliminare lo spazio.
undergroundmonorail,

2

APL (Dyalog Classic) , 44 byte

1∊⍞⍷↑{⍉0,⍵,↑(0,⊢)\↓0,⍵}¨{⍉⌽⍵}\4⍴⊂↑a⊆⍨a≠⊃⌽a←⎕

Provalo online!


Uhm, mi dispiace, ma sembra che qui non si possa ottenere un input del genere, deve essere separato \n(ovvero avere ⎕TC[2]come separatore).
Erik the Outgolfer,

@EriktheOutgolfer oh merda ... Lo riparerò più tardi. Grazie.
ngn,

risolto ora, purtroppo molto più a lungo
ngn

0

J , 60 53 byte

<@[e.[:,[:(;|.)@>[:<\\.@>[:(<"1,</.)@>@(;|.@|:)[;.2@]

Provalo online!

Richiede il primo input per non contenere nuove righe.

Spiegazione:

linkrotate=: ;|.@|:     NB. link with itself rotated 90° ccw
infixes   =: <\\.       NB. list of boxes containing the infixes
lines     =: <"1 , </.  NB. horizontal and diagonal lines, boxed
linkrev   =: ;|.        NB. link with itself reversed
appearin  =: <@[ e. [: , [: linkrev@> [: infixes@> [: lines@>@linkrotate [;.2@]

Provalo online!

I ganci sono utili.


Sembra che questo funziona anche. (51 byte)
user202729

0

Gelatina , 16 byte

Risolto un problema correlato (forse un duplicato) con 15 di questi 16 byte come nucleo del codice ...

ỴZU$3С;ŒD$€Ẏw€Ẹ

Un collegamento diadico che accetta un elenco di caratteri a sinistra e un elenco di caratteri a destra che restituisce 1 se trovato e 0 se no.

Provalo online!

Come?

ZU$3С;ŒD$€Ẏw€Ẹ - Link: words, grid
   3С          - repeat three times and collect the results (inc input):
  $             -   last two links as a monad:
Z               -     transpose
 U              -     upend     (together these rotate by a quarter)
          €     - for €ach:
         $      -   last two links as a monad:
       ŒD       -     get forward-diagonals
      ;         -     concatenate
           Ẏ    - tighten (to get all the runs across the grid) 
             €  - for €ach run:
            w   -   sublist-index (0 if not found)
              Ẹ - any truthy? (i.e. was the word found?)
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.