Le problème du pont et de la torche

17

L'inspiration pour ce casse - tête de golf de code est le problème du pont et la flamme , où d personnes au début d'un pont doivent tous franchir dans le moins de temps.

Le hic, c'est qu'au plus deux personnes peuvent traverser en même temps, sinon le pont s'écraserait sous leur poids, et le groupe n'a accès qu'à une seule torche, qui doit être portée pour traverser le pont.

Chaque personne dans le puzzle entier a un temps spécifié qu'elle prend pour traverser le pont. Si deux personnes se croisent, la paire va aussi lentement que la personne la plus lente.

Il n'y a pas de nombre fixe de personnes qui doivent traverser le pont; votre solution DOIT fonctionner pour n'importe quelle valeur de d .

Vous n'avez pas besoin d'utiliser d'entrée standard pour ce problème, mais pour expliquer le problème, j'utiliserai le format d'entrée et de sortie suivant pour l'explication. Le premier chiffre, d , est le nombre de personnes au début du pont. Ensuite, le code recherchera les nombres d , chacun représentant la vitesse d'une personne.

La sortie du code sera le MOINS de temps requis pour traverser tout le monde du début du pont à la fin du pont, tout en répondant aux critères expliqués précédemment.

Voici quelques cas d'entrée et de sortie et l'explication du premier cas d'entrée. C'est à vous de dériver un algorithme à partir de ces informations pour résoudre le problème dans le moins d'octets de code possible.

contribution

4
1 2 5 8

production

15

Pour atteindre cette sortie, les gens doivent traverser de la manière suivante.

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)

Voici un autre cas de test pour vous guider sur votre chemin.

contribution

5
3 1 6 8 12

production

29

Règles:

  1. Supposons que l'entrée ne sera pas triée et vous devez le faire vous-même (si vous en avez besoin)
  2. Le nombre de personnes dans le puzzle n'est pas fixé à 4 (N> = 1)
  3. Chaque passage de groupe et individuel doit avoir une torche. Il n'y a qu'une seule torche.
  4. Chaque groupe doit être composé d'un maximum de 2 personnes seulement!
  5. Non, vous ne pouvez pas sauter du pont et nager de l'autre côté. Pas d'autres astuces comme celle-ci;).
baseman101
la source
Comme trouvé par xnor ci-dessous, assurez-vous de tester des cas comme 1 3 4 5, qui devraient renvoyer 14 et non 15.
ravi
1 4 5 6 7a un problème similaire. 25 contre 26
Sherlock9
1
Cela semble être une question étrange, mais quel est le nombre minimum et maximum de personnes dans le puzzle? En travaillant sur mes solutions, j'ai remarqué qu'elles ne traitent que les N >= 2personnes (ce qui signifie, curieusement, que c'est un travail supplémentaire pour gérer le cas trivial de "1 personne a besoin de traverser"), donc une clarification sur ce point serait formidable. Merci d'avance.
Sherlock9
@ Sherlock9 Supposons que votre solution doit fonctionner pour N> = 1
baseman101
Les cas de test montrent que nous pouvons utiliser la longueur comme paramètre, mais pouvez-vous préciser cela dans les règles? L'entrée peut-elle être le tableau des heures et le nombre de personnes, ou est-ce seulement les heures autorisées?
Sherlock9

Réponses:

8

Python 3, 100 99 octets

une solution récursive

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

Merci à @xnor pour cet article

Grâce à @lirtosiast, économisez 2 octets, à @movatica, économisez 1 octet et à @gladed indiquant que ma solution précédente ne fonctionne pas

utilisez l'astuce suivante pour évaluer quelque chose dans la fonction lambda s.sort() or s ici, nous calculons le tri et renvoyons le résultat du tests.sort()or len(s)>3

Non 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

Résultats

>>> 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
la source
Vous pouvez enregistrer 1 octet et passer len(s)==2àlen(s)<3
Mr Public
@MrPublic vous trouvez un bug, j'ai changé la solution ce n'est s[0]*(len(s)==2)pas (s[0]*len(s)==2) avec le bug f([1]) -> 0que nous ne pouvons pas le remplacer par <3merci
Erwan
Ce document a une expression pour le moment optimal qui est le minimum de multiples possibilités. Êtes-vous sûr que votre solution est optimale dans tous les cas?
xnor
@xnor wow, il semble que j'ai la solution optimale J'utilise l'expression dans le lemme 3A5:22
Erwan
1
Mise à jour de @movatica avec votre suggestion
Erwan
4

Python 2, 119 114 112 112 119 110 100 95 octets

On m'a conseillé de séparer mes réponses.

Une solution utilisant Theorem 1, A2:09 ce papier xnor linked . Pour citer le document (le changer en indexation nulle):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
Sherlock9
la source
êtes-vous sûr que nous pouvons supposer que la longueur peut être un argument?
Erwan
@Erwan Les exemples de cas de test semblent le permettre. Je vais demander
Sherlock9
2

Ruby, 94 133 97 96 101 96 99 octets

On m'a conseillé de séparer mes réponses.

Ceci est une solution basée sur l'algorithme décrit dans A6:06-10de cet article sur le problème du pont et de la torche .

Edit: Correction d'un bug où a=s[0]n'est pas encore défini quand aest appelé à la fin 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
Sherlock9
la source
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))}

Un peu golfé:

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
}

Testeur:

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

Pas génial en général, mais peut-être pas mal pour une langue fortement typée. Et à contrecœur grâce à xnor d'avoir repéré un cas que je n'ai pas attrapé.

content
la source
Ce document a une expression pour le moment optimal qui est le minimum de multiples possibilités. Êtes-vous sûr que votre solution est optimale dans tous les cas?
xnor
1

Rubis, 104 95 93 octets

On m'a conseillé de séparer mes réponses.

Il s'agit d'une solution basée sur ma solution Python 2 et Theorem 1, A2:09de cet article sur le problème du pont et de la torche .

->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
Sherlock9
la source