Un buon momento per rifiutare


16

Il set up

Supponiamo che ti vengano dati n fusibili, con 1 ≤ n ≤ 5, ognuno dei quali è lungo un metro e dove ciascun fusibile ha una velocità di combustione associata di N metri per D ore.

Un fusibile può essere acceso a una o entrambe le estremità, successivamente spento a una o entrambe le estremità, riacceso, estinto, ecc., Tutte le volte che è necessario fino a quando il fusibile è completamente consumato. Sei in grado di accendere e spegnere istantaneamente le micce e puoi osservare esattamente l'istante in cui una miccia è completamente consumata (bruciata).

Non è possibile tagliare un fusibile né accenderlo da nessuna parte tranne che alle estremità.

Tale impostazione consente un sistema di temporizzazione estremamente preciso, misurando il tempo tra due eventi di illuminazione / consumo dei fusibili. Ad esempio, dati due fusibili con una velocità di combustione di 1 metro all'ora, è possibile misurare esattamente 45 minuti (3/4 ore) di

  1. contemporaneamente: accendere il primo fusibile ad entrambe le estremità, accendere il secondo fusibile ad un'estremità e segnare l'inizio dell'intervallo di tempo
  2. accendere la seconda estremità del secondo fusibile nel momento in cui il primo fusibile viene consumato (30 minuti dopo)
  3. segnando la fine dell'intervallo di tempo nel momento in cui viene consumato il secondo fusibile (15 minuti dopo)

La sfida

Dato un numero frazionario di ore t e un insieme di n frazioni che rappresentano le esatte velocità di combustione di n fusibili, scrivere un programma o una funzione che emetta / restituisca un valore di verità se t ore possono essere misurate con precisione attraverso la combustione sistematica dei fusibili o un falsa valore altrimenti.

L'input per il programma può essere uno dei seguenti:

  • argomenti della riga di comando del modulo TN/TD N1/D1 N2/D2 N3/D3 ...
  • una stringa del modulo TN/TD N1/D1 N2/D2 N3/D3 ...letta stdino equivalente
  • una stringa del modulo TN/TD N1/D1 N2/D2 N3/D3 ...passata come argomento di funzione
  • una matrice di stringhe ["TN/TD", "N1/D1", "N2/D2", "N3/D3", ...]passata come argomento di funzione

In tutti i casi t = TN/ TD, dove TN, TD∈ [1.10000].

Allo stesso modo, in tutti i casi: velocità di combustione per il fusibile i = N i / D i = N<i>/ D<i>, dove N<i>, D<i>∈ [1,10] ∀ i .

Si può presumere che ci saranno sempre tra 1 e 5 fusibili (inclusi) e che tutti gli ingressi siano validi e compresi nell'intervallo. Si può anche presumere che tutte le frazioni di input siano fornite in termini più bassi.

Per questa sfida non puoi usare numeri in virgola mobile con componenti frazionari. Cioè, se si utilizzano numeri in virgola mobile in qualsiasi punto dell'applicazione, questi possono assumere solo valori integrali con zero componente frazionario.

punteggio

Si tratta di una sfida di , quindi verrà premiata la sottomissione conforme più breve in byte.


Ingressi / uscite di esempio

input:  29/6 3/2 2/3 3/5 3/7 7/5
output: true

One solution:
  - light both ends of fuse 1, mark start of interval
  - on fuse 1 consumption: light both ends of fuse 2, light one end of fuse 5
  - on fuse 5 consumption: extinguish one end of fuse 2, light both ends of fuse 3,
    light both ends of fuse 4
  - on fuse 2 consumption: extinguish one end of fuse 3, extinguish both ends of
    fuse 4
  - on fuse 3 consumption: relight one end of fuse 4
  - on consumption of fuse 4: mark end of interval (29/6 hours)

input:  2/1 3/1 5/1 7/1
output: false

input:  5/1 6/1 1/6 9/1 1/9
output: true

One solution:
  - light fuse 1 at one end, light fuse 2 at both ends, light fuse 4 at both ends
  - on fuse 1 consumption: extinguish one end of fuse 2, mark start of interval
  - on fuse 4 consumption: relight one end of fuse 2
  - on fuse 2 consumption: mark end of interval (5 hours)

Felice fusione! :)


@ MartinBüttner Immagino che sarebbe la limitazione del numero in virgola mobile.
hmatt1,

2
@ MartinBüttner Sono d'accordo che non è una restrizione sul codice sorgente. Non credo che [fonte limitata] si adatti a questa domanda così come è attualmente.
hmatt1,

@chilemagic: volevo attirare l'attenzione sul fatto che la logica in virgola mobile non poteva essere utilizzata, ma se il consenso è che non è un uso corretto del tag, lo spoglio.
COTO,

I casi di test sono troppo grandi :)
feersum

5
Lol, sto usando un algoritmo O ((n!) ^ 3) per scopi di golf.
feersum

Risposte:


8

Python 2, 305

Questa è la versione da golf. È praticamente inutilizzabile per n> 3 , poiché la complessità del tempo (e dello spazio) è come 3 n 2 ... in realtà potrebbe essere troppo bassa per il tempo. Ad ogni modo, la funzione accetta un elenco di stringhe.

def f(i):
 Z=range;r=map(__import__('fractions').Fraction,i);R=r[1:];n=len(R);L=[[[1]*n,[0]]];g=0
 for m,p in L: 
  for d in([v/3**i%3for i in Z(n)]for v in Z(3**n)):
    try:x=min(m[i]/R[i]/d[i]for i in Z(n)if m[i]*d[i]>0);L+=[[[m[i]-x*R[i]*d[i]for i in Z(n)],[p[0]+x]+p]]
    except:g|=p[0]-r[0]in p
 return g

Una versione leggermente ottimizzata può completare i casi di test in un paio di minuti. Potrebbe essere comunque lento per un caso n = 5 impossibile .

def fLessslow(i):
 Z=range
 r=map(__import__('fractions').Fraction,i)
 R=r[1:]
 n=len(R)
 L=[((1,)*n,(0,))]
 ls = set(L)
 for m,p in L: 
  if p[0]-r[0]in p: return 1
  for d in([v/3**i%3 for i in Z(n)]for v in Z(3**n)):
   if any(d[i] and m[i]<=0 for i in Z(n)):continue
   try:
    x=min(m[i]/R[i]/d[i]for i in Z(n)if m[i]*d[i]>0)
    thing = (tuple(m[i]-x*R[i]*d[i]for i in Z(n)),(p[0]+x,)+p)
    if thing not in ls:L+=[thing];ls.add(thing)
   except:5
 return 0

print fLessslow('5/1 6/1 1/6 9/1 1/9'.split())
print fLessslow('29/6 3/2 2/3 3/5 3/7 7/5'.split())

1
Bello, 8 voti positivi per un codice errato: chiamare la funzione con l'esempio nella descrizione: print f ('3/4 1/1 1 / 1'.split ()) restituisce 0, anche se come dice la descrizione, è risolvibile .
Jakube,

@Jakube Grazie per il test ... è molto raro su questo sito! Ora è stato risolto; Ho dimenticato in un punto di dividere per il fattore 1 o 2 a seconda di quante estremità della corda sono accese.
febbraio

3

Python 2, 331

È un po 'più lungo della versione di feersum, ma è molto più veloce. Tutti i test insieme richiedono circa 3 secondi sul mio laptop. Una ricerca completa per n = 5 richiede però circa 10 minuti. Parte del codice è simile alla versione di feersum, ma non ho copiato deliberatamente alcun codice.

from fractions import*
f=Fraction
r=range
g=lambda x:h(f(x[0]),[1/f(i)for i in x[1:]],[])
def h(t,x,y):
 for i in r(1,3**len(x)):
  c=[[],[],[]]
  for j in r(len(x)):c[i/3**j%3]+=[x[j]]
  n,b,w=c
  m=min(b+[i/2 for i in w])
  if h(t,[i for i in n+[j-m for j in b]+[j-2*m for j in w]if i],[i+m for i in y]+[m]):return True
 return t in y

Uso:

print g('3/4 1/1 1/1'.split())
print g('29/6 3/2 2/3 3/5 3/7 7/5'.split())
print g('2/1 3/1 5/1 7/1'.split())
print g('5/1 6/1 1/6 9/1 1/9'.split())

Spiegazione:

L'espressione lambda g esegue una preelaborazione dell'input, come la conversione di stringhe in frazioni, la separazione del tempo di obiettivo dalle velocità di combustione e il calcolo dei tempi di combustione (= 1 / velocità di combustione).

La funzione h divide tutti i tempi di combustione x in 3 set n, bew (n sta per non_burning, b per one_end_burning e w per both_ends_burning). Esamina tutte quelle disposizioni (tranne la disposizione n = x, b = [], w = []), determina il fusibile con la velocità di combustione più breve (risparmia tempo in m) e chiama ricorsivamente h con tempi di combustione aggiornati. In y salvo tutte le volte che qualcuno può misurare usando i fusibili. Nella chiamata ricorsiva anche questi valori vengono aggiornati.

Non appena trovo il valore, termina tutte le chiamate con True.


4
Voi giovani programmatori Python avete l'imbarazzo della scelta con tutte le vostre frazioni integrate e grandi numeri interi. Quando ero una giovane ragazza, tutto ciò che avevamo erano gli 1"e 0", che dovevamo digitare uno alla volta su una console senza monitor. A volte non avevamo 1s.
COTO
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.