골롬의 자기 설명 순서의 n 번째 항을 계산


11

이전 질문에서 영감을 얻었습니다 .

골롬의 자기-설명 서열 g (n)은 임의의 자연수 n가 서열 g (n) 시간 내에 반복되는 서열이다.

시퀀스의 처음 몇 숫자는 다음과 같습니다.

n    1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18 19 20
g(n) 1  2  2  3  3  4  4  4  5  5  5  6  6  6  6  7  7  7  7  8

g (4) = 3이고 "4"가 시퀀스에서 3 번 반복됨을 알 수 있습니다.

입력이 주어지면 noutput g(n).

제한 사항 : n <100000.

가장 작은 코드가 승리합니다.


순진이 그것을 사용하는 것을 제외하고는 앞의 질문과 동일 접근 n보다는 2 - n % 1. 답변이 크게 다를 것으로 예상 할만한 이유가 있습니까?
피터 테일러

2
Haskell에서는 다음을 사용할 수 있습니다.golomb=1:2:2:concat(zipWith replicate(drop 2 golomb)[3..])
FUZxxl

@ PeterTaylor : 나는 그것을 몰랐다.
beary605

답변:


5

GolfScript (31 자)

~([1 2.]2{.2$=[1$)]*@\+\)}3$*;=

데모


좋았지 만 실제로 n = 99999로 시도 했습니까? 그렇다면 얼마나 오래 걸렸습니까? (나는 그것을 시도 할 때, 나는 그것을 설정하려는 100의 MIB 메모리 제한을 타격과 충돌하기 전에 시간 동안 달렸다.)
Ilmari 카로 넨

@IlmariKaronen, 아니오. 이 질문은 메모리 또는 시간 효율성에 대한 제한을 설정하지 않으므로 입력 크기의 경계는 고정 너비 int가있는 언어에 대한 것으로 가정합니다.
피터 테일러

6

비경쟁 젤리

10 바이트이 대답은 경쟁이 아니기 때문에 도전이 젤리를 만들기 전에 시작됩니다.

’ßßạ¹ß‘µṖ¡

OEIS 페이지 의 재귀 수식 a (1) = 1, a (n + 1) = 1 + a (n + 1-a (a (n))) 을 사용합니다.

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

작동 원리

’ßßạ¹ß‘µṖ¡ Main link. Input: n

’          Decrement; yield n - 1.
 ßß        Recursively call the main link twice, with argument n - 1.
   ạ¹      Take the absolute difference of a(a(n - 1)) and n.
     ß     Recursively call the main link, with argument n - a(a(n - 1)).
      ‘    Increment the result, yielding 1 + a(n - a(a(n - 1))).
       µ   Combine the chain to the left into a single link.
        Ṗ  Pop [1, ..., n]. This yields [] iff n == 1.
         ¡ Execute the chain iff Ṗ returned a non-empty array.

4

PHP-63 문자

function g($n){for(;++$i<=$n;){for(;++$j<=$i;){echo $i;}$j=0;}}

빠르고 짧습니다.

순서가 잘못되었습니다. Derp.

이것은 정확하고 빠르며 짧습니다.

function g($n){for(;++$i<$n;){echo round(1.201*pow($i,.618));}}

정확도는 필요한 100,000 마크를 넘을 수 있지만 실제로 마크를 충족했습니다.


3

PHP

이 재귀 버전은 더 짧지 만 (60) 계산적으로 비효율적입니다.

function g($n){return$n==1?1:1+g($n-g(g($n-1)));}echo g($n);

이것은 훨씬 빠르지 만 길다 (78).

$a=[1,2,2];for($i=3;$i<$n;$i++)for($j=0;$j<$a[$i-1];$j++)$a[]=$i;echo$a[$n-1];

훨씬 빠르지 만 89 자이면 다음과 같습니다.

$a=[1,2,2];for($i=3;!isset($a[$n-1]);$i++)for($j=0;$j<$a[$i-1];$j++)$a[]=$i;echo$a[$n-1];

어느 것이 O (n)



3

오아시스 , 7 바이트 (비경쟁)

암호:

n<aae>T

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

Oasis는 Adnan 이 디자인 한 언어 로 시퀀스에 특화되어 있습니다.

현재이 언어는 재귀 및 닫힌 양식을 수행 할 수 있습니다.

T말은 속기 인 10것을 나타냅니다, a(0) = 0그리고 a(1) = 1. 테스트 케이스를 더 추가하려면 끝에있는 목록에 추가하십시오.

n<aae>T
n<aae>10  expanded

       0  a(0) = 0
      1   a(1) = 1

n         push n (input)
 <        -1
  a       a(above)  [a is the sequence]
   a      a(above)
    e     a(n-above)
     >    +1

이제 우리는 기본적으로 계산했습니다 a(n-a(a(n-1))+1.


2

펄, 48 자

(@a=(@a,($,)x($a[$,++]||$,)))<$_?redo:say$,for<>

stdin에 입력하고 stdout에 출력합니다. 기능 -M5.010을 사용하려면 Perl 5.10 이상이 필요 say합니다. 비효율적 인 배열 조작으로 인해 약 O ( n 2 ) 시간이 걸리지 만 최대 10 만 항까지 쉽게 계산할 수있을 정도로 빠릅니다.


2

줄리아-28

A로 재귀 방법 :

a(n)=n==1?1:1+a(n-a(a(n-1)))

산출:

[a(i) for i=1:20]'
1x20 Array{Int64,2}:
 1  2  2  3  3  4  4  4  5  5  5  6  6  6  6  7  7  7  7  8

2

파이썬-64 자

n=input()
g=[1,2,2]
for i in range(3,n):g+=[i]*g[i-1]
print g[n]

1
좋은 데요 나는 그렇게 [i]*g[i-1]할 것이라고 생각하지 않았 으므로 다른 방법으로 뒤로 구부 렸습니다. 나는 ... 더 어떤 이유로 스칼라 행렬을 곱처럼 행동 것이라고 생각
chucksmash

1

자바 스크립트, 93 자

c=[,1],i=c.length;function g(n){for(i;i<n;i++) c[i]=g(i);return c[n]||(c[n]=1+g(n-g(g(n-1))))}

1

J, 43 자

f=:3 :'<.@:+&0.5(p^2-p)*y^p-1[p=:(+%)/20$1'

위키 백과 페이지에 제공된 점근 적 표현을 사용하여 함수를 정의합니다.

   f 5
3
   f 20
8
   f 100000
1479

성가신 9 문자는 가장 가까운 정수로 반올림하는 데 사용됩니다.


1

전주곡 , 69 55 54 바이트

?1-(v  #1)-
1   0v ^(#    0 (1+0)#)!
    (#)  ^#1-(0)#

표준 호환 인터프리터가 사용되면 입력 및 출력을 바이트 값으로 사용합니다 . 실제로 STDIN / STDOUT에서 십진수를 사용하려면 Python 인터프리터NUMERIC_OUTPUT = True추가 옵션이 필요 합니다NUMERIC_INPUT = True .

설명

프로그램의 골격은

?1-(    1 -
1                     )!

우리 N는 첫 번째 음성으로 입력 을 읽고 그것을 얻기 위해 감소시킵니다 N-1. 또한 두 번째 음성을로 초기화합니다 1. 그런 다음 N-1각 반복이 두 번째 스택에서 시퀀스의 다음 값을 가져옵니다. 마지막으로 우리는 Nth 숫자를 인쇄합니다 .

프로그램의 아이디어는 시퀀스의 각 요소를 세 번째 음성의 대기열에 넣고 각 반복에서 해당 대기열의 헤드를 줄이는 것입니다. 헤드가 도달 0하면 시퀀스 값을 증가시키고 제거합니다 0.

이제 문제는 Prelude가 대기열이 아닌 스택을 사용한다는 것입니다. 따라서 대기열처럼 사용하려면 해당 스택을 약간 이동해야합니다.

v  #
0v ^
(#)

이렇게하면 시퀀스의 현재 값이 첫 번째 음성 (임시 사본으로)에 복사 0되고 두 번째 음성으로 푸시됩니다 (대기열의 끝 표시). 그런 다음 루프를 수행하여 세 번째 스택을 두 번째 스택으로 이동 (및 반대로)합니다. 루프 후, 현재 시퀀스 값의 사본을 두 번째 스택 (큐의 꼬리) 위에 놓습니다.

 )
(#
 ^#1-

이것은 약간 추한 것처럼 보이지만 본질적으로 스택을 세 번째 음성으로 다시 이동시키는 루프입니다. )가 쉬프팅 명령과 동일한 열에 있기 때문에, 0두 번째 음성을 더 일찍 붙인 것은 세 번째 음성을 끝내게되므로 다른 음성으로 제거해야합니다 #. 그런 다음 세 번째 음색의 맨 위, 즉 큐의 헤드를 줄입니다.

이제 약간 성가시다-그 값이 0인 경우 코드를 실행하고 싶지만 Prelude의 유일한 제어 구조 (루프)는 0이 아닌 값에만 응답합니다.

 0 (1+0)#
(0)#

두 번째 음성의 상단은 진실합니다 (골롬 시퀀스에 0s가 포함되어 있지 않기 때문에 ). 따라서 작업량은 그 음성 (후자의 괄호 쌍)으로 들어갑니다. 우리 는 대기열의 머리가 아직 없다면 그것을 막을 필요가 0있습니다. 먼저 0큐의 헤드가 여전히 0이 아닌 경우 세 번째 음색에 "루프"가있어 두 번째 음색으로 A를 푸시 합니다. 또한 0루프를 즉시 종료하기 위해 세 번째 음색을 사용합니다. #제 보이스는 그 중 하나를 제거하는 0경우, 또는 큐의 선두 이미 제로였다. 이제 두 번째 루프는 대기열의 헤드가 0 인 경우에만 입력됩니다.0두 번째 목소리는 결코 밀리지 않았습니다). 이 경우 시퀀스의 현재 값을 증가시키고 a 0를 눌러 루프를 종료합니다. 마지막으로 항상 0스택 맨 위에 있어야하므로 버려야합니다.

나는 Prelude에서 논리적 부정이 성가신 것이라고 말했다.


1

Mathematica, 27 바이트

f@1=1;f@n_:=1+f[n-f@f[n-1]]

또 다른 재귀 솔루션.


1

CJam, 14 바이트

CJam 은이 도전보다 훨씬 젊으 므로이 답변은 녹색 확인 표시를 사용할 수 없습니다. 그러나 사용하기가 매우 드 quite니다j 이것을 잘 때문에 어쨌든 게시하고 싶었습니다.

l~2,{_(jj-j)}j

여기에서 테스트하십시오.

설명

j기본적으로 "기억 된 재귀 연산자"입니다. 정수 N, 배열 및 블록이 필요 F합니다. 배열은 메모를 초기화하는 데 사용됩니다 . index의 요소 i가에 대해 반환됩니다 F(i). j그런 다음 값을 아직 메모하지 않은 경우 F(N)찾거나 블록 n에서 스택 을 실행 하여을 계산합니다. 정말 멋진 기능은 블록 에서 jinteger 만 가져 i오고 F(i)재귀 적으로 호출 한다는 것 입니다. 코드는 다음과 같습니다.

l~             "Read and eval input.";
  2,           "Push a 2-range onto the stack, i.e. [0 1]. The first value is irrelevant
                but the second value is the base case of the recursion.";
    {       }j "Compute F(N).";
     _(        "Duplicate i and decrement to i-1.";
       jj      "Compute F(F(i-1)).";
         -     "Subtract from i.";
          j    "Compute F(n-F(F(i-1))).";
           )   "Increment the result.";

1

J, 16 바이트

    <:{1($1+I.)^:[~]

    (<:{1($1+I.)^:[~]) every 1+i.20  NB. results for inputs 1..20
1 2 2 3 3 4 4 4 5 5 5 6 6 6 6 7 7 7 7 8

이 솔루션은되어 크게 기반으로 algorithmshark의 솔루션 유사한 문제. 이 방법에 대한 설명이 있습니다.

J, 33 바이트

이 방법에서 나는 일련의 구축 h(k)첫 번째 인덱스의 값 정도 . 입력이 있는 표현식으로 간단히 얻을 수 있습니다.ig(i)=kh = 1 2 4 6 9 12 16...h(k)h(1..k-1)({:+1+[:+/#<:])h(1..k-1) .

출력을 계산하는 h것은 간단합니다.h ([:+/]>:[) input

[:+/]>:1 2(,{:+1+[:+/#<:])@]^:[~]


0

파이썬-76 자

n=20;g=[1,2,2];[[g.append(i)for j in range(g[i-1])]for i in range(3,n)];g[n]

이것은 실제로 목록을 Nones로 채 웁니다 . Nones tho :) 의 "정확한"양인 것 같습니다
daniero

1
@Daniero 예, 이상한 코드입니다. 실제로 작동했는지 확인하기 위해 몇 번 실행해야했습니다. list.append ()가 None타입을 리턴하기 때문에리스트 이해를 다수의 None으로 채 웁니다 . 방금 중첩 목록 이해를 사용하여 중첩 루프를 달성했습니다. 그들이 값을 던져 있습니다 - 여기에 지능형리스트의 유일한 목적은 루프 배의 오른쪽 숫자 코드를 야기하는 것입니다
chucksmash

전통적인 중첩 루프를 수행하면 두 문자가 절약됩니다. :)
chucksmash

불행히도 우리가 허용하지 않는 입력을 하드 코딩하고 REPL 환경을 가정 하여이 조각을 만들 것 같습니다. 기본적 으로 모든 제출은 스 니펫 대신 기본 I / O 방법 중 하나를 사용하는 전체 프로그램 또는 기능이어야합니다 . 궁금한 점이 있으면 알려주세요.
Alex A.

@AlexA. 약간의 고고학을하고 있습니까?
chucksmash

0

자바 스크립트-48 자

for(g=[,i=j=k=1,2];i<1e5;k=--k?k:g[++j])g[i++]=j

g시퀀스 값을 포함 하는 1 인덱스 배열 을 만듭니다 .

편집-JavaScript-46 자

v=[,1];for(x=2;x<1e5;)v[x]=1+v[x-v[v[x++-1]]]

v시퀀스 값을 포함 하는 1 인덱스 배열 을 만듭니다 .

편집 2-ECMAScript 6-27 자

g=x=>x-1?1+g(x-g(g(x-1))):1

처음 두 개는 상당히 빠릅니다. 세 번째는 매우 느립니다.


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