เมื่อกระสุนชนกัน


16

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

งาน

รับรายการความเร็วกระสุนตามลำดับที่กำหนดในการยิงตรวจสอบว่ากระสุนทั้งหมดถูกทำลายหรือไม่

กฎระเบียบ

  • อินพุตคือรายการของจำนวนเต็มไม่เป็นลบคั่นด้วยตัวคั่นใด ๆ และมีอักขระตัวเลือกหนึ่งตัวก่อนและหลัง เหล่านี้เป็นปัจจัยการผลิตที่ถูกต้อง: และ1 2 3 4 5 6 [1,2,3,4,5,6]โปรแกรมเมอร์เลือกได้
  • เอาท์พุทค่าความจริงถ้ากระสุนอย่างน้อยหนึ่งอยู่รอดตลอดไปและค่าความเท็จเป็นอย่างอื่น
  • ความเร็วกระสุนจะได้รับในหน่วยต่อวินาที
  • กระสุนเคลื่อนไหวพร้อมกันและต่อเนื่อง
  • สัญลักษณ์แสดงหัวข้อย่อยอาจชนกันที่ออฟเซ็ตเศษส่วน
  • กระสุนหลายนัดซึ่งไปถึงตำแหน่งเดียวกันที่แน่นอนพร้อมกันไม่ว่าจะเป็นการชดเชยแบบอินทิกรัลหรือเศษส่วนจากแหล่งกำเนิดชนกันทั้งหมด

ตัวอย่าง

ในแผนภาพเหล่านี้Gหมายถึงปืน>กระสุนและ*เวลาที่กระสุนชนกันและระเบิด

Truthy

การป้อนข้อมูล: 0

        0123456789
Time 0 G>
     1 G>
     2 G>
   ...

เอาท์พุท: 1


การป้อนข้อมูล: 0 0 0

        0123456789
Time 0 G>
     1 G*
     2 G>
     3 G>
     4 G>
   ...

เอาท์พุท: 1


การป้อนข้อมูล: 1

        0123456789
Time 0 G>
     1 G >
     2 G  >
     3 G   >
   ...

เอาท์พุท: 1


การป้อนข้อมูล: 2 1

        0123456789
Time 0 G>
     1 G> >
     2 G >  >
     3 G  >   >
     4 G   >    >
   ...

เอาท์พุท: 1


การป้อนข้อมูล: 2 3 1

        0123456789
Time 0 G>
     1 G> >
     2 G>  >>
     3 G >    *
     4 G  >
     5 G   >
   ...

เอาท์พุท: 1


Falsy

การป้อนข้อมูล: 1 2 3 4 5 6

        Unit      1111111111
        01234567890123456789
Time 0 G>
     1 G>>
     2 G> *
     3 G>  >
     4 G>   > >
     5 G>    >  >>
     6 G      >   > *
     7 G            >  >
     8 G                  > >
     9 G                        >>
    10 G                              *
                  111111111122222222223
        0123456789012345678901234567890

เอาท์พุท: 0


การป้อนข้อมูล: 1 0 0 3

        Unit
        0123456789
Time 0 G>
     1 G>>
     2 G* >
     3 G>  >
     4 G   >>
     5 G     *

(การชนกันครั้งที่สองเป็นเวลา 4.5)
ผลลัพธ์:0


การป้อนข้อมูล: 2 1 2 3 6 5

        Unit      1111111111
        01234567890123456789
Time 0 G>
     1 G> >
     2 G>>  >
     3 G> *   >
     4 G>  >    >
     5 G>     *   >
     6 G     >      >
     7 G          >   >
     8 G               >>
     9 G                *
                  1111111111
        01234567890123456789

เอาท์พุท: 0


การป้อนข้อมูล: 2 3 6

        Unit
        0123456789
Time 0 G>
     1 G> >
     2 G>  >>
     3 G      *

เอาท์พุท: 0


ฉันจะขอให้คั่นด้วยอินพุตได้1<enter>2<enter>3...อย่างไร
แมว

@sysreq: นั่นคือการผลักดัน แต่ฉันจะอนุญาต
El'endia Starman

ฉันเห็นด้วยกับ qunitopia - ความท้าทายนี้ชั่วร้ายอย่างหนัก แต่ฉันกำลังหาทางแก้ปัญหา ...
zmerch

คำตอบ:


4

Python 2, 388 392 388 346 342 336 331 ไบต์

z=k=input();l=len(k);v=range;u=v(l)
while l<z:
 r="";o=[r]*l;z=l
 for h in v(l):
    if r:o[h-1]=o[m]=r;m=h;r=""
    for j in v(h+1,l):
     p=k[h];q=k[j];t=u[j];n=(1.0*q*t-p*u[h])/(q-p)if q-p else""if p>0 else t
     if t<=n<r<()>o[j]>=n<=o[h]:r=n;m=j
 i=0;s=o and min(o)
 while i<l:
    if o[i]==s!="":del k[i],o[i],u[i];l-=1
    else:i+=1
print l

พระเจ้าของฉันมีขนาดใหญ่มาก แต่ฉันเชื่อว่าใช้งานได้จริง เมื่อคุณเห็นความซับซ้อนทั้งหมดของมันความท้าทายนี้ยากมาก

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

หลักขนาดใหญ่ในขณะที่วนซ้ำจนกว่ารายการอินพุตจะไม่ลดลง

การซ้อนสำหรับลูป (คุณเชื่อหรือไม่ว่าการซ้อนสำหรับลูปนั้นสั้นที่สุดที่นี่หรือ?) จะวนซ้ำไปเรื่อย ๆ ในแต่ละสัญลักษณ์แสดงหัวข้อย่อยและใช้numpy.rootsในการคำนวณการคำนวณ ณ เวลาที่สัญลักษณ์แสดงหัวข้อย่อยชนกัน ที่นี่""ถูกใช้เพื่อหมายถึงไม่มีที่สิ้นสุด (ไม่มีทางแยก) จะต้องรวมเงื่อนไขเพิ่มเติมเพื่อให้แน่ใจว่ากระสุนที่ถูกหยุดนั้นถูกทำเครื่องหมายว่าเป็นการชนขณะที่ปรากฏขึ้นแทนที่จะเป็นศูนย์เวลา

สำหรับแต่ละหมายเลขเราจะติดตามว่าสัญลักษณ์แสดงหัวข้อย่อยจะตีเร็วที่สุดถ้ามีและoจะอัปเดตด้วยเวลาปะทะต่ำสุดสำหรับกระสุนที่เกี่ยวข้อง

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

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

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

แก้ไข: ขอขอบคุณเป็นพิเศษ feersum สำหรับการสร้างกรณีทดสอบเพื่อช่วยฉันค้นหาข้อบกพร่อง

แก้ไข 2: บันทึก 42 bytes โดยการแก้สมการเชิงเส้นด้วยมือแทนที่จะใช้ numpy และแบ่งเวลาเริ่มต้นออกเป็นรายการแยกต่างหากและปรับโครงสร้างเงื่อนไข

แก้ไข 3: บันทึก 4 ไบต์โดยเปลี่ยนชื่อช่วง

แก้ไข 4: บันทึกอีก 6 ไบต์โดยแทนที่ช่องว่างสองครั้งด้วยแท็บ นอกจากนี้ feersum ก็ใจดีพอที่จะให้การดำเนินการของเขาโดยใช้เศษส่วนและชุดสำหรับการเปรียบเทียบ ฉันตีกอล์ฟนิดหน่อยและมันก็ออกมาที่ 331 ไบต์โดยคาดว่าจะแก้ปัญหาของฉัน

แก้ไข 5: บันทึก 5 ไบต์โดยการลบการกำหนดค่าเริ่มต้นที่ไม่จำเป็นและเขียนเงื่อนไขใหม่


คุณไม่ได้ทดสอบตัวอย่างอินพุตอีกครั้งหรือไม่ [1, 0, 0, 3] ไม่ทำงาน
feersum

@feersum นั่นเป็นสิ่งเดียวที่ฉันไม่ได้ทดสอบ แต่คงที่ ด้วยความพยายามทั้งหมดนี้ฉันดีกว่าที่จะได้รับการเปลี่ยนแปลง : P
quintopia

ยังไม่ทำงาน [1, 16, 18, 20, 30] ควรกลับมา 1
feersum

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