El problema del puente y la antorcha

17

La inspiración para este rompecabezas código de golf es el problema del puente y de la antorcha , en la que d personas en el inicio de un puente deben todos cruzarlo en la menor cantidad de tiempo.

El problema es que, como máximo, dos personas pueden cruzar a la vez, de lo contrario el puente se aplastará bajo su peso, y el grupo solo tiene acceso a una antorcha, que debe transportarse para cruzar el puente.

Cada persona en todo el rompecabezas tiene un tiempo específico que toman para cruzar el puente. Si dos personas se cruzan juntas, la pareja va tan lenta como la persona más lenta.

No hay un número establecido de personas que deben cruzar el puente; su solución DEBE funcionar por cualquier valor de d .

No necesita utilizar la entrada estándar para este problema, pero para explicar el problema, utilizaré el siguiente formato de entrada y salida para la explicación. El primer número, d , es el número de personas al comienzo del puente. Luego, el código buscará d números, cada uno de los cuales representa la velocidad de una persona.

La salida del código será la MENOR cantidad de tiempo requerida para cruzar a todos desde el inicio del puente hasta el final del puente, mientras cumple con los criterios explicados anteriormente.

Aquí hay algunos casos de entrada y salida y la explicación para el primer caso de entrada. Depende de usted derivar un algoritmo de esta información para resolver el problema en la menor cantidad de bytes posible de código.

entrada

4
1 2 5 8

salida

15

Para alcanzar este resultado, las personas deben cruzar de la siguiente manera.

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)

Aquí hay otro caso de prueba para guiarlo en su camino.

entrada

5
3 1 6 8 12

salida

29

Reglas:

  1. Suponga que la entrada no se ordenará y debe hacerlo por su cuenta (si es necesario)
  2. El número de personas en el rompecabezas no está fijado en 4 (N> = 1)
  3. Cada grupo y cruce individual debe tener una antorcha. Solo hay una antorcha.
  4. ¡Cada grupo debe constar de un máximo de solo 2 personas!
  5. No, no puedes saltar del puente y nadar hacia el otro lado. No hay otros trucos como este;).
baseman101
fuente
Como se encuentra en xnor a continuación, asegúrese de probar casos como 1 3 4 5, que deberían devolver 14 no 15.
claro
1 4 5 6 7tiene un problema similar 25 contra 26
Sherlock9
1
Esto parece una pregunta extraña, pero ¿cuál es el número mínimo y máximo de personas en el rompecabezas? Mientras trabajaba en mis soluciones, noté que solo manejan N >= 2personas (lo que significa, curiosamente que es un trabajo adicional manejar el caso trivial de "1 persona necesita cruzar"), por lo que alguna aclaración sobre este punto sería genial. Gracias por adelantado.
Sherlock9
@ Sherlock9 Suponga que su solución debe funcionar para N> = 1
baseman101
Los casos de prueba muestran que podemos usar la longitud como parámetro, pero ¿puedes aclararlo en las reglas? ¿Se permite que la entrada sea el conjunto de tiempos y el número de personas, o solo se permiten los tiempos?
Sherlock9

Respuestas:

8

Python 3, 100 99 bytes

una solución recursiva

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:])

Gracias a @xnor por este artículo

Gracias a @lirtosiast save 2 bytes, @movatica save 1 bytes y @gladed señalando que mi solución anterior no funciona

use el siguiente truco para evaluar algo en la función lambda s.sort() or s aquí calculamos ordenar y devolver el resultado de la pruebas.sort()or len(s)>3

Sin golf

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

Resultados

>>> 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
Erwan
fuente
Puede guardar 1 byte y cambiar len(s)==2alen(s)<3
Mr Public
@MrPublic, encuentra un error, cambié la solución, s[0]*(len(s)==2)no es (s[0]*len(s)==2) con el error, f([1]) -> 0por eso no podemos reemplazarlo <3gracias
Erwan
Este artículo tiene una expresión para el tiempo óptimo que es el mínimo de múltiples posibilidades. ¿Estás seguro de que tu solución es óptima en todos los casos?
xnor
@xnor wow parece que tengo la solución óptima. Uso la expresión en Lemma 3A5:22
Erwan
1
@movatica actualización con su sugerencia
Erwan
4

Python 2, 119 114 112 119 110 100 95 bytes

Me han aconsejado que separe mis respuestas.

Una solución utilizando Theorem 1, A2:09 este documento xnor vinculado . Para citar el artículo (cambiándolo a indexación cero):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))

No golfista:

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
Sherlock9
fuente
¿estás seguro de que podemos suponer que la longitud puede ser un argumento?
Erwan
@Erwan Los casos de prueba de ejemplo parecen permitirlo. Preguntaré
Sherlock9
2

Ruby, 94 133 97 96 101 96 99 bytes

Me han aconsejado que separe mis respuestas.

Esta es una solución basada en el algoritmo descrito en A6:06-10de este papel en el puente y la antorcha problema .

Editar: Corregir un error donde a=s[0]aún no está definido cuando ase llama al final si 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]}

No golfista:

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
Sherlock9
fuente
1

Scala, 113 135 (maldita sea)

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 algo:

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
}

Ensayador:

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(", "))

No es genial en general, pero quizás no sea malo para un lenguaje fuertemente tipado. Y de mala gana gracias a xnor por detectar un caso que no entendí.

claro
fuente
Este artículo tiene una expresión para el tiempo óptimo que es el mínimo de múltiples posibilidades. ¿Estás seguro de que tu solución es óptima en todos los casos?
xnor
1

Ruby, 104 95 93 bytes

Me han aconsejado que separe mis respuestas.

Esta es una solución basada en mi solución Python 2 y Theorem 1, A2:09en este documento sobre el problema del puente y la antorcha .

->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}

No golfista:

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
Sherlock9
fuente