Golomb'un kendini tanımlayan dizisinin nci terimini hesapla


11

Önceki sorudan ilham alındı .

Golomb'un kendi kendini tanımlayan sekansı g (n), herhangi bir doğal sayının nsekans g (n) kez içinde tekrarlandığı bir sekanstır.

Dizideki ilk birkaç sayı şunlardır:

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 olduğunu ve "4" ifadesinin sırayla 3 kez tekrarlandığını görebilirsiniz.

Girdi n, çıktı g(n).

Sınırlamalar: n <100000.

En küçük kod kazanır.


Saf yaklaşımlar için bu, bir önceki soru ile aynıdır, ancak bunun nyerine kullanır 2 - n % 1. Yanıtların önemli ölçüde farklı olmasını beklemek için herhangi bir nedeniniz var mı?
Peter Taylor

2
Haskell'de şunları kullanabilirsiniz:golomb=1:2:2:concat(zipWith replicate(drop 2 golomb)[3..])
FUZxxl

@PeterTaylor: Bunu bilmiyordum.
beary605

Yanıtlar:


5

GolfScript (31 karakter)

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

gösteri


Güzel, ama bunu gerçekten n = 99999 ile denediniz ve eğer öyleyse, ne kadar sürdü? (Denediğimde, bunun için belirlediğim ve çöktüğüm 100 MiB bellek sınırına ulaşmadan bir saat sürdü.)
Ilmari Karonen

@IlmariKaronen, hayır. Soru, bellek veya zaman verimliliği için herhangi bir sınırlama getirmediğinden, giriş boyutundaki sınırın sabit genişlikli ints olan diller için olduğunu varsayıyorum.
Peter Taylor

6

Jöle , rakipsiz

10 bayt Zorluk Jelly'nin yaratılmasından önce geldiğinden bu cevap rakipsizdir.

’ßßạ¹ß‘µṖ¡

Bu, OEIS sayfasındaki özyinelemeli a (1) = 1, a (n + 1) = 1 + a (n + 1 - a (a (n))) formülünü kullanır .

Çevrimiçi deneyin!

Nasıl çalışır

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

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

Hızlı ve kısa.

Aklımda yanlış bir sıra varmış gibi görünüyor. Derp.

Bu DOĞRU, hızlı ve kısa.

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

Doğruluk, gerekli 100.000 işaretini geçebilir, ancak aslında işareti karşıladım.


3

PHP

Bu özyinelemeli sürüm daha kısadır (60), ancak hesaplama açısından verimsiz:

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

Bu çok daha hızlı ama daha uzundur (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];

Çok daha hızlı, ancak 89 karakterde:

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

Hangisi O (n)



3

Vaha , 7 bayt (rakip olmayan)

Kod:

n<aae>T

Çevrimiçi deneyin!

Oasis, diziler konusunda uzmanlaşmış Adnan tarafından tasarlanan bir dildir .

Şu anda, bu dil özyineleme ve kapalı form yapabilir.

TSonunda için kısaltmadır 10belirtir, a(0) = 0ve a(1) = 1. Daha fazla testcases eklemek için sondaki listeye eklemeniz yeterlidir.

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

Şimdi esasen hesapladık a(n-a(a(n-1))+1.


2

Perl, 48 karakter

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

Stdin girişi, stdout çıkışı. Özelliği -M5.010etkinleştirmek için Perl 5.10+ ve gereklidir say. Verimsiz dizi manipülasyonu nedeniyle yaklaşık O ( n 2 ) zaman alır, ancak yine de 100.000. Terime kadar kolayca hesaplamak için yeterince hızlıdır.


2

Julia - 28

Bir By özyinelemeli şekilde:

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

Çıktı:

[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
Bu iyi. Yapmanın [i]*g[i-1]bunu yapacağını düşünmedim , bu yüzden başka bir şekilde yapmak için geriye doğru eğildim; Ben daha çok bir nedenden dolayı bir matris ile bir skaler çarpma gibi olacağını düşündüm ...
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'

Vikipedi sayfasında verilen asimtotik ifadeyi kullanarak bir işlevi tanımlar.

   f 5
3
   f 20
8
   f 100000
1479

En yakın tam sayıya yuvarlayarak can sıkıcı 9 karakter kullanılır.


1

Başlangıç , 69 55 54 bayt

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

Standart uyumlu bir yorumlayıcı kullanılıyorsa, bu girdi ve çıktıyı bayt değerleri olarak alır . Aslında STDIN / STDOUT üzerinde ondalık sayılar kullanmak için, ihtiyacım olacağını Python yorumlayıcısı ile NUMERIC_OUTPUT = Trueve ek bir seçenek NUMERIC_INPUT = True.

açıklama

Programın iskeleti

?1-(    1 -
1                     )!

Nİlk sese girdiyi okur ve almak için azaltırız N-1. Ayrıca ikinci sesi ilklendiririz 1. Sonra N-1bir kez döngü yaparız , her yinelemesi ikinci yığındaki dizinin bir sonraki değerini alır. Sonunda Ninci numarasını yazdırıyoruz .

Programın amacı, dizinin her öğesini üçüncü sesde bir kuyruğa koymak ve her yinelemede bu kuyruğun başını azaltmaktır. Kafa ulaştığında 0, dizinin değerini artırır ve çıkarırız 0.

Şimdi mesele, Prelude'un sıraları değil yığınları kullanmasıdır. Yani bir yığın gibi kullanmak için bu yığını biraz kaydırmamız gerekiyor.

v  #
0v ^
(#)

Bu, dizinin geçerli değerini ilk sese (geçici bir kopya olarak) kopyalar, a'yı 0ikinci sese doğru iter (kuyruğun sonunu işaretlemek için). Ve sonra üçüncü yığını ikinciye kaydırmak (ve böylece tersine çevirmek) için bir döngü gerçekleştirir. Döngüden sonra, geçerli sıra değerinin kopyasını ikinci yığının (sıramızın kuyruğu) üzerine koyarız.

 )
(#
 ^#1-

Bu biraz çirkin görünüyor, ama aslında yığını üçüncü sese geri döndüren bir döngü. Yana )değişen talimatlar ile aynı sütunda ise, 0biz başkasıyla kaldırmak gerekir bu yüzden ikinci bir sesle koymak daha önce de, üçüncü bir sesle sona erecek #. Sonra 3. sesin üst kısmını azaltın, yani sıranın başını azaltın.

Şimdi biraz can sıkıcı oluyor - bu değer olduğunda bir kod çalıştırmak istiyoruz 0, ancak Prelude'un tek kontrol yapısı (döngü) sadece sıfır olmayan değerlere yanıt veriyor.

 0 (1+0)#
(0)#

İkinci sesin üst kısmının doğru olduğuna dikkat edin (Golomb dizisi herhangi bir 0s içermez ). Böylece iş yükü bu sese girer (ikinci parantez çifti). Kuyruğun başı henüz değilse bunun olmasını engellememiz gerekir 0. İlk olarak, üçüncü ses 0üzerinde, kuyruk başı hala sıfır değilse ikinci sesi üzerine a iten bir "döngü" var . Ayrıca 0, döngüden hemen çıkmak için üçüncü sesi de ekledik. #Üçüncü sesime sonra ya o kaldırır 0veya eğer sıranın başını kaldıran o zaten sıfır oldu. Şimdi bu ikinci döngü sadece kuyruğun başı sıfırsa (ve0ikinci ses asla itilmedi). Bu durumda dizinin geçerli değerini artırır 0ve döngüden çıkmak için a düğmesine basarız. Son olarak, her zaman 0yığının üstünde, atmamız gereken bir tane olacaktır.

Prelude'da mantıksal olumsuzlamanın sinir bozucu olduğunu söyledim ...


1

Mathematica, 27 bayt

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

Başka bir özyinelemeli çözüm.


1

CJam, 14 bayt

CJam bu meydan okumadan çok daha genç, bu nedenle bu cevap yeşil onay işareti için uygun değil. Ancak, jbu güzel kullanmak için oldukça nadirdir , bu yüzden yine de göndermek istedim.

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

Burada test edin.

açıklama

jtemel olarak "memoised özyineleme operatörü" dür. Bir tamsayı N, bir dizi ve bir blok alır F. Dizi, notu başlatmak için kullanılır: dizindeki öğe iiçin döndürülür F(i). jdaha sonra F(N)ya bakarak veya ndeğer henüz kaydedilmemişse bloğu ( yığın üzerinde) çalıştırarak hesaplar . Gerçekten şık özelliği, blok içindej sadece bir tamsayı alır ive F(i)özyinelemeli olarak çağırır . İşte kod:

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 bayt

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

Bu çözüm büyük ölçüde algoritmashark'ın benzer bir soruna çözümüne dayanmaktadır . Bu yöntem hakkında bazı açıklamaları burada bulabilirsiniz.

J, 33 bayt

Bu yaklaşımda bir dizisini oluşturmak h(k)ilk indeksler değerleri ile çok . Girişin bulunduğu ifadeden oldukça basit bir şekilde alabiliriz .ig(i)=kh = 1 2 4 6 9 12 16...h(k)h(1..k-1)({:+1+[:+/#<:])h(1..k-1)

Çıktısının hesaplanması hbasittir.h ([:+/]>:[) input

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

1

Brachylog , 13 bayt (rakip olmayan)

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

Çevrimiçi deneyin!

açıklama

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]

Bu aslında listeyi bir sürü Nones ile doldurur . NoneS tho "doğru" miktarı gibi görünüyor :)
daniero

1
@ Daniero evet garip bir kod. Kendimi gerçekten işe yaradığına ikna etmek için birkaç kez çalıştırmak zorunda kaldım. List.append () Nonetürünü döndürdüğü için liste kavrayışını bir grup Nones ile doldurur . Yuvalanmış bir döngü elde etmek için iç içe liste kavramalarını kullandım. Buradaki liste kavrayışlarının tek amacı, kodun doğru sayıda döngü oluşturmasına neden olmaktır - bunlar değerleri atarlar
chucksmash

Geleneksel iç içe döngüler yapmış olsaydım iki karakter kaydeder :)
chucksmash

Maalesef, izin vermediğimiz girişi zor kodluyorsunuz ve bunu bir pasaj haline getirecek bir REPL ortamı varsayalım. Varsayılan olarak , tüm gönderimler parçacıklar yerine varsayılan G / Ç yöntemlerimizden birini kullanan tam programlar veya işlevler olmalıdır . Herhangi bir sorunuz varsa bize bildirin.
Alex A.

@AlexA. Biraz arkeoloji mi yapıyorsunuz?
chucksmash

0

JavaScript - 48 Karakter

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

gDizi değerlerini içeren 1 dizinli bir dizi oluşturur .

Düzenle - JavaScript - 46 Karakter

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

vDizi değerlerini içeren 1 dizinli bir dizi oluşturur .

Düzenle 2 - ECMAScript 6 - 27 Karakter

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

İlk ikisi oldukça hızlı - üçüncüsü çok yavaş


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.