Hệ số Fibonacci


21

Số Fibonacci

Các số Fibonacci bắt đầu bằng f(1) = 1f(2) = 1(một số bao gồm f(0) = 0nhưng điều này không liên quan đến thử thách này. Sau đó, cho n > 2, f(n) = f(n-1) + f(n-2).

Các thách thức

Nhiệm vụ của bạn là tìm và xuất ra nsố dương thứ-n có thể được biểu thị dưới dạng các sản phẩm của các số Fibonacci. Bạn có thể chọn làm cho nó 0 chỉ mục hoặc 1 chỉ mục, tùy theo điều kiện nào phù hợp với bạn hơn, nhưng bạn phải chỉ định điều này trong câu trả lời của mình.

Ngoài ra, câu trả lời của bạn phải tính toán thuật ngữ thứ 100 trong một thời gian hợp lý.

Tủ thử

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

Tài liệu tham khảo


Trong trường hợp thử nghiệm tại sao một số trong số họ n = result, trong khi đối với 7 trở lên thì chúng không bằng nhau. Có lẽ tôi không hiểu câu hỏi. Nhưng tôi chỉ muốn kiểm tra
george

1
7không thể được biểu diễn dưới dạng tích số của các số Fibonacci. Do đó, số 1thứ bắt buộc là 1, 2thứ n là 2, ..., 6thứ là 6, nhưng 7thứ là 8.
Rò rỉ Nun

Tất nhiên, điều đó có ý nghĩa
george

Bạn nên in tất cả các cách trong việc tạo ra một số. Ví dụ 16 có hai cách, hoặc bạn chỉ có thể xuất một?
george

3
@george Tôi tin rằng " corresponding product" chỉ để làm rõ. Mã của bạn chỉ cần xuất " result".
trichoplax

Câu trả lời:


6

Thạch , 26 24 23 21 byte

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

Hãy thử trực tuyến!

Làm thế nào nó hoạt động

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
Sự phức tạp của thuật toán này, về mặt đầu vào là gì?
Rò rỉ Nun

Trong mọi trường hợp, nó rất nhanh! Chưa đến 2 giây cho nhiệm kỳ thứ 100
Luis Mendo

@LeakyNun Tôi không biết làm thế nào để tính toán điều đó, nhưng xem cách đầu vào 400 mất 32 lần so với đầu vào 100, tôi sẽ nói rằng đó là số mũ. Xử lý 100 dễ dàng mặc dù.
Dennis

1
Chà, chỉ có bạn mới biết thuật toán của bạn là gì ...
Leaky Nun

Tôi đã xoay sở để làm cho nó nhanh hơn rất nhiều bằng cách không tính toán lại chuỗi Fibonacci cho mỗi số được kiểm tra. Tôi sẽ thêm một lời giải thích ngay sau khi tôi chơi golf xong.
Dennis

5

Julia, 79 byte

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

Hãy thử trực tuyến!

Lý lịch

Trong các vấn đề và giải pháp nâng cao, H-187: Fibonacci là một hình vuông , người đề xuất cho thấy rằng

Nhận dạng Fibonacci / Lucas

trong đó L n biểu thị số Lucas thứ n và ngược lại - nếu

converse Fib nhận dạng / Lucas

thì n là số Fibonacci và m là số Lucas.

Làm thế nào nó hoạt động

Chúng tôi xác định toán tử nhị phân <|cho các mục đích của chúng tôi. Nó không được xác định trong các phiên bản gần đây của Julia, nhưng vẫn được trình phân tích cú pháp công nhận.

Khi được gọi chỉ với một đối số ( n ), <|khởi tạo k1 . Trong khi n là tích cực, nó trừ ! K ( 1 nếu k là một sản phẩm của số Fibonacci, 0 nếu không muốn nói) từ n và đệ quy gọi bản thân, gia số k bằng 1 . Khi n đạt 0 , số lượng sản phẩm mong muốn đã được tìm thấy, do đó <|trả về giá trị trước đó của k , tức là ~ -k = k - 1 .

Toán tử đơn nguyên !, được xác định lại như là một thử nghiệm cho các sản phẩm số Fibonacci, đạt được nhiệm vụ của nó như sau.

  • Nếu k = 1 , k là sản phẩm của các số Fibonacci. Trong trường hợp này, chúng tôi nâng giá trị trả về của lũy any(...)thừa ~ -k = k - 1 = 0 , vì vậy kết quả sẽ là 1 .

  • Nếu k> 1 , kết quả sẽ là giá trị của any(....), giá trị này sẽ trả về true khi và chỉ khi vị từ √(5i^2+[4,-4])%1∋k%i<!(k÷i)trả về true cho một số nguyên i sao cho 2 ≤ i k .

    Các điều kiện xích trong trạng thái giữ vị ngữ nếu k%ithuộc √(5i^2+[4,-4])%1k%inhỏ hơn !(k÷i).

    • √(5i^2+[4,-4])%1lấy căn bậc hai của 5i 2 + 45i 2 - 4 và tính toán dư lượng của chúng modulo 1 . Mỗi mô-đun là 0 nếu số tương ứng là một hình vuông hoàn hảo và một số dương nhỏ hơn 1 nếu không.

      k%itrả về một số nguyên, nó chỉ có thể thuộc về mảng mô đun nếu k% i = 0 (nghĩa là k chia hết cho i ) và ít nhất một trong số 5i 2 + 45i 2 - 4 là một hình vuông hoàn hảo (nghĩa là i là một số Fibonacci).

    • !(k÷i)gọi đệ quy 1 với đối số k ÷ i (phép chia số nguyên), sẽ lớn hơn 0 khi và chỉ khi k ÷ i là sản phẩm của các số Fibonacci.

Theo cảm ứng , ! có tài sản mong muốn.


5

Python, 90 byte

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)

Hàm chính gxuất ra ksản phẩm Fibonacci thứ 1, được lập chỉ mục 1. Nó tính g(100)như 315gần như ngay lập tức. Nó diễn ra như vậy với một công thức đệ quy chung là đếm các số ntìm kiếm các kthể hiện thỏa mãn hàm f. Mỗi trường hợp như vậy làm giảm số lượng yêu cầu kcho đến khi nó đạt được0 .

Hàm phụ trợ fkiểm tra một số để trở thành một sản phẩm Fibonacci. Nó đệ quy tạo ra các số Fibonacci trong các đối số tùy chọn ab. Nó xuất ra "có" nếu bất kỳ điều nào sau đây là đúng:

  • n<2. Điều này nghĩa làn==1 , sản phẩm tầm thường)
  • n%a<f(n/a). Điều này đòi hỏi n%a==0f(n/a)==True, tức là đó nlà bội số của số Fibonacci avà loại bỏ hệ số này làa vẫn mang lại sản phẩm Fibonacci.
  • n-a>0<f(n,b,a+b), tương đương với n>a and f(n,b,a+b). Kiểm tra xem số Fibonacci hiện tại đang được kiểm tra ít nhất không n, và một số số Fibonacci lớn hơn hoạt động. Cảm ơn Dennis vì đã lưu 2 byte bằng cách sử dụng ngắn mạch bất đẳng thức thay vì and.

Hàm gcó thể ngắn hơn một byte như

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

nếu g(k)luôn luôn là nhiều nhất k*k, điều mà tôi không chắc là không đúng sự thật. Một ràng buộc của 2**kđủ, nhưng sau đó g(100)mất quá nhiều thời gian. Có lẽ thay vì đệ quy gcó thể được thực hiện trong f.


Theo bảng này tại OEIS, g(k)vượt quá k*kkhi k = 47000và ở trên.
isaacg

2

Perl 6 ,  95  93 byte

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

(Chỉ số dựa trên 0)

Kiểm tra:

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;
}

Giải trình:

{
  (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

Trăn 3, 175 170 148 byte

Cảm ơn @Dennis cho -22 byte

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)

Lấy đầu vào từ STDIN và in sang STDOUT. Đây là một chỉ mục. Việc tính toán thuật ngữ thứ 100 mất khoảng một phần mười giây.

Làm thế nào nó hoạt động

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

Hãy thử nó trên Ideone


2

Python 2, 120 107 byte

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

Kiểm tra nó trên Ideone .

Làm thế nào nó hoạt động

Chúng tôi khởi tạo F là tuple (2, 3) (hai số Fibonacci đầu tiên lớn hơn 1 ), k0n là số nguyên được đọc từ STDIN.

Trong khi n là dương, chúng tôi làm như sau:

  • Nối số Fibonacci kế tiếp, tính như F [k] + F [-1] , tức là tổng của hai yếu tố cuối cùng của F đến tuple F .

  • Tăng k .

  • Trừ g (k) từ n .

g trả về 1 khi và chỉ khi k là sản phẩm của các số Fibonacci, do đó, khi n đạt 0 , k là số Fibonacci thứ n và chúng tôi in nó thành STDOUT.

g đạt được mục đích của nó như sau.

  • Nếu k1 , thì đó là sản phẩm của các số Fibonacci và 1/kđảm bảo chúng ta trả về 1 .

  • Nếu k lớn hơn 1 , chúng ta gọi là g(k/i)đệ quy cho tất cả các số Fibonacci i trong F .

    g(k/i)kiểm tra đệ quy nếu k / i là sản phẩm số Fibonacci. Nếu g(k/i)trả về 1i chia đều cho k , k% i = 0 và điều kiện k%i<g(k/i)giữ, do đó g sẽ trả về 1 khi và chỉ khi có một số Fibonacci sao cho k là sản phẩm của số Fibonacci đó và một sản phẩm khác của các số Fibonacci.


1

JavaScript (ES6), 136

Khá chậm chơi golf theo cách này, tính toán 100 trong khoảng 8 giây trong PC của tôi.

(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')

Ít chơi gôn và cũng nhanh hơn (tránh 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
}

Kiểm tra

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 byte

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!!)

Rất lười, nhiều vô hạn!

Có thể không phải là con đường ngắn, nhưng tôi đã phải thử phương pháp này, một khái quát về một phương pháp khá nổi tiếng để tính toán danh sách các số hamming. flà danh sách các số Wikipedia bắt đầu từ 2. Để đơn giản, giả sử lol (danh sách danh sách) là một danh sách vô hạn các danh sách vô hạn được sắp xếp theo thứ tự, được sắp xếp theo các yếu tố đầu tiên của chúng. mlà một chức năng để hợp nhất một lol, loại bỏ trùng lặp. Nó sử dụng hai chức năng trợ giúp infix. ?chèn một danh sách được sắp xếp vô hạn vào một lol. #xóa một giá trị khỏi một lol có thể xuất hiện dưới dạng đầu của danh sách đầu tiên, xác nhận lại danh sách còn lại với ?.

Cuối cùng, llà danh sách các số là sản phẩm của các số của Wikipedia, được định nghĩa là 1 theo sau là sự hợp nhất của tất cả các danh sách thu được bằng cách nhân lvới một số Wikipedia. Dòng cuối cùng nêu hàm yêu cầu (như bình thường mà không ràng buộc nó với tên, vì vậy đừng sao chép nó như hiện tại) bằng cách sử dụng !!để lập chỉ mục vào danh sách, làm cho hàm 0 được lập chỉ mục.

Không có vấn đề tính toán số thứ 100 hoặc 100.000.



0

Python 2, 129 128 125 123 121 byte

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

Kiểm tra nó trên Ideone .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.