แปดเหรียญสำหรับราชาผู้ยิ่งใหญ่


22

นี่คือ "คู่" ของจิ๊กซอว์อีกชิ้นหนึ่งแปดเหรียญสำหรับราชาที่เป็นธรรมใน Puzzling.SE

คุณสามารถอ่านปริศนาด้านบนสำหรับพื้นหลัง รายละเอียดเกี่ยวกับตัวต่อนี้มีดังนี้

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

ตัวอย่างเช่น (นำมาจากคำตอบของ Glorfindel) หากได้รับชุดเหรียญมูลค่า 1, 2, 5, 13, 34, 89, 233, 610 โปรแกรมของคุณควรส่งออก 1596 เพราะทุกตัวเลขระหว่าง 0 ถึง 1596 (รวม) สามารถแสดงผลได้โดยไม่รวม มากกว่า 8 หมายเลขจากรายการที่ระบุ (อาจทำซ้ำหมายเลข) ในขณะที่ 1597 ไม่สามารถแสดงด้วยวิธีดังกล่าว

ในทางคณิตศาสตร์ถ้าใส่เป็นชุด S ซึ่งประกอบด้วย 8 จำนวนเต็มบวกที่ต้องการตอบสนองการส่งออกยังไม่มีที่ใดจำนวนnระหว่าง 0 และ N มีอยู่ x1, x2, x3, ... , x8 ดังกล่าวว่า

x1+x2+...+x8=nandx1,x2,...,x8{0}S

เป้าหมายของคุณคือการเขียนโปรแกรมฟังก์ชั่นหรือตัวอย่างที่มี 8 ตัวเลขเป็นอินพุตและส่งออก N สูงสุดตามที่อธิบายไว้ข้างต้น

กฎ:

  • อนุญาตให้ใช้ I / O ที่ยืดหยุ่นได้ดังนั้นโปรแกรมของคุณสามารถรับอินพุตในรูปแบบใดก็ได้ที่เหมาะสมที่สุด คุณอาจสมมติว่าหมายเลขอินพุตถูกจัดเรียงตามวิธีที่เหมาะสมที่สุดสำหรับโปรแกรมของคุณ
    • โปรดระบุในคำตอบของคุณหากโปรแกรมของคุณขึ้นอยู่กับคำสั่งซื้อ
  • อินพุตคือชุดของจำนวนเต็มบวกจำนวน 8 ค่าที่ต่างกัน (ไม่มีศูนย์) เอาท์พุทเป็นจำนวนเต็มหนึ่งที่ไม่เป็นลบ
    • ในกรณีที่ไม่มีหมายเลข 1 ในชุดอินพุตโปรแกรมของคุณควรส่งออก 0 เพราะหมายเลขใด ๆ จาก 0 ถึง 0 ตรงตามข้อกำหนด
    • ในกรณีของการป้อนข้อมูลที่ไม่ถูกต้อง (ชุดมีจำนวนศูนย์ลบหรือซ้ำกัน) โปรแกรมของคุณสามารถทำอะไรได้
  • ช่องโหว่มาตรฐานเป็นสิ่งต้องห้าม
  • โปรแกรมของคุณควรทำงานภายในไม่กี่นาทีบนคอมพิวเตอร์ที่ทันสมัย

กรณีทดสอบ (ส่วนใหญ่นำมาจากคำตอบภายใต้คำถามที่เชื่อมโยงกับ Puzzling):

[1, 2, 3, 4, 5, 6, 7, 8] => 64
[2, 3, 4, 5, 6, 7, 8, 9] => 0
[1, 3, 4, 5, 6, 7, 8, 9] => 72
[1, 2, 5, 13, 34, 89, 233, 610] => 1596
[1, 5, 16, 51, 130, 332, 471, 1082] => 2721
[1, 6, 20, 75, 175, 474, 756, 785] => 3356

นี่คือดังนั้นโปรแกรมหรือตัวอย่างที่สั้นที่สุดในแต่ละภาษาจะชนะ!


1
ปริศนาดี แต่โดยส่วนตัวฉันคิดว่ากรณีทดสอบอีกจำนวนหนึ่งจะมีประโยชน์ในการทดสอบการส่งของเรา
Mr. Xcoder

มันจะดีกว่าหรือไม่ที่จะทำให้ขนาดอินพุตเป็นพารามิเตอร์ วิธีการที่ดุร้ายกำลังจะต่อสู้กับ 8
Luis Mendo

1
@iBug จากนั้นกฎทั่วไปคือบางสิ่งเช่น "การส่งเสียงร้องทำงานภายในหนึ่งนาทีในคอมพิวเตอร์สมัยใหม่" มันคลุมเครือ แต่มักจะดีพอเพราะความแตกต่างระหว่างแรงเดรัจฉานกับวิธีการที่มีประสิทธิภาพมีขนาดใหญ่มาก
Luis Mendo

1
แรงเดรัจฉานยังคงเป็นไปได้ด้วยการ จำกัด เวลาของคุณ "ไม่กี่นาที" คำตอบของฉันที่ได้รับการแก้ไขเล็กน้อยใช้งานกรณีทดสอบล่าสุดใน 1m20s บนแล็ปท็อปอายุ 7 ปีของฉัน
nimi

1
@Arnauld ชี้แจง
iBug

คำตอบ:


14

Python 3 , 113 62 ไบต์

for i in[1]*3:x|={a+b for a in x for b in x}
while{i+1}&x:i+=1

นี่xคืออินพุตเป็นชุดของ int และiเป็นเอาต์พุต

ลองออนไลน์!

(ขอบคุณ: Erik the Outgolfer, Mr. Xcoder, Lynn)


1
96 ไบต์
Erik the Outgolfer

x=0,*xบันทึก 1 ไบต์ ยังดีกว่าx+=0,ประหยัด 2
Mr. Xcoder

78 bytesใน Python 2
Lynn

9

เยลลี่ 12 ไบต์

œċⱮ8Ẏ§ṢQJƑƤS

ลองออนไลน์!

ใช้เวลาเฉลี่ย 3.7 วินาทีในการเรียกใช้ทุกกรณีทดสอบบน TIO บนโทรศัพท์ของฉันดังนั้นมันจึงค่อนข้างเร็ว

คำอธิบาย

œċⱮ8Ẏ§ṢQJƑƤS     Monadic link / Full program.
  Ɱ8             Promote 8 to [1 ... 8] and for each value k:
œċ                    Generate all combinations of k elements from the list.
    Ẏ§           Tighten, then sum. Flatten to a 2D list then sum each.
      ṢQ         Sort the result and remove equal entries.
        JƑƤ      For each prefix of this list, return 1 if it is equal to its length range, 0 otherwise.
           S     Finally, sum the result (counts the 1's which is equivalent to what is being asked).

7

Haskell, 56 50 ไบต์

g c=[x|x<-[1..],all((/=x).sum)$mapM(0:)$c<$c]!!0-1

ลองออนไลน์!

วิธีการกำลังดุร้าย เพิ่ม0เข้าไปในรายการเหรียญและลองชุดทั้งหมด 8 ตัวเลือก ค้นหาหมายเลขแรกnที่ไม่เท่ากับผลรวมของการเลือกและการส่งคืนn-1ใด ๆ

ใช้เวลาประมาณ 5m30s สำหรับ[1, 2, 5, 13, 34, 89, 233, 610]ฮาร์ดแวร์แล็ปท็อปอายุ 7 ปีของฉัน

แก้ไข: -6 ไบต์ขอบคุณ @ Ørjan Johansen

รุ่นที่สั้นกว่า (-2 ไบต์ขอขอบคุณ @ Ørjan Johansen) อีกครั้ง

Haskell, 48 ไบต์

g c=[x|x<-[1..],all((/=x).sum)$mapM(:0:c)c]!!0-1

แต่ใช้หน่วยความจำเพิ่มขึ้นอย่างมากและทำงานหนักในเพจจิ้งบนเครื่องของฉันและไม่เสร็จสิ้น "ภายในไม่กี่นาที"


1
mapM(0:)$c<$cคุณสามารถใช้ (อันที่จริงmapM(:0:c)cควรใช้งานได้ แต่หมดเวลาสำหรับ TIO สำหรับกรณีทดสอบที่กำหนด)
Ørjan Johansen

4

เยลลี่ขนาด 9 ไบต์

Żœċ8§ḟ’$Ṃ

ลองออนไลน์!

มันทำงานอย่างไร

Żœċ8§ḟ’$Ṃ  Main link. Argument: A (array)

Ż          Prepend a 0 to A.
 œċ8       Take all combinations of length 8, with repetitions.
    §      Take the sum of each combination.
       $   Combine the two links to the left into a monadic chain.
      ’      Decrement all sums.
     ḟ       Filterfalse; keep only sums that do not appear in the decremented sums.
        Ṃ  Take the minimum.

2
Żṗ8§ḟ’$Ṃช่วยประหยัดหนึ่งไบต์ แต่ผมไม่แน่ใจว่าถ้านับ 8.5 นาทีไม่กี่
เดนนิส


4

JavaScript (ES6),  100 88 80  76 ไบต์

นี่คือการค้นหาที่โหดร้าย แต่ได้รับการปรับปรุงด้วยการตัดแต่งกิ่งเพื่อเพิ่มความเร็ว เวลาดำเนินการเฉลี่ยสำหรับกรณีทดสอบใกล้ถึง 1 วินาทีสำหรับ TIO

สมมติว่าอาร์เรย์อินพุตถูกเรียงลำดับจากสูงสุดไปต่ำสุด

a=>[...Array(a[0]*9)].findIndex(g=(i=8,s)=>s*i>0?a.every(x=>g(i-1,s-x)):s)-1

ลองออนไลน์!

แสดงความคิดเห็น

a =>                      // a[] = input array
  [...Array(a[0] * 9)]    // create an array of 9 * max(a) entries
  .findIndex(             // find the position of the first truthy result
    g = (i = 8, s) =>     // g = recursive function taking a counter i, initialized to 8
                          //     and a sum s, initialized to the position in the above array
      s * i > 0 ?         //   if s is positive and i is not equal to 0:
        a.every(x =>      //     for each value x in a[]:
          g(i - 1, s - x) //       do a recursive call with i - 1 and s - x
        )                 //     end of every()
      :                   //   else:
        s                 //     yield s (s = 0 means success and makes findIndex go on)
  ) - 1                   // end of findIndex(); decrement the result


3

Pari / GP , 57 ไบต์

a->n=-1;while(polcoeff((1+sum(i=1,8,x^a[i]))^8,n++),);n-1

ลองออนไลน์!


นี่คือการใช้ฟังก์ชั่นการสร้าง?
อย่าสดใส

1
@donbright ใช่
alephalpha

1
มันยอดเยี่ยมมาก .. หนึ่งในไม่กี่คำตอบที่ไม่ได้บังคับให้แก้ปัญหา ภาษาจำนวนมากอาจไม่ได้สร้างขึ้นในคุณสมบัติสัญลักษณ์พหุนาม Pari GP เจ๋งมาก
อย่าสดใส

2

Python 2 , 125 115 111 bytes

lambda c:sum(i==j for i,j in enumerate(sorted(set(map(sum,product([0]+c,repeat=8))))))-1
from itertools import*

ลองออนไลน์!

ต้องการรายการจำนวนเต็มเป็นอินพุต

คำอธิบาย:

# an anonymous function
lambda c:
                                                          # get all length-8 combinations of values, from (0,0,0,0,0,0,0,0) to (8,8,8,8,8,8,8,8)
                                                          # zero is added to ensure that combinations of fewer than 8 coins are represented Ex:(1,0,0,0,0,0,0,0)
                                                          product([0]+c,repeat=8)
                                                  # for each combination, sum the values
                                                  map(sum,.......................)
                                       # get unique values, then sort them smallest to largest
                                       sorted(set(................................))
             # for each index, value pair, return if the index is equal to the value
             i==j for i,j in enumerate(.............................................)
         # in Python arithmetic, False is 0 and True is 1. So, count how many items match their index.
         # Since zero was added to the list, there will always be one extra match (0==0). So offset by one.
         sum(........................................................................)-1
from itertools import*

2

Perl6, 65 63 41 ไบต์ ( 39 37 ตัวอักษร)

{@_=(0,|@_)X+(0,|@_)for ^3;($_ if $_==$++for @_.sort.unique)-1}

ลองออนไลน์!

นี่คือบล็อกที่ไม่ระบุชื่อที่ได้รับข้อมูลผ่านเป็นอาร์เรย์ (0,|@_)เป็นวิธีที่รวดเร็วเพื่อเพิ่ม0การ@_และแม้ว่าจะทำสองครั้งก็ยังคงบิตสั้นกว่าซึ่งจะต้องแล้วช่องว่างหลังจากที่@_.push: 0; _นี่เป็นวิธีการที่ดุร้ายที่ชี้นำความจริงที่ว่ามันเป็นการรวมกัน 8 แบบ หลังจากเพิ่มการข้ามรายการที่ไม่ระบุชื่อจะถูกสร้างขึ้นสำหรับค่าตามลำดับ ด้วยตัวดำเนินการทางคณิตศาสตร์รายการจะประเมินความยาวของมันดังนั้น -1 จะดึงหน้าที่สอง: การบัญชีสำหรับ 0 และบังคับให้มีค่า Int

การทำเช่นนี้อาจใช้เวลาค่อนข้างหวาน แต่ด้วยการเปลี่ยนอย่างใดอย่างหนึ่งหรือทั้งสองอย่าง(0,|@_)เป็น(0,|@_.unique)ก่อนหน้าforนั้นจะสามารถเร่งความเร็วได้อย่างมาก ที่เพิ่ม+7 (รันไทม์ <60s) หรือ+14 (รันไทม์ <10s) ให้คะแนนถ้าคุณรู้สึกว่าคนแรกช้าเกินไป (ฉันทำเช่นนี้สำหรับรหัสที่เชื่อมโยงเพื่อหลีกเลี่ยงการหมดเวลาหลังจาก 60 วินาที)

แก้ไข: JoKing ในความคิดเห็นได้ปรับปรุง (ความคิดเดียวกันข้ามเพิ่มจากนั้นส่งกลับผลลัพธ์ที่ต่อเนื่องกันล่าสุด) ไปยังตัวอักษรที่น่าอัศจรรย์ 39 ตัวอักษร (41 ไบต์):

{(@_=@_ X+0,|@_)xx 3;first *+1@_,^∞}

ลองออนไลน์!

การจัดตารางสุดท้ายไม่จำเป็นต้องมี 0 บันทึกสองสามไบต์โดยเพียงแค่ต้องการเพิ่ม 0 ในครั้งเดียว xx 3เลียนแบบสำหรับวง (ยังคงชีสบนเหรียญเป็นอำนาจของ 2) firstย่อยกลับหมายเลขแรกในรายการที่ไม่มีที่สิ้นสุด0..*( ^Infเป็นไปได้เหมือนกัน แต่ไม่ได้ประหยัดพื้นที่) ซึ่ง+1ไม่ได้เป็นสมาชิกของรายการเพิ่มข้าม เช่นเดียวกับของฉันมันช้าดังนั้นเพิ่ม+7สำหรับ a uniqueafter ก่อนเท่ากับถ้าคุณรู้สึกว่ามันช้าเกินไปสำหรับแนวทาง


1
48 ไบต์ ในทางเทคนิคแล้วuniqueมันไม่จำเป็น แต่มันเพิ่มความเร็วขึ้นมาก
Jo King

@JoKing xxดีฉันไม่ทราบว่าทำไมฉันไม่คิดว่าเกี่ยวกับการใช้ ฉันรู้ว่าต้องมีวิธีการทำตารางสุดท้ายในวิธีที่สั้นกว่ามากโดยใช้ฟังก์ชั่นชุด แต่สมองของฉันไม่ทำงาน
user0721090601

สิ่งที่xx 1ควรเป็นxx 3
Jo King

@ แก้ไขโจคกิ้งแล้ว นอกจากนี้ฉันยังตระหนักว่าสองตัวอักษร (แต่ไม่มีไบต์) สามารถบันทึกโดยใช้^∞
user0721090601

ที่จริงแล้วคุณสามารถบันทึกไบต์ด้วย(1...*∉@_)-1แทนที่จะใช้first(ซึ่งฉันรู้ว่าเป็นวิธีเดียวกับที่ฉันใช้ที่นี่ )
Jo King


1

ภาษา Wolfram (Mathematica)ขนาด 46 ไบต์

0//.x_/;Min[Tr/@FrobeniusSolve[#,x+1]]<9:>x+1&

ลองออนไลน์!

วิธีเดรัจฉานบังคับ: ตรวจสอบจำนวนเต็มนับจนถึงค่าที่ไม่สามารถจ่ายได้ใน 8 เหรียญ ช้ามาก (หมดเวลา) แต่ฉันค่อนข้างแน่ใจว่าสภาพถูกต้อง


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