ゴロムの自己記述シーケンスの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回繰り返されていることがわかります。

の入力が与えられた場合n、output 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のメモリ制限に達する前に1時間実行されてクラッシュしました。)
Ilmari Karonen

@IlmariKaronen、いいえ。この質問では、メモリや時間の効率に制限は設定されていません。そのため、入力サイズの制限は、固定幅のintを持つ言語向けであると想定しています。
ピーターテイラー

6

ゼリー、非競合

10 バイト この答えは、Jellyの作成よりも前のチャレンジなので、競合しません。

’ßßạ¹ß‘µṖ¡

これは、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

Oasis、7バイト(非競合)

コード:

n<aae>T

オンラインでお試しください!

Oasisは、シーケンスに特化したAdnanによって設計された言語です。

現在、この言語は再帰と閉じた形式を実行できます。

T終了時には、の省略形である10ことを示している、a(0) = 0a(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

Perl、48文字

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

stdinへの入力、stdoutへの出力。Perl 5.10以降と-M5.010say機能を有効にする必要があります。非効率的な配列操作のために約O(n 2)時間かかりますが、100,000番目の項まで簡単に計算できるほど高速です。


2

ジュリア-28

することにより、再帰的な方法:

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

Python-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

Javascript、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で実際に10進数を使用するには、PythonインタープリターNUMERIC_OUTPUT = True追加オプションが必要NUMERIC_INPUT = Trueです。

説明

プログラムのスケルトンは

?1-(    1 -
1                     )!

入力Nを最初の音声に読み込み、それをデクリメントして取得しN-1ます。また、2番目の音声をに初期化し1ます。次に、ループをN-11回繰り返し、その繰り返しごとに、2番目のスタックのシーケンスの次の値を取得します。最後にNth番目の数字を出力します。

プログラムの考え方は、シーケンスの各要素を3番目の音声のキューに入れ、各反復でそのキューの先頭を減らすことです。頭に達する0と、シーケンスの値を増やしてそれを取り除き0ます。

問題は、Preludeがキューではなくスタックを使用することです。そのため、キューのように使用するには、そのスタックを少し移動する必要があります。

v  #
0v ^
(#)

これは、シーケンスの現在の値を最初の音声にコピーし(一時コピーとして)、02番目の音声にプッシュします(キューの終わりをマークするため)。そして、ループを実行して、3番目のスタックを2番目のスタックにシフトします(つまり、逆にします)。ループの後、現在のシーケンス値のコピーを2番目のスタック(キューの末尾)の上に置きます。

 )
(#
 ^#1-

これは少しいように見えますが、基本的にはスタックを3番目のボイスに戻すループです。以来)シフト命令と同じ列にある、0私たちはお互いにそれを削除する必要があるので、私たちは第2の音声に置くには、以前にも、第三声になってしまいます#。次に、3番目の音声の先頭、つまりキューの先頭をデクリメントします。

少し面倒です-その値がのときにコードを実行したいのですが0、Preludeの唯一の制御構造(ループ)はゼロ以外の値にのみ応答します。

 0 (1+0)#
(0)#

2番目の音声の上部は真実です(ゴロムシーケンスには0s が含まれていないため)。したがって、ワークロードはその音声(後者の括弧のペア)に入ります。キューの先頭がまだない場合は、それを防ぐ必要があります0。したがって、最初に3番目の音声に「ループ」が0あり、キューの先頭がまだゼロでない場合に2 番目の音声にプッシュします。また0、3番目の音声にaを付けて、ループをすぐに抜けます。#第三声には、いずれかのことを削除する0場合、またはキューの先頭を削除することがすでにゼロでした。これで、キューの先頭がゼロの場合にのみ2番目のループに入ります(そして02番目の声ではプッシュされませんでした)。その場合、シーケンスの現在の値をインクリメントし、a 0を押してループを終了します。最後に、常に0スタックの一番上にあり、破棄する必要があります。

プレリュードでは論理否定が迷惑だと言いました...



1

CJam、14バイト

CJamはこの課題よりもはるかに若いため、この回答は緑色のチェックマークの対象ではありません。ただし、jこれをうまく使用することは非常にまれなので、とにかくそれを投稿したかったです。

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

ここでテストしてください。

説明

j基本的に「記憶された再帰演算子」です。整数N、配列、ブロックを取りますF。配列は、メモ化を初期化するために使用されます。インデックスの要素iが返されF(i)ます。j次にF(N)、ルックアップするnか、値がまだメモされていない場合は(スタック上で)ブロックを実行することにより、を計算します。本当に気の利いた機能は、ブロック内でj整数のみを受け取り、再帰的に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

Python-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()はNonetypeを返すので、リストの内包をNonesの束で埋めます。ネストされたリストの内包表記を使用して、ネストされたループを実現しました。彼らは値を捨てている-ここでは、リストの内包表記の唯一の目的は、ループのコード回の右数せることである
chucksmash

従来のネストされたループを行っていた場合、2つの文字を節約できます:)
チャックスマッシュ

残念ながら、許可されていない入力をハードコーディングしていて、これをスニペットにするREPL環境を想定しているようです。デフォルトでは、すべての送信は、スニペットではなくデフォルトのI / Oメソッドの 1つを使用する完全なプログラムまたは機能でなければなりません。何か質問があれば教えてください。
アレックスA.

@AlexA。少し考古学をしていますか?
チャックスマッシュ

0

JavaScript-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

最初の2つは適度に速い-3番目は非常に遅い


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.