피보나치 분해


21

피보나치 수

피보나치 숫자로 시작 f(1) = 1하고 f(2) = 1(일부는 포함 f(0) = 0하지만이이 문제에 무관하다. 그런 다음, 대한 n > 2, f(n) = f(n-1) + f(n-2).

도전

당신의 임무는 n피보나치 수의 곱으로 표현 될 수 있는- 번째 양수 를 찾아서 출력하는 것 입니다. 0 색인 또는 1 색인 중 더 적합한 것을 선택할 수 있지만 답에이를 지정해야합니다.

또한 답은 적절한 시간에 100 번째 항을 계산해야합니다.

테스트 케이스

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 이상에서는 동일하지 않습니다. 어쩌면 나는 그 질문을 이해하지 못할 수도 있습니다. 하지만 그냥 확인하고 싶습니다
george

1
7피보나치 수의 곱으로 표현할 수 없습니다. 따라서, 1명세서가 필요 수는 11, 2ND가되는 2제 1, ..., 6일이 6있지만, 7제이다 8.
Leaky Nun

아, 물론 말이됩니다.
George

당신은 숫자를 만드는 모든 방법을 인쇄해야합니다. 예를 들어 16에는 두 가지 방법이 있습니까? 아니면 하나만 출력 할 수 있습니까?
george

3
@george 나는 " 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
입력 측면에서이 알고리즘의 복잡성은 무엇입니까?
Leaky Nun

어쨌든 매우 빠릅니다! 100 번째 학기 동안 2 초 미만
Luis Mendo 2016 년

@LeakyNun 나는 그것을 계산하는 방법을 모른다. 그러나 입력 400이 입력 100보다 32 배 더 오래 걸리는 것을 보는 것은 지수라고 말합니다. 그래도 쉽게 100을 처리합니다.
Dennis

1
글쎄, 오직 당신 만이 알고있는 알고리즘은 ...
Leaky Nun

테스트 된 모든 숫자에 대해 피보나치 시퀀스를 다시 계산하지 않으면 훨씬 빨라졌습니다. 골프를 마치 자마자 설명을 추가하겠습니다.
Dennis

5

줄리아, 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 : 피보나치는 정사각형 , 제안자 쇼 그

피보나치 / 루카스 정체성

어디서? L nn 번째 루카스 숫자를 나타내며 반대로 –

대화 피보나치 / 루카스 정체성

다음 N 피보나치 수이고 m은 루카스 번호이다.

작동 원리

우리는 <|목적을 위해 이진 연산자 를 정의합니다 . 최근 버전의 Julia에서는 정의되지 않았지만 여전히 파서에서 연산자로 인식됩니다.

하나의 인수 ( n ) 만으로 호출하면 k1<|초기화 합니다. 하지만 n이 긍정적이고, 그것은 감산 ! K ( 1 경우 K는 피보나치 수의 제품 0 에서하지 않은 경우) N 재귀 증분, 자신을 호출 K 의해 1 . 일단 n 개 에 도달 0 , 제품의 원하는 양이 발견되었다, 그래서 의 이전 값을 반환<| K , 즉, ~ -k = 케이 - 1 .

단항 연산자 !피보나치 수 제품에 대한 테스트로 재정 는 다음과 같은 작업을 수행합니다.

  • 경우 K = 1 , k는 피보나치 수의 산물이다. 이 경우, 우리는 반환 값 올리는 any(...)힘에 ~ -k = 케이 - 1 = 0 므로 결과는 1이 됩니다.

  • 경우 K> 1 , 결과의 값이됩니다 any(....)반환합니다 진정한 경우에만, 술어 √(5i^2+[4,-4])%1∋k%i<!(k÷i)반환 사실을 일부 정수에 대한 되도록 2 ≤ ≤ I 케이 .

    술어 홀드의 체인 조건이있는 경우 k%i에 속 √(5i^2+[4,-4])%1하고k%i 미만이다 !(k÷i).

    • √(5i^2+[4,-4])%1의 제곱근 소요 5I 2 + 45I 2 4 - 그들의 잔류가 모듈로 계산 1 . 각 계수는해당 숫자가 완전 제곱이면 0 이고, 그렇지 않으면 양수는 1 보다 작습니다 .

      이후 k%i경우에 반환 정수, 단지 계수들의 어레이에 속할 수 유전율 % I = 0 (즉, k는 로 나누어 I 적어도 하나 사이에서) 5I 2 + 45I 2 - 4로 완벽한 정사각형이다 (즉, 나는 피보나치 수입니다).

    • !(k÷i)k ÷ i (정수 나누기) 를 인수 1 로 재귀 적으로 호출 합니다. k ÷ i 가 피보나치 수의 곱인 경우에만 0 보다 큽니다 .

귀납으로 ! 원하는 속성이 있습니다.


5

파이썬, 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)

주요 기능 gk피보나치 제품을 1- 색인으로 출력합니다 . 거의 즉시 계산 g(100)됩니다 315. 함수를 만족시키는 인스턴스를 n찾는 숫자를 세는 일반적인 재귀 레시피와 함께 사용 k됩니다 f. 이러한 각 인스턴스는에 k도달 할 때까지 필요한 수를 줄 0입니다.

보조 기능 f은 피보나치 제품인 숫자를 테스트합니다. 선택적 인수 a및로 피보나치 수를 재귀 적으로 생성합니다 b. 다음 중 하나라도 해당되면 "yes"가 출력됩니다.

  • 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 바이트를 절약 해 준 Dennis에게 감사합니다 and.

함수 g는 다음과 같이 1 바이트 더 짧을 수 있습니다.

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

if g(k)는 항상 최대 k*k이지만 확실하지 않은 것은 확실합니다. A는의 경계 2**k충분하다, 그러나 g(100)너무 오래 걸립니다. 대신에 재귀를 g수행 할 수 있습니다 f.


에 따르면 이 테이블 OEIS에서, g(k)초과 k*kk = 47000이상.
isaacg

2

펄 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

파이썬 3, 175 170 148 바이트

-22 바이트에 대한 @Dennis 덕분에

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 번째 항을 계산하는 데 대략 1/10 초가 걸립니다.

작동 원리

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

파이썬 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 를 튜플 (2, 3) ( 1 보다 큰 처음 두 피보나치 수 ), k0 , n 은 STDIN에서 읽은 정수 로 초기화 합니다.

n 은 양수 이지만 다음을 수행합니다.

  • F [k] + F [-1] 으로 계산 된 다음 피보나치 수, 즉 F 의 마지막 두 요소의 합을 튜플 F에 추가 합니다.

  • 증분 k .

  • n 에서 g (k) 를 뺍니다 .

g는 반환 1 경우만 k는 피보나치 수의 곱이므로 한번 인 N 에 도달 0 , k는 은 IS N 번째 피보나치 수 우리는 STDOUT에 출력한다.

g 는 다음과 같은 목적을 달성합니다.

  • 경우 k는 이다 1 , 그것은 피보나치 수의 제품이며, 1/k반드시 우리가 반환한다 1 .

  • 경우 k는 보다 큰 1 , 우리는 전화를 g(k/i)모두 피보나치 번호를 반복적으로 F .

    g(k/i)k / i 가 피보나치 수 제품 인지 재귀 적으로 테스트합니다 . 경우 g(k/i)리턴 1내가 분할 케이 균일 K % 나 0 = 조건이 k%i<g(k/i)보유되도록 g이 반환 1 되도록 피보나치 수있을 경우에만, k는 의 생성물임을 피보나치 수와 피보나치 수의 다른 제품.


1

자바 스크립트 (ES6), 136

내 PC에서 약 8 초 만에 용어 100을 계산하는 방식으로 상당히 느리게 골프를 쳤다.

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

골프가 적고 속도도 빠름 (피하기 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

하스켈, 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간결함을 위해 lol (목록의 목록)은 순서가있는 무한 목록의 첫 번째 요소가 첫 번째 요소로 정렬되어 있다고 가정 해 봅시다. m롤을 병합하고 중복을 제거하는 기능입니다. 두 가지 중위 도우미 기능을 사용합니다. ?무한 정렬 목록을 lol에 삽입합니다. #첫 번째 목록의 헤드로 나타날 수있는 lol에서 값을 제거하고 나머지 목록을? .

마지막으로, l피보나치 수의 곱인 피보나치 수의 곱인 숫자 목록이 1로 정의되고이어서 l피보나치 수와 곱하여 얻은 모든 목록이 병합 됩니다. 마지막 줄은 다음과 같이 사용하여 필요한 기능을 나타냅니다 (평소와 같이 이름에 바인딩하지 않고 그대로 복사하지 마십시오).!! 은 목록에 색인을 작성 기능을 0 색인화합니다.

100 번째 또는 100,000 번째 숫자를 계산하는 데 아무런 문제가 없습니다.



0

파이썬 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.