ปัญหาสะพานและคบเพลิง


17

แรงบันดาลใจสำหรับปริศนากอล์ฟรหัสนี้คือปัญหาของสะพานและคบเพลิงซึ่งdคนที่เริ่มต้นของสะพานทั้งหมดจะต้องข้ามมันในปริมาณที่น้อยที่สุดของเวลา

จับได้ว่ามากที่สุดสองคนสามารถข้ามในเวลาเดียวกันมิฉะนั้นสะพานจะบี้ภายใต้น้ำหนักของพวกเขาและกลุ่มมีเพียงการเข้าถึงหนึ่งไฟฉายซึ่งจะต้องดำเนินการข้ามสะพาน

แต่ละคนในตัวต่อทั้งหมดมีเวลาที่กำหนดที่จะใช้ในการเดินข้ามสะพาน ถ้าคนสองคนข้ามกันทั้งคู่จะช้าเท่ากับคนที่ช้าที่สุด

ไม่มีคนกำหนดจำนวนคนที่ต้องข้ามสะพาน โซลูชันของคุณต้องทำงานเพื่อค่าใด ๆ ของd 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
gladed

1 4 5 6 7มีปัญหาที่คล้ายกัน 25 กับ 26
Sherlock9

1
ดูเหมือนว่าเป็นคำถามแปลก ๆ แต่อะไรคือจำนวนคนที่น้อยที่สุดและมากที่สุดในปริศนา ในขณะที่ทำงานกับวิธีแก้ปัญหาของฉันฉันสังเกตเห็นว่าพวกเขาจัดการกับN >= 2ผู้คนเท่านั้น(หมายถึงแปลกมากที่มันเป็นงานพิเศษที่จะจัดการกับกรณีเล็ก ๆ น้อย ๆ ของ "1 คนจำเป็นต้องข้าม") ดังนั้นการชี้แจงในประเด็นนี้จะดีมาก ขอบคุณล่วงหน้า.
Sherlock9

@ Sherlock9 สมมติว่าโซลูชันของคุณต้องใช้กับ N> = 1
baseman101

กรณีทดสอบแสดงให้เห็นว่าเราสามารถใช้ความยาวเป็นพารามิเตอร์ แต่คุณสามารถทำให้ชัดเจนในกฎได้หรือไม่ อินพุตได้รับอนุญาตให้เป็นอาร์เรย์ของเวลาและจำนวนคนหรือเป็นเพียงเวลาที่อนุญาตหรือไม่
Sherlock9

คำตอบ:


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

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

ผล

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

@MrPublic คุณพบข้อผิดพลาดผมเปลี่ยนวิธีการแก้ก็s[0]*(len(s)==2)ไม่ได้(s[0]*len(s)==2) มีข้อผิดพลาดf([1]) -> 0ที่ว่าทำไมเราไม่สามารถแทนที่โดย<3ขอบคุณ
Erwan

กระดาษนี้มีการแสดงออกสำหรับเวลาที่เหมาะสมที่เป็นไปได้น้อยที่สุด คุณแน่ใจหรือว่าทางออกของคุณดีที่สุดในทุกกรณี?
xnor

@ xnor ดูเหมือนว่าฉันมีทางออกที่ดีที่สุดที่ฉันใช้การแสดงออกในเลมม่า 3A5:22
Erwan

1
@movatica อัปเดตพร้อมข้อเสนอแนะ
Erwan

4

Python 2, 119 114 112 119 110 100 95 ไบต์

ฉันได้รับคำแนะนำให้แยกคำตอบออก

วิธีการแก้ปัญหาโดยใช้Theorem 1, A2:09 xnor เชื่อมโยงนี้ ในการอ้างอิงกระดาษ (เปลี่ยนเป็น zero-indexing):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

@Erwan ตัวอย่างกรณีทดสอบดูเหมือนจะอนุญาต ฉันจะถาม
Sherlock9

2

Ruby, 94 133 97 96 101 96 99 ไบต์

ฉันได้รับคำแนะนำให้แยกคำตอบออก

นี่คือวิธีการแก้ปัญหาเป็นไปตามขั้นตอนวิธีการที่อธิบายไว้ในA6:06-10ของบทความนี้บนสะพานและไฟฉายปัญหา

แก้ไข:แก้ไขข้อผิดพลาดที่a=s[0]ยังไม่ได้กำหนดไว้เมื่อถูกเรียกในตอนท้ายถ้าas.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 (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))}

Ungolfed บ้าง:

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
}

Tester:

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

Ruby, 104 95 93 ไบต์

ฉันได้รับคำแนะนำให้แยกคำตอบออก

นี่คือวิธีการแก้ปัญหาขึ้นอยู่กับวิธีการแก้ปัญหางูหลาม 2 ของฉันและTheorem 1, A2:09ของบทความนี้บนสะพานและไฟฉายปัญหา

->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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.