Van Eck序列的N项


41

输出Van Eck序列的第N个项。

Van Eck序列定义为:

  • 从0开始。
  • 如果最后一项是该项的首次出现,则下一项为0。
  • 如果上一个术语先前已发生,则下一个术语是最近一次发生的退后几步。

https://oeis.org/A181391

https://www.youtube.com/watch?v=etMJxB-igrc

https://www.youtube.com/watch?v=8VrnqRU7BVU

顺序:0,0,1,0,2,0,2,2,1,6,0,5,0,2,...

测试:

输入| 输出量

  • 1 | 0
  • 8 | 2
  • 19 | 5
  • 27 | 9
  • 52 | 42
  • 64 | 0

编辑

首选1索引,可接受0索引;这可能会改变一些已经提交的解决方案。

请只是第N个学期。

相同(除了看到已经发布的部分),似乎代码高尔夫球手和亲密电视爱好者之间有相当大的重叠。


9
观看了工作中的麻木录像,当我回到家时打算将其发布。诅咒你先到达那里。:P
Draco18s

17
它必须是1索引的,还是可以使用0索引的?
罗宾·赖德

6
我们可以返回还是输出无限序列?
Jo King

2
...还是第一n项?
毛茸茸的

@ Draco18s同样,我在看完Numberphile视频后来到这里发布。
Geza Kerecsenyi

Answers:


25

JavaScript(ES6), 46 41  37字节

n=>(g=p=>--n?g(g[p]-n|0,g[p]=n):p)(0)

在线尝试!

怎么样?

我们不需要存储完整序列。我们只需要跟踪序列中出现的每个整数的最后位置。为此,我们使用递归函数的基础对象。g

对于给定的项,我们不需要将设置为其序列中的实际绝对位置,因为我们只对与当前位置的距离感兴趣。这就是为什么我们可以只存储输入的当前值,该值在代码中用作递减计数器。pg[p]n

因此,该距离由。方便的是,如果这是的首次出现,则此值为NaN,可以很容易地将其转换为预期的。g[p]np 0p0

已评论

n => (             // n = input
  g = p =>         // g = recursive function taking p = previous term of the sequence
                   //     g is also used as an object to store the last position of
                   //     each integer found in the sequence
    --n ?          // decrement n; if it's not equal to 0:
      g(           //   do a recursive call:
        g[p] - n   //     subtract n from the last position of p
                   //     if g[p] is undefined, the above expression evaluates to NaN
        | 0,       //     in which case we coerce it to 0 instead
        g[p] = n   //     update g[p] to n
      )            //   end of recursive call
    :              // else:
      p            //   we've reached the requested term: stop recursion and return it
)(0)               // initial call to g with p = 0

18

Python 3中69个 63 62字节

f=lambda n,l=0,*s:f(n-1,l in s and~s.index(l),l,*s)if n else-l

在线尝试!

注意:正如Outgolfer的Erik所提到的,此代码在Python 2中也能正常工作。

0索引(尽管完全不正确,您可以通过更改if nif~n:P 使其成为-1索引)

利用Python出色的解压缩“明星算子”,以递归方式建立系列,直至n达到零。

该函数以相反的顺序构建序列,以避免为了搜索而不得不将其反转。此外,它实际上存储了所有元素的取反,因为最后将它们转换回是免费的(否则,-它们本来必须是一个空格),并且通过使用~s.index(l)代替来节省了我们一个字节-~s.index(l)

如果Python元组具有与find字符串相同的功能(可能会返回-1,而不是引发错误),则可能为51个字节,但是没有这种运气...


3
其实,“明星经营者”你正在使用的不是Python 3中的拆包经营者,而是可变参数运营商也存在于Python的2
埃里克Outgolfer

3
第一个是,但是第二个不是s为递归调用解包吗?
ArBo

1
我已经在Python 2中对其进行了测试,并且可以正常工作。
暴民埃里克

@EriktheOutgolfer嗯,但是第二个用途不是解压缩吗?该函数不必支持varargs即可使用此类语法。
ArBo

@ArBo:没什么不同def func(f, *args): f(*args);在函数调用中解包是有效的py2。仅限py3的是在列表/字典解析(即[1, 2, *s])内解包或对变量进行解包:a, *b = [1,2,3,4]
Ehsan Kia

9

R,62个字节

function(n){while(sum(F|1)<n)F=c(match(F[1],F[-1],0),F)
+F[1]}

在线尝试!

反向建立列表;match返回(列表的其余部分)中(先前值)的第一个索引,如果未找到匹配项,则返回。F[1]F[-1]0

F在循环的第一遍被初始化为FALSE并被强制为。0while


2
match当您以这种方式构造它时,我会对这个问题有多好感到敬畏。真的很干净。
刑事

第二行的加号在这里做什么吗?我以为它固定了一个边缘盒,但我找不到它。
刑事

1
@CriminallyVulgar应该强迫F0n==1别人会回报FALSE
朱塞佩

嗯,我明白了。有道理,我尝试了很多范围,但没有尝试使用单个值。
刑事

9

Perl 6的47 42个字节

-5字节归功于nwellnhof

{({+grep(@_[*-1],:k,[R,] @_)[1]}...*)[$_]}

在线尝试!

匿名代码块,该代码块输出序列中的0索引元素。

说明:

{                                            } # Anonymous codeblock
 (                                      )[$_]  # Return the nth element
                                    ...*       # Of the infinite sequence
  {                            }  # Where each element is
    grep(        :k        )[1]   # The key of the second occurrence
         @_[*-1],                 # Of the most recent element
                   ,[R,] @_       # In the reversed sequence so far
   +     # And numify the Nil to 0 if the element is not found

8

Bourne Shell,102个字节

until [ 0"$i" -eq $1 ];do i=$((${i:-0}+1)) a=${n:-0};eval 'n=$(($i-${m'$a:-$i'}))' m$a=$i;done;echo $a

在线尝试


3
欢迎来到PPCG!
Arnauld


6

J29 23字节

1{(,~#|1+}.i.{.)@]^:[&0

在线尝试!

真正的工作是在幂动词的迭代动词中完成的,该动词^:迭代次数为自变量多次[,并从常数值0开始迭代&0...

  • (#|1+}.i.{.)这就是迭代。分解...
  • }.i.{.i.在列表{.的末尾找到列表头的索引}.。这将返回从0开始的索引,因此,如果当前项在上一个之前被发现,它将返回0。如果未找到,则将返回列表的长度,即尾部的长度。
  • 1+由于Ven Eck的“多远”是基于1的,因此将值加1可以更正基于0的索引。请注意,如果找不到,则该值现在将是完整列表的长度。
  • #|当除以完整列表的长度时,返回上一步中计算出的值的余数。请注意,这会将“未找到”变为0,但所有其他值保持不变。
  • ,~将新值追加到列表的前面。为了方便起见,我们使用正面而不是最后。
  • 1{ 返回列表中的第二个项目,因为我们计算了太多次,因为这种方式更短。

6

Python,51字节

f=lambda n,i=1:n>i and[f(n,i+1),i][f(n-1)==f(n+~i)]

在线尝试!

输出False0。从字面上实现规范,寻找最低的正整数,i例如f(n-1)==f(n-i-1)。如果这样的搜索导致i>=n以前的元素以前没有出现,我们就产生了0

该函数不会执行诸如将早期值存储在列表中之类的合理操作,而是仅在需要时(有时在不需要时)从头开始递归地重新计算它们。这使得该功能对于输入大于10的输入非常慢。


5

APL(Dyalog Unicode)19个 17 字节SBCS

非常感谢ngn,Adám,Richard Park和H.PWiz在The APL Orchard(这是学习APL并获得APL帮助的好地方)的写作和打高尔夫球方面的帮助。

编辑:从Adám-2个字节。

⊃(⊢,⍨≢|1∘↓⍳⊃)⍣⎕-1

在线尝试!

说明

⊃(⊢,⍨≢|1∘↓⍳⊃)⍣⎕-1

                 -1  We initialize our array of results with -1.
 (           )⍣⎕     repeats the train (in parentheses) our input, ⎕, times.
        1∘↓⍳⊃        We take the index of the head (our last element in the sequence).
                     To signify "element not found", this returns the length of the array.
      ≢|             We take our index modulo the length of the array.
                     This turns our "element not found" from the length of the array to 0.
  ⊢,⍨                And we prepend to our array.
                    Finally, we return the first element of the array,
                     which is the most recently-generated.
                     This is the ⍵-th element of the Van Eck sequence.


4

05AB1E,8 个字节

F¯Rćk>Dˆ

n

说明:

F         # Loop the (implicit) input amount of times:
 ¯        #  Push the global array
  R       #  Reverse it
   ć      #  Extract the head; push the remainder and the head to the stack
    k     #  Get the 0-based index of the head in the remainder (-1 if not found)
     >    #  Increase it by 1 to make it 1-indexed (or 0 if not found)
      Dˆ  #  Add a copy to the global array
          # (after the loop, output the top of the stack implicitly as result,
          #  which is why we need the `D`/duplicate)

1
这是审查亵渎行为的怪异方式!
7

1
@negativeseven大声笑,花了我几分钟才知道您的意思,但我想您指的是F¯Rćk?;)
Kevin Cruijssen

4

Java,96 80 76字节

n->{int i,v=0,m[]=new int[n];for(;--n>0;m[v]=n,v=i<1?0:i-n)i=m[v];return v;}

不混淆:

Function<Integer, Integer> vanEck =
n -> {

    int i;                  // i is the value of n when v was previously encountered
    int v = 0;              // v is the current element of vanEck sequence
    int[] m = new int[n];   // m[v] is the value of n when v was previously encountered

    while (--n > 0) {       // n is used as a decrementing counter

        i = m[v];
        m[v] = n;
        v = i == 0 ? 0 : i - n;
    }

    return v;
};

2
通过将while循环更改为for循环,您应该能够删除一些字节。
MegaTom

1
您好,您可以通过内联声明int[]中的int声明来打高尔夫,也可以使用<1代替==0。示例:int f(int n){int l[]=new int[n],i=0,j,v=0;while(++i<n){j=l[v];l[v]=i;v=j<1?0:i-j;}return v;}
OlivierGrégoire

2
而现在一个lambda,以及由@MegaTom共80个字节中提到高尔夫球:n->{int l[]=new int[n],i=0,j,v=0;for(;++i<n;l[v]=i,v=j<1?0:i-j)j=l[v];return v;}
奥利维尔·格雷瓜尔


3

木炭,23字节

≔⁰θF⊖N«≔⊕⌕⮌υθη⊞υθ≔ηθ»Iθ

在线尝试!链接是详细版本的代码。说明:

≔⁰θ

将第一项设置为0。

F⊖N«

循环n-1时间。(如果可接受0索引,则可以将其删除以节省1个字节。)

≔⊕⌕⮌υθη

下一项是前一项的反向列表中当前项的递增索引。

⊞υθ

将当前术语添加到以前的术语列表中。

≔ηθ

将当前术语设置为下一个术语。

»Iθ

在循环末尾打印当前项。



2

果冻,8 字节

ẎiḢ$;µ¡Ḣ

nnth

在线尝试!

怎么样?

ẎiḢ$;µ¡Ḣ - Link: n
     µ¡  - repeat this monadic link n times - i.e. f(f(...f(n)...)):
         - (call the current argument L)
Ẏ        -   tighten (ensures we have a copy of L, so that Ḣ doesn't alter it)
   $     -   last two links as a monad:
  Ḣ      -     head (pop off & yield leftmost of the copy)
 i       -     first index (of that in the rest) or 0 if not found
    ;    -   concatenate with L
       Ḣ - head

请注意,没有决赛,我们实际上已经收集了[a(n), a(n-1), ..., a(2), a(1), n]



2

Haskell68 67 66字节

相当简单的实现(使用基于0的索引)。

f n|all((/=f(n-1)).f)[0..n-2]=0|m<-n-1=[k|k<-[1..],f(m-k)==f m]!!0

在线尝试!





2

Python 3中128个 114 111 102 99字节

102-> 99个字节,感谢Jonathan Frech

f=lambda n,i=1,l=[0]:f(n,i+1,l+[l[i-2::-1].index(l[-1])+1if l[-1]in l[:-1]else 0])if n>i else l[-1]

在线尝试!


您可以取消条件并使用-而不是!=保存字节。
Jonathan Frech

另外,由于高尔夫似乎没有副作用,因此可以使用列表代替元组。
Jonathan Frech

@JonathanFrech但是,如果我有一个列表作为默认参数,它将无法在连续调用中正常工作?
ruohola

为什么不呢?
Jonathan Frech

1
最可能的原因是您以前的脚本修改了列表,即不是副作用少的示例
乔纳森·弗雷奇


1

Python 3,112字节

a=[0]
for _ in a*int(input()):k=a[-1];a+=k in a[:-1]and[a[::-1].index(k)+~a[-2::-1].index(k)]or[0]
print(-a[-2])

在线尝试!

-3个字节归功于mypetlion


第二行可以for _ in a*int(input()):k=a[-1];a+=k in a[:-1]and[a[::-1].index(k)+~a[-2::-1].index(k)]or[0]节省3个字节。
mypetlion

@mypetlion感谢
HyperNeutrino


1

CJam(15字节)

0a{_(#)\+}qi*0=

在线演示。这是一个完整的程序,索引为0。

解剖

0a      e# Push the array [0]
{       e# Loop...
  _(#   e#   Copy the array, pop the first element, and find its index in the array
  )\+   e#   Increment and prepend
}qi*    e# ... n times, where n is read from stdin
0=      e# Take the first element of the array

0

Clojure,69个字节

#((fn f[i c t](if(= i 1)t(f(dec i)(assoc c t i)(-(or(c t)i)i))))%{}0)

可悲的是,一种更实用的方法似乎更长。


0

DC,94 91 90字节

在程序执行期间进行输入。将其保存到文件,然后执行“ dc”运行。绝对不是最短的,但我对DC中的此类挑战感到很开心。输入是基于1的索引,这是首选。

[st1si0swlbxltlwlu1-sulu0!=m]sm[dlt=qSsli1+siz0!=b0siLs]sb[0pq]sf[lisw2Q]sq?2-dsu1>f0dlmxp

Main control macro
[st                         ]sm   save top value as target
[  1si0sw                   ]sm   reset i to 1 and w to 0
[        lbx                ]sm   execute macro b to get next value in w
[           ltlw            ]sm   restore target to the stack and add w to the stack
[               lu1-su      ]sm   decrement the user inputted variable
[                     lu0!=m]sm   if the user inputted variable is not 0 recurse

Next value finder macro
[dlt=q                  ]sb     if the value on the stack is the target, quit
[     Ss                ]sb     save top value to s register
[       li1+si          ]sb     increment i register
[             z0!=b     ]sb     recurse if still more values            
[                  0si  ]sb     set i to 0 (will be saved to w if relevant)
[                     Ls]sb     move top value of s register to stack

[lisw2Q]sq   Load i, save it to w, and then quit this macro and the one that called it

[0pq]sf print 0 and quit the program
```

0

C ++(clang)241 235 234 219 197 189字节

197-> 189字节,感谢ceilingcat

#import<bits/stdc++.h>
int f(int n,int i=0,std::vector<int>l={0}){return~-n>i?l.push_back(find(begin(l),end(l)-1,l[i])-end(l)+1?find(rbegin(l)+1,rend(l),l[i])-rbegin(l):0),f(n,i+1,l):l[i];}

在线尝试!


0

Pyth,18个字节

VQ=Y+?YhxtYhY0Y;hY

在线尝试!

反向建立序列并打印第一个元素(序列的最后一项)。

VQ                 # for N in range(Q) (Q=input)
  =Y+         Y    # Y.prepend(
        xtY        #   Y[1:].index(    )
           hY      #               Y[0]
       h           #                     +1
     ?Y      0     #                        if Y else 0)
               ;hY # end for loop and print Y[0]
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.