序列太元


25

我们从一个空白的1索引序列开始:

_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,...

在第n 步骤中,我们填写每次(n)的与大于1的整数起始于第一剩余空白,其中a(n)是第n坯料序列中的条目。

第一步之后:

2,_,3,_,4,_,5,_,6,_,7,_,8,_,9,_,10,_,11,_,12,_,13,_,...

请注意,a(1)必须为2,因为大于1的第一个整数为2。

在第二步中,我们填写每个a(2)空白。显然,a(2)必须为2。

2,2,3,_,4,3,5,_,6,4,7,_,8,5,9,_,10,6,11,_,12,7,13,_,...

在第三步中,我们填写每个a(3)空白。从序列中,a(3)= 3。

2,2,3,2,4,3,5,_,6,4,7,_,8,5,9,3,10,6,11,_,12,7,13,_,...

在第四步中,我们填写每个a(4)空白。从序列中,a(4)= 2。

2,2,3,2,4,3,5,2,6,4,7,_,8,5,9,3,10,6,11,3,12,7,13,_,...

最终:

2,2,3,2,4,3,5,2,6,4,7,2,8,5,9,3,10,6,11,3,12,7,13,2,...

任务

给定n,返回序列的 n 元素。

该序列的前10,000,000个术语可以在此处找到。

这是。以字节为单位的最短答案将获胜。有标准漏洞


@LuisMendo谢谢,我已经添加了它。
Leaky Nun

只是好奇,一个先生被排除在顺序之外是什么错?
死者负鼠,

@DeadPossum好吧,如果您填写每个空白,那么一步就完成了。
Leaky Nun

2
@DeadPossum如果a(n)为1,则第n步将填充所有剩余的空白,从而终止生成。
Leaky Nun

1
@QBrute我提供了问题中链接的前10,000,000个列表;只是画他们。
Leaky Nun

Answers:


20

Haskell80 67字节

g~(a:b)|let k!l=k:take(a-1)l++(k+1)!drop(a-1)l=2!g b
m=g m
(!!)$0:m

在线尝试!

Haskell是用于根据自身定义无限列表的理想语言。


1
鉴于TIO链接可以按预期工作,我想我的问题应该改为:您能对此做些解释吗?
朱利安·沃尔夫

2
@JulianWolf听起来您不熟悉let图案保护套。pattern1 | let pattern2 = expr2 = expr1与含义相同pattern1 = let pattern2 = expr2 in expr1(出于相同的原因,与[expr1 | let pattern2 = expr2]含义相同[let pattern2 = expr2 in expr1])。
Anders Kaseorg

1
我必须记住let模式后卫(尤其是他们可以执行功能)!而且,m=2:2:2`drop`g m短一个字节。
与Orjan约翰森

1
(!!)$0:m是短两个字节。
与Orjan约翰森

1
实际上,您可以2:2:稍微懒惰地完全丢弃这些东西:g ~(a:b)|...m=g m
与Orjan约翰森

10

C,123字节

f(n){int*p=calloc(n,4),i=0,j,k;for(*p=p[1]=2;i<n;++i)for(j=0,k=i/2?0:2-i;j<n;++j)p[j]||k++%p[i]||(p[j]=k/p[i]+2);n=p[n-1];}

在线尝试!

演练

f(n){int*p=calloc(n,4),

分配由n个整数组成的数组以存储序列的前n个元素。硬编码sizeof(int)4,这在大多数情况下是一个安全的假设,当然我愿意在代码高尔夫的背景下进行。:)

i=0,j,k;

这些都是计数器:i对于我们正在执行的步骤的索引,j循环遍历序列以查找空白,并k计算已看到多少空白。

for(*p=p[1]=2;i<n;++i)

在开始主循环之前,我们先对to的序列的前两个元素进行了初始化2。(p[0]= *(p + 0)= *p。)k虽然这不算什么,但是...

for(j=0,k=i/2?0:2-i;j<n;++j)

...我们还对进行了偷偷摸摸的初始化k,该初始化会测试是否i小于,2并纠正kif 的起始值。内部循环也从此处开始,它在每个步骤中一直迭代整个序列。

p[j]||k++%p[i]||(p[j]=k/p[i]+2);

这行可能确实需要一些解释。我们可以将其扩展为:

if (!(p[j] || ((k++) % p[i]))) {
    p[j] = k / p[i] + 2;
}

通过短路,然后通过De Morgan的定律以及0C中虚假的事实:

if (p[j] == 0 && ((k++) % p[i]) == 0) {
    p[j] = k / p[i] + 2;
}

本质上说:“如果该空间为空,则递增k。如果k先前是步长的倍数,则运行以下语句。” 因此,我们在每个步长元素上运行该语句,这正是描述序列的方式。语句本身很简单;它是所有产生234,...

n=p[n-1];}

使用与配合使用的棘手的返回而没有返回gcc,我们“返回” 了序列中前n个项的最后一个元素,恰好是第n个项。


3

Pyth,29个字节

M?tH?eJ.DtHg1GghG-tHhJ+2hJ2g1

在线尝试

怎么运行的

除了使用列表之外,它还使用简单的递归公式。

M                                def g(G, H):
 ?tH                                 if H - 1:
      J.DtHg1G                           J = divmod(H - 1, g(1, G))
    ?e                                   if J[-1]:
              ghG-tHhJ                       return g(G + 1, H - 1 - J[0])
                                         else:
                      +2hJ                   return 2 + J[0]
                                     else:
                          2              return 2
                           g1Q   print(g(1, eval(input())))

3

Haskell,67个字节

0%j=2
i%j|d<-div i$f j=last$d+2:[(i-d-1)%(j+1)|d*f j<i]
f=(%1).pred

在线尝试!

递归算术解决方案,其结果基本上与Anders Kaseorg的Pyth答案相同

这段代码涵盖了疣-看起来像丑陋的丑陋零件,可以打掉,但我不知道怎么做。

该函数i%j确实要使用防护来检查mod i(f j)>0并评估相应的两个表达式之一。但是,两个表达式都使用div i(f j)。将其绑定到守卫中不会使其适用于双方。据我所知,不能让一个警卫“分配”其他警卫。let而且where太长了。因此,代码last在守卫绑定变量时使用了两个表达式之一。啊。

理想情况下,我们会使用,divMod因为divmod都使用了,但是它(d,m)<-divMod ...是一个长表达式。相反,我们通过查看div值与除数的乘积是否小于原始值来暗中检查mod是否为零。

0%j=2如果Haskell短路div 0,则不需要这种情况,而不必这样。该.pred转换1索引输入到零指数的,否则就不会有-1修正无处不在。


如果您将%索引设为1索引,则需要五个字节的校正-这才很重要。但是,您可以免费直接f插入%,然后f成为匿名用户,这样就可以节省两个字节。
与Orjan约翰森

@ØrjanJohansen您的内联是什么意思?我看不到如何更改引用f而不丢失字节。
xnor

divMod似乎便宜了一个字节,因为它允许使用进行分支!!(0^m)。到目前为止,我有:1%j=2;i%j|(d,m)<-divMod(i-1)$j%1=[(i-d-1)%(j+1),d+2]!!(0^m);(%1)
与Orjan约翰森

如您所见,内联以1-reindexing为前提,它删除了.pred
与Orjan约翰森

2

JavaScript(ES6),98 93 91字节

结果可用后立即停止的递归函数。

f=(n,p,a=[...Array(n)])=>a[n-1]||f(n,-~p,a.map(c=>c?c:i?i++%(a[p]||2)?c:++v:(i=1,v=2),i=0))

替代版本,90字节

由Shaggy建议的-1个字节

这个必须用来调用f(n)()。尽管meta中相应的帖子当前得分为正,但此语法显然存在争议。

n=>g=(p,a=[...Array(n)])=>a[n-1]||g(-~p,a.map(c=>c?c:i?i++%(a[p]||2)?c:++v:(i=1,v=2),i=0))

演示版


n=>g=(p,a=[...Array(n)])=>a[n-1]||g(-~p,a.map(c=>c?c:i?i++%k?c:++v:(i=1,v=2),i=0,k=a[p]||2))应该工作92个字节。用调用f(n)()
毛茸茸的

@粗野的谢谢!作为替代版本添加。
Arnauld

1

Java 8,124字节

(i)->{int j=1,a[]=new int[i+1],k,s,n;for(;a[i]<2;){for(k=0,n=2;a[++k]>0;);for(s=a[j++]|2*k;k<=i;k+=s)a[k]=n++;}return a[i];}

Lambda表达式。

创建一个整数数组并连续填充它,直到第n个值被填充为止。

在顶部预先声明变量以减少尽可能多的声明,每个声明int占用4个字节的空间,而不是添加,n 2。

j计算的第一个迭代中,必须跳过的“空白”数量等于a[j](或2,如果为空白)。结果表明,如果我们必须填写的第一个空白位于位置k, 则为k * a[j]我们提供“台阶”(s)。

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.