คำนวณคำที่ n ของลำดับการอธิบายตนเองของ Golomb


11

แรงบันดาลใจจากคำถามก่อนหน้านี้

ลำดับ g (n) อธิบายตนเองของ Golombเป็นลำดับที่มีจำนวนธรรมชาติใด ๆ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 ครั้งตามลำดับ

ได้รับการป้อนข้อมูลของเอาท์พุทng(n)

ข้อ จำกัด : n <100000

รหัสที่เล็กที่สุดชนะ


สำหรับไร้เดียงสาวิธีนี้เป็นเช่นเดียวกับคำถามก่อนหน้านี้ยกเว้นว่าจะใช้มากกว่าn 2 - n % 1คุณมีเหตุผลที่คาดหวังคำตอบที่แตกต่างกันอย่างมีนัยสำคัญหรือไม่
Peter Taylor

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 Karonen

@IlmariKaronen ไม่ คำถามไม่ได้ตั้งค่าขีด จำกัด ใด ๆ เกี่ยวกับหน่วยความจำหรือประสิทธิภาพเวลาดังนั้นฉันคิดว่าขอบเขตของขนาดอินพุตสำหรับภาษาเหล่านั้นที่มี int-width คงที่
Peter Taylor

6

เยลลี่ไม่ใช่การแข่งขัน

10 ไบต์ คำตอบนี้ไม่ใช่การแข่งขันเนื่องจากความท้าทายมาก่อนการสร้างเยลลี่

’ßßạ¹ß‘µṖ¡

ใช้สูตรแบบเรียกซ้ำa (1) = 1, a (n + 1) = 1 + a (n + 1 - a (a (n)))จากหน้า OEIS

ลองออนไลน์!

มันทำงานอย่างไร

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

เร็วและสั้น

ฉันดูเหมือนจะมีลำดับที่ไม่ถูกต้องในใจ 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) = 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

Perl, 48 ตัวอักษร

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

อินพุตบน stdin, เอาต์พุตไปยัง stdout ต้องการ Perl 5.10+ และ-M5.010เพื่อเปิดใช้งานsayคุณลักษณะ ใช้เวลาประมาณ O ( n 2 ) เนื่องจากการจัดการอาเรย์ที่ไม่มีประสิทธิภาพ แต่ยังเร็วพอที่จะคำนวณได้อย่างง่ายดายถึงคำที่ 100,000



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

J, 43 ตัวอักษร

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

กำหนดฟังก์ชั่นโดยใช้การแสดงออก asymptotic ที่ได้รับในหน้าวิกิพีเดีย

   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 คุณจะต้องล่ามหลามด้วยและตัวเลือกเพิ่มเติมNUMERIC_OUTPUT = TrueNUMERIC_INPUT = True

คำอธิบาย

โครงกระดูกของโปรแกรมคือ

?1-(    1 -
1                     )!

เราอ่านการป้อนข้อมูลบนเสียงครั้งแรกและพร่องมันจะได้รับN N-1นอกจากนี้เรายัง initialise 1เสียงที่สองที่จะ จากนั้นเราวนN-1หนึ่งครั้งซ้ำแต่ละครั้งซึ่งได้รับค่าถัดไปของลำดับในกองที่สอง ในตอนท้ายเราพิมพ์Nหมายเลข th

ความคิดของโปรแกรมคือการทำให้แต่ละองค์ประกอบของลำดับในคิวเสียงที่สามและลดหัวของคิวนั้นในการทำซ้ำแต่ละครั้ง เมื่อมาถึงหัวเราเพิ่มมูลค่าของลำดับและลบที่ว่า00

ตอนนี้ปัญหาคือโหมโรงใช้กองซ้อนไม่ใช่คิว ดังนั้นเราต้องเลื่อนไปรอบ ๆ สแต็กเล็กน้อยเพื่อใช้มันเหมือนคิว

v  #
0v ^
(#)

สิ่งนี้จะคัดลอกค่าปัจจุบันของลำดับไปยังเสียงแรก (เป็นสำเนาชั่วคราว), ส่ง0ไปยังเสียงที่สอง (เพื่อทำเครื่องหมายจุดสิ้นสุดของคิว) จากนั้นทำการวนซ้ำเพื่อเปลี่ยน (และย้อนกลับ) สแต็กที่สามลงบนที่สอง หลังจากวนรอบเราวางสำเนาของค่าลำดับปัจจุบันที่ด้านบนของสแต็กที่สอง (ซึ่งคือส่วนท้ายของคิวของเรา)

 )
(#
 ^#1-

มันดูน่าเกลียดนิดหน่อย แต่โดยพื้นฐานแล้วมันคือวงที่เลื่อนสแต็กกลับไปที่เสียงที่สาม ตั้งแต่)อยู่ในคอลัมน์เดียวกับคำแนะนำการขยับที่เราใส่ในเสียงที่สองก่อนหน้านี้ก็จะจบลงในเสียงที่สามดังนั้นเราจึงจำเป็นที่จะเอามันออกไปอีกด้วย0 #จากนั้นย่อส่วนบนของเสียงที่ 3 นั่นคือส่วนหัวของคิว

ตอนนี้มันน่ารำคาญนิดหน่อย - เราต้องการรันโค้ดบางอย่างเมื่อค่านั้นเป็น0แต่โครงสร้างการควบคุม (ลูป) ของ Prelude เพียงตอบสนองต่อค่าที่ไม่เป็นศูนย์เท่านั้น

 0 (1+0)#
(0)#

โปรดทราบว่าเสียงด้านบนสุดของเสียงที่สองนั้นเป็นจริง (เนื่องจากลำดับ Golomb ไม่มี0s) ดังนั้นปริมาณงานจะเข้าสู่เสียงนั้น (วงเล็บคู่หลัง) เราแค่ต้องป้องกันไม่ให้เกิดขึ้นถ้าหัวคิว0ยังไม่เกิดขึ้น ดังนั้นก่อนอื่นเรามี "วน" บนเสียงที่สามซึ่งผลัก a 0ลงบนเสียงที่สองถ้าหัวของคิวยังคงไม่เป็นศูนย์ เรายังใส่0เสียงที่สามเพื่อออกจากลูปทันที #ในเสียงที่สามแล้วทั้งเอาที่0หรือเอาหัวคิ้วถ้าที่มีอยู่แล้วเป็นศูนย์ ตอนนี้ลูปที่สองจะถูกป้อนก็ต่อเมื่อส่วนหัวของคิวเป็นศูนย์ (และ0ในเสียงที่สองไม่เคยผลัก) ในกรณีนี้เราเพิ่มค่าปัจจุบันของลำดับและกด a 0เพื่อออกจากลูป สุดท้ายจะมีส่วน0บนของสแต็คเสมอซึ่งเราต้องทิ้ง

ฉันบอกคุณแล้วว่าการปฏิเสธทางตรรกะน่ารำคาญในโหมโรง ...



1

CJam, 14 ไบต์

CJam อายุน้อยกว่าความท้าทายนี้ดังนั้นคำตอบนี้จึงไม่มีสิทธิ์ใช้เครื่องหมายถูกสีเขียว อย่างไรก็ตามมันค่อนข้างหายากที่คุณจะใช้jสิ่งนี้ได้อย่างดีดังนั้นฉันจึงต้องการโพสต์ต่อไป

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

ทดสอบที่นี่

คำอธิบาย

jนั้นเป็น "ตัวดำเนินการเรียกซ้ำที่เรียกคืนแล้ว" มันต้องใช้เวลาเป็นจำนวนเต็มอาร์เรย์และบล็อกN Fอาร์เรย์จะใช้ในการ initialise memoisation นี้: องค์ประกอบที่ดัชนีจะกลับมาi จากนั้นคำนวณโดยค้นหามันหรือเรียกใช้บล็อก (ด้วยสแต็ค) หากยังไม่ได้บันทึกค่าไว้ คุณสมบัติที่น่าสนใจจริงๆคือภายในบล็อคนั้นใช้เพียงจำนวนเต็มเท่านั้นและการโทรซ้ำ ดังนั้นนี่คือรหัส:F(i)jF(N)njiF(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)มีค่าของดัชนีแรกiที่เป็นg(i)=kเช่นh = 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]

นี่เติมรายการด้วยจำนวนNoneจริง ดูเหมือนว่าจะเป็นจำนวนที่ "ถูกต้อง" ของNoneสรรพสินค้า :)
daniero

1
@Daniero ใช่มันเป็นรหัสแปลก ๆ ฉันต้องวิ่งสองสามครั้งเพื่อโน้มน้าวตัวเองว่ามันใช้งานได้จริง เติมความเข้าใจของรายการด้วย Nones จำนวนมากตั้งแต่ list.append () ส่งคืนNoneชนิด ฉันเพิ่งใช้ความเข้าใจในรายการซ้อนเพื่อให้ได้ลูปซ้อนกัน จุดประสงค์เดียวของรายการความเข้าใจที่นี่คือการทำให้โค้ดวนซ้ำในจำนวนที่ถูกต้อง - มันถูกทิ้งค่า
chucksmash

มันจะช่วยประหยัดตัวละครสองตัวมากกว่าถ้าผมได้ทำลูปซ้อนกันแบบดั้งเดิม :)
chucksmash

โชคไม่ดีที่ดูเหมือนว่าคุณกำลังเข้ารหัสข้อมูลที่เราไม่อนุญาตและสมมติว่าเป็นสภาพแวดล้อมแบบ REPL ซึ่งจะทำให้มันเป็นตัวอย่าง ตามค่าเริ่มต้นการส่งทั้งหมดจะต้องเป็นโปรแกรมหรือฟังก์ชั่นเต็มรูปแบบซึ่งใช้หนึ่งในวิธีการเริ่มต้น I / O เริ่มต้นของเราแทนที่จะเป็นตัวอย่าง แจ้งให้เราทราบหากคุณมีคำถามใด ๆ
Alex A.

@AlexA ทำโบราณคดีหน่อย
chucksmash

0

JavaScript - 48 ตัวอักษร

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

สร้างอาร์เรย์ 1 ดัชนีgที่มีค่าลำดับ

แก้ไข - JavaScript - 46 ตัวอักษร

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

สร้างอาร์เรย์ 1 ดัชนีvที่มีค่าลำดับ

แก้ไข 2 - ECMAScript 6 - 27 ตัวอักษร

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

สองคนแรกนั้นเร็วพอสมควร - คนที่สามช้ามาก


0

Haskell, 63 ไบต์

f n|n<3=n|n<4=2|1>0=foldr1(++)[replicate(f m)m|m<-[1..]]!!(n-1)

นี่เป็นวิธีการที่ไร้เดียงสาฉันไม่ทราบถึงการเกิด recurison สั้น ๆ เมื่อฉันเขียนสิ่งนี้ แต่ฉันคิดว่าฉันโพสต์ไว้แล้วแม้จะยากกว่าการใช้งาน Haskell อื่น ๆ ทั้งหมดเช่น

คำนวณคำที่ n ของลำดับการอธิบายตนเองของ Golomb

และ

https://codegolf.stackexchange.com/a/23979/24877

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.