기지에서 1-2-3- 트리 보나 치까지


19

배경

1-2-3- 트리 보나 치 시퀀스

다음으로 표준 반복 공식을 대체하여 피보나치 시퀀스를 만들 수있는 초 동안 상상 :

트리 보나 치

기본적으로, 대신 다음을 얻기 위해 마지막 두를 합산, 당신은 마지막 세의 합계. 이것은 1-2-3-Tribonacci 시퀀스에 대한 기초이다.

브라운의 기준

당신이 순서의 구성원의 합으로 정수 값을 나타낼 수 있다는 브라운의 기준 상태가 제공 :

  1. x sub n은 1과 같습니다

  2. 모든 내용은 n1보다 큰,x sub n 2 미만 x sub n-1

이것이 도전에 의미하는 것

다음 초기 조건에 의해 형성된 1-2-3-Tribonacci 계열의 구성원들의 합으로 임의의 양의 정수를 기술 할 수있다 :

초기 조건

이것은이 시퀀스의 모든 값으로 알려져 측면 사이의 비율은 2 (약 1.839에서 밖으로 비율 평균)보다 절대 크다.

이 수치 표현 시스템에서 작성하는 방법

리틀 엔디안 표현을 사용한다고 가정 해 봅시다. 다음과 같이 시퀀스 멤버를 정렬하십시오.

1  2  3  6 11 20 37 68

그런 다음 표시되는 전화 번호를 가지고 (우리의 테스트를 들어, 그것의 가정 해 봅시다 63)와 63 합 주어진 1-2-3-Tribonacci의 값을 찾을 수 있습니다 (먼저 가장 큰 값을 사용하여!) . 숫자가 합계의 일부이면 그 아래에 1을 넣고 그렇지 않으면 0을 넣으십시오.

1  2  3  6 11 20 37 68
0  0  0  1  0  1  1  0

주어진 정수에 대해이 작업을 수행 할 수 있습니다-주어진 입력 아래에서 가장 큰 값을 먼저 사용하는지 확인하십시오!

정의 (마지막)

n1과 언어의 최대 값 사이에 양의 정수 입력 (표준 기반으로 작성)이 주어지면 다음을 수행하는 프로그램이나 함수를 작성하십시오.

  1. 값을 정의 된 1-2-3- 트리 보나 치의 숫자 표현으로 변환하십시오.
  2. 이진 유사 표현을 사용하여 마치 이진 인 것처럼 읽습니다. 이것은 숫자가 동일하게 유지되지만 의미가 변경됨을 의미합니다.
  3. 이 이진수를 가져 와서 원래 숫자의 밑으로 변환하십시오.
  4. 출력 또는이 새 번호를 반환합니다.

그러나 출력이 유효하면 다음 단계를 수행하지 않아도됩니다. 더 짧고 (수학적으로 동등한) 수식을 마술처럼 찾으면 자유롭게 사용하십시오.

함수가 보자 f정의에 의해 기술 된 기능, 그리고하자 [](이 문제는 안하지만, 리틀 엔디안으로) 수행 단계를 나타냅니다 (이 과정을 수행 할 필요가 없습니다, 이것은 단지 과정이 설명되어 있습니다) :

>>> f(1)
[1]
[1]
[1]
1

>>> f(5)
[5]
[0, 1, 1]
[6]
6

>>> f(63)
[63]
[0, 0, 0, 1, 0, 1, 1]
[104]
104

짧지 않지만 질문을 더 빨리 해결할 수있는 별도의 프로그램을 제출할 수 있습니까? log (n) + n 시간과 달리 log (log (n)) + n 시간. N 번째 파워 매트릭스로 이동하십시오.
fəˈnɛtɪk

@LliwTelracs 솔루션 게시를 중단 할 수는 없습니다. 올바른 방법으로 경쟁하고 있는지 확인하기 위해 솔루션 방법을 지식에 간결하게 지정하십시오.
Addison Crump

글쎄, 적어도 이것을하지 않을 것입니다. 이 행렬의 빠른 지수는 엄청나게 장황하다
fəˈnɛtɪk

2
@LliwTelracs 어쩌면 기존 게시물의 부록으로 추가하십시오.
Jonathan Allan

당신의 도전은 이미지를 보여줄 수없는 사람들에게는 읽을 수 없습니다.
Mindwin

답변:


7

자바 스크립트 117111 바이트

5 바이트의 골프 오프를 도와 준 @theonlygusti에게 감사합니다

x=>{r=0;a=[1,2,3];i=1;while(a[++i]<x)a[i+1]=a[i]+a[i-1]+a[i-2];for(;x;i--)if(x>=a[i]){r+=1<<i;x-=a[i]}return r}

작동 원리

먼저, 함수는 입력보다 하나 더 큰 것을 찾을 때까지 모든 트리 보나 치 수를 생성합니다.

a=[1,2,3];i=1;for(;a[++i]<x;)a[i+1]=a[i]+a[i-1]+a[i-2];

그런 다음 숫자 목록을 반대로 검색합니다. 숫자가 입력 값보다 작 으면 반환 값에 2 ^ (해당 숫자의 인덱스)를 더하고 해당 숫자만큼 입력을 줄입니다.

for(;x;i--)if(x>=a[i]){r+=1<<i;x-=a[i]}

마지막으로 결과를 반환합니다.

온라인으로 사용해보십시오


1
무엇에 대해 a[++i]<x조건에 대한 내부 바이트를 저장하려면?
theonlygusti

1
또한, 교체 할 수 있습니다 x>0x. 다른 2 바이트를 저장하십시오.
theonlygusti

꽤 좋은 알고리즘입니다. oo
Addison Crump

7

파이썬 (2) , 110 (102) 바이트

Rod 덕분에 -3 바이트 (부울 i을 int로 캐스팅 하기 위한 깔끔한 트릭으로 +irepr `+i`작동)

n=input()
x=[3,2,1]
r=''
while x[0]<n:x=[sum(x[:3])]+x
for v in x:i=n>=v;n-=v*i;r+=`+i`
print int(r,2)

온라인으로 사용해보십시오!


1
당신은 대체 할 수 '01'[i]`+i`
로드

i부울은 정수가 아닙니다. 편집-오 +i, 깔끔합니다.
Jonathan Allan

3
@Rod는 파이썬이 팁과 트릭 트릭인가?
애디슨 크럼

나는 그렇게 생각하지 않습니다 @VoteToClose
로드

7

자바 스크립트 (ES6), 97 93 바이트

여기서는 reduce()재귀 함수를 사용 하고 있습니다. 출력은 31 비트 (JS가 비트 단위 연산을 위해 쉽게 작업 할 수있는 가장 큰 부호없는 양) 인 것으로 가정합니다.

n=>[...Array(x=31)].reduce(p=>(c=(F=k=>k<4?k:F(--k)+F(--k)+F(--k))(x--))>n?p:(n-=c,p|1<<x),0)

현명한 성능, 이것은 매우 효율적이지 않습니다.

호기심을 위해 :

  • F()N + 1 reduce()반복 대 N 반복 호출 횟수 간의 비율 은 트리 보나 치 상수 (Constant 1.83929)로 빠르게 수렴됩니다. 따라서 출력의 각 추가 비트는 이전 비트보다 약 두 배의 시간이 걸립니다.
  • 31 비트에서는이 F()기능을 1 억 2 천 6 백만 번이라고합니다.

테스트

주의 : 완료하는 데 1 ~ 2 초가 걸릴 수 있습니다.


와우, 사용하면 브라우저가 뒤쳐집니다. xD
Addison Crump

@VoteToClose 성능면에서, 이것은 매우 비효율적입니다. :-) 테스트 코드가 너무 오래 지연되어서는 안됩니다. 내 상자에는 Firefox에서 약 600ms, Chrome에서 900ms를 얻습니다. 당신 쪽이 훨씬 느려요?
Arnauld 2012

5 초 정도 xD
Addison Crump

@VoteToClose 지금 조금 더 빨라야합니다. 32 번째 반복은 의미가 없으므로 출력을 부호없는 31 비트 정수로 제한했습니다.
Arnauld 2012

6

Mathematica, 78 74 바이트

Fold[#+##&,#~NumberDecompose~Reverse@LinearRecurrence[{1,1,1},{1,2,3},#]]&

LinearRecurrence[{1,1,1},{1,2,3},#]1-2-3 개의 트리 보나 치 수의 입력과 동일한 길이의 목록을 생성합니다. (이는 {1,1,1}앞의 세 항의 합계를 나타내며 {1,2,3}초기 값 이지만 ) #~NumberDecompose~입력을 목록의 요소 합계로 쓰는 가장 좋은 방법을 찾습니다 (이는 화폐 금액을 배수의 배수로 분해하는 동일한 함수입니다). 예를 들어 사용 가능한 통화). 마지막으로 Fold[#+##&,...]결과 이진 목록을 (기본 10) 정수로 변환합니다.

이전 제출 :

Fold[#+##&,#~NumberDecompose~Reverse@Array[If[#<4,#,Tr[#0/@(#-Range@3)]]&,#]]&

위와 같지 않은 경우가 많지만,이 골프 버전은 길이가 입력 인 트라이브 목록을 (최적화되지 않은 재귀로) 생성하기 때문에 20보다 큰 입력에서는 매우 느립니다. 최종 #을보다 합리적인 범위로 대체하면 Round[2Log@#+1]성능이 훨씬 향상됩니다.


화? Mathematica는 123Tribonacci[]내장되어 있지 않습니까?
palsch

1
정확히는 아니지만 내장 기능을 사용하면 약간 도움이됩니다.
Greg Martin

5

하스켈, 95 바이트

(a!b)c=a:(b!c)(a+b+c)
e#(r,c)|c-e<0=(2*r,c)|1<2=(2*r+1,c-e)
f n=fst$foldr(#)(0,n)$take n$(1!2)3

사용 예 : f 63-> 104. 온라인으로 사용해보십시오! .

작동 방식 : !1-2-3- 트리 보나 치 시퀀스를 구축합니다. 을 감안할 때 1, 2그리고 3시작 매개 변수로, 우리는 첫 번째 걸릴 n시퀀스의 요소를. 그리고 우리는 바로 함수에서 배 #다음 요소를 뺀 e에서 n반환 값에 비트를 설정 r하는 경우 e필요하거나 비트 해제를 할 수있다. 비트 설정은 두 배가 r되고 추가하는 1것입니다.


4

젤리 , 31 바이트

S=³
3RUµḣ3S;µ<³Ạµ¿µŒPÇÐfṀe@ЀµḄ

온라인으로 사용해보십시오!

젤리에서 이것을 달성하는 훨씬 짧은 방법이 있다고 확신합니다.

어떻게?

S=³ - Link 1, compare sum to input: list
S   - sum
  ³ - 3rd command line argument which is 1st program argument.
 =  - equal?

3RUµḣ3S;µ<³Ạµ¿µŒPÇÐfṀe@ЀµḄ - Main link: n
3RU                         - range(3) upended -> [3,2,1]
   µ    µ   µ¿              - while
         <³                 - less than input (vectorises)
           Ạ                - all?
    ḣ3S;                    -     head(3), sum, and concatenate
                                  [3,2,1] -> [6,3,2,1] -> [11,6,3,2,1] -> ...
              µ             - monadic chain separation, call the result x
               ŒP           - power set of x - e.g. for [6,3,2,1] -> [[],[6],[3],[2],[1],[6,3],[6,2],[6,1],[3,2],[3,1],[2,1],[6,3,2],[6,3,1],[6,2,1],[3,2,1],[6,3,2,1]]
                  Ðf        - filter keep
                 Ç          -     last link (1) as a monad (those that sum to the input)
                    Ṁ       - maximum (e.g. an input of 63 would yield [[37,20,6],[37,20,3,2,1]], the maximum of which is [37,20,6], the one with the largest numbers used)
                         µ  - monadic chain separation (to have x as the right argument below)
                     e@Ѐ   - exists in with reversed arguments mapped over x (e.g. [37,20,6] with x = [68,37,20,11,6,3,2,1] yields [0,1,1,0,1,0,0,0])
                          Ḅ - convert from binary to integer.        

4

펄 6 , 93 91 바이트

b2gill 덕분에 -2 바이트

{my@f=1,2,3,*+*+*...*>$^n;sum @f».&{$_~~any first *.sum==$n,@f.combinations}Z*(2 X**^∞)}

작동 원리

  • 우선, 입력보다 큰 첫 번째 요소까지 1-2-3-Tribonacci 시퀀스를 생성한다 :

    my @f = 1, 2, 3, *+*+* ... * > $^n;
  • 이를 기반으로 입력에 합산되는 시퀀스의 하위 집합을 찾습니다.

    first *.sum==$n, @f.combinations
  • 이를 기반으로 시퀀스의 각 요소가 합계의 일부인지 여부를 지정하는 부울 목록을 구성합니다.

    @f».&{$_~~any ...}
  • 마지막으로 True = 1, False = 0 값의 목록을 밑수 2로 해석하고 (밑수 10) 숫자로 반환합니다.

    sum ... Z* (2 X** ^∞)

1
당신은 사용하여이 단축 될 수 있습니다 *>$^n.sum==$n. 또한 공간을 사이에 필요하지 않습니다 my@f
브래드 길버트는 b2gills

3

자바 스크립트 (ES6), 61 60 바이트

n=>(g=(x,y,z)=>(n>x&&g(y,z,x+y+z)*2)+!(n<x||![n-=x]))(1,2,3)

1-2-3-Tribonacci 숫자가 원래 숫자에 도달 할 때까지 계산 한 다음 재귀가 풀리면 하나씩 차례로 빼려고 시도하여 결과가 두 배가되도록합니다.

편집 : @ Arnauld 덕분에 1 바이트가 절약되었습니다.


와! 아주 좋아요 n=>(g=(x,y,z)=>(n>x&&g(y,z,x+y+z)*2)+!(n<x||![n-=x]))(1,2,3)바이트를 저장할 수 있습니까?
Arnauld 2013

@ Arnauld 나는 뭔가를 찾고 n<x||있었지만 그것은 ![]천재입니다.
Neil

2

배치, 151 (148) 145 바이트

@set/ar=0,n=%1
@call:c 3 2 1
@echo %r%
@exit/b
:c
@set/as=%1+%2+%3
@if %n% gtr %3 call:c %s% %*
@set/ar*=2
@if %n% geq %3 set/an-=%3,r+=1

내 JavaScript 답변의 포트. 편집 : 내 서브 루틴 인수를 역순으로 전달하여 3 바이트를 절약하고 @대신 각 줄에 개별을 사용하여 3 바이트를 절약했습니다 @echo off.


2

젤리 , 19 18 17 바이트

Ḣx3+
BÇL¡2ị
²Ç€»ċ

온라인으로 사용해보십시오!

배경

정수를 1,2,3-Tribonacci 염기로 변환 한 다음 이진수에서 정수로 변환하는 대신 정수를 이진수로 변환 한 다음 1,2,3-Trionacci 염기를 정수로 변환하고 반환 입력과 일치하는 가장 높은 것 이것은 쉽게 달성됩니다.

입력 ( 63) 의 프로세스 , 특히 104 가 테스트 되는 단계 를 예시 할 것이다 . 이진수에서 최상위에서 최하위 숫자까지 104 는 다음과 같습니다.

 1  1  0  1  0  0  0
37 20 11  6  3  2  1

여기서 두 번째 행은 해당 자릿수의 위치 값을 나타냅니다.

1,2,3-Tribonacci 시퀀스를 오른쪽으로 확장하여 추가 된 숫자가 동일한 재귀 수식을 따르는 지 관찰합니다. 세 mre 숫자의 경우

 1  1  0  1  0  0  0  0  0  0
37 20 11  6  3  2  1  0  1  0

이제 기본 1,2,3- 트리 보나 치 수의 값을 계산하기 위해 재귀 공식을 사용할 수 있습니다. 각 숫자는 오른쪽 위의 세 숫자의 합이므로 (위의 표에서) 첫 번째 숫자를 제거하고 나머지 배열의 첫 번째 세 숫자에이를 추가 할 수 있습니다. 이진 자릿수 104 와 같은 7 단계 후 , 우리는 3 자리 숫자 만 남지 않습니다.

 1  1  0  1  0  0  0  0  0  0
37 20 11  6  3  2  1  0  1  0

    2  1  2  0  0  0  0  0  0
   20 11  6  3  2  1  0  1  0

       3  4  2  0  0  0  0  0
      11  6  3  2  1  0  1  0

          7  5  3  0  0  0  0
          6  3  2  1  0  1  0

            12 10  7  0  0  0
             3  2  1  0  1  0

               22 19 12  0  0
                2  1  0  1  0

                  41 34 22  0
                   1  0  1  0

                     75 63 41
                      0  1  0

이제 첫 번째와 마지막 숫자가 모두 위치 값 0 이므로 결과는 중간 자릿수, 즉 63 입니다.

작동 원리

²Ç€»ċ   Main link. Argument: n

²       Yield n². Since 1.839² = 3.381921 > 2, the range [1, ..., n²] will contain
        the answer. Better bounds, at the cost of additional bytes are possible.
 Ç€     Map the the second helper link over [1, ..., n²].
   »    Take the maximum of n and each result.
    ċ   Count the occurrences of n.


BÇL¡2ị  Second helper link. Left argument: k. Right argument: n

B       Convert k to binary. Let's call the result A.
  L     Length; count the number of binary digits. Let's call the result l.
 Ç ¡    Apply the first helper link l times to A.
    2ị  Retrieve the second element.


Ḣ×3+    First helper link. Argument: A (array)

Ḣ       Head; pop and yield the first element of A.
 x3     Repeat it thrice.
   +    Add the result, component by component, to the beheaded A.

2

젤리 ( 포크 ), 17 16 바이트

ḣ3S;µ¡
3RṚdzæFṪḄ

@Dennis 덕분에 실행하지 않고도 1 바이트를 절약했습니다.

이것은 실망스럽게도 효율적인 Frobenius solve atom 구현을 위해 노력하고있는 Jelly 포크에 의존합니다. 관심있는 사람들을 위해 Mathematica의 속도와 일치시키고 싶습니다. FrobeniusSolve행운 적으로 그들의 방법에 대한 설명이 있습니다. 맞추고 싶습니다. 다행스럽게도 Daniel Lichtblau의 "변화를 만들고 찾기 : 배낭 균형 잡기"논문 에 있습니다.

설명

ḣ3S;µ¡  Helper link. Input: a list
    µ   Create monadic chain
ḣ3        Take the first 3 items
  S       Sum
   ;      Prepend to the list
     ¡  Repeat it n (initial argument from main) times

3RṚdzæFṪḄ  Main link. Input: integer n
3          The constant 3
 R         Range. Makes [1, 2, 3]
  Ṛ        Reverse. Makes [3, 2, 1]
   Ç       Call the helper link on that list.
           Generates the first (n+3) 123-Tribonacci values in reverse
    ³      Get n
     æF    Frobenius solve for n using the first n 123-Tribonacci values in reverse
       Ṫ   Tail. Take the last value. The results of Frobenius solve are ordered
           where the last result uses the least
        Ḅ  Unbinary. Convert digits from base 2 to base 10

3
당신은 당신이 수퍼-에 소랑 포크를 사용할 때 코드 골프에 깊이 빠져 있음을 알고 있습니다.
애디슨 크럼

시겠습니까 ḣ3S;µ¡¶3RṚdzæFṪḄ일? 포크를 설치하지 않았으므로 테스트 할 수 없습니다.
Dennis

@Dennis 그것은 논쟁이 아닌 stdin으로부터 입력을 받고 있습니다. 나는 인수를 사용하는 데 문제가 있었고 다른 방식으로 작동한다는 것을 깨달았습니다.
마일

아닙니다. 그것은 여전히 ​​논쟁이되어야합니다. ³첫 번째 인수를 참조합니다.
데니스

@Dennis Nvm, 인수로 작동합니다 jelly.py. 마지막 커밋 후에 다른 것들이있었습니다.
마일

1

DC , 110 102 바이트

?se1sa2sb3sc_1sf[laddSdlbdsalcdsb++sclf1+sfle>y]dsyx0sk[lk2lf^+skler-se]sr[Lddle!<rlf1-dsf0!>z]dszxlkp

글쎄, 좋은 생각 똑같이 생각하는 것 같습니다 . 분명히, 내가 가진 알고리즘은 다음과 같은 한계를 극복했습니다.dc 찾은 은 우연히 @LliwTelrac의 대답에 사용 된 것과 똑같은 알고리즘입니다. 흥미 롭군

온라인으로 사용해보십시오!



1

bash + BSD 유틸리티 (OS X 등), 53 바이트

jot $[2#$1**4]|egrep -v '[2-9]|11(1|$)'|sed $[2#$1]!d

bash + GNU 유틸리티 (BSD에서도 작동), 59 바이트

seq -f2o%.fp $[2#$1**2]|dc|egrep -v '11(1|$)'|sed $[2#$1]!d

위의 두 가지 입력 및 출력은 모두 바이너리입니다.


TIO에서 GNU 버전을 사용해보십시오. (이 예제는 이진수 63111 인 111111의 입력과 이진수 104 인 1101000의 출력을 보여줍니다.)

TIO가 BSD 옵션을 제공하지는 않지만 Mac을 사용할 수 있다면 두 가지 모두를 사용해 볼 수 있습니다. (59 바이트 프로그램은 53 바이트 프로그램보다 훨씬 빠릅니다.)


불행하게도, seq단순히 대신에 BSD 솔루션으로 삭제할 수 없습니다 jot에 대한 출력 형식 때문에,seq 이 999999 이상의 출력에 대해 다르기 .

jot위의 내용을 대체 seq -f%.f하여 GNU 유틸리티에서 작동하도록 할 수 있지만 동일한 59 바이트에 대해 위의 GNU 솔루션을 사용할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.