ห่วงโซ่การเติมสั้นที่สุด


23

เชนเพิ่มเติมคือลำดับของจำนวนเต็มเริ่มต้นด้วย 1 โดยที่ทุก ๆ จำนวนเต็มนอกเหนือจาก 1 เริ่มต้นคือผลรวมของจำนวนเต็มก่อนหน้านี้สอง

ตัวอย่างเช่นนี่คือเชนเพิ่มเติม:

[1, 2, 3, 4, 7, 8, 16, 32, 39, 71]

นี่คือผลรวมที่ทำให้เป็นห่วงโซ่เพิ่มเติม:

1 + 1 = 2
1 + 2 = 3
1 + 3 = 4
3 + 4 = 7
1 + 7 = 8
8 + 8 = 16
16 + 16 = 32
7 + 32 = 39
32 + 39 = 71

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

ตัวอย่าง - โปรดทราบว่ามีเอาต์พุตจำนวนมากที่เป็นไปได้ทั้งหมดที่คุณต้องค้นหาคือเชนเพิ่มเติมที่สั้น:

1: [1]
2: [1, 2]
3: [1, 2, 3]
4: [1, 2, 4]
5: [1, 2, 3, 5]
6: [1, 2, 3, 6]
7: [1, 2, 3, 4, 7]
11: [1, 2, 3, 4, 7, 11]
15: [1, 2, 3, 5, 10, 15]
19: [1, 2, 3, 4, 8, 11, 19]
29: [1, 2, 3, 4, 7, 11, 18, 29]
47: [1, 2, 3, 4, 7, 10, 20, 27, 47]
71: [1, 2, 3, 4, 7, 8, 16, 32, 39, 71]

กฎ I / O มาตรฐาน ฯลฯ ช่องโหว่มาตรฐานถูกห้าม โค้ดกอล์ฟ: จำนวนไบต์ที่น้อยที่สุดที่ชนะ




1
เราได้รับอนุญาตให้ส่งออกโซ่ในลำดับย้อนกลับ?
Arnauld

@Arnauld ไม่คำสั่งนี้โดยเฉพาะ
isaacg

คำตอบ:


6

Haskell , 57 ไบต์

c=[1]:[x++[a+b]|x<-c,a<-x,b<-x]
f n=[x|x<-c,last x==n]!!0

วิธีการแก้ปัญหากำลังดุร้าย ลองออนไลน์!

คำอธิบาย

รายการที่ไม่มีที่สิ้นสุดcประกอบด้วยเชนเพิ่มเติมทั้งหมดเรียงตามความยาว มันถูกกำหนด inductively ในแง่ของตัวเองโดยการใช้รายการxจากcสององค์ประกอบจากและการผนวกรวมของพวกเขาไปx xฟังก์ชั่นfค้นหารายการแรกcที่ลงท้ายด้วยหมายเลขที่ต้องการ

c=            -- c is the list of lists
 [1]:         -- containing [1] and
 [x           -- each list x
  ++[a+b]     -- extended with a+b
 |x<-c,       -- where x is drawn from c,
  a<-x,       -- a is drawn from x and
  b<-x]       -- b is drawn from x.
f n=          -- f on input n is:
 [x           -- take list of those lists x
 |x<-c,       -- where x is drawn from c and
  last x==n]  -- x ends with n,
 !!0          -- return its first element.

4

Brachylogขนาด 14 ไบต์

∧≜;1{j⊇Ċ+}ᵃ⁽?∋

ลองออนไลน์!

การส่งกำลังดุร้ายที่สร้างโซ่เพิ่มเติมทั้งหมดที่เป็นไปได้โดยใช้การวนซ้ำลึกลงหยุดเมื่อพบโซ่ที่มีการโต้แย้งที่ถูกต้อง ซึ่งแตกต่างจากการส่ง Brachylog ส่วนใหญ่นี่คือการส่งฟังก์ชั่นที่อินพุตผ่านอาร์กิวเมนต์ขวา (ตามอัตภาพเรียกว่าเอาท์พุท) และเอาท์พุทผ่านอาร์กิวเมนต์ซ้าย (ตามอัตภาพเรียกว่าอินพุต); การทำเช่นนี้ค่อนข้างขัดแย้ง แต่คำตอบเมตาที่ได้รับคะแนนสูงสุดในเรื่องบอกว่ามันถูกกฎหมาย (และการทำเช่นนั้นสอดคล้องกับค่าเริ่มต้น I / O ปกติของเราสำหรับฟังก์ชั่น) หากเราใช้อินพุทและเอาท์พุทในแบบที่ธรรมดากว่านี้จะเป็น 16 ไบต์ (∧≜;1{j⊇Ċ+}ᵃ⁽.∋?∧) เนื่องจากด้านขวาของโปรแกรมจะไม่สามารถใช้ประโยชน์จากข้อ จำกัด โดยนัย (ดังนั้นจะต้องมีการปิดใช้งานและข้อ จำกัด ที่ชัดเจนใหม่ที่กำหนดไว้ที่ราคา 2 ไบต์)

คำอธิบาย

∧≜;1{j⊇Ċ+}ᵃ⁽?∋
∧               Disable implicit constraint to read the left argument
 ≜;        ⁽    Evaluation order hint: minimize number of iterations
    {    }ᵃ     Repeatedly run the following:
   1      ᵃ       From {1 on the first iteration, results seen so far otherwise}
     j            Make {two} copies of each list element
      ⊇           Find a subset of the elements
       Ċ          which has size 2
        +         and which sums to {the new result for the next iteration}
             ∋    If the list of results seen so far contains {the right argument}
            ?     Output it via the left argument {then terminate}

ความละเอียดอ่อนที่น่าสนใจที่นี่คือสิ่งที่เกิดขึ้นในการทำซ้ำครั้งแรกโดยที่อินพุตเป็นตัวเลขแทนที่จะเป็นรายการที่เหมือนกันในการทำซ้ำอื่น ๆ เราเริ่มต้นด้วยหมายเลข 1, ทำสำเนาสองหลักของทุกหลัก (ทำหมายเลข 11), จากนั้นหาลำดับ 2 หลักของมัน (เช่นหมายเลข 11) จากนั้นเราก็หาผลรวมหลักซึ่งก็คือ 2 และตามลำดับนั้นเริ่มต้น[1,2]อย่างที่เราต้องการ เกี่ยวกับการทำซ้ำในอนาคตเราจะเริ่มต้นกับรายการเหมือน[1,2]เสแสร้งมัน[1,2,1,2]แล้วการ subsequence สององค์ประกอบ ( [1,1], [1,2], [2,1]หรือ[2,2]); ชัดเจนจำนวนเงินของแต่ละเหล่านี้จะถูกต้ององค์ประกอบถัดไปของห่วงโซ่การเพิ่ม

มันน่าผิดหวังเล็กน้อยที่นี่ต้องการคำแนะนำการประเมินผลที่นี่โดยเฉพาะอย่างยิ่งองค์ประกอบ (ปรากฏว่าใช้คำสั่งการประเมินผลจากภายในมากกว่าภายนอกโดยค่าเริ่มต้นดังนั้นการใช้คำสั่งที่ค่อนข้างหยาบเพื่อบังคับให้เกิดปัญหา)


ฉันได้ลองใช้เวลาประมาณ 30 นาทีเพื่อหาวิธีสั้น ๆ ในการทำสิ่งนี้ ทางออกของฉันยาวกว่านี้มาก
เสียชีวิต

1
@Falize: เป็นหนึ่งในbuildins ที่ไม่ค่อยเกิดขึ้น แต่เมื่อคุณต้องการคุณจำเป็นต้องใช้จริงๆเพราะไม่มีวิธีที่จะนำมันไปใช้โดยใช้โครงสร้างควบคุมอื่น เมื่อฉันตระหนักว่านี่เป็นความท้าทายส่วนที่เหลือมาจากที่นั่นโดยตรง

2

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

’ŒP;€µ+þ;1Fḟ@µÐḟḢ

ส่งออกการแก้ปัญหาคำศัพท์แรกในเวลาเอ็กซ์โปเนนเชียล

ลองออนไลน์!

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

’ŒP;€µ+þ;1Fḟ@µÐḟḢ  Main link. Argument: n (integer)

’                  Decrement; n-1.
 ŒP                Powerset; generate all subarrays of [1, ..., n-1], sorted first
                   by length, then lexicographically.
   ;€              Append n to all generate subarrays.
     µ       µÐḟ   Filterfalse; keep only subarrays for which the chain between the
                   two chain separators (µ) returns a falsy value.
     µ             Monadic chain. Argument: A (array of integers)
      +þ               Add table; compute the sums of all pairs of elements in x,
                       grouping the results by the right addend.
        ;1             Append 1 to the resulting 2D array.
          F            Flatten the result.
           ḟ@          Filterfalse swapped; remove all elements of A that appear in
                       the result. This yields an empty list for addition chains.
                Ḣ  Head; select the first result.

2

JavaScript (ES6), 83 86 ไบต์

แก้ไข: แก้ไขเพื่อส่งออกรายการในลำดับที่ไม่ใช่แบบย้อนกลับ

n=>(g=(s,a=[1])=>s-n?s>n||a.map(v=>g(v+=s,a.concat(v))):r=1/r|r[a.length]?a:r)(r=1)&&r

การสาธิต


2

PHP, 195 ไบต์

function p($a){global$argn,$r;if(!$r||$a<$r)if(end($a)==$argn)$r=$a;else foreach($a as$x)foreach($a as$y)in_array($w=$x+$y,$a)||$w>$argn||$w<=max($a)?:p(array_merge($a,[$w]));}p([1]);print_r($r);

ลองออนไลน์!


น่าเสียดายอัลกอริทึมนี้ไม่ได้ให้คำตอบที่ดีที่สุดเช่นสำหรับ 15
Neil

@ ถึงตอนนี้มันก็จะนานกว่า แต่มันก็ใช้งานได้ ฉันไม่มีความคิดในเวลาที่จะตัดสินใจว่าวิธีใดเหมาะสมทั้งสองวิธี บางทีการนับจำนวนเฉพาะมีบทบาท
JörgHülsermann

รหัสนี้ไม่ผ่านการทดสอบ 149 ครั้ง ความยาวควรเป็น 10 ไม่ใช่ 11
J42161217

@Jenny_mathy แก้ไขแล้ว
JörgHülsermann

1

Mathematica, 140 ไบต์

t={};s={1};(Do[While[Last@s!=#,s={1};While[Last@s<#,AppendTo[s,RandomChoice@s+Last@s]]];t~AppendTo~s;s={1},10^4];First@SortBy[t,Length@#&])&

.

สร้างห่วงโซ่การเติมที่สั้นที่สุดที่แตกต่างกันทุกครั้งที่คุณเรียกใช้

ลอง
วางรหัสออนไลน์ด้วย ctrl + v วางข้อมูลเช่น [71] ที่ท้ายรหัสแล้วกด Shift + enter


เมื่อฉันไม่สามารถเข้าถึง Mathematica สิ่งนี้จะให้ความยาวของโซ่ 15 สำหรับการป้อนข้อมูล?
Neil

ทางขวาหนึ่ง {1, 2, 3, 5, 10, 15}
J42161217

3
สำหรับอินพุต 149 ฉันได้สายโซ่ยาว 11 จากโปรแกรมของคุณ แต่มีหนึ่งในความยาว 10 ( [1,2,4,5,9,18,36,72,77,149]) ดูเหมือนว่าโปรแกรมของคุณใช้การสุ่มตัวอย่างและไม่รับประกันว่าจะหาทางออกที่ดีที่สุด
Zgarb

การแก้ไข! แต่จะใช้เวลานานกว่า
J42161217

1

Pyth, 13 ไบต์

h-DsM^N2/#QyS

ชุดทดสอบ

ให้สายที่สั้นที่สุดเป็นครั้งแรกของพจนานุกรม มันค่อนข้างช้า แต่ก็ไม่ได้แย่ขนาดนั้น - 19ใช้เวลาประมาณ 30 วินาทีในการใช้ pypy

แนวคิดบางอย่างจากโซลูชันของ @ Dennis

ฉันชอบอันนี้มาก - มีกลอุบายมากมายที่เกี่ยวข้อง

คำอธิบาย:

h-DsM^N2/#QyS
h-DsM^N2/#QySQ    Implicit variable introduction
            SQ    Inclusive range, 1 to input.
           y      Subsets - all subsets of the input, sorted by length then lexicographically
                  Only sorted subsets will be generated.
                  Our addition chain will be one of these.
        /#Q       Filter for presence of the input.
  D               Order by
 -                What's left after we remove
     ^N2          All pairs of numbers in the input
   sM             Summed
h                 Output the list that got sorted to the front.

มันยังยากที่จะเข้าใจ แต่ให้ฉันพยายามอธิบายในรายละเอียดให้มากขึ้น

เราเริ่มต้นด้วยySQซึ่งจะให้เซตย่อยที่เป็นไปได้ทั้งหมด[1, 2, ... Q]เพื่อเพิ่มขนาด ห่วงโซ่การเติมที่สั้นที่สุดนั้นเป็นหนึ่งในสิ่งเหล่านี้อย่างแน่นอน แต่เราต้องหามันให้เจอ

สิ่งแรกที่เราจะทำคือการกรองรายการที่จะเพียง Qแต่ให้รายการที่มี /#Qเราทำเช่นนี้กับ

ต่อไปเราจะเรียงลำดับรายการสิ่งที่เหลืออยู่หลังจากเราลบผลลัพธ์ของฟังก์ชั่นบางอย่าง -Dสั่งซื้อโดยส่วนที่เหลือหลังจากลบบางสิ่ง

สิ่งที่เราเป็นลบsM^N2ซึ่งNเป็นรายการที่เรากำลังเอาสิ่งที่มาจาก ^N2จะช่วยให้สินค้าคาร์ทีเซียนของด้วยตัวเองคู่เป็นไปได้ทั้งหมดของทั้งสององค์ประกอบในN จากนั้นสรุปแต่ละคู่NsM

ผลลัพธ์ที่เล็กที่สุดที่เป็นไปได้หลังจากที่เราทำการลบนี้คืออะไร? องค์ประกอบที่เล็กที่สุดในรายการอินพุตจะยังคงอยู่อย่างแน่นอนเพราะตัวเลขทั้งหมดเป็นบวกดังนั้นผลรวมของตัวเลขสองจำนวนใด ๆ จะมากกว่าจำนวนที่เล็กที่สุด และจะมีตัวเลขอย่างน้อยหนึ่งตัวเพราะเราตรวจสอบว่าอินพุตนั้นมีอยู่ในรายการ ดังนั้นผลที่มีขนาดเล็กที่สุดจะได้รับเมื่อจำนวนยกเว้นจำนวนที่น้อยที่สุดทุกคนคือผลรวมของตัวเลขสองอื่น ๆ ในรายการและจำนวนที่น้อยที่สุดในรายการคือ 1. [1]ในกรณีนี้ที่สำคัญจะเรียงลำดับ ข้อกำหนดเหล่านี้หมายความว่ารายการจะต้องเป็นห่วงโซ่การเพิ่ม

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

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