Проблема "Міст і факел"


17

Натхнення для цього коду гольф головоломки є проблема моста і факел , в якому г люди на початку моста все повинні перетнути його в найменшу кількість часу.

Зловживання полягає в тому, що максимум двоє людей можуть перетнутись одразу, інакше міст зруйнується під їхньою вагою, а група має доступ лише до одного факела, який потрібно перевезти, щоб перейти через міст.

У кожної людини в цілій головоломці є визначений час, який вона бере на прогулянку через міст. Якщо двоє людей перетинаються разом, пара йде так само повільно, як і найповільніша людина.

Немає встановленої кількості людей, які повинні перейти міст; ваше рішення ОБОВ'ЯЗКОВО працює над будь-яким значенням d .

Для цієї проблеми не потрібно використовувати стандартний ввід, але для пояснення проблеми я буду використовувати наступний формат вводу та виводу для пояснення. Перше число, d - це кількість людей на початку мосту. Потім код просканує на d числа, кожне з яких представляє швидкість людини.

Вихід коду буде ДІЛЬШИЙ час, необхідний для перетину всіх від початку мосту до кінця мосту, дотримуючись критеріїв, пояснених раніше.

Ось декілька вхідних та вихідних випадків та пояснення першого вхідного випадку. Ви повинні вивести алгоритм з цієї інформації, щоб вирішити проблему в найменших можливих байтах коду.

вхід

4
1 2 5 8

вихід

15

Щоб досягти цього результату, люди повинні перетнутись таким чином.

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)

Ось ще один тестовий випадок, який допоможе вам на вашому шляху.

вхід

5
3 1 6 8 12

вихід

29

Правила:

  1. Припустимо, що введення не буде відсортовано, і ви повинні зробити це самостійно (якщо потрібно)
  2. Кількість людей у ​​головоломці не визначено на рівні 4 (N> = 1)
  3. Кожна група та індивідуальний переїзд повинні мати факел. Є лише один факел.
  4. Кожна група повинна складатися з максимум 2 осіб!
  5. Ні, ви можете не зістрибнути з мосту і переплисти на інший бік. Жодних інших хитрощів, як це;).

Як виявив xnor нижче, обов'язково перевіряйте такі випадки 1 3 4 5, які повинні повернутися 14, а не 15.
засклений

1 4 5 6 7має подібну проблему. 25 проти 26
Шерлок9

1
Це здається дивним питанням, але яка мінімальна та максимальна кількість людей у ​​головоломці? Працюючи над своїми рішеннями, я помітив, що вони поводяться лише з N >= 2людьми (це означає, як це не дивно, що для вирішення тривіального випадку "1 людина має перетнути" зайва робота), тому деякі уточнення з цього приводу були б чудовими. Заздалегідь спасибі.
Шерлок9

@ Sherlock9 Припустимо, що ваше рішення повинно працювати для N> = 1
baseman101

Тестові випадки показують, що ми можемо використовувати довжину як параметр, але чи можете ви зробити це більш зрозумілим у правилах? Чи дозволено вводити масив разів та кількість людей, або дозволений лише час?
Шерлок9

Відповіді:


8

Python 3, 100 99 байт

рекурсивне рішення

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

Завдяки @xnor за цей документ

Завдяки @lirtosiast зберегти 2 байти, @movatica зберегти 1 байт і @gladed вказуючи на те, що моє попереднє рішення не працює

використовуємо наступний трюк, щоб оцінити щось у лямбда-функції, s.sort() or s тут ми обчислимо сортування та повернемо результат тестуs.sort()or len(s)>3

Безумовно

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

Результати

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

Ви можете зберегти 1 байт і змінити його len(s)==2наlen(s)<3
паблік Public,

@MrPublic ви знайдете помилку, я змінив рішення, це s[0]*(len(s)==2)не (s[0]*len(s)==2) з помилкою f([1]) -> 0, тому ми не можемо замінити <3подяку
Ерван

У цьому документі є вираз для оптимального часу, який є мінімальним числом можливостей. Ви впевнені, що ваше рішення є оптимальним у всіх випадках?
xnor

@xnor Вау здається, що в мене є оптимальне рішення, я використовую вираз у лемі 3A5:22
Ерван

1
Оновлення @movatica з вашою пропозицією
Ерван

4

Пітон 2, 119 114 112 119 110 100 95 байт

Мені порадили відокремлювати відповіді.

Рішення із використанням Theorem 1, A2:09 цього паперового xnor пов'язано . Щоб процитувати статтю (змінивши її на нульову індексацію):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

Ви впевнені, що можемо припустити, що довжина може бути аргументом?
Ерван

@Erwan Приклад тестових випадків, здається, дозволяє це. Я запитаю
Шерлок9

2

Рубі, 94 133 97 96 101 96 99 байт

Мені порадили відокремлювати відповіді.

Це рішення на основі алгоритму , описаного в A6:06-10з цього паперу на мосту і факелом проблеми .

Редагувати: виправлення помилки, де a=s[0]ще не визначено, коли aвикликається в кінці, якщо 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

Скала, 113 135 (дарніт)

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

Дещо незрозумілий:

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
}

Тестер:

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

Загалом не чудово, але, можливо, непогано для сильно набраної мови. І зневажливо завдяки xnor за те, що він помітив справу, яку я не спіймав.


У цьому документі є вираз для оптимального часу, який є мінімальним числом можливостей. Ви впевнені, що ваше рішення є оптимальним у всіх випадках?
xnor

1

Рубі, 104 95 93 байт

Мені порадили відокремлювати відповіді.

Це рішення, засноване на моєму рішенні Python 2 і Theorem 1, A2:09на цій роботі про проблему 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.