Imposter allo Zoo


42

Vuoi aprire un nuovo zoo. Sarà fantastico. Ma essendo il cheapskate che sei, vuoi permetterti solo animali di tre lettere (tutti sanno che il costo di un animale è proporzionale alla lunghezza del suo nome). Ecco il tuo sogno di far pagare la gente per vederne uno elephant. Ma all'improvviso hai un'idea geniale. Se si posizionano correttamente gli animali nella penna, è possibile creare l'illusione ottica di un elephant! Ecco una vista dall'alto verso il basso del tuo nuovo "elefante composto":

elk
  eel
   pig
    hog
     ant

--------  (fence)
    ^
    | viewing direction

Ahah, quei visitatori creduloni!

Sì, è così che funziona la percezione.

La sfida

Data una parola non vuota costituita solo da lettere inglesi minuscole, determinare se può essere formata dalla sovrapposizione delle seguenti 30 parole di animali di tre lettere:

ant ape asp ass bat bee boa cat cod cow 
dab dog eel elk emu fly fox gnu hog ide 
jay kea kob koi olm owl pig rat ray yak

Sì, ce ne sono più di 30, ma è un bel numero rotondo.

Puoi facoltativamente ricevere questo elenco come input (in qualsiasi elenco ragionevole o formato stringa, purché non sia pre-elaborato). Probabilmente vorrai farlo, a meno che la lettura e l'elaborazione di questo elenco di input non sia molto più costosa della codifica e della compressione nella tua lingua preferita. Nota che anche se prendi la lista come input puoi presumere che sarà sempre esattamente questa lista, quindi se il tuo codice si basa sulla lista passata lunga 30 elementi e non contenente una parola z, va bene.

Ogni parola può essere utilizzata più volte. Gli animali non possono essere tagliati alle estremità, solo parzialmente nascosti da altri animali. Quindi oxnon è una stringa possibile, anche se abbiamo fox.

L'output dovrebbe essere veritiero, se possibile, e falsare diversamente.

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

Il tuo codice dovrebbe gestire tutti i casi di test in pochi secondi.

Si applicano le regole standard del .

Altri esempi

  • Qualsiasi parola di una o due lettere è ovviamente falsa.
  • Lo stesso vale per qualsiasi parola di tre lettere che non figura nell'elenco sopra.
  • Anche se abbiamo gnue rat, gnatè falso poiché non c'è modo di disporli in modo tale da vedere solo due lettere di ciascuno (non vogliamo tagliare gli animali in terzi).

Alcuni esempi veritieri:

pigment

    ant
  bee
 olm
pig
antioxidant

   fox
 koi  ide
ant     ant

Casi test

La maggior parte dei casi di test è stata presa dall'esecuzione di un'implementazione di riferimento su un dizionario. Le ultime "parole" sono state generate casualmente e sono lì solo per garantire che gli invii siano sufficientemente efficienti.

Truthy:

ant
owl
bass
pride
bobcat
peafowl
elephant
hedgehogs
crocodile
antidemocrat
aspidoganoidei
biodegradability
angioelephantiasis
propreantepenultimate
acategnukeaidabeleenaspcodcoidyakwakoasshogattkjaypigkobolcodidaskearaywelkwboaxbeeuflapaspoapemaassaaspeewoglmabiemuwjadogacagnuepigjaycownbatjaemuifoxkeaeekekeagratsseeluejdoghogaolmgpigbeaeelemulasphogjaydabemukgnunueifoasdoglrayyadogpewlayroassasslgnuaspyyakkbokeaodxilopgnuasppigkobelratelkolmakob
koigdgaspslycoyakehrdabowbatdkkeapogkobelrowlyarpidepetlfoxeboaiderbeefoxbgnuapeocowgiecowlkoieeltbategspemuideatdogbeeecatgeaoccattbbeassgnasolkeaflyelkaognubeeabrratoccolmobodoglyelraywelkoxantowleedrayflypeappigogatraoyakccpiganaaspkobabjaspkointantybjbeeanolmuijaylratojaynueidflyjarayabatmmpigtfly
eolmantjkobeeaorayogaowldfoxayeassapibatmflylyraelaspsseolmbelkkaoantlmufodasgnueantaidenthyakcodoxuepigodggnuantatlcatnuuelkpemucbapeeoiahdogplkowletbatdrayarayoaelkgrayodcatgkantewkobeljaybeeyfkobtbdabadoghbatfoxtflygaspdeidogtowlkeaolmyraelfleelejayehogowlccatoxeabiemkobpigolmdkobrcidekyakabboyidep

Falsy:

a
ox
ram
bear
koala
antelope
albatross
zookeeper
salamander
caterpillar
hippopotamus
koigdgaspslycoyakehrdabowbatdkkeapogkobelrowlyarpidepetlfoxeboaiderbeefoxbgnuapeocowgiecowlkoieeltbategspemuideatdogbeezcatgeaoccattbbeassgnasolkeaflyelkaognubeeabrratoccolmobodoglyelraywelkoxantowleedrayflypeappigogatraoyakccpiganaaspkobabjaspkointantybjbeeanolmuijaylratojaynueidflyjarayabatmmpigtfly
koigdgaspslycoyakehrdabowbatdkkeapogkobelrowlyarpidepetlfoxeboaiderbeefoxbgnuapeocowgiecowlkoieeltbategspemuideatdogbeeecatgeaoccattbbeassgnasolkeaflxelkaognubeeabrratoccolmobodoglyelraywelkoxantowleedrayflypeappigogatraoyakccpiganaaspkobabjaspkointantybjbeeanolmuijaylratojaynueidflyjarayabatmmpigtfly
beyeodpgspeclxlkbkaylldnceepkocbdmymsaogsowpbawbauaioluaaagaetdoaoialeoxaagspoelegflpylptylnolnatrjabaorkdteeydloiebbptatdtfdfgoodtbkoafmounbduaffcrfelcnawmxaskgaoenaattbaobgbgabnhkesbgaaaaotafkiiieatworginaeowaehuddegooaalowaoososaksahoimkulbtoadyyelkcmkacbuostadppcuglbnmotedfgfkoleldonknemomnmoutykg

Prendo ancora suggerimenti per un titolo migliore ...
Martin Ender,

You may optionally receive this list as input- vuol dire che non conta ai fini del punteggio, mentre sarebbe difficile codificarlo?
Marin il

@marinus Sì. Quindi probabilmente vorrai prenderlo come input aggiuntivo, a meno che leggere più di una stringa in input sia davvero ingombrante nella tua lingua preferita. (Non voglio consentire l'hardcoding + "se lo fai, sottralo dal tuo punteggio", perché in questo modo otterrai persone che lo codificano e lo comprimono, il che essenzialmente darebbe loro un bonus al loro punteggio.)
Martin Ender

" Parametro funzione (fuori) " include parametri per riferimento ?
mınxomaτ,

5
Non riesco a credere di aver perso il commento "numero rotondo" nella sandbox. Vergogna, signore! Intorno a queste parti 32 è un numero tondo, non 30. (E non è del tutto provato che hai lasciato fuori i nomi per gli animali maschi - vedi maiale).
Peter Taylor,

Risposte:


7

Japt, 51 48 45 36 33 19 byte

Salvato 9 byte grazie a @PeterTaylor

;!UeVrE"[$& ]" S² x

Provalo online!

Accetta l'input come stringa da testare, seguito dall'elenco di parole di tre lettere, delimitate da |. Nota: questo non funziona nell'ultima versione dell'interprete, quindi si prega di utilizzare il collegamento invece di copiare e incollare il codice.

Come funziona

L'idea di base è prendere la stringa di input e sostituire ripetutamente una delle 30 parole in essa contenute con due caratteri di riempimento. Uso uno spazio come carattere di riempimento. Inoltre, vogliamo sostituire antin elephant, a  in ela   ,  ntin e   nt, ecc. Quindi quello che vogliamo fare è cambiare la stringa di 30 parole in una regex che corrisponda a una di queste combinazioni:

ant|ape|asp|...
Becomes:
[a ][n ][t ]|[a ][p ][e ]|[a ][s ][p ]|...

Possiamo farlo abbastanza facilmente:

;VrE"[$& ]"
          // Implicit: V = "ant|ape|asp|..."
;         // Set the vars A-J to various values. E is set to "[a-z]".
VrE       // Take V and replace each lowercase letter with:
"[$& ]"   //  "[" + the char + " ]".

Tuttavia, ciò ha l'effetto indesiderato di abbinare anche tre spazi, il che non ha alcun effetto sul risultato e quindi termina la sostituzione ricorsiva. Possiamo aggirare il problema sostituendo la partita con due spazi anziché tre:

Ue    S²  // Take U, and recursively replace matches of the regex with " ".repeat(2).

Ecco una dimostrazione di base di come e perché funziona (usando .al posto di uno spazio):

First match at the end: 
eleant
ele..   (ant)
el..    (eel)
...     (elk)
..      (...)
true

First match at the beginning: 
antmua
..mua   (ant)
...a    (emu)
..a     (...)
..      (boa)
true

First match in the middle: 
cantay
c..ay   (ant)
..ay    (cat)
...     (jay)
..      (...)
true

Per casi di test veritieri, questo ci lascia con una serie di tutti gli spazi. Per falsi casi di test, ci sono ancora alcune lettere nel mix. Questo può essere tradotto in vero / falso in questo modo:

     x   // Trim all spaces off the ends of the resulting string.
!        // Take the logical NOT of the result.
         // Empty string -> true; non-empty string -> false.

E questo è tutto! Un vantaggio di questo metodo è che anche i casi di test più grandi finiscono in meno di 5 millisecondi. ( Testato qui )


" Questa non è una cosa facile con regex da solo " - cosa c'è che non va (?!,,,)?
Peter Taylor,

@PeterTaylor facepalm Grazie, che salva circa 10 byte ...
ETHproductions

1
@PeterTaylor Ho trovato un metodo molto più breve: basta sostituire con due spazi anziché tre. Fino a 19 byte!
ETHproductions

Un altro momento facepalm allora?
Neil,

@Neil Yep, praticamente. Avevo pensato di provare due spazi anziché tre, ma non mi ero reso conto che avrebbe funzionato così bene fino a stamattina quando ho riflettuto su molte strategie alternative.
ETHproductions

3

GNU grep, 62 + 1 = 63 byte

^(((.+)(?=.*!\3))*(...)(?=.*\4!)((.+)(?=.*\6!))*([^qvz]\B)?)+ 

Questo richiede l' Popzione. Si prevede che l'input sia l'animale da sintetizzare, seguito da uno spazio, seguito dall'elenco di animali di 3 lettere aperti, chiusi e delimitati da punti esclamativi. Esempio di utilizzo (supponendo che il programma sia salvato come zoo):

> grep -Pf zoo
hippopotamus !ant!ape!asp!ass!bat!bee!boa!cat!cod!cow!dab!dog!eel!elk!emu!fly!fox!gnu!hog!ide!jay!kea!kob!koi!olm!owl!pig!rat!ray!yak!

Per un input vero, la riga di input viene ripetuta. Per un input falso, non c'è output.

Grazie a Martin per aver individuato un bug e avermi avvisato dell'esistenza di \Buna parola non limite.


Grep non ha limiti di non parole \Bcosì puoi liberarti dell'ultimo lookahead? (In caso contrario, passare a Retina risparmierebbe alcuni byte. In realtà penso che salverebbe comunque un byte, perché non ha bisogno Pdell'opzione.)
Martin Ender,

Non posso testare con grep in questo momento, ma questo in realtà gestisce i casi di falsi test di grandi dimensioni in pochi secondi? A Retina il backtracking richiede parecchio tempo.
Martin Ender,

1
@ MartinBüttner Per l'ultima coppia di casi falsi, in realtà ha rinunciato e stampato grep: exceeded PCRE's backtracking limit.
feersum

1
Usare GNU per risolverlo sembra altamente appropriato.
Antti29,

2

ES6, 122 121 119 104 byte

Avevo trovato il modo di farlo fino alla risposta di ETHproduction ma non riuscivo a pensare a come gestire il ,,,problema *, così naturalmente quando ho visto il commento di Peter Taylor tutto è diventato chiaro. Quindi ETHproductions è riuscito a trovare un modo migliore per gestire il problema che consente di risparmiare 15 byte.

L'input è la parola target e una serie di parole animali.

(s,a)=>[...s].map(_=>s=s.replace(RegExp(a.map(a=>a.replace(/./g,"[&$&]")).join`|`),'&&'))&&!/\w/.test(s)

Modifica: salvato 1 byte 3 byte grazie a @ETHproductions.

* Tranne che ho usato & s perché sembra più bello nel mio replace.


Molto bella! Funzionerebbe una di queste cose: 1) usando (`(?!&&&)(${a.map...})`)come stringa, 2) rimuovendo le parentesi dopo averlo fatto, 3) usando eval`/(?!&&&).../` ?
ETHproductions

@ETHproductions Ho fatto l'errore di rimuovere gli esterni ()che non funzionano; con il ()funziona e mi fa risparmiare un byte. evalha anche bisogno della ()s in modo che non salvi più nulla, scusa.
Neil,

Penso che tu abbia anche un paio di parentesi extra in giro a.replace(...).
ETHproductions

È possibile salvare un gruppo: la s=s.replace(RegExp(a.map(a=>a.replace(/./g,"[&$&]")).join`|`),'&&')sostituzione con due caratteri anziché tre rimuove la possibilità di rimanere bloccati sostituendo gli stessi tre caratteri più e più volte.
ETHproductions

0

JS ES6, 77 byte

s=>/^(((.+)(?=.*!\3))*(...)(?=.*\4!)((.+)(?=.*\6!))*([^qvz][^\b])?)+/.test(s)

(questo è anonimo fn)

L'input è lo stesso dell'input di esempio grep sopra


Se stai ricevendo input con prompt()non dovresti utilizzare output alert()? (In alternativa, fai solo una funzione.)
Neil

@Neil grazie, ho usato anon. fn
username.ak
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.