Il problema del ponte e della torcia


17

L'ispirazione per questo codice golf puzzle è il problema Bridge and Torch , in cui d all'inizio di un bridge tutti devono attraversarlo nel minor tempo possibile.

Il problema è che al massimo due persone possono attraversare contemporaneamente, altrimenti il ​​ponte si frantumerà sotto il loro peso e il gruppo ha accesso a una sola torcia, che deve essere trasportata per attraversare il ponte.

Ogni persona in tutto il puzzle ha un tempo specificato che impiegano per attraversare il ponte. Se due persone si incrociano, la coppia procede lentamente quanto la persona più lenta.

Non esiste un numero prestabilito di persone che devono attraversare il ponte; la tua soluzione DEVE funzionare per qualsiasi valore di d .

Non è necessario utilizzare l'input standard per questo problema, ma per motivi di spiegazione del problema, userò il seguente formato di input e output per la spiegazione. Il primo numero, d , è il numero di persone all'inizio del ponte. Quindi, il codice ricercherà d numeri, ciascuno rappresentante la velocità di una persona.

L'output del codice sarà il minimo tempo necessario per attraversare tutti dall'inizio del bridge alla fine del bridge, rispettando i criteri spiegati in precedenza.

Ecco alcuni casi di ingresso e di uscita dei casi e la spiegazione per il primo caso ingresso. Spetta a voi ricavare un algoritmo da queste informazioni per risolvere il problema nel minor numero di byte di codice possibile.

ingresso

4
1 2 5 8

produzione

15

Per raggiungere questa uscita, il popolo deve attraversare nel modo seguente.

A and B cross forward (2 minutes)
A returns (1 minute)
C and D cross forward (8 minutes)
B returns (2 minutes)
A and B cross forward (2 minutes)

Ecco un altro caso di test che ti guiderà lungo il tuo cammino.

ingresso

5
3 1 6 8 12

produzione

29

Regole:

  1. Supponi che l'input non verrà ordinato e devi farlo da solo (se necessario)
  2. Il numero di persone nel puzzle non è fissato a 4 (N> = 1)
  3. Ogni gruppo e singolo incrocio deve avere una torcia. C'è solo una torcia.
  4. Ogni gruppo deve essere composto da un massimo di solo 2 persone!
  5. No, non puoi saltare dal ponte e nuotare dall'altra parte. Nessun altro trucco come questo;).

Come trovato da xnor di seguito, assicurati di testare casi simili 1 3 4 5, che dovrebbero restituire 14 non 15.
felice

1 4 5 6 7ha un problema simile. 25 vs. 26
Sherlock9

1
Sembra una domanda strana, ma quali sono il numero minimo e massimo di persone nel puzzle? Mentre lavoravo sulle mie soluzioni, ho notato che gestiscono solo le N >= 2persone (il che significa, stranamente, che è un lavoro extra per gestire il banale caso di "1 persona deve attraversare"), quindi alcuni chiarimenti su questo punto sarebbero grandi. Grazie in anticipo.
Sherlock9

@ Sherlock9 Supponiamo che la tua soluzione debba funzionare per N> = 1
baseman101

I casi di test mostrano che possiamo usare la lunghezza come parametro, ma puoi renderlo più chiaro nelle regole? L'input può essere l'array di tempi e il numero di persone o sono consentiti solo i tempi?
Sherlock9

Risposte:


8

Python 3, 100 99 byte

una soluzione ricorsiva

f=lambda s:s[0]+s[-1]+min(2*s[1],s[0]+s[-2])+f(s[:-2])if s.sort()or 3<len(s)else sum(s[len(s)==2:])

Grazie a @xnor per questo documento

Grazie alla @lirtosiast Salva 2 byte, @movatica Save 1 byte e che punta a @gladed a che la mia precedente soluzione non funziona

usa il seguente trucco per valutare qualcosa nella funzione lambda s.sort() or s qui calcoliamo l'ordinamento e restituiamo il risultato del tests.sort()or len(s)>3

Ungolfed

def f(s):
    s.sort()                                   # sort input in place
    if len(s)>3:                               # loop until len(s) < 3
        a = s[0]+s[-1]+min(2*s[1],s[0]+s[-2])  # minimum time according to xnor paper
        return  a + f(s[:-2])                  # recursion on remaining people
    else:
        return sum(s[len(s)==2:])              # add last times when len(s) < 3

risultati

>>> f([3, 1, 6, 8, 12])
29
>>> f([1, 2, 5, 8])
15
>>> f([5])
5
>>> f([1])
1
>>> f([1, 3, 4, 5])
14

Puoi salvare 1 byte e passare len(s)==2alen(s)<3
Mr Public

@MrPublic si trova un bug, ho cambiato la soluzione è s[0]*(len(s)==2)non (s[0]*len(s)==2) con il bug f([1]) -> 0per questo che non possiamo sostituire con <3grazie
Erwan

Questo documento ha un'espressione per il tempo ottimale che è il minimo di molteplici possibilità. Sei sicuro che la tua soluzione sia ottimale in tutti i casi?
xnor

@xnor wow sembra che io abbia la soluzione ottimale che uso l'espressione in Lemma 3A5:22
Erwan

1
Aggiornamento @movatica con il tuo suggerimento
Erwan,

4

Python 2, 119 114 112 119 110 100 95 byte

Mi è stato consigliato di separare le mie risposte.

Una soluzione che utilizza Theorem 1, A2:09 questo documento xnor collegato . Per citare il documento (modificandolo in zero-indexing):The difference between C_{k-1} and C_k is 2*t_1 - t_0 - t_{N-2k}.

lambda n,t:t.sort()or(n-3)*t[0]*(n>1)+sum(t)+sum(min(0,2*t[1]-t[0]-t[~k*2])for k in range(n/2))

Ungolfing:

def b(n, t): # using length as an argument
    t.sort()
    z = sum(t) + (n-3) * t[0] * (n>1) # just sum(t) == t[0] if len(t) == 1
    for k in range(n/2):
        z += min(0, 2*t[1] - t[0] - t[-(k+1)*2]) # ~k == -(k+1)
    return z

sei sicuro che possiamo supporre che la lunghezza possa essere un argomento?
Erwan,

@Erwan I casi di test di esempio sembrano consentirlo. Chiederò
Sherlock9

2

Rubino, 94 133 97 96 101 96 99 byte

Mi è stato consigliato di separare le mie risposte.

Questa è una soluzione basata sull'algoritmo descritto A6:06-10di questa carta sul ponte e torcia problema .

Modificare: correzione di un bug in cui a=s[0]non è ancora definito quando aviene chiamato alla fine se s.size <= 3.

->s{r=0;(a,b,*c,d,e=s;r+=a+e+[b*2,a+d].min;*s,y,z=s)while s.sort![3];r+s.reduce(:+)-~s.size%2*s[0]}

Ungolfing:

def g(s)
  r = 0
  while s.sort![3]      # while s.size > 3
    a, b, *c, d, e = s  # lots of array unpacking here
    r += a + e + [b*2, a+d].min
    *s, y, z = s        # same as s=s[:-2] in Python, but using array unpacking
  end
  # returns the correct result if s.size is in [1,2,3]
  return r + s.reduce(:+) - (s.size+1)%2 * s[0]
end

1

Scala, 113 135 (darnit)

def f(a:Seq[Int]):Int={val(s,b)=a.size->a.sorted;if(s<4)a.sum-(s+1)%2*b(0)else b(0)+Math.min(2*b(1),b(0)+b(s-2))+b(s-1)+f(b.take(s-2))}

Ungolfed un po ':

def f(a:Seq[Int]):Int = {
    val(s,b)=a.size->a.sorted      // Sort and size
    if (s<4) a.sum-(s+1)%2*b(0)    // Send the rest for cases 1-3
    else Math.min(b(0)+2*b(1)+b(s-1),2*b(0)+b(s-2)+b(s-1)) + // Yeah.
        f(b.take(s-2))             // Repeat w/o 2 worst
}

Tester:

val tests = Seq(Seq(9)->9, Seq(1,2,5,8)->15, Seq(1,3,4,5)->14, Seq(3,1,6,8,12)->29, Seq(1,5,1,1)->9, Seq(1,2,3,4,5,6)->22, Seq(1,2,3)->6, Seq(1,2,3,4,5,6,7)->28)
println("Failures: " + tests.filterNot(t=>f(t._1)==t._2).map(t=>t._1.toString + " returns " + f(t._1) + " not " + t._2).mkString(", "))

Non eccezionale in generale, ma forse non male per un linguaggio fortemente tipizzato. E a malincuore grazie a xnor per aver individuato un caso che non ho colto.


Questo documento ha un'espressione per il tempo ottimale che è il minimo di molteplici possibilità. Sei sicuro che la tua soluzione sia ottimale in tutti i casi?
xnor

1

Rubino, 104 95 93 byte

Mi è stato consigliato di separare le mie risposte.

Questa è una soluzione basata sulla mia soluzione Python 2 e Theorem 1, A2:09di questo documento sul problema Bridge and Torch .

->n,t{z=t.sort!.reduce(:+)+t[0]*(n>1?n-3:0);(n/2).times{|k|z+=[0,2*t[1]-t[0]-t[~k*2]].min};z}

Ungolfing:

def b(n, t) # using length as an argument
  z = t.sort!.reduce(:+) + t[0] * (n>1 ? n-3 : 0)
  (n/2).times do each |k|
    a = t[1]*2 - t[0] - t[-(k+1)*2] # ~k == -(k+1)
    z += [0, a].min
  end
  return z
end
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.