ตัวเลขเริ่มต้นที่ต่ำที่สุดในลำดับที่เหมือน Fibonacci


22

รับอินพุตจำนวนเต็มบวกNส่งออกตัวเลขที่ไม่เป็นลบสองตัวคือaและbโดยที่<bโดยมีค่าเฉลี่ยต่ำที่สุดที่เป็นไปได้ซึ่งจะส่งผลให้ตัวเลขNเป็นส่วนหนึ่งของลำดับความสัมพันธ์ที่เกิดซ้ำ:

f(0) = a
f(1) = b
f(n) = f(n-2)+f(n-1)

ในกรณีที่มีมากกว่าหนึ่งในโซลูชั่นที่มีค่าเฉลี่ยของและBมีน้อยแล้วคุณควรเอาท์พุทหนึ่งกับต่ำสุดข

คุณสามารถสมมติว่าNอยู่ในช่วงตัวแทนของจำนวนเต็มในภาษา / ระบบของคุณ

กรณีทดสอบ

N = 1
a = 0, b = 1

N = 15
a = 0, b = 3

N = 21
a = 0, b = 1

N = 27
a = 0, b = 9   <- Tricky test case. [3, 7] is not optimal and [4, 3] is not valid

N = 100
a = 4, b = 10

N = 101
a = 1, b = 12

N = 102
a = 0, b = 3

N = 1000
a = 2, b = 10

ถ้าa>=0และa<bจะมีวิธีแก้ปัญหาที่หลากหลาย?
Jonathan Allan

ฉันไม่สามารถรับประกันได้ว่าจะมีหรือไม่มีวิธีแก้ปัญหาหลายอย่าง ทั้งสอง1,4และ2,3จะให้5และพวกเขามีค่าเฉลี่ยเดียวกัน ฉันเดาว่าเป็นไปได้ที่จะพบกรณีที่คล้ายคลึงกับกรณีนี้ซึ่งค่าเหล่านี้เป็นค่าเฉลี่ยต่ำสุด หากคุณสามารถแสดง / พิสูจน์ว่าไม่มีวิธีแก้ปัญหาหลายวิธีคุณไม่จำเป็นต้องตรวจสอบเงื่อนไขนั้น
Stewie Griffin

2
แรงบันดาลใจอย่างสิ้นเชิงจากcodegolf.stackexchange.com/q/147200/67961
J42161217

3
ที่สอดคล้องกับลำดับ OEIS สำหรับต่ำที่สุดเฉลี่ยA249783มีป่ามองกราฟ
Peter Kagey

1
@ ØrjanJohansenฉันเพิ่มหลักฐานให้กับคำตอบของฉันว่าไม่มีวิธีแก้ไขปัญหาซ้ำซ้อน (เนื่องจากคำตอบของฉันขึ้นอยู่กับมัน)
cardboard_box

คำตอบ:


8

Husk , 19 18 16 14 13 15 ไบต์

ขอบคุณ Zgarb สำหรับการบันทึก 1 ไบต์

ḟö£⁰ƒẊ++ÖΣṖ2Θḣ⁰

ลองออนไลน์!

คำอธิบาย:

คำเตือน:ฉันไม่เข้าใจในȯƒẊ++ส่วนของรหัส

แก้ไข: ดูเหมือนว่าจะแปลเป็น Haskell fix.(mapad2(+).).(++)ซึ่งmapad2มีการใช้ฟังก์ชั่นกับคู่ที่อยู่ติดกันทั้งหมดในรายการ (แม้ว่าการรู้จักแกลบในบริบทของโปรแกรมนี้อาจหมายถึงอย่างอื่น)

            Θḣ⁰    Create the list [0..input]
          Ṗ2       Generate all possible sublists of length 2
        ÖΣ         Sort them on their sums
ḟ                  Find the first element that satisfies the following predicate.
    ƒẊ++             Given [a,b], magically generate the infinite Fibonacci-like
                     sequence from [a,b] without [a,b] at the start.
 ö£⁰                 Is the input in that list (given that it is in sorted order)?


ฉันแน่ใจว่าฉันลองมัน ...
H.PWiz

8

JavaScript (Node.js) , 92 90 89 91 83 82 ไบต์

-3 ไบต์ -1 ไบต์ขอบคุณ ThePirateBay

-8 -9 ไบต์ขอบคุณ Neil

f=(n,a=1,b=0,c=(a,b)=>b<n?c(a+b,a):b>n)=>c(a,b)?b+2<a?f(n,a-1,b+1):f(n,b-~a):[b,a]

ลองออนไลน์!

หมายเหตุ: การแก้ปัญหานี้ขึ้นอยู่กับความจริงที่ว่าไม่มีวิธีการแก้ปัญหาน้อยที่สุด

พิสูจน์ว่าไม่มีทางแก้ไขหลายทาง:

อนุญาตFIB(a,b,k)เป็นลำดับ Fibonacci เหมือนเริ่มต้นด้วยa,b:

FIB(a,b,0) = a
FIB(a,b,1) = b
FIB(a,b,k) = FIB(a,b,k-1) + FIB(a,b,k-2)

บทแทรก 1

FIB(a1,b1,k) - FIB(a0,b0,k) = FIB(a1-a0,b1-b0,k)ความแตกต่างระหว่างฟีโบนักชีเหมือนลำดับฟีโบนักชีเป็นตัวเองเหมือนเช่น หลักฐานที่เหลือให้ผู้อ่าน

บทแทรก 2

สำหรับn >= 5การแก้ปัญหาที่a,bมีอยู่น่าพอใจa+b < n:

ถ้าnเป็นเช่นนั้นFIB(0,n/2,3) = n

ถ้าnแปลกFIB(1,(n-1)/2,3) = n

พิสูจน์

กรณีที่n < 5สามารถตรวจสอบได้อย่างละเอียดถี่ถ้วน

สมมติว่าเรามีสองโซลูชั่นน้อยที่สุดสำหรับn >= 5, a0,b0และa1,b1ด้วยและa0 + b0 = a1 + b1a0 != a1

จากนั้นก็มีอยู่เช่นนั้นk0,k1FIB(a0,b0,k0) = FIB(a1,b1,k1) = n

  • กรณีที่ 1: k0 = k1

    WLOG ถือว่าb0 < b1(และดังนั้นa0 > a1)

    ให้DIFF(k)เป็นความแตกต่างระหว่างลำดับเหมือน Fibonnaci เริ่มต้นด้วยa1,b1และa0,b0:

    DIFF(k) = FIB(a1,b1,k) - FIB(a0,b0,k) = FIB(a1-a0,b1-b0,k) (บทแทรก 1)

    DIFF(0) = a1 - a0 < 0

    DIFF(1) = b1 - b0 > 0

    DIFF(2) = (a1+b1) - (a0+b0) = 0

    DIFF(3) = DIFF(1) + DIFF(2) = DIFF(1) > 0

    DIFF(4) = DIFF(2) + DIFF(3) = DIFF(3) > 0

    เมื่อลำดับเหมือน Fibonnaci มี 2 คำบวกทุกคำที่ตามมาจะเป็นบวก

    ดังนั้นเวลาเท่านั้น DIFF(k) = 0คือเมื่อk = 2เพื่อให้เป็นทางเลือกสำหรับเป็นk0 = k12

    ดังนั้น n = FIB(a0,b0,2) = a0 + b0 = a1 + b1

    การย่อขนาดของโซลูชันเหล่านี้ขัดแย้งกับเลมม่า 2

  • กรณีที่ 2: k0 != k1 ::

    WLOG ถือว่า k0 < k1ถือว่า

    เรามี FIB(a1,b1,k1) = n

    ปล่อย a2 = FIB(a1,b1,k1-k0)

    ปล่อย b2 = FIB(a1,b1,k1-k0+1)

    แล้วก็ FIB(a2,b2,k0) = FIB(a1,b1,k1) = FIB(a0,b0,k0) (ออกกำลังกายสำหรับผู้อ่าน)

    เนื่องจากFIB(a1,b1,k)ไม่ใช่เชิงลบสำหรับk >= 0จึงไม่ลดลงเช่นกัน

    สิ่งนี้ทำให้เราa2 >= b1 > a0และb2 >= a1+b1 = a0+b0และ

    จากนั้นให้DIFF(k) = FIB(a2,b2,k) - FIB(a0,b0,k) = FIB(a2-a0,b2-b0,k)(เล็มม่า 1)

    DIFF(0) = a2 - a0 > 0

    DIFF(1) = b2 - b0 >= (a0 + b0) - b0 = a0 >= 0

    DIFF(2) = DIFF(0) + DIFF(1) >= DIFF(0) > 0

    DIFF(3) = DIFF(1) + DIFF(2) >= DIFF(2) > 0

    อีกครั้ง DIFFมี 2 ​​คำบวกและดังนั้นคำที่ตามมาทั้งหมดจะเป็นบวก

    ดังนั้นเพียงครั้งเดียวเมื่อมันเป็นไปได้ว่าDIFF(k) = 0จะเป็นk = 1เพื่อให้เป็นทางเลือกสำหรับมีk01

    FIB(a0,b0,1) = n

    b0 = n

    สิ่งนี้ขัดแย้งกับเลมม่า 2




@Neil ลดขนาดที่bแทนของการลดa+bและทำให้การแก้ปัญหาของคุณให้แต่ทางออกที่ดีที่สุดคือf(27) = [3,7] f(27)=[0,9]หลังจากคืนค่าการเปลี่ยนแปลงที่แยกเราจะลดลงเหลือ 83 ไบต์
cardboard_box

1
ฉันคิดว่าคุณสามารถบันทึกไบต์อื่นโดยใช้แทนb-~a a+b+1
Neil

1
มีข้อผิดพลาดเล็ก ๆ ในกรณีที่สองของคุณ: ไม่ถูกต้องเมื่อa2 >= a1 + b1 k1-k0=1แต่คุณสามารถใช้a2 >= b1 > a0และb2 >= a1+b1 = a0+b0จากนั้นส่วนที่เหลือต่อไปนี้
Ørjan Johansen

8

Haskell , 76 72 74 ไบต์

แก้ไข:

  • -4 ไบต์: @ H.PWiz แนะนำให้ใช้/แทนdivถึงแม้ว่าจะต้องใช้ประเภทตัวเลขเศษส่วน
  • 2 ไบต์: แก้ไขข้อผิดพลาดกับช่วงโดยการเพิ่มEnum-1

fรับค่าDoubleหรือRationalพิมพ์และคืนค่า tuple เหมือนกัน Doubleควรเพียงพอสำหรับค่าทั้งหมดที่ไม่ใหญ่พอที่จะทำให้เกิดข้อผิดพลาดในการปัดเศษในขณะที่Rationalไม่ จำกัด ตามหลักวิชา

f n|let a?b=b==n||b<n&&b?(a+b)=[(a,s-a)|s<-[1..],a<-[0..s/2-1],a?(s-a)]!!0

ลองออนไลน์! (ด้วยการปรับส่วนหัวของ H.PWiz เป็นอินพุต / เอาต์พุตRationals ในรูปแบบจำนวนเต็ม)

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

  • ?fเป็นผู้ประกอบการที่ซ้อนกันในประเทศในขอบเขตของ a?bทำซ้ำขั้นตอนผ่านลำดับเหมือน Fibonacci เริ่มต้นด้วยa,bจนถึงb>=nกลับTrueiff มันกระทบnอย่างแน่นอน
  • ในรายการความเข้าใจ:
    • siterates ผ่านตัวเลขทั้งหมดจากการ1ขึ้นไปเป็นตัวแทนของผลรวมของและab
    • aiterates ผ่านตัวเลขจากไป0 s/2-1(ถ้าsเป็นเลขคี่จุดสิ้นสุดของช่วงจะปัดเศษขึ้น)
    • a?(s-a)ทดสอบถ้าลำดับที่เริ่มต้นด้วยเพลงฮิตa,s-a nถ้าเป็นเช่นนั้นเข้าใจรายการรวมถึง (a,s-a)tuple (นั่นคือb=s-aแม้ว่าจะสั้นเกินกว่าจะตั้งชื่อได้)
    • !!0 เลือกองค์ประกอบแรก (กด) ในความเข้าใจ

8

APL (Dyalog) , 75 71 64 59 53 48 44 43 ไบต์

บันทึก 2 ไบต์ด้วย @ Adám

บันทึก 12 ไบต์ด้วย @ngn

o/⍨k∊¨+\∘⌽⍣{k≤⊃⍺}¨oa/⍨</¨a←,⍉|-21+k←⎕

ลองออนไลน์!

⎕IO←0การใช้ประโยชน์

อย่างไร? นี่มันบ้าจริงไปหมดแล้ว

k←⎕ - กำหนดอินพุตให้ k

⍳2⍴1+k←⎕- ผลิตภัณฑ์คาร์ทีเซียนของช่วงที่0จะkด้วยตัวเอง

|-\¨ - ย่อส่วนองค์ประกอบคู่ขวาจากทางซ้ายและรับค่าสัมบูรณ์

a←,⍉ - ขนย้ายแบนและกำหนดให้ a

o←a/⍨</¨a - เก็บเฉพาะคู่ที่องค์ประกอบด้านซ้ายมีขนาดเล็กกว่าด้านขวาและกำหนดให้ o

oตอนนี้มีรายการของคู่ทั้งหมดที่มีa < bสั่งโดยค่าเฉลี่ยทางคณิตศาสตร์ของพวกเขา

+\∘⌽⍣{k≤⊃⍺}¨o- สำหรับแต่ละคู่oใช้ fibonacci (สลับคู่และ cumsum) จนกว่าจะถึงkระยะที่สูงกว่า

k∊¨- จากนั้นตัดสินใจว่าkเป็นคำสุดท้ายหรือไม่ (หมายถึงมีอยู่ในลำดับ)

o/⍨- และเก็บคู่oที่ใช้การตรวจสอบก่อนหน้านี้

- ส่งคืนผลลัพธ์แรก


5

Python 2 , 127 109 107 ไบต์

-2 ไบต์ต้องขอบคุณ ovs (เปลี่ยนandเป็น*)

g=lambda x,a,b:a<=b<x and g(x,b,a+b)or b==x
f=lambda n,s=1,a=0:g(n,a,s-a)*(a,s-a)or f(n,s+(a==s),a%s+(a<s))

ลองออนไลน์!

ใด ๆ ที่คะแนนโบนัสสำหรับn,a,s-a?

คำอธิบาย:

  • บรรทัดแรกประกาศแลมบ์ดาแบบเรียกซ้ำgซึ่งยืนยันว่าการa, bขยายเป็นลำดับฟีโบนักชีจะไปถึงxหรือไม่ นอกจากนี้ยังตรวจสอบว่าa <= bเป็นหนึ่งในเกณฑ์ของคำถาม (สิ่งนี้จะอนุญาตกรณีที่a == bแต่ในกรณีเช่นนี้0, aจะถูกค้นพบและส่งคืนแล้ว)
    • ถูกล่ามโซ่ความไม่เท่าเทียมกันa<=b<xดำเนินการสองงานที่มีประโยชน์ในครั้งเดียว: การตรวจสอบและa <= bb < x
    • ถ้าb < xให้ผลตอบแทนTrueฟังก์ชันจะเรียกตัวเองอีกครั้งด้วยตัวเลขสองตัวถัดไปในลำดับฟีโบนักชี:b, a+bฟังก์ชันเรียกตัวเองอีกครั้งด้วยตัวเลขสองต่อไปในลำดับฟีโบนักชี:ซึ่งหมายความว่าฟังก์ชั่นจะยังคงทำงานออกข้อกำหนดใหม่จนกว่า ...
    • หากb < xอัตราผลตอบแทนที่แล้วเราได้มาถึงจุดที่เราต้องตรวจสอบว่าFalse b==xถ้าเป็นเช่นนี้จะกลับมาTrue, แสดงว่าทั้งคู่เริ่มต้นในที่สุดก็จะถึงa, b xมิฉะนั้นถ้าb > xคู่นั้นไม่ถูกต้อง
  • บรรทัดที่สองบอกอีกแลมบ์ดาเวียนเกิดซึ่งพบว่าวิธีการแก้ปัญหาสำหรับค่าที่กำหนดf nมันซ้ำพยายามคู่เริ่มต้นใหม่a, bจนกว่าอัตราผลตอบแทนg(n, a, b) Trueโซลูชันนี้จะถูกส่งคืน
    • ฟังก์ชันจะนับจำนวนคู่ Fibonacci เริ่มต้นซ้ำโดยใช้สองตัวแปรs(เริ่มแรก 1) และa(เริ่มต้น 0) ในการวนซ้ำแต่ละครั้งaจะเพิ่มขึ้นและa, s-aใช้เป็นคู่แรก อย่างไรก็ตามเมื่อถูกaโจมตีsมันจะถูกรีเซ็ตกลับเป็น 0 และsเพิ่มขึ้น นี่หมายความว่าทั้งคู่จะถูกนับในรูปแบบต่อไปนี้:
      s = 1 (0, 1) (1, 0)
      s = 2 (0, 2) (1, 1) (2, 0)
      s = 3 (0, 3) (1, 2), (2, 1), (3, 0)
      
      เห็นได้ชัดว่านี่มีบางคู่ที่ไม่ถูกต้องอย่างไรก็ตามสิ่งเหล่านี้จะถูกกำจัดทันทีเมื่อผ่านไปg(ดูจุดแรก)
    • เมื่อค่าaและsพบเช่นg(n, a, s-a) == Trueนั้นแล้วค่านี้จะถูกส่งกลับ เนื่องจากวิธีแก้ปัญหาที่เป็นไปได้จะถูกนับตาม 'ขนาด' (เรียงตามค่าเฉลี่ยแล้วค่าต่ำสุด) โซลูชั่นแรกที่พบจะเล็กที่สุดเสมอตามคำขอการท้าทาย

3

R , 183 ไบต์ 160 ไบต์

n=scan();e=expand.grid(n:0,n:0);e=e[e[,2]>e[,1],];r=e[mapply(h<-function(n,a,b,r=a+b)switch(sign(n-r)+2,F,T,h(n,b,r)),n,e[,1],e[,2]),];r[which.min(rowSums(r)),]

ลองออนไลน์!

ขอบคุณ Giuseppe สำหรับการเล่นกอล์ฟที่ 23 ไบต์

คำอธิบายรหัส

n=scan()                        #STDIO input
e=expand.grid(n:0,n:0)          #full outer join of integer vector n to 0
e=e[e[,2]>e[,1],]               #filter so b > a
r=e[mapply(
  h<-function(n,a,b,r=a+b)switch(sign(n-r)+2,F,T,h(n,b,r)),
                                #create a named recursive function mid-call 
                                #(requires using <- vs = to denote local variable creation 
                                #rather than argument assignment
  n,e[,1],e[,2]),]              #map n, a and b to h() which returns a logical
                                #which is used to filter the possibilities
r[which.min(rowSums(r)),]       #calculate sum for each possibility, 
                                #get index of the minimum and return
                                #because each possibility has 2 values, the mean and 
                                #sum will sort identically.

1
160 ไบต์ - โดยทั่วไปคุณควรบันทึกไบต์ทุกที่ที่คุณสามารถทำได้เพื่อประหยัด 4 ไบต์โดยการเอาการตั้งชื่อที่ดีคือไม่เพียง แต่ได้รับการยอมรับหรือได้รับการสนับสนุน แต่ในความรู้สึกบางอย่างที่จำเป็นโดยรหัสกอล์ฟ ถึงแม้จะเป็นคำตอบที่ดี +1
Giuseppe


1

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

ṫ-Sṭµ¡³e
0rŒcÇÐfSÐṂ

ลองออนไลน์!

-1 ขอบคุณไบต์เพื่อพิสูจน์โดยcardboard_box ในกรณีที่ไม่ได้รับการพิสูจน์คุณสามารถผนวกUṂṚท้ายบรรทัดที่สองรวมเป็น 22 ไบต์


... การเพิ่มขึ้นชั้นนำควรแก้ไข @ การสังเกตของ StewieGriffin
Jonathan Allan

ฉันมีความรู้สึกที่คุณสามารถดรอป
Jonathan Allan

1
เราเพียงแค่ต้องค้นหาเมล็ดพันธุ์ที่ทำให้การป้อนข้อมูลxปรากฏขึ้นล่าสุด หากx ถูกพบได้ที่ดัชนีที่สามสำหรับหลาย ๆ แล้วมันทำงานให้0,xและดังนั้นจึงยังทำงานที่ทั้ง1,(x-1)/2( xแปลก) หรือ2,x/2-1( xแม้) ครั้นแล้วxจะปรากฏในภายหลังผลเพื่อให้เคยชินเกิดขึ้น สำหรับการปะทะกันต่อมาค่าเฉลี่ยเท่านั้นที่สามารถจะเหมือนกันถ้าเงื่อนไขที่สามเหมือนกันเกินไป แต่แล้วหนึ่งจะต้องมีความแตกต่างระหว่างที่ต่ำกว่าข้อตกลงเบื้องต้น (อื่นที่พวกเขาต้องการจะเหมือนกัน) และด้วยเหตุนี้จะxพบได้ที่ดัชนีภายหลัง . เช่นนี้เราสามารถทำการṫ-Sṭµ¡i³¶ḶŒcÇÐṀบันทึกสี่ไบต์
Jonathan Allan

... อุ๊ปส์บวกส่วนเพิ่ม:ṫ-Sṭµ¡i³¶‘ḶŒcÇÐṀ
Jonathan Allan

@StewieGriffin ไม่มีกรณีทดสอบเมื่อฉันตอบ: p
Erik the Outgolfer

1

GolfScript - 88 77 ไบต์

~:N[,{1+:a,{[.;a]}/}/][{[.~{.N<}{.@+}while\;N=]}/]{)1=\;},{(\;~+}$(\;);~~' '\

ฉันไม่ได้ตรวจสอบการแก้ไขปัญหาต่าง ๆ ขอบคุณ cardboard_box!

คำอธิบาย

~:N                           # Reads input
[,{1+:a,{[.;a]}/}/]           # Creates an array of pairs [a b]
[{[.~{.N<}{.@+}while\;N=]}/]  # Compute solutions
{)1=\;},         # Pairs that are not solutions are discarded
{(\;~+}$         # Sorts by mean
(\;);~~' '\      # Formats output


0

แบตช์160 158 ไบต์

@set/aa=b=0
:g
@if %a% geq %b% set/ab-=~a,a=0
@set/ac=a,d=b
:l
@if %c% lss %1 set/ad+=c,c=d-c&goto l
@if %c% gtr %1 set/aa+=1,b-=1&goto g
@echo %a% %b%

นี้ (ยัง) ให้กับการป้อนข้อมูล3 7 วิธีการแก้ปัญหาที่ถูกต้องคือ27 0 9
cardboard_box

@cardboard_box ยังไม่เห็นที่คำถามที่ต้องว่า ...
นีล

ในประโยคแรก: "ด้วยค่าเฉลี่ยที่ต่ำที่สุดที่เป็นไปได้"
cardboard_box

@cardboard_box อ่าขอโทษง่ายเกินไปที่จะมองข้าม
Neil

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