ช่วงเวลาที่ดีในการปฏิเสธ


16

การตั้งค่า

สมมติว่าคุณได้รับฟิวส์nด้วย 1 ≤ n ≤ 5 ซึ่งแต่ละอันมีความยาวเมตรและที่ฟิวส์แต่ละอันมีอัตราการเผาไหม้ที่เกี่ยวข้องNเมตรต่อDชั่วโมง

ฟิวส์สามารถติดไฟที่ปลายด้านหนึ่งหรือทั้งสองด้านจากนั้นดับที่ปลายด้านหนึ่งหรือทั้งสองข้าง relit, re-extinguished และอื่น ๆ หลาย ๆ ครั้งตามต้องการจนกว่าฟิวส์จะถูกใช้จนหมด คุณสามารถจุดไฟและดับฟิวส์ได้ทันทีและคุณสามารถสังเกตได้ทันทีว่าฟิวส์ถูกใช้หมดแล้ว (ไหม้)

ฟิวส์ไม่สามารถตัดและไม่สามารถติดที่ใดก็ได้ยกเว้นที่ปลาย

การตั้งค่าดังกล่าวช่วยให้ระบบจับเวลามีความแม่นยำอย่างไม่สิ้นสุดโดยการวัดเวลาระหว่างเหตุการณ์ไฟ / การใช้ฟิวส์สองครั้ง ตัวอย่างเช่นเมื่อได้รับฟิวส์สองครั้งที่มีอัตราการเผาไหม้ 1 เมตรต่อชั่วโมงคุณสามารถวัดได้ 45 นาที (3/4 ชั่วโมง)

  1. พร้อมกัน: ส่องฟิวส์แรกที่ปลายทั้งสองข้างส่องไฟฟิวส์ที่สองที่ปลายด้านหนึ่งและทำเครื่องหมายจุดเริ่มต้นของช่วงเวลาของคุณ
  2. จุดไฟที่สองของฟิวส์ที่สองในทันทีที่ฟิวส์แรกถูกใช้ (30 นาทีต่อมา)
  3. ทำเครื่องหมายจุดสิ้นสุดของช่วงเวลาของคุณในทันทีที่มีการใช้ฟิวส์ตัวที่สอง (15 นาทีต่อมา)

ความท้าทาย

กำหนดจำนวนเศษส่วนของเวลาtและชุดของเศษส่วนnแทนอัตราการเผาไหม้ที่แน่นอนของฟิวส์nเขียนโปรแกรมหรือฟังก์ชันที่เอาต์พุต / ส่งกลับค่าความจริงถ้าtชั่วโมงสามารถวัดได้อย่างแม่นยำผ่านการเผาระบบของฟิวส์หรือ ค่าที่ผิดพลาดเป็นอย่างอื่น

อินพุตไปยังโปรแกรมสามารถเป็นดังต่อไปนี้:

  • อาร์กิวเมนต์บรรทัดคำสั่งของฟอร์ม TN/TD N1/D1 N2/D2 N3/D3 ...
  • สตริงของแบบฟอร์มTN/TD N1/D1 N2/D2 N3/D3 ...อ่านจากstdinหรือเทียบเท่า
  • สตริงของฟอร์มที่TN/TD N1/D1 N2/D2 N3/D3 ...ส่งผ่านเป็นอาร์กิวเมนต์ของฟังก์ชัน
  • อาร์เรย์ของสตริงที่["TN/TD", "N1/D1", "N2/D2", "N3/D3", ...]ส่งผ่านเป็นอาร์กิวเมนต์ของฟังก์ชัน

ในทุกกรณีT = TN/ TDที่TN, TD∈ [1,10000]

ในทำนองเดียวกันในทุกกรณี: เผาอัตราฟิวส์ฉัน = N ฉัน / D ฉัน = N<i>/ D<i>ที่N<i>, D<i>∈ [1,10] ∀ ฉัน

คุณอาจคิดว่าจะมีฟิวส์อยู่ระหว่าง 1 ถึง 5 ฟิวส์ (รวมอยู่ด้วย) และอินพุตทั้งหมดนั้นใช้ได้และอยู่ในช่วง คุณอาจสมมติว่าเศษส่วนที่ป้อนเข้าทั้งหมดจะได้รับในเงื่อนไขต่ำสุด

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

เกณฑ์การให้คะแนน

นี่คือความท้าทายของดังนั้นการส่งตามที่สั้นที่สุดเป็นไบต์จะได้รับรางวัลชนะ


ตัวอย่างอินพุต / เอาท์พุต

input:  29/6 3/2 2/3 3/5 3/7 7/5
output: true

One solution:
  - light both ends of fuse 1, mark start of interval
  - on fuse 1 consumption: light both ends of fuse 2, light one end of fuse 5
  - on fuse 5 consumption: extinguish one end of fuse 2, light both ends of fuse 3,
    light both ends of fuse 4
  - on fuse 2 consumption: extinguish one end of fuse 3, extinguish both ends of
    fuse 4
  - on fuse 3 consumption: relight one end of fuse 4
  - on consumption of fuse 4: mark end of interval (29/6 hours)

input:  2/1 3/1 5/1 7/1
output: false

input:  5/1 6/1 1/6 9/1 1/9
output: true

One solution:
  - light fuse 1 at one end, light fuse 2 at both ends, light fuse 4 at both ends
  - on fuse 1 consumption: extinguish one end of fuse 2, mark start of interval
  - on fuse 4 consumption: relight one end of fuse 2
  - on fuse 2 consumption: mark end of interval (5 hours)

มีความสุข! :)


@ MartinBüttnerฉันจะเดาว่ามันจะเป็นข้อ จำกัด จำนวนจุดลอยตัว
hmatt1

2
@ MartinBüttnerฉันยอมรับว่ามันไม่ใช่ข้อ จำกัด ของซอร์สโค้ด ฉันไม่คิดว่า [จำกัด แหล่งที่มา] เหมาะกับคำถามนี้ในขณะนี้
hmatt1

@ chilmagic: ฉันต้องการที่จะดึงความสนใจไปที่ความจริงที่ว่าตรรกะจุดลอยไม่สามารถใช้ แต่ถ้าฉันทามติคือว่ามันไม่ได้ใช้แท็กที่เหมาะสมฉันจะตัดมัน
COTO

กรณีทดสอบมีขนาดใหญ่เกินไป :)
feersum

5
ฮ่า ๆ ฉันใช้อัลกอริทึม O ((n!) ^ 3) เพื่อการเล่นกอล์ฟ
feersum

คำตอบ:


8

Python 2, 305

นี่เป็นเวอร์ชั่น golfed มันใช้ไม่ได้จริงสำหรับn> 3เนื่องจากความซับซ้อนของเวลา (และช่องว่าง) นั้นเหมือนกับ3 n 2 ... จริง ๆ แล้วมันอาจจะต่ำเกินไปสำหรับเวลา อย่างไรก็ตามฟังก์ชั่นยอมรับรายการของสตริง

def f(i):
 Z=range;r=map(__import__('fractions').Fraction,i);R=r[1:];n=len(R);L=[[[1]*n,[0]]];g=0
 for m,p in L: 
  for d in([v/3**i%3for i in Z(n)]for v in Z(3**n)):
    try:x=min(m[i]/R[i]/d[i]for i in Z(n)if m[i]*d[i]>0);L+=[[[m[i]-x*R[i]*d[i]for i in Z(n)],[p[0]+x]+p]]
    except:g|=p[0]-r[0]in p
 return g

รุ่นที่ปรับให้เหมาะสมเล็กน้อยสามารถเสร็จสิ้นกรณีทดสอบในสองสามนาที มันก็ยังคงอาจจะช้าไปไม่ได้สำหรับn = 5กรณีแม้ว่า

def fLessslow(i):
 Z=range
 r=map(__import__('fractions').Fraction,i)
 R=r[1:]
 n=len(R)
 L=[((1,)*n,(0,))]
 ls = set(L)
 for m,p in L: 
  if p[0]-r[0]in p: return 1
  for d in([v/3**i%3 for i in Z(n)]for v in Z(3**n)):
   if any(d[i] and m[i]<=0 for i in Z(n)):continue
   try:
    x=min(m[i]/R[i]/d[i]for i in Z(n)if m[i]*d[i]>0)
    thing = (tuple(m[i]-x*R[i]*d[i]for i in Z(n)),(p[0]+x,)+p)
    if thing not in ls:L+=[thing];ls.add(thing)
   except:5
 return 0

print fLessslow('5/1 6/1 1/6 9/1 1/9'.split())
print fLessslow('29/6 3/2 2/3 3/5 3/7 7/5'.split())

1
Nice, 8 upvotes สำหรับรหัส buggy: การเรียกใช้ฟังก์ชันด้วยตัวอย่างในคำอธิบาย: print f ('3/4 1/1 1 / 1'.split ()) ส่งคืนค่า 0 แม้ว่าตามคำอธิบายจะสามารถแก้ไขได้ .
Jakube

@Jakube ขอบคุณสำหรับการทดสอบ ... มันหายากมากในเว็บไซต์นี้! มันได้รับการแก้ไขแล้ว ฉันลืมที่จะหารด้วยตัวประกอบของ 1 หรือ 2 ขึ้นอยู่กับว่าเชือกมีกี่จุด
feersum

3

Python 2, 331

มันยาวกว่าเวอร์ชั่น feersum เล็กน้อย แต่เร็วกว่ามาก การทดสอบทั้งหมดใช้เวลาประมาณ 3 วินาทีบนแล็ปท็อปของฉัน การค้นหาที่สมบูรณ์สำหรับ n = 5 ใช้เวลาประมาณ 10 นาที รหัสบางส่วนคล้ายกับรุ่นของ feersum แต่ฉันไม่ได้คัดลอกรหัสใด ๆ โดยเจตนา

from fractions import*
f=Fraction
r=range
g=lambda x:h(f(x[0]),[1/f(i)for i in x[1:]],[])
def h(t,x,y):
 for i in r(1,3**len(x)):
  c=[[],[],[]]
  for j in r(len(x)):c[i/3**j%3]+=[x[j]]
  n,b,w=c
  m=min(b+[i/2 for i in w])
  if h(t,[i for i in n+[j-m for j in b]+[j-2*m for j in w]if i],[i+m for i in y]+[m]):return True
 return t in y

การใช้งาน:

print g('3/4 1/1 1/1'.split())
print g('29/6 3/2 2/3 3/5 3/7 7/5'.split())
print g('2/1 3/1 5/1 7/1'.split())
print g('5/1 6/1 1/6 9/1 1/9'.split())

คำอธิบาย:

แลมบ์ดานิพจน์ g ทำการประมวลผลอินพุตล่วงหน้าบางส่วนเช่นการแปลงสตริงเป็นเศษส่วนแยกเวลาเป้าหมายจากอัตราการเบิร์นและการคำนวณเวลาการเบิร์น (= 1 / อัตราการเบิร์น)

ฟังก์ชั่น h หารการเบิร์นทั้งหมด x เป็น 3 ชุด n, b และ w (n หมายถึง non_burning, b สำหรับ one_end_burning และ w สำหรับ both_ends_burning) มันวนซ้ำทุกการเตรียมการเหล่านั้น (ยกเว้นการจัดเรียง n = x, b = [], w = []) กำหนดฟิวส์ด้วยอัตราการเผาไหม้ที่สั้นที่สุด (ประหยัดเวลาเป็น m) และเรียก h ด้วยการอัพเดตซ้ำ ใน y ฉันบันทึกทุกครั้งที่เป็นไปได้ที่ใครบางคนสามารถวัดได้โดยใช้ฟิวส์ ในการเรียกแบบเรียกซ้ำค่าเหล่านี้จะได้รับการปรับปรุงด้วย

ทันทีที่ฉันพบค่ามันก็จะยุติการโทรที่แท้จริงด้วย True


4
โปรแกรมเมอร์ Python รุ่นเยาว์ของคุณเสียเวลากับเศษส่วนและจำนวนเต็มขนาดใหญ่ ย้อนกลับไปตอนที่ฉันยังเป็นเด็ก ๆ ทุกสิ่งที่เรามีก็คือ1และ0สิ่งที่เราต้องพิมพ์ครั้งละครั้งที่คอนโซลโดยไม่มีจอภาพ บางครั้งเราไม่ได้มี1s
COTO
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.