计算Golomb自描述序列的第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,输出g(n)

限制:n <100000。

最小的代码获胜。


对于天真的方法,除了使用n而不是之外,这与上一个问题相同2 - n % 1。您是否有理由期望答案会大不相同?
彼得·泰勒

2
在Haskell中,您可以使用以下代码:golomb=1:2:2:concat(zipWith replicate(drop 2 golomb)[3..])
FUZxxl 2012年

@PeterTaylor:我不知道。
beary605

Answers:


5

GolfScript(31个字符)

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

演示版


很好,但是您是否真的尝试过n = 99999的尝试,如果是这样,它花了多长时间?(当我尝试它时,它运行了一个小时,然后才达到我为其设置的100 MiB内存限制并崩溃了。)
Ilmari Karonen 2012年

@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;}}

快速而简短。

我似乎记错了顺序。德普

这是正确,快速和简短的。

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) = 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.010才能启用该say功能。由于数组处理效率低下,大约需要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 2012年


1

J,43个字符

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

使用Wikipedia页面上给出的渐近表达式定义函数。

   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 = TrueNUMERIC_INPUT = True

说明

该程序的框架是

?1-(    1 -
1                     )!

我们将输入内容读到N第一个声音上并递减以获得N-1。我们还将第二个声音初始化为1。然后我们循环N-1一遍,每次迭代都会在第二个堆栈上获得序列的下一个值。最后,我们打印N第一个数字。

该程序的想法是将序列的每个元素放入第三个声音的队列中,并在每次迭代中减小该队列的开头。当头达到时0,我们增加序列的值并删除它0

现在的问题是Prelude使用堆栈而不是队列。因此,我们需要稍微移动一下堆栈以使其像队列一样使用。

v  #
0v ^
(#)

这会将序列的当前值复制到第一个语音(作为临时副本),将a 0推入第二个语音(以标记队列的结尾)。然后执行循环以将第三个堆栈移动(从而反转)到第二个堆栈上。循环之后,我们将当前序列值的副本放在第二个堆栈的顶部(这是队列的尾部)。

 )
(#
 ^#1-

这看起来有些丑陋,但从本质上讲,这是一个循环,将堆栈移回第三个声音。由于处于)与换档指令相同的列中,因此0我们较早放置第二个声音的位置也会最终出现在第三个声音的位置,因此我们需要用另一个声音将其删除#。然后减小第三个声音的顶部,即队列的开头。

现在有点烦人-我们想在该值为时运行一些代码0,但Prelude的唯一控件结构(循环)仅响应非零值。

 0 (1+0)#
(0)#

请注意,第二个声音的开头是真实的(因为Golomb序列不包含任何0s)。因此,工作负载进入了该声音(后面的括号)。如果队列头还没有,我们只需要防止这种情况发生0。因此,首先我们在第三个语音上有一个“循环”,0如果队列的头部仍非零,则将“ a”推到第二个语音上。我们还将0第三个声音设为“ a ”以立即退出循环。所述#第三语音然后或者将删除0,或删除队列的头部,如果是已经为零。现在,仅当队列的开头为零(并且0在第二个声音从未被推动)。在那种情况下,我们增加序列的当前值并按a 0退出循环。最后,0在堆栈的顶部总是有一个,我们需要将其丢弃。

我告诉过你《前奏曲》中的逻辑否定很烦人...


1

Mathematica,27个字节

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

另一个递归解决方案。


1

CJam,14个字节

CJam比这个挑战要年轻得多,因此此答案不符合绿色复选标记的条件。但是,很少能j很好地使用它,因此无论如何我都希望将其发布。

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

在这里测试。

说明

j基本上是“记忆递归运算符”。它需要一个整数N,一个数组和一个块F。该数组用于初始化备注:index处的元素i将为返回F(i)j然后F(N)通过查找它,或者通过运行该块(n在堆栈上)来计算,如果尚未存储该值。真正的精妙之处在于,该块内,j它只接受一个integer 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

该解决方案很大程度上基于algorithmhark针对类似问题的解决方案。您可以在此处找到有关此方法的一些说明。

J,33个字节

在这种方法我建立一个序列h(k)与第一指标的值,ig(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+[:+/#<:])@]^:[~]

1

Brachylog,13个字节(非竞争)

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

在线尝试!

说明

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个字符

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 填充列表。似乎是“正确的”量None:)
daniero 2012年

1
@Daniero是的,这是一种奇怪的代码。我不得不运行几次,以使自己确信它确实有效。由于list.append()返回None类型,因此它用一堆None填充列表推导。我只是使用嵌套列表推导来实现嵌套循环。列表理解的唯一目的是使代码循环正确的次数-它们被丢弃的值
chucksmash 2012年

如果我做过传统的嵌套循环,它可以节省两个字符:)
chucksmash 2012年

不幸的是,您似乎在对输入进行硬编码(这是我们不允许的),并假设使用REPL环境,这会使其成为一个摘要。默认情况下,所有提交都必须是使用我们默认I / O方法之一而不是摘要的完整程序或函数。如果您有任何问题,请告诉我。
Alex A.

@AlexA。有点考古?
chucksmash '16

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

前两个相当快-第三个非常慢


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.