数数然后返回然后加倍


24

算一算...

数到2再回到1
数到4再回到1
数到6再回到1
...好吧,你明白了...

将所有这些放在一起,您将获得以下顺序

 {1,2,1,2,3,4,3,2,1,2,3,4,5,6,5,4,3,2,1,2,3,4,5,6,7,8,7,6,5,4,3,2,1,2,3...}

挑战
给定n>01索引(或n>=00索引)的整数,输出此序列的第n个项

测试用例

Input->Output  

1->1  
68->6  
668->20  
6667->63  
10000->84

规则

您的程序必须在一分钟之内就能计算出n = 10000的解

这是,因此以字节为单位的最短代码胜出!


2
谁决定花一分钟的时间?使用乐高积木制造时间最佳的图灵机将花费很长时间,而用C语言模拟的同一图灵机则可能需要数秒或数分钟,具体取决于运行的处理器。因此,如果我提交上述图灵机描述,是否有效?
亚瑟

2
@Arthur我认为您可以理解我为什么要进行此限制...我不希望算法通过产生大量列表来使“永远”找到n = 10000。这里的大多数人给出了找到数百万人的出色答案很快。

4
@BillSteihn我认为限制是不必要的。
暴民埃里克(Erik the Outgolfer)'17年

2
@EriktheOutgolfer哥德高尔夫答案可能很棘手...在没有限制的情况下,产生10.000元组[1,2 ... 2n..2,1]的答案将是有效的。限制仅适用于此类答案。我只是想让您的答案在合理的时间内找到所有测试用例。

3
@StraklSeth这里的普遍共识是,它应该在理论上起作用,而在实践中却不一定。
暴民埃里克(Erik the Outgolfer)'17年

Answers:


16

JavaScript(ES7), 59 ... 44  43字节

感谢Titus,节省了1个字节

预期输入:1索引。

n=>(n-=(r=(~-n/2)**.5|0)*r*2)<++r*2?n:r*4-n

最初受到A004738公式的启发,该公式是类似的序列。但是我最终完全重写了它。

测试用例

怎么样?

序列可以排列成三角形,左部分按升序排列,右部分按降序排列。

以下是前4行,包含前32个字词:

            1 | 2
        1 2 3 | 4 3 2
    1 2 3 4 5 | 6 5 4 3 2
1 2 3 4 5 6 7 | 8 7 6 5 4 3 2

现在,让我们介绍一些变量:

 row  | range   | ascending part              | descending part
 r    | x to y  | 1, 2, ..., i                | 4(r+1)-(i+1), 4(r+1)-(i+2), ...
------+---------+-----------------------------+-----------------------------------------
  0   |  1 -  2 |                           1 | 4-2
  1   |  3 -  8 |                   1   2   3 | 8-4  8-5  8-6
  2   |  9 - 18 |           1   2   3   4   5 | 12-6 12-7 12-8  12-9  12-10
  3   | 19 - 32 |   1   2   3   4   5   6   7 | 16-8 16-9 16-10 16-11 16-12 16-13 16-14

我们从顶部的2个元素开始,并在每个新行上添加4个元素。因此,索引为0的行r上的元素数可以表示为:

a(r) = 4r + 2

r的以1索引的起始位置x由该算术序列中所有先前项的总和加上1得出,得出:

x(r) = r * (2 + a(r - 1)) / 2 + 1
     = r * (2 + 4(r - 1) + 2) / 2 + 1
     = 2r² + 1

相应地,给定序列中具有1索引的位置n,则可以找到以下相应的行:

r(n) = floor(sqrt((n - 1) / 2))

或作为JS代码:

r = (~-n / 2) ** 0.5 | 0

一旦我们知道R(N) ,我们减去起始位置X(R)减去一个从ñ

n -= r * r * 2

我们将na(r)/ 2 +1 = 2r + 2进行比较,以确定我们是处于上升部分还是下降部分:

n < ++r * 2 ?

如果此表达式为true,则返回n。否则,我们返回4(r +1)-n。但是由于r在上一条语句中已经增加,因此简化为:

n : r * 4 - n

1
好吧,我想我明白了。每个上下部分的长度是2,6,10,14 ...因此总和与行数的平方成正比,因此与sqrt呈正比。非常好!
JollyJoker

7

Haskell,37个字节

(!!)$do k<-[1,3..];[1..k]++[k+1,k..2]

在线尝试!

零索引。生成列表并对其进行索引。感谢ØrjanJohansen节省了2个字节!


Haskell,38个字节

(!!)[min(k-r)r|k<-[0,4..],r<-[1..k-2]]

在线尝试!

零索引。生成列表并对其进行索引。


Haskell,39个字节

n%k|n<k=1+min(k-n)n|j<-k+4=(n-k)%j
(%2)

在线尝试!

零索引。递归方法。



5

外壳,8字节

!…ṁoe1DN

1个索引。 在线尝试!

说明

!…ṁoe1DN  Implicit input (an integer).
       N  Positive integers: [1,2,3,4,...
  ṁo      Map and concatenate
      D   double: [2,4,6,8,...
    e1    then pair with 1: [1,2,1,4,1,6,1,8,...
 …        Fill gaps with ranges: [1,2,1,2,3,4,3,2,1,2,3,4,5,6,...
!         Index with input.

3

Perl 6、29个字节

{({|(1...$+=2...2)}...*)[$_]}

在线尝试

从0开始

展开:

{  # bare block lambda with implicit parameter 「$_」

  (
    # generate an outer sequence

    {           # bare block lambda

      |(        # flatten into outer sequence

        # generate an inner sequence

        1       # start at 1

        ...     # go (upward) towards:

        $       # an anonymous state variable (new one for each outer sequence)
          += 2  # increment by 2

        ...     # go (downward) towards:

        2       # stop at 2 (1 will come from the next inner sequence)

      )
    }

    ...         # keep generating the outer sequence until:
    *           # never stop

  )[ $_ ]       # index into outer sequence
}

内部序列1...$+=2...2产生

(1, 2).Seq
(1, 2, 3, 4, 3, 2).Seq
(1, 2, 3, 4, 5, 6, 5, 4, 3, 2).Seq
(1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2).Seq
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2).Seq
...

要使其基于1,请0,在第二个之前{添加,或在第二个-1之后添加$_


3

R,64字节

function(n)unlist(sapply(seq(2,n,2),function(x)c(2:x-1,x:2)))[n]

带参数的函数n。它创建一个2:n增量为2 的向量。对于每个向量1:(x-1)x:2都会创建和。总计将比更长n。我们unlist得到一个向量并采用n-th项。


你能1:n*2代替seq(2,n,2)吗?它将超出您的需要,但是应该没问题!此外,我不认为这与工作seq(2,n,2)n=1呢!
朱塞佩

2

Python 2,56个字节

def f(x):n=int((x/2)**.5);print 2*n-abs(2*n*n+2*n+1-x)+2

在线尝试!

这是0索引。

-1字节感谢@JustinMariner

运作方式

我们注意到,1-索引n第基(1, 2, ... 2n ..., 2, 1)发生时从元件编号为0索引2(n-1)^22n^2

为了找到在索引元件x,我们可以发现组号nx是,从这一点,我们从该组的中心计算的距离x是。(此距离为abs(2*n**2+2*n+2-x))。

但是,由于元素从组的中心逐渐减小,因此我们从组的最大值减去距离。


我已经打高尔夫球了这一部分:print 2*n-abs(2*n*n+2*n+1-x)+2- 2*n*n+2*n可以2*n*-~n并且+2+2*n可以变成-~n*2,这使我们可以将其移动到开头以节省字节(53字节
Xcoder先生17年

2

05AB1E,8个字节

码:

ÅÈ€1Ÿ¦¹è

使用05AB1E编码。在线尝试!

说明:

ÅÈ           # Get all even numbers until input (0, 2, ..., input)
  €1         # Insert 1 after each element
    Ÿ        # Inclusive range (e.g. [1, 4, 1] -> [1, 2, 3, 4, 3, 2, 1])
     ¦       # Remove the first element
      ¹è     # Retrieve the element at the input index

5
除非您删除¦,否则它无法正常工作,这也会节省一个字节的
c

€1很奇怪...
魔术章鱼缸

2

JavaScript,39个字节

f=(n,t=2)=>n>t?f(n-t,t+4):n>t/2?t-n+2:n

2

果冻10,9个字节

ḤŒḄṖµ€Fị@

在线尝试!

还索引了1个,并且很快完成。

感谢@ErikTheOutgolfer,节省了一个字节!

说明:

假设,假设输入(a)为3。

    µ€      # (Implicit) On each number in range(a):
            #
Ḥ           # Double
            #   [2, 4, 6]
            #
 ŒḄ         # Convert to a range, and Bounce
            #   [[1, 2, 1], [1, 2, 3, 4, 3, 2, 1], [1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1]]
            #
   Ṗ        # Pop
            #   [[1, 2], [1, 2, 3, 4, 3, 2], [1, 2, 3, 4, 5, 6, 5, 4, 3, 2]]
            #
     F      # Flatten
            #   [1, 2, 1, 2, 3, 4, 3, 2, 1, 2, 3, 4, 5, 6, 5, 4, 3, 2]
            #
      ị@    # Grab the item[a]
            #   1
            #

您的代码等同于Ḥ€ŒḄ€Ṗ€Fị@,因此您可以使用µ€-1(开始时三个或三个以上的monad ):ḤŒḄṖµ€Fị@
Egg the Outgolfer

对于12以符合10,000的要求,它实际上应该是ḤŒḄṖ<newline> ½ĊÇ€Fị@(在我的i7上本地运行9字节代码大约需要2:20并使用7GB)
Jonathan Allan

1

MATL,15字节

li:"@EZv4L)]vG)

基于1。

在线尝试!

对于TIO中最大的测试用例,这会超时,但会在我的台式计算机(运行在MATLAB R2017a上的编译器)上及时完成。要显示经过的时间,请Z`在代码末尾添加。

>> matl 'li:"@EZv4L)]vG)Z`'
> 10000
84
15.8235379852476

说明

该代码生成了比必要更多的术语。具体来说,它计算n序列的“片段”,其中每个片段都是向上计数并返回到1。

l       % Push 1
i       % Push input, n
:       % Range [1 2 ...n]
"       % For each k in that range
  @E    %   Push 2*k
  Zv    %   Symmetric range: [1 2 ... 2*k-1 2*k 2*k-1 ... 2 1]
  4L)   %   Remove last entry: [1 2 ... 2*k-1 2*k 2*k-1 ... 2]
]       % End
v       % Concatenate all stack contents into a column vector
G)      % Get n-th entry. Implicitly display

真好!有时TIO很慢...

1
好吧,这里变慢的主要原因是算法(生成的项多于必要项)。此外,MATL编译器并不是特别快
Luis Mendo

1

外壳12个 10字节

!ṁ§¤+hḣṫİ0

在线尝试!

1索引,工作速度非常快

说明

!ṁ§¤+hḣṫİ0
 ṁ      İ0    Map the following function over the even numbers and concatenate the results together
  §   ḣṫ      Get the ranges 1-n and n-1, then... 
   ¤+h         remove the last element from both of them and concatenate them together
!             Return the element of the resulting list at the given index

使用8个字节
Zgarb

@Zgarb是个好主意,您可能应该将其发布为答案:)
Leo



1

视网膜,62字节

.+
$*
^((^.|\2..)*)\1.
6$*1$2$2;1
(?=.+;(.+))\1(.+).*;\2.*
$.2

在线尝试!链接包括测试用例。输入为1索引。第一阶段只是十进制到一元的转换。第二阶段找到s严格小于一半的最高平方数n; $1$2而是2s-1。它计算两个值,第一个是当前向上/向下运行中的数字数,即4(s+1) = 4s+4 = 2$2+6,其次是该运行中的位置,即n-2s² = n-(2$1+1)+1 = n-$&+1,只需要一个1即可弥补1用来强制严格不等式的情况。然后,最后阶段从该位置开始计数,直到运行的开始和结束,然后取较低的结果并将其转换为小数。



1

Perl 5,43 +1(-p)= 44字节

$_=($n=2*int sqrt$_/2)+2-abs$n/2*$n+$n+1-$_

在线尝试!

我正在研究一个公式来直接计算第n个元素。然后我看到@ fireflame241完成了这项工作,然后将其打入了Perl。

Perl 5中,50 + 1(-n)= 51个字节的

push@r,1..++$",reverse 2..++$"while@r<$_;say$r[$_]

在线尝试!

结果被索引为0。


1

哈斯克尔115 81字节

y%x=snd(span(<x)$scanl(+)y[y+1,y+3..])!!0
g 1=1
g x|1%x>2%x=1+g(x-1)|1>0=g(x-1)-1

在线尝试!

这里发生了一些魔术。如果我使用常规方法,则可能会更短。

说明

首先我们定义%%是,有两个变量的函数x,和y。它构造一个列表,scanl(+)y[y+1,y+3..]并找到该列表的第一个元素大于xscanl(+)只是执行迭代总和,以获得我们将要做的三角数scanl(+)0[1..],获得我们将要做的平方数scanl(+)0[1,3..]。特别是我们将要构建的两个列表是scanl(+)2[3,5..]scanl(+)1[2,4..]这些模式的拐点。

现在,我们定义一个主函数g,它需要一个x。如果x为,则返回,1因为这是第一个值。否则,我们将检查接下来的两个拐点,如果向下的拐点较大,1%x>2x则返回的后继拐点,g$x-1否则返回的前拐点。g$x-1

好吧,那为什么行得通呢?

首先,“寻找顶点的方式如何?”。重要的是要注意相同类型的连续顶点之间的距离。您会注意到差异每次都增加2。这是有道理的,因为三角形的底边每次变宽2个。我们可以像这样使用列表文字使列表常数有所不同[2,4..],我们使用scanl(+)来把这些列表到我们的顶点名单的基础上,第一个顶点的位置和第一差。

因此,既然我们有了查找向上和向下顶点的方法,就可以使用该信息来获取值。我们说第一个值是1否则我们必须采用后继者或前任者。如果下一个顶点是向上的顶点,我们希望采用前一个顶点,否则,我们选择后继顶点。

Haskell56 51 46字节

这是我用更少的数学和更少的字节更好的解决方案。

d x|e<-[1..x-1]=e++map(x+1-)e
(([1..]>>=d)!!0)

在线尝试!



1

C#(.NET Core),120字节

说明:非常简单,第一个嵌套循环爬升到我们的最大值,第二个嵌套循环爬回向下到2。每个2的倍数重复。

x=>{var a=0;for(int i=2,j=0;j<x;i+=2){for(var b=1;b<=i&j<x;b++,j++){a=b;}for(var c=i-1;c>1&j<x;c--,j++){a=c;}}return a;}

在线尝试!


1

红宝石78 75字节

感谢Step Hen,节省了1个字节

多亏了Xcoder先生,节省了1个字节

->n{a=0;b=2;c=1;n.times{if a==b then c=0;b+=2;end;c=1if a<2;a+=c<1?-1:1};a}

在线尝试!

希望我能得到一些技巧来进一步减少字节数。我试图采取一种简单的方法。


欢迎来到PPCG!c=1 if可以打高尔夫球c=1if
斯蒂芬(Stephen)

76个字节:->n{a=0;b=2;c=1;n.times{if a==b then c=0;b+=2;end;c=1if a==1;a+=c<1?-1:1};a}
Xcoder先生

1

Java(OpenJDK 8),53字节

n->{int i=2;for(;n>i;i+=4)n-=i;return n>i/2?i-n+2:n;}

在线尝试!

-2个字节,感谢Nevay。

1个索引。

TL; DR我们将序列分成方便的块,找到块n在其中,然后找到块中的nth位置。

在这里,我们可以像那样分割序列[[1,2],[1,2,3,4,3,2],[1,2,3,4,5,6,5,4,3,2],...],这使我们的块大小为4i-2。从开始i=2,我们i从中减去n,实际上每次向上移动一个块。一旦满足n<=i,我们便知道n当前块中正确值的位置。

然后,我们通过与块大小进行比较n来获得该值i。每个块的中点等于i/2+1; 如果n小于此,我们简单地返回n。如果n更大,我们返回i-n+2

n = 16, i = 2

Is n > i? Yes, n = n - 2 = 14, i = i + 4 = 6
Is n > i? Yes, n = n - 6 = 8, i = i + 4 = 10
Is n > i? No, stop looping.
10 / 2 + 1 = 6
Is n > 6? Yes, return i - n + 2 = 8 - 6 + 2 = 4

您不需要+1return n>i/2?i-n+2:n就足够了。
涅瓦

嗯 谢谢,整数除法。
Xanderhall '17

1

Python 2、5!字节(120字节:P)

r=range
a=[]
for i in r(2,998,2): 
	for j in r(1,i+1): a.append(j)
	for j in r(i-1,1,-1): a.append(j)
print a[input()-1]

在线尝试!

直截了当,创建列表,然后使用input'th元素


谢谢那些投票的人!现在我有50名代表,所以我可以发表评论!DABS强烈
Husnain拉扎

0

Python 3中184个 156字节

l,n,r=list,next,range
h=lambda x:l(r(1,x))+l(r(x-2,1,-1))
def g():
	x=3
	while True:yield from h(x);x+=2
def f(i):
	x=g()
	for _ in r(i-1):n(x)
	return n(x)

在线尝试!

与Python生成器配合使用以进行“惰性”评估


0

QBIC,47字节

g=q{p=p+1~p=:|_Xg\g=g+q~g=1or g>=r|r=r+1┘q=q*-1

说明

g=q         var g is the current value of the sequence; set to 1 at the start
{           DO infinitely
p=p+1       raise the step counter (var p)
~p=:|_Xg    IF p equals the input term a (read from cmd line) THEN QUIT, printing g
\           ELSE
g=g+q       raise (or decrement) g by q (q is 1 at the start of QBIC)
~g=1        IF g is at the lower bound of a subsequence
    or g>=r OR g is at the upper bound (r start as 2 in QBIC)
|r=r+1      THEN increment r (this happens once on lower bound, and once on upper, 
            total of 2 raise per subsequence)
┘q=q*-1     and switch q from 1 to -1

0

Röda,54个字节

f n{seq 1,n|{|i|seq 1,2*i;seq 2*i-1,2}_|head n+2|tail}

在线尝试!

致电: try f(n)

此函数快速返回答案,但是此后进行一些不必要的计算,最终耗尽内存。

由于该函数在调用后不久(很明显在一分钟内)确实返回了实际答案,因此我认为此答案有效。

(在Röda函数中,由于并行性,函数可以在退出之前返回值。)



0

PHP,65 + 1字节

for($x=$d=$z=1;--$argn;)$d=($x+=$d)>1?$x>$z?-1:$d:!!$z+=2;echo$x;

与管道一起运行,-R在线尝试(或取消注释其他版本之一)。

tsh的递归JavaScript端口占用66个字节:

function f($n,$t=2){return$t<2*$n?$t<$n?f($n-$t,$t+4):$t-$n+2:$n;}

Arnauld的解决方案港口需要62 + 1:

$n=$argn;echo($n-=($r=(~-$n/2)**.5|0)*$r*2)<++$r*2?$n:$r*4-$n;

到目前为止,Xanderhall Java的高尔夫球端口具有最短的代码(55 + 1字节):

for($n=$argn;$n+2>$i+=4;)$n-=$i-2;echo$n*2>$i?$i-$n:$n;

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.