Masalah Jembatan dan Obor

17

Inspirasi untuk ini teka-teki kode golf adalah Jembatan dan Torch masalah , di mana d orang pada awal jembatan semua harus menyeberang dalam jumlah sedikit waktu.

Tangkapannya adalah bahwa paling banyak dua orang dapat menyeberang sekaligus, jika tidak jembatan akan hancur karena beratnya, dan kelompok hanya memiliki akses ke satu obor, yang harus dibawa untuk menyeberangi jembatan.

Setiap orang di seluruh teka-teki memiliki waktu yang ditentukan untuk berjalan melintasi jembatan. Jika dua orang saling bersilangan, pasangan berjalan selambat orang paling lambat.

Tidak ada jumlah orang yang harus menyeberangi jembatan; solusi Anda HARUS bekerja untuk nilai d .

Anda tidak perlu menggunakan input standar untuk masalah ini, tetapi demi menjelaskan masalah, saya akan menggunakan format input dan output berikut untuk penjelasan. Angka pertama, d , adalah jumlah orang di awal jembatan. Kemudian, kode akan memindai angka d , masing-masing mewakili kecepatan seseorang.

Output kode akan menjadi jumlah waktu TERAKHIR yang diperlukan untuk melintasi semua orang dari awal jembatan ke ujung jembatan, sementara memenuhi kriteria yang dijelaskan sebelumnya.

Berikut adalah beberapa kasus input dan kasus output dan penjelasan untuk kasus input pertama. Terserah kepada Anda untuk memperoleh algoritma dari informasi ini untuk menyelesaikan masalah dalam byte kode sesedikit mungkin.

memasukkan

4
1 2 5 8

keluaran

15

Untuk mencapai hasil ini, orang-orang harus menyeberang dengan cara berikut.

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)

Berikut ini adalah test case lain untuk memandu Anda.

memasukkan

5
3 1 6 8 12

keluaran

29

Aturan:

  1. Asumsikan bahwa input tidak akan diurutkan, dan Anda harus melakukannya sendiri (jika perlu)
  2. Jumlah orang dalam puzzle tidak tetap pada 4 (N> = 1)
  3. Setiap kelompok dan persilangan individu harus memiliki obor. Hanya ada satu obor.
  4. Setiap grup harus terdiri dari maksimal hanya 2 orang!
  5. Tidak, Anda tidak boleh melompat dari jembatan dan berenang ke sisi lain. Tidak ada trik lain seperti ini;).
baseman101
sumber
Seperti yang ditemukan oleh xnor di bawah ini, pastikan untuk menguji kasus-kasus seperti 1 3 4 5, yang seharusnya mengembalikan 14 bukan 15.
memudar
1 4 5 6 7memiliki masalah serupa. 25 vs 26
Sherlock9
1
Ini sepertinya pertanyaan aneh, tetapi berapa jumlah minimum dan maksimum orang dalam puzzle? Saat mengerjakan solusi saya, saya perhatikan bahwa mereka hanya menangani N >= 2orang (artinya, anehnya itu pekerjaan ekstra untuk menangani kasus sepele "1 orang perlu menyeberang"), sehingga beberapa klarifikasi tentang hal ini akan menjadi besar. Terima kasih sebelumnya.
Sherlock9
@ Sherlock9 Asumsikan solusi Anda harus bekerja untuk N> = 1
baseman101
Kasus uji menunjukkan bahwa kita dapat menggunakan panjang sebagai parameter, tetapi bisakah Anda membuatnya lebih jelas dalam aturan? Apakah input diperbolehkan menjadi array waktu dan jumlah orang, atau hanya kali saja diizinkan?
Sherlock9

Jawaban:

8

Python 3, 100 99 byte

solusi rekursif

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

Terima kasih kepada @xnor untuk makalah ini

Terima kasih kepada @ lirtosiast simpan 2 byte, @movatica simpan 1 byte dan @gladed menunjukkan bahwa solusi saya sebelumnya tidak berfungsi

gunakan trik berikut untuk mengevaluasi sesuatu dalam fungsi lambda di s.sort() or s sini kita menghitung sort dan mengembalikan hasil tess.sort()or len(s)>3

Tidak disatukan

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

Hasil

>>> 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
sumber
Anda dapat menyimpan 1 byte dan mengubahnya len(s)==2kelen(s)<3
Mr Public
@Mrpublic Anda menemukan bug, saya mengubah solusi itu s[0]*(len(s)==2)bukan (s[0]*len(s)==2) dengan bug f([1]) -> 0itu sebabnya kami tidak bisa menggantinya dengan <3terima kasih
Erwan
Makalah ini memiliki ekspresi untuk waktu optimal yang merupakan min dari beberapa kemungkinan. Apakah Anda yakin solusi Anda optimal dalam semua kasus?
xnor
@ xnor wow sepertinya saya punya solusi optimal Saya menggunakan ekspresi dalam Lemma 3A5:22
Erwan
1
@movatica diperbarui dengan saran Anda
Erwan
4

Python 2, 119 114 112 119 110 100 95 byte

Saya disarankan untuk memisahkan jawaban saya.

Solusi penggunaan Theorem 1, A2:09 makalah ini xnatau ditautkan . Mengutip makalah (mengubahnya menjadi pengindeksan-nol):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))

Tidak melakukan pelanggaran:

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
sumber
apakah Anda yakin kita dapat berasumsi bahwa panjang dapat menjadi argumen?
Erwan
@ Erwan Contoh uji kasus tampaknya memungkinkan. Saya akan bertanya
Sherlock9
2

Ruby, 94 133 97 96 101 96 99 byte

Saya disarankan untuk memisahkan jawaban saya.

Ini adalah solusi yang didasarkan pada algoritma yang dijelaskan dalam A6:06-10dari makalah ini di Jembatan dan Torch Masalah .

Sunting: Memperbaiki bug a=s[0]yang belum didefinisikan saat adipanggil di akhir jika 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]}

Tidak melakukan pelanggaran:

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

Agak tidak disatukan:

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
}

Penguji:

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

Tidak hebat secara umum, tapi mungkin tidak buruk untuk bahasa yang sangat diketik. Dan bersyukur kepada xnor karena telah menemukan case yang tidak saya tangkap.

pudar
sumber
Makalah ini memiliki ekspresi untuk waktu optimal yang merupakan min dari beberapa kemungkinan. Apakah Anda yakin solusi Anda optimal dalam semua kasus?
xnor
1

Ruby, 104 95 93 byte

Saya disarankan untuk memisahkan jawaban saya.

Ini adalah solusi berdasarkan saya solusi Python 2 dan Theorem 1, A2:09dari makalah ini di Jembatan dan Torch Masalah .

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

Tidak melakukan pelanggaran:

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
sumber