O problema da ponte e da tocha


17

A inspiração para este enigma de golfe código é o problema da ponte e da tocha , em que d pessoas no início de uma ponte todos devem atravessá-la no menor espaço de tempo.

O problema é que no máximo duas pessoas podem atravessar ao mesmo tempo, caso contrário, a ponte esmagará com o peso e o grupo só terá acesso a uma tocha, que deve ser carregada para atravessar a ponte.

Cada pessoa no quebra-cabeça inteiro tem um tempo especificado para atravessar a ponte. Se duas pessoas se cruzam, o par fica tão lento quanto a pessoa mais lenta.

Não há um número definido de pessoas que precisam atravessar a ponte; sua solução DEVE trabalhar com qualquer valor de d .

Você não precisa usar a entrada padrão para esse problema, mas, para explicar o problema, usarei o seguinte formato de entrada e saída para a explicação. O primeiro número, d , é o número de pessoas no início da ponte. Então, o código procurará por números d , cada um representando a velocidade de uma pessoa.

A saída do código será a ÚLTIMA quantidade de tempo necessária para atravessar todos, desde o início da ponte até o final da ponte, atendendo aos critérios explicados anteriormente.

Aqui estão alguns casos de entrada e de saída e a explicação para o primeiro caso de entrada. Cabe a você derivar um algoritmo dessas informações para resolver o problema no menor número possível de bytes de código possível.

entrada

4
1 2 5 8

resultado

15

Para alcançar esse resultado, as pessoas devem atravessar da seguinte maneira.

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)

Aqui está outro caso de teste para guiá-lo ao longo do caminho.

entrada

5
3 1 6 8 12

resultado

29

Regras:

  1. Suponha que a entrada não será classificada e você deve fazê-lo por conta própria (se necessário)
  2. O número de pessoas no quebra-cabeça não é fixado em 4 (N> = 1)
  3. Todo grupo e travessia individual deve ter uma tocha. Existe apenas uma tocha.
  4. Cada grupo deve consistir em no máximo apenas 2 pessoas!
  5. Não, você não pode pular da ponte e nadar para o outro lado. Não há outros truques como este;).

Como encontrado por xnor abaixo, certifique-se de casos de teste como 1 3 4 5, que deve retornar 14 não 15.
gladed

1 4 5 6 7tem um problema semelhante. 25 vs 26
Sherlock9

11
Parece uma pergunta estranha, mas qual é o número mínimo e máximo de pessoas no quebra-cabeça? Enquanto trabalhava em minhas soluções, notei que elas apenas lidam com N >= 2pessoas (o que significa que, por incrível que pareça, é um trabalho extra lidar com o caso trivial de "uma pessoa precisa atravessar"), portanto, alguns esclarecimentos sobre esse ponto seriam ótimos. Desde já, obrigado.
Sherlock9

@ Sherlock9 Assuma sua solução trabalho obrigação para N> = 1
baseman101

Os casos de teste mostram que podemos usar o comprimento como parâmetro, mas você pode deixar isso mais claro nas regras? É permitido que a entrada seja o intervalo de horas e o número de pessoas ou apenas os horários são permitidos?
Sherlock9

Respostas:


8

Python 3, 100 99 bytes

uma solução 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:])

Obrigado a @xnor por este artigo

Graças a @lirtosiast salvar 2 bytes, @movatica salvar 1 bytes e @gladed apontando que minha solução anterior não funciona

use o seguinte truque para avaliar algo na função lambda s.sort() or s aqui, calculamos a classificação e retornamos o resultado do testes.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

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

Você pode salvar 1 byte e alterar len(s)==2paralen(s)<3
Mr Public

@MrPublic você encontrar um bug, eu mudei a solução é s[0]*(len(s)==2)não (s[0]*len(s)==2) com o bug f([1]) -> 0por isso que não podemos substituir por <3graças
Erwan

Este artigo tem uma expressão para o tempo ideal, que é o mínimo de múltiplas possibilidades. Tem certeza de que sua solução é ótima em todos os casos?
Xnor

@xnor wow, parece que eu tenho a solução ideal, eu uso a expressão no lema 3A5:22
Erwan

11
atualização @movatica com você sugestão
Erwan

4

Python 2, 119 114 112 119 110 100 95 bytes

Fui aconselhado a separar minhas respostas.

Uma solução usando Theorem 1, A2:09 este documento xnor linked . Para citar o artigo (alterando-o para indexação zero):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

tem certeza de que podemos assumir que o comprimento pode ser um argumento?
Erwan

@ Erwan Os casos de teste de exemplo parecem permitir isso. Eu pergunto
Sherlock #

2

Ruby, 94 133 97 96 101 96 99 bytes

Fui aconselhado a separar minhas respostas.

Esta é uma solução com base no algoritmo descrito na A6:06-10de este trabalho na ponte e Torch problema .

Editar: Corrigindo um bug onde a=s[0]ainda não está definido quando aé chamado no final if 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 (ver)

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 um pouco:

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
}

Testador:

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

Não é bom em geral, mas talvez não seja ruim para um idioma fortemente tipado. E relutante, graças ao xnor por detectar um caso que não entendi.


Este artigo tem uma expressão para o tempo ideal, que é o mínimo de múltiplas possibilidades. Tem certeza de que sua solução é ótima em todos os casos?
Xnor

1

Ruby, 104 95 93 bytes

Fui aconselhado a separar minhas respostas.

Esta é uma solução baseada em minha solução Python 2 e Theorem 1, A2:09do presente trabalho na ponte e Torch problema .

->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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.