Hitung suku ke-9 dari urutan penggambaran diri Golomb


11

Terinspirasi oleh pertanyaan sebelumnya .

Urutan penggambaran diri Golomb g (n) adalah urutan di mana bilangan alami ndiulang dalam urutan g (n) kali.

Beberapa angka pertama dalam urutan adalah:

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

Anda dapat melihat bahwa g (4) = 3, dan "4" diulang 3 kali dalam urutan.

Diberikan input n, output g(n).

Keterbatasan: n <100000.

Kode terkecil menang.


Untuk pendekatan naif, ini sama dengan pertanyaan sebelumnya kecuali yang digunakan nalih-alih 2 - n % 1. Apakah Anda punya alasan untuk mengharapkan jawaban berbeda secara signifikan?
Peter Taylor

2
Di Haskell, Anda dapat menggunakan ini:golomb=1:2:2:concat(zipWith replicate(drop 2 golomb)[3..])
FUZxxl

@ PeterTaylor: Saya tidak tahu itu.
beary605

Jawaban:


5

GolfScript (31 karakter)

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

Demo


Bagus, tetapi apakah Anda sudah benar-benar mencoba ini dengan n = 99999, dan jika demikian, berapa lama? (Ketika saya mencobanya, itu berjalan selama satu jam sebelum mencapai batas memori 100 MiB yang saya tetapkan untuknya dan menabrak.)
Ilmari Karonen

@IlmariKaronen, no. Pertanyaannya tidak menetapkan batas pada efisiensi memori atau waktu, jadi saya berasumsi bahwa batas pada ukuran input adalah untuk bahasa-bahasa yang memiliki int-lebar tetap.
Peter Taylor

6

Jelly , tidak bersaing

10 byte Jawaban ini tidak bersaing, karena tantangan mendahului pembuatan Jelly.

’ßßạ¹ß‘µṖ¡

Ini menggunakan rumus rekursif a (1) = 1, a (n + 1) = 1 + a (n + 1 - a (a (n))) dari halaman OEIS.

Cobalah online!

Bagaimana itu bekerja

’ßßạ¹ß‘µṖ¡ 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 Chars

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

Cepat DAN pendek.

Tampaknya saya memiliki urutan yang salah dalam pikiran. Derp.

Ini BENAR, cepat, dan pendek.

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

Akurasi mungkin lebih tinggi dari tanda 100.000 yang diperlukan, tetapi saya benar-benar memenuhi tanda itu.


3

PHP

Versi rekursif ini lebih pendek (60) tetapi tidak efisien secara komputasional:

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

Ini jauh lebih cepat tetapi lebih lama (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];

Jauh lebih cepat, tetapi pada 89 karakter adalah:

$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];

Yaitu O (n)



3

Oasis , 7 byte (tidak bersaing)

Kode:

n<aae>T

Cobalah online!

Oasis adalah bahasa yang dirancang oleh Adnan yang memiliki spesialisasi dalam urutan.

Saat ini, bahasa ini dapat melakukan rekursi dan formulir tertutup.

Pada Takhirnya adalah singkatan untuk 10, yang menunjukkan itu a(0) = 0dan a(1) = 1. Untuk menambahkan lebih banyak testcases, cukup tambahkan ke daftar di akhir.

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

Sekarang kami pada dasarnya menghitung a(n-a(a(n-1))+1.


2

Perl, 48 karakter

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

Input pada stdin, output ke stdout. Perlu Perl 5.10+ dan -M5.010untuk mengaktifkan sayfitur. Membutuhkan waktu sekitar O ( n 2 ) karena manipulasi array yang tidak efisien, tetapi masih cukup cepat untuk dengan mudah menghitung hingga jangka waktu ke-100.000.


2

Julia - 28

Dengan cara rekursif :

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

Keluaran:

[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 karakter

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

1
Itu bagus. Saya tidak berpikir melakukan itu [i]*g[i-1]akan terjadi, jadi saya membungkuk ke belakang untuk melakukannya dengan cara lain; Saya pikir itu akan berperilaku lebih seperti mengalikan matriks dengan skalar untuk beberapa alasan ...
chucksmash

1

Javascript, 93 karakter

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 karakter

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

Menentukan fungsi menggunakan ekspresi asimptotik yang diberikan pada halaman wikipedia.

   f 5
3
   f 20
8
   f 100000
1479

Annoyingly 9 karakter digunakan hanya pembulatan ke bilangan bulat terdekat.


1

Prelude , 69 55 54 byte

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

Jika juru bahasa yang memenuhi standar digunakan, ini mengambil input dan output sebagai nilai byte . Untuk benar-benar menggunakan angka desimal pada STDIN / STDOUT, Anda memerlukan interpreter Python dengan NUMERIC_OUTPUT = Truedan opsi tambahan NUMERIC_INPUT = True.

Penjelasan

Kerangka program adalah

?1-(    1 -
1                     )!

Kami membaca input Nke suara pertama dan menurunkannya untuk mendapatkan N-1. Kami juga menginisialisasi suara kedua 1. Kemudian kita putar N-1satu kali, setiap iterasi yang mendapatkan nilai urutan berikutnya pada tumpukan kedua. Pada akhirnya kami mencetak Nnomor th.

Gagasan dari program ini adalah untuk menempatkan setiap elemen dari urutan dalam antrian pada suara ketiga, dan untuk mengurangi kepala antrian itu di setiap iterasi. Saat head mencapai 0, kami menambah nilai urutan dan menghapusnya 0.

Sekarang masalahnya adalah Prelude menggunakan tumpukan dan bukan antrian. Jadi kita perlu menggeser tumpukan itu sedikit untuk menggunakannya seperti antrian.

v  #
0v ^
(#)

Ini menyalin nilai urutan saat ini ke suara pertama (sebagai salinan sementara), mendorong a 0ke suara kedua (untuk menandai akhir antrian). Dan kemudian melakukan loop untuk menggeser (dan dengan demikian membalikkan) tumpukan ketiga ke tumpukan kedua. Setelah loop, kami meletakkan salinan nilai urutan saat ini di atas tumpukan kedua (yang merupakan ekor dari antrian kami).

 )
(#
 ^#1-

Ini terlihat agak jelek, tetapi pada dasarnya itu adalah loop yang menggeser tumpukan kembali ke suara ketiga. Karena )berada di kolom yang sama dengan instruksi pemindahan gigi, 0kita menempatkan suara kedua sebelumnya juga akan berakhir pada suara ketiga, jadi kita harus menghapusnya dengan yang lain #. Kemudian kurangi bagian atas suara ke-3, yaitu kepala antrian.

Sekarang jadi sedikit menjengkelkan - kami ingin menjalankan beberapa kode ketika nilainya 0, tetapi satu-satunya struktur kontrol Prelude (loop) hanya merespon nilai-nilai yang tidak nol.

 0 (1+0)#
(0)#

Perhatikan bahwa bagian atas suara kedua adalah benar (karena urutan Golomb tidak mengandung 0s). Jadi beban kerja masuk ke suara itu (sepasang kurung terakhir). Kita hanya perlu mencegah hal itu terjadi jika kepala antrian 0belum. Jadi pertama-tama kita memiliki "loop" pada suara ketiga yang mendorong a 0ke suara kedua jika kepala antrian masih nol. Kami juga menggunakan 0suara ketiga untuk segera keluar dari loop. The #pada suara ketiga maka baik menghapus yang 0, atau menghilangkan kepala antrian jika itu sudah nol. Sekarang loop kedua hanya dimasukkan jika kepala antrian adalah nol (dan0pada suara kedua tidak pernah didorong). Dalam hal ini kami menambah nilai saat ini dari urutan dan mendorong 0untuk keluar dari loop. Terakhir, akan selalu ada 0tumpukan di atas, yang harus kita buang.

Saya katakan bahwa negasi logis mengganggu di Prelude ...



1

CJam, 14 byte

CJam jauh lebih muda dari tantangan ini, jadi jawaban ini tidak memenuhi syarat untuk tanda centang hijau. Namun, sangat jarang Anda bisa menggunakannya jdengan baik, jadi saya tetap ingin mempostingnya.

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

Uji di sini.

Penjelasan

jpada dasarnya adalah "operator rekursi memoised". Dibutuhkan integer N, array, dan blok F. Array digunakan untuk menginisialisasi memoisation: elemen pada index iakan dikembalikan F(i). jkemudian menghitung F(N), baik dengan melihatnya, atau dengan menjalankan blok (dengan ndi stack) jika nilainya belum memoised. Fitur yang sangat bagus adalah bahwa di dalam blok, jhanya membutuhkan integer i, dan panggilan F(i)secara rekursif. Jadi inilah kodenya:

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 byte

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

Solusi ini sangat didasarkan pada solusi algoritme hiu untuk masalah serupa. Anda dapat menemukan penjelasan tentang metode ini di sana.

J, 33 byte

Dalam pendekatan ini saya membangun urutan h(k)dengan nilai-nilai indeks pertama di imana g(i)=kbegitu h = 1 2 4 6 9 12 16.... Kita bisa mendapatkan h(k)cukup hanya h(1..k-1)dengan ekspresi di ({:+1+[:+/#<:])mana input berada h(1..k-1).

Menghitung output dari hsangat mudah.h ([:+/]>:[) input

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

1

Brachylog , 13 byte (tidak bersaing)

1|-₁↰↰:?-ṅ↰+₁

Cobalah online!

Penjelasan

1                Input = 1 = Output
 |               Or
  -₁↰            a(Input - 1)
     ↰           a(a(Input - 1))
      :?-ṅ       Input - a(a(Input - 1))
          ↰      a(Input - a(a(Input - 1))
           +₁    1 + a(Input - a(a(Input -1))

0

Python - 76 karakter

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

Ini sebenarnya mengisi daftar dengan sekelompok Nones. Tampaknya jumlah "benar" dari Nones :) :)
daniero

1
@ Dariero ya itu semacam kode aneh. Saya harus menjalankannya beberapa kali untuk meyakinkan diri saya bahwa itu benar-benar berhasil. Itu mengisi pemahaman daftar dengan sekelompok Nones sejak list.append () mengembalikan Nonetipe. Saya hanya menggunakan pemahaman daftar bersarang untuk mencapai loop bersarang. Satu-satunya tujuan dari pemahaman daftar di sini adalah untuk menyebabkan kode untuk mengulang jumlah yang tepat - mereka membuang nilai
chucksmash

Menghemat dua karakter jika saya telah melakukan loop bersarang tradisional :)
chucksmash

Sayangnya sepertinya Anda mengkodekan input, yang tidak kami izinkan, dan mengasumsikan lingkungan REPL, yang akan menjadikan ini cuplikan. Secara default , semua pengiriman harus berupa program atau fungsi lengkap yang menggunakan salah satu metode I / O standar kami alih-alih cuplikan. Beri tahu saya jika Anda memiliki pertanyaan.
Alex A.

@AlexA. Melakukan sedikit arkeologi?
chucksmash

0

JavaScript - 48 Karakter

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

Membuat array 1-diindeks gberisi nilai-nilai urutan.

Edit - JavaScript - 46 Karakter

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

Membuat array 1-diindeks vberisi nilai-nilai urutan.

Sunting 2 - ECMAScript 6 - 27 Karakter

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

Dua yang pertama cukup cepat - yang ketiga sangat lambat


Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.