Quando i proiettili si scontrano


16

Questa sfida si basa su un indovinello che ho letto in qualche libro qualche tempo fa, che ho trovato di nuovo qui . Si tratta di proiettili sparati da una pistola una volta al secondo a velocità variabili che viaggiano in linea retta per sempre. Quando un proiettile colpisce un altro, entrambi vengono completamente distrutti. (Sentiti libero di sostituire tutte le istanze di "proiettile" con "missile".)

L'obiettivo

Dato un elenco di velocità dei proiettili nell'ordine in cui vengono sparati, determina se tutti i proiettili vengono distrutti.

Le regole

  • L'input è un elenco di numeri interi non negativi, separati da qualsiasi delimitatore e con un carattere opzionale prima e dopo. Questi sono input validi: 1 2 3 4 5 6e [1,2,3,4,5,6]. Il programmatore fa la scelta.
  • Emetti un valore veritiero se almeno un proiettile sopravvive per sempre e un valore falso altrimenti.
  • Le velocità dei proiettili sono indicate in unità al secondo.
  • I proiettili si muovono contemporaneamente e continuamente.
  • I proiettili possono scontrarsi con offset frazionari.
  • Molteplici proiettili che raggiungono contemporaneamente la stessa identica posizione, sia in offset integrale che frazionario rispetto all'origine, si scontrano tra loro.

Esempi

In questi diagrammi, Grappresenta la pistola, >i proiettili e *sono momenti in cui i proiettili si scontrano ed esplodono.

Truthy

Ingresso: 0

        0123456789
Time 0 G>
     1 G>
     2 G>
   ...

Produzione: 1


Ingresso: 0 0 0

        0123456789
Time 0 G>
     1 G*
     2 G>
     3 G>
     4 G>
   ...

Produzione: 1


Ingresso: 1

        0123456789
Time 0 G>
     1 G >
     2 G  >
     3 G   >
   ...

Produzione: 1


Ingresso: 2 1

        0123456789
Time 0 G>
     1 G> >
     2 G >  >
     3 G  >   >
     4 G   >    >
   ...

Produzione: 1


Ingresso: 2 3 1

        0123456789
Time 0 G>
     1 G> >
     2 G>  >>
     3 G >    *
     4 G  >
     5 G   >
   ...

Produzione: 1


Falsy

Ingresso: 1 2 3 4 5 6

        Unit      1111111111
        01234567890123456789
Time 0 G>
     1 G>>
     2 G> *
     3 G>  >
     4 G>   > >
     5 G>    >  >>
     6 G      >   > *
     7 G            >  >
     8 G                  > >
     9 G                        >>
    10 G                              *
                  111111111122222222223
        0123456789012345678901234567890

Produzione: 0


Ingresso: 1 0 0 3

        Unit
        0123456789
Time 0 G>
     1 G>>
     2 G* >
     3 G>  >
     4 G   >>
     5 G     *

(La seconda collisione è al momento 4.5)
Uscita:0


Ingresso: 2 1 2 3 6 5

        Unit      1111111111
        01234567890123456789
Time 0 G>
     1 G> >
     2 G>>  >
     3 G> *   >
     4 G>  >    >
     5 G>     *   >
     6 G     >      >
     7 G          >   >
     8 G               >>
     9 G                *
                  1111111111
        01234567890123456789

Produzione: 0


Ingresso: 2 3 6

        Unit
        0123456789
Time 0 G>
     1 G> >
     2 G>  >>
     3 G      *

Produzione: 0


posso richiedere che gli input siano delimitati come 1<enter>2<enter>3...?
cat

@sysreq: Lo sta spingendo, ma lo permetterò.
El'endia Starman,

Sono d'accordo con qunitopia - questa sfida è dura, ma sto lavorando a una soluzione ...
zmerch,

Risposte:


4

Pitone 2, 388 392 388 346 342 336 331 byte

z=k=input();l=len(k);v=range;u=v(l)
while l<z:
 r="";o=[r]*l;z=l
 for h in v(l):
    if r:o[h-1]=o[m]=r;m=h;r=""
    for j in v(h+1,l):
     p=k[h];q=k[j];t=u[j];n=(1.0*q*t-p*u[h])/(q-p)if q-p else""if p>0 else t
     if t<=n<r<()>o[j]>=n<=o[h]:r=n;m=j
 i=0;s=o and min(o)
 while i<l:
    if o[i]==s!="":del k[i],o[i],u[i];l-=1
    else:i+=1
print l

Mio Dio, questa cosa è enorme, ma credo che funzioni davvero. Una volta che ne vedi tutte le complessità, questa sfida è ridicolmente difficile.

Non sono sicuro di poter spiegare come funziona in dettaglio senza digitare per ore, quindi fornirò solo un riepilogo esecutivo.

Il grande ciclo while principale è in loop fino a quando l'elenco di input non si restringe.

Il ciclo nidificato per il ciclo (riesci a credere che un ciclo nidificato per il ciclo sia effettivamente il più breve qui?) Passa in rassegna ogni velocità del proiettile e usa numpy.rootsper calcolare i calcoli in cui quel proiettile si scontrerà con ogni proiettile che verrà dopo. Qui, ""viene utilizzato per indicare l'infinito (nessuna intersezione). È necessario includere un ulteriore condizionale per garantire che i proiettili fermati siano contrassegnati come collisione nel momento in cui appaiono anziché al momento zero.

Per ogni numero teniamo traccia di quale proiettile colpirà prima, se presente, e quindi oviene aggiornato con i tempi minimi di collisione per i proiettili coinvolti.

Al termine di questo doppio ciclo, passiamo all'elenco di input ed eliminiamo qualsiasi punto elenco che si scontrerà al minimo di tutti i tempi di collisione, se presenti. Questo ci consente di eliminare contemporaneamente un gran numero di proiettili se si verificano tutti in collisione nello stesso momento.

Quindi ripetiamo l'intero processo sui proiettili rimanenti, poiché potrebbero essere in grado di farcela ora che i proiettili con cui si sarebbero scontrati sono stati distrutti.

Non appena non vengono eliminati i punti elenco (indicato dall'elenco che non si restringe), si evita il ciclo while e si stampa la lunghezza dell'elenco rimanente. Pertanto, questo programma non solo stampa in modo vero se i proiettili sopravvivono, ma in realtà stampa esattamente il numero di proiettili che sopravvivono.

EDIT: Un ringraziamento speciale a feersum per la generazione di casi di test per aiutarmi a trovare i bug.

EDIT 2: salvato 42 byte risolvendo l'equazione lineare a mano invece di usare numpy e suddividendo i tempi di inizio in un elenco separato e ristrutturando un condizionale.

EDIT 3: salvato 4 byte rinominando l'intervallo

EDIT 4: salvato altri 6 byte sostituendo i doppi spazi con le schede. Inoltre, feersum è stato così gentile da fornire la sua implementazione usando frazioni e set per il confronto. L'ho giocato un po 'e arriva a 331 byte, legando la mia soluzione.

EDIT 5: salvato 5 byte rimuovendo un'inizializzazione non necessaria e riscrivendo un condizionale


Non hai testato di nuovo gli input di esempio? [1, 0, 0, 3] non funziona.
feersum

@feersum è stato l'unico che non ho testato, pericolo. ma riparato. CON TUTTO QUESTO SFORZO, MEGLIO OTTENERE UN VOTO. : P
quintopia,

Non funziona ancora. [1, 16, 18, 20, 30] dovrebbe restituire 1
febbraio

OK sembra funzionare ora, il più delle volte almeno.
feersum
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.