ตัวประกอบ Fibonacci


21

ตัวเลขฟีโบนักชี

ตัวเลข Fibonacci เริ่มต้นด้วยf(1) = 1และf(2) = 1(บางคนรวมถึงf(0) = 0แต่เรื่องนี้ไม่เกี่ยวข้องกับความท้าทายนี้. แล้วสำหรับ,n > 2f(n) = f(n-1) + f(n-2)

ความท้าทาย

งานของคุณคือการค้นหาและส่งออกnจำนวนบวก -th ที่สามารถแสดงเป็นผลิตภัณฑ์ของหมายเลขฟีโบนักชี คุณสามารถเลือกที่จะทำให้ดัชนี 0 หรือดัชนี 1 ดัชนีใดก็ตามที่เหมาะกับคุณดีกว่า แต่คุณต้องระบุสิ่งนี้ในคำตอบของคุณ

นอกจากนี้คำตอบของคุณจะต้องคำนวณคำที่ 100 ในเวลาที่เหมาะสม

Testcases

n   result corresponding product (for reference)
1   1      1
2   2      2
3   3      3
4   4      2*2
5   5      5
6   6      2*3
7   8      2*2*2 or 8
8   9      3*3
9   10     2*5
10  12     2*2*3
11  13     13
12  15     3*5
13  16     2*2*2*2 or 2*8
14  18     2*3*3
15  20     2*2*5
16  21     21
17  24     2*2*2*3 or 3*8
18  25     5*5
19  26     2*13
20  27     3*3*3
100 315    3*5*21

อ้างอิง


ในกรณีทดสอบเหตุใดบางคนจึง n = ผลลัพธ์ในขณะที่สำหรับ 7 และสูงกว่านั้นไม่เท่ากัน บางทีฉันอาจไม่เข้าใจคำถาม แต่ฉันแค่ต้องการตรวจสอบ
จอร์จ

1
7ไม่สามารถแสดงเป็นผลิตภัณฑ์ของหมายเลขฟีโบนักชี ดังนั้น1จำนวน ST ต้องมี1การ2ครั้งที่มีการ2... ที่6วันที่เป็น6แต่วันที่เป็น7 8
Leun Nun

อาแน่นอนว่าเหมาะสมแล้ว
george

หากคุณพิมพ์ทุกวิธีในการสร้างตัวเลข ตัวอย่างเช่น 16 มีสองวิธีหรือคุณเพียงแค่เอาท์พุท?
george

3
@ จอร์จฉันเชื่อว่า " corresponding product" เป็นเพียงเพื่อความกระจ่าง รหัสของคุณต้องการส่งออก " result" เท่านั้น
trichoplax

คำตอบ:


6

เยลลี่ , 26 24 23 21 ไบต์

ÆDf÷߀FðḊ¡
1ç#2+С1¤Ṫ

ลองออนไลน์!

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

1ç#2+С1¤Ṫ  Main link. Argument: n (integer)

        ¤   Combine the three links to the left into a niladic chain.
   2          Set the left argument and the return value to 2 (third positive
              Fibonacci number).
       1      Yield 1 (second positive Fibonacci number).
    +С       Compute the sum of the return value and right argument, replacing the
              return value with the sum and the right argument with the previous
              return value.
              Do this n times, collecting all return values in a list.
              This returns A, the first n Fibonacci numbers greater than 1.
1             Set the return value to 1.
 ç#           Call the helper link with left argument k = 1, 2, 3... and right
              argument A = [2, 3, 5...] until n of them return a truthy value.
              Collect the matches in a list.
           Ṫ  Tail; extract the last (n-th) match.


ÆDf÷߀FðḊ¡    Helper link. Left argument: k. Right argument: A

        Ḋ     Dequeue; yield r := [2, ..., k].
       ð ¡    If r in non-empty, execute the chain to the left. Return k otherwise.
ÆD              Yield the positive divisors of k.
   ÷            Divide k by all Fibonacci numbers in A.
  f             Filter; keep divisors that belong to k÷A, i.e., all divisors
                d for which k÷d belongs to A.
    ߀          Recursively call the helper link for each kept divisor d, with left
                argument d and right argument A.
      F         Flatten the result, yielding a non-empty array iff any of the
                recursive calls yielded a non-empty array or a number.
                If the left argument is 1, the helper link returns 1, so the
                array will be non-empty if the consecutive divisions by Fibonacci
                numbers eventually produced a 1.

2
ความซับซ้อนของอัลกอริทึมนี้ในแง่ของอินพุตคืออะไร
Leun Nun

ไม่ว่าในกรณีใดมันเร็วมาก! น้อยกว่า 2 วินาทีสำหรับคำศัพท์ที่ 100
Luis Mendo

@LeakyNun ฉันไม่รู้ว่าจะคำนวณอย่างไร แต่เมื่อเห็นว่า 400 ใช้เวลานานกว่าอินพุท 100 ถึง 32 เท่าฉันจะบอกว่ามันแทนเลขชี้กำลัง จัดการ 100 ได้อย่างง่ายดายแม้ว่า
Dennis

1
มีเพียงคุณเท่านั้นที่รู้ว่าอัลกอริทึมของคุณคืออะไร
Leun Nun

ฉันจัดการเพื่อให้เร็วขึ้นมากโดยไม่ทำการคำนวณลำดับ Fibonacci ใหม่สำหรับทุกหมายเลขที่ทดสอบ ฉันจะเพิ่มคำอธิบายทันทีที่ฉันเล่นกอล์ฟเสร็จ
Dennis

5

Julia, 79 ไบต์

!k=any(i->√(5i^2+[4,-4])%1k%i<!(k÷i),2:k)^~-k
<|(n,k=1)=n>0?n-!k<|-~k:~-k

ลองออนไลน์!

พื้นหลัง

ในปัญหาขั้นสูงและการแก้ปัญหา H-187: Fibonacci เป็นรูปสี่เหลี่ยมจัตุรัสผู้เสนอนั้นแสดงให้เห็นว่า

เอกลักษณ์ของ Fibonacci / Lucas

ที่L nหมายถึงn TH จำนวนลูคัสและที่ - ตรงกันข้าม - ถ้า

การสนทนา Fibonacci / Lucas เอกลักษณ์

ดังนั้นnคือหมายเลขฟีโบนักชีและmคือหมายเลขลูคัส

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

เรากำหนดผู้ประกอบการแบบไบนารี<|สำหรับวัตถุประสงค์ของเรา มันไม่ได้กำหนดไว้ใน Julia เวอร์ชันล่าสุด แต่ยังคงได้รับการยอมรับว่าเป็นตัวดำเนินการโดย parser

เมื่อเรียกว่ามีเพียงหนึ่งอาร์กิวเมนต์ ( n ) <|เริ่มต้นkเป็น1 ในขณะที่nเป็นบวกก็หัก! k ( 1ถ้าkเป็นผลิตภัณฑ์ของตัวเลข Fibonacci เป็น0หากไม่ได้) จากnและซ้ำเรียกตัวเองเพิ่มขึ้นkโดย1 เมื่อnถึง0 , จำนวนเงินที่ต้องการของผลิตภัณฑ์ที่ได้รับการพบเพื่อ<|ส่งกลับค่าก่อนหน้าของkคือ~ -k = k - 1

ผู้ประกอบการเอกที่!นิยามใหม่เป็นการทดสอบผลิตภัณฑ์หมายเลขฟีโบนักชีประสบความสำเร็จในงานดังต่อไปนี้

  • ถ้าk = 1 , kเป็นผลคูณของตัวเลขฟีโบนักชี ในกรณีนี้เรายกค่าตอบแทนของany(...)อำนาจ~ -k = k - 1 = 0ดังนั้นผลจะเป็น1

  • ถ้าk> 1ผลที่ได้จะเป็นค่าของany(....)ที่จะกลับมาจริงและถ้าหากคำกริยา√(5i^2+[4,-4])%1∋k%i<!(k÷i)ผลตอบแทนที่แท้จริงสำหรับจำนวนเต็มบางฉันเช่นที่2 ≤≤ฉัน k

    ถูกล่ามโซ่เงื่อนไขในการระงับกริยาถ้าk%iเป็น√(5i^2+[4,-4])%1และมีค่าน้อยกว่าk%i!(k÷i)

    • √(5i^2+[4,-4])%1ใช้เวลารากที่สองของ5I 2 + 4และ5I 2 - 4และคำนวณตกค้างของพวกเขาแบบโมดูโล1 แต่ละโมดูลัสเป็น0ถ้าจำนวนที่สอดคล้องกันเป็นตารางที่สมบูรณ์และเป็นจำนวนบวกน้อยกว่า1มิฉะนั้น

      เนื่องจากk%iส่งกลับจำนวนเต็มมันจะเป็นของอาเรย์ของ moduli ถ้าk% i = 0 (เช่นkคือตัวหารด้วยi ) และอย่างน้อยหนึ่งในหมู่5i 2 + 4และ5i 2 - 4เป็นตารางที่สมบูรณ์แบบ (เช่นฉันคือหมายเลขฟีโบนักชี)

    • !(k÷i)เรียก1ซ้ำด้วยอาร์กิวเมนต์k ÷ i (การหารจำนวนเต็ม) ซึ่งจะมากกว่า0ถ้าหากว่าk ÷ iเป็นผลคูณของตัวเลขฟีโบนักชี

โดยการเหนี่ยวนำ! มีคุณสมบัติที่ต้องการ


5

Python ขนาด 90 ไบต์

f=lambda n,a=2,b=3:n<2or n%a<f(n/a)or n-a>0<f(n,b,a+b)
g=lambda k,n=1:k and-~g(k-f(n),n+1)

ฟังก์ชั่นหลักgส่งออกkผลิตภัณฑ์ Fibonacci ลำดับที่ 1 ซึ่งจัดทำดัชนี มันคำนวณg(100)เป็น315เกือบจะทันที มันจะไปให้กับสูตร recursive ทั่วไปของการนับตัวเลขที่nมองหาอินสแตนซ์ที่ตอบสนองการทำงานk fแต่ละกรณีดังกล่าวจะช่วยลดการนับที่จำเป็นจนกว่าจะถึงk0

ฟังก์ชั่นเสริมfทดสอบตัวเลขสำหรับการเป็นผลิตภัณฑ์ Fibonacci มันซ้ำสร้างตัวเลขฟีโบนักชีในการขัดแย้งที่ไม่จำเป็นของตนและa bมันจะส่งออก "ใช่" หากสิ่งใดสิ่งหนึ่งต่อไปนี้เป็นจริง:

  • n<2. นี่หมายถึงn==1ผลิตภัณฑ์ที่น่ารำคาญ)
  • n%a<f(n/a). สิ่งนี้ต้องการn%a==0และf(n/a)==Trueนั่นnคือจำนวนทวีคูณของจำนวนฟีโบนักชีaและการลบปัจจัยนี้aยังคงให้ผลิตภัณฑ์ฟีโบนักชี
  • n-a>0<f(n,b,a+b)n>a and f(n,b,a+b)เพื่อเทียบเท่า ตรวจสอบว่าหมายเลขฟีโบนักชีปัจจุบันที่ทดสอบไม่น้อยnและหมายเลขฟีโบนัชชีที่มากขึ้นนั้นใช้ได้ ขอขอบคุณที่เดนนิสสำหรับ 2 andไบต์ประหยัดโดยใช้ความไม่เท่าเทียมกันลัดวงจรแทน

ฟังก์ชั่นgนี้สามารถสั้นลงหนึ่งไบต์ได้

lambda k:filter(f,range(k*k+1))[k]

หากg(k)เป็นอย่างมากที่สุดk*kซึ่งฉันไม่แน่ใจว่าเป็นเรื่องจริงเชิงเส้นกำกับ ขอบเขตของความ2**kพอเพียง แต่จากนั้นg(100)ใช้เวลานานเกินไป บางทีแทนที่จะ recursive ของสามารถทำได้ในgf


ตามตารางนี้ที่ OEIS g(k)เกินk*kเวลาk = 47000และสูงกว่า
isaacg

2

Perl 6 ,  95  93 ไบต์

{(1..*).grep({$/=$_;map {->{$/%$_||($//=$_);$/}...*!%%$_;0},reverse 2,3,&[+]...*>$_;2>$/})[$_]}
{(1..*).grep({$/=$_;map {->{$/%$_||($//=$_);$/}...*%$_;0},reverse 2,3,&[+]...*>$_;2>$/})[$_]}

(ดัชนีตาม 0)

ทดสอบ:

my &fib-prod = {(1..*).grep({$/=$_;map {->{$/%$_||($//=$_);$/}...*%$_;0},reverse 2,3,&[+]...*>$_;2>$/})[$_]}

say fib-prod 0 ..^ 20;
# (1 2 3 4 5 6 8 9 10 12 13 15 16 18 20 21 24 25 26 27)
say time-this { say fib-prod 100 -1; };
# 315
# 1.05135779

sub time-this (&code) {
  my $start = now;
  code();
  now - $start;
}

คำอธิบาย:

{
  (1..*).grep(
    {
      $/ = $_; # copy the input ($_) to $/
      map { # map used just for side effect
        ->{
          $/ % $_    # if $/ is divisible by the current fib factor
        ||
          ($/ /= $_) # divide it out once
        ;
          # return the current value in $/
          $/
        }
        ... # repeat until that returns:
        * !%% $_ # something that is not divisible by the current fib factor
        ;0
      },
      # the possible fibonacci factors plus one, reversed
      # ( the extra is to save one byte )
      reverse 2,3,&[+] ... *>$_;

      # is the end result of factoring equal to 1
      # ( for the grep above )
      2 > $/
    }
  )[ $_ ] # get the value at 0-based index
}

2

Python 3, 175 170 148 ไบต์

ขอบคุณ @Dennis สำหรับ -22 ไบต์

j=x=int(input())
y=1,1
exec('y+=y[-2]+y[-1],;'*x)
i=c=0
while c<x:
    if j>=x:j=0;i+=1;t=i
    if t%y[~j]<1:t/=y[~j];j-=1
    if t<2:c+=1;j=x
    j+=1
print(i)

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

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

j=x=int(input())                Get term number x from STDIN and set Fibonacci number index
                                j to x to force initialisation of j later 
y=1,1                           Initialise tuple y with start values for Fibonacci sequence
exec('y+=y[-2]+y[-1],;'*x)      Compute the Fibonacci sequence to x terms and store in y
i=c=0                           Initialise test number i and term counter c
while c<x:                      Loop until x th term is calculated
    if j>=x:j=0;i+=1;t=i        Initialise Fibonacci number index j, increment i and
                                initialise temp variable t for looping through all j for
                                some i. Executes during the first pass of the loop since
                                at this point, j=x
    if t%y[~j]<1:t/=y[~j];j-=1  Find t mod the j th largest Fibonacci number in y and if no
                                remainder, update t by dividing by this number.
                                Decrementing j means that after a later increment, no
                                change to j occurs, allowing for numbers that are 
                                divisible by the same Fibonacci number more than once by
                                testing again with the same j
    if t<2:c+=1;j=x             If repeated division by ever-smaller Fibonacci numbers
                                leaves 1, i must be a Fibonacci product and c is
                                incremented. Setting j equal to x causes j to be reset
                                to 0 during the next loop execution
    j+=1                        Increment j
print(i)                        i must now be the x th Fibonacci product. Print i to STDOUT

ลองใช้กับ Ideone


2

Python 2, 120 107 ไบต์

g=lambda k:1/k+any(k%i==0<g(k/i)for i in F)
F=2,3;k=0;n=input()
while n:F+=F[k]+F[-1],;k+=1;n-=g(k)
print k

ทดสอบบนIdeone

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

เรากำหนดค่าเริ่มต้นFเป็น tuple (2, 3) (สองหมายเลขแรกของฟีโบนักชีมากกว่า1 ), kเป็น0และnเป็นจำนวนเต็มอ่านจาก STDIN

ในขณะที่nเป็นค่าบวกเราทำดังต่อไปนี้:

  • ผนวกจำนวนฟีโบนักชีต่อไปคำนวณเป็นF [k] + F [-1]คือผลรวมของทั้งสององค์ประกอบสุดท้ายของFกับ tuple F

  • เพิ่มค่าk

  • ลบกรัม (k)จากn

gส่งคืน1ถ้าหากkเป็นผลคูณของหมายเลขฟีโบนักชีดังนั้นเมื่อnถึง0 , kคือจำนวนฟีโบนักชีลำดับที่nและเราพิมพ์มันลงใน STDOUT

gบรรลุวัตถุประสงค์ดังนี้

  • ถ้าkเป็น1มันเป็นผลิตภัณฑ์ของตัวเลข Fibonacci และ1/kทำให้แน่ใจว่าเราจะกลับ1

  • ถ้าkเป็นจำนวนมากกว่า1เราเรียกg(k/i)ซ้ำสำหรับตัวเลขทั้งหมด Fibonacci ฉันในF

    g(k/i)ทดสอบซ้ำว่าk / iเป็นผลิตภัณฑ์หมายเลขฟีโบนักชี หากg(k/i)ส่งคืน1และฉันหารkเท่ากันk% i = 0และเงื่อนไขk%i<g(k/i)ถือดังนั้นgจะส่งคืน1ถ้าหากมีหมายเลขฟีโบนักชีเช่นนั้นkคือผลิตภัณฑ์ของหมายเลขฟีโบนักชีนั้นและผลิตภัณฑ์อีกตัวของหมายเลขฟีโบนักชี


1

JavaScript (ES6), 136

เล่นกอล์ฟช้าด้วยวิธีนี้ระยะการคำนวณ 100 ในประมาณ 8 วินาทีในพีซี

(n,F=i=>i>1?F(i-1)+F(i-2):i+1,K=(n,i=1,d,x)=>eval('for(;(d=F(i++))<=n&&!(x=!(n%d)&&K(n/d)););x||n<2'))=>eval('for(a=0;n;)K(++a)&&--n;a')

น้อย golfedและเร็วเกินไป (หลีกเลี่ยงeval)

n=>{
  F=i=> i>1 ? F(i-1)+F(i-2) : i+1; // recursive calc Fibonacci number
  K=(n,i=1,d,x)=>{ // recursive check divisibility
    for(; (d=F(i++))<=n && !(x=!(n%d)&&K(n/d)); );
    return x||n<2
  };
  for(a=0; n; )
    K(++a) && --n;
  return a
}

ทดสอบ

X=(n,F=i=>i>1?F(i-1)+F(i-2):i+1,K=(n,i=1,d,x)=>eval('for(;(d=F(i++))<=n&&!(x=!(n%d)&&K(n/d)););x||n<2'))=>eval('for(a=0;n;)K(++a)&&--n;a')

function test() {
  var i=+I.value
  O.textContent=X(i)
}

test()
<input id=I value=100 >
<button onclick="test()">Go</button><pre id=O></pre>


1

Haskell, 123 ไบต์

f=2:scanl(+)3f
m((a:b):c)=a:m(b?(a#c))
v#((a:b):c)|v==a=b?(v#c)
_#l=l
y?(z:e)|y>z=z:y?e
a?b=a:b
l=1:m[[a*b|b<-l]|a<-f]
(l!!)

ขี้เกียจมากไม่มีที่สิ้นสุดมาก!

อาจไม่ใช่วิธีที่สั้น แต่ฉันต้องลองวิธีนี้ซึ่งเป็นวิธีการทั่วไปที่รู้จักกันดีในการคำนวณรายการของตัวเลขการแฮ็ก fคือรายการของหมายเลขฟีโบนักชีเริ่มต้นที่ 2 สำหรับความกะทัดรัดสมมติว่า lol (รายการของรายการ) เป็นรายการที่ไม่มีที่สิ้นสุดของรายการที่ไม่มีคำสั่งซึ่งเรียงลำดับตามองค์ประกอบแรก mเป็นฟังก์ชั่นที่จะรวม lol โดยลบรายการที่ซ้ำกัน มันใช้สองฟังก์ชั่นผู้ช่วยมัด ?แทรกรายการที่เรียงไม่สิ้นสุดลงใน lol #เอาค่าจากฮ่า ๆ ?ที่อาจปรากฏเป็นหัวของรายการแรกที่ใส่เข้าไปใหม่รายการที่เหลือด้วย

ในที่สุดlก็คือรายการของตัวเลขซึ่งเป็นผลคูณของตัวเลขฟีโบนักชีหมายถึง 1 ตามด้วยการผสานของรายการทั้งหมดที่ได้จากการคูณlด้วยจำนวนฟีโบนักชี บรรทัดสุดท้ายระบุฟังก์ชั่นที่ต้องการ (ตามปกติโดยไม่มีการเชื่อมโยงกับชื่อดังนั้นอย่าคัดลอกตามที่เป็นอยู่) !!เพื่อทำดัชนีลงในรายการซึ่งทำให้ฟังก์ชัน 0 เป็นดัชนี

ไม่มีปัญหาในการคำนวณตัวเลขที่ 100 หรือ 100,000


1

Husk , 13 ไบต์

โปรดทราบว่า Husk นั้นใหม่กว่าความท้าทายนี้ อย่างไรก็ตามมันและฟังก์ชั่นที่มีประโยชน์ที่สุดสำหรับกอล์ฟนี้ ( Ξ) ไม่ได้ถูกสร้างขึ้นโดยคำนึงถึงความท้าทายนี้

S!!Ṡ¡ȯuΞIṪ*İf

ลองออนไลน์!

รุ่นที่มีประสิทธิภาพมากขึ้นสำหรับ 14 ไบต์:

ลองออนไลน์!


0

Python 2, 129 128 125 123 121 ไบต์

g=lambda k:1/k|any(abs(round(5**.5*i)**2-5*i*i)==4>k%i<g(k/i)for i in range(k+1))
f=lambda n,k=1:n and f(n-g(k),k+1)or~-k

ทดสอบบนIdeone

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