像青蛙一样跳!


12

给定非负整数数组,您的任务是仅保留其某些元素,如下所述。

  • 假设数组为[1, 3, 2, 4, 11, 5, 2, 0, 13, 10, 1]

  • 首先获取数组的第一个元素n。保留第一个n元素并丢弃下一个元素(丢弃n+1th)。新数组为[1, 2, 4, 11, 5, 2, 0, 13, 10, 1]

  • 然后,您在删除的元素后面抓取元素,并执行完全相同的操作。重新应用该过程,我们得到[1, 2, 11, 5, 2, 0, 13, 10, 1]

  • 重复此过程,直到到达数组范围之外/数组中没有剩余元素。我们停止,因为11它大于数组的长度。

  • 现在,您应该输出结果。

输入/输出可以任何标准形式获取/提供。该数组永远不会为空,并且将仅包含非负整数。禁止所有标准漏洞。

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


测试用例

输入->输出

[1、2、3、4、5]-> [1、3、4]

[6,1,0,5,6]-> [6,1,0,5,6]

[1、2、3、2、4、11、5、2、0、13、10、1]-> [1、2、11、5、2、0、13、10、1]

[2,2,2,2,2,2]-> [2,2]

[1、2、3、1、2、3、1、2、3]-> [1、2]

[3,1,2,4,0]-> [] *

*最后一个测试用例涉及0,因此我决定将流程发布得更加清晰:

[3, 1, 2, 4, 0] --> [3, 1, 2, 0] --> [1, 2, 0] --> [1, 0] --> [0] --> [] )

灵感来自OutgolferErik的挑战


我已经完全手动编写了所有测试用例,如果您认为有误,请通知我!

1
为什么要2在第一步中将其删除而不是3
Leaky Nun

@LeakyNun我的错。纠正。如果我犯了其他任何错误

建议的测试用例:[1, 2, 3, 1, 2, 3, 1, 2, 3]
Rod

1
因此要澄清一下,当您移至新的“ n”时,您总是从数组的开头开始保留n元素吗?(正如我乍看之下)不是将n元素保留在n您要评估的第一个元素的位置吗?
布赖恩J

Answers:



5

JavaScript(ES6),45个字节

f=(a,k=0,x=a[k])=>1/x?f(a.splice(x,1)&&a,x):a

测试用例


4

Haskell,50个字节

g.pure.(0:)是一个匿名函数,接受并返回Ints 的列表,用作(g.pure.(0:))[1,2,3,4,5]

g.pure.(0:)
g(a,_:b:c)=g$splitAt b$a++b:c
g(a,_)=a

在线尝试!

怎么运行的

  • 该函数g采用表示拆分列表的元组参数。a是在上一步中保留的初始元素的列表,_是要丢弃的元素,b是要用作长度的下一个元素,并且c是其余元素。
    • 如果在元组的第二部分中有足够的元素来选择a b,则将执行新的拆分并g递归。否则,结果将停止a
  • 匿名函数g.pure.(0:)通过g使用元组调用来开始所有操作([],0:l),其中元组在哪里l,输入0立即被丢弃g
    • pure这里使用Applicative(二进制)元组的实例,并通过结果类型([Int],[Int])方便地将其参数作为第二个元素放入[]作为第一元素的元组中。

3

Python 3,59个字节

f=lambda a,i=0:f(a[:a[i]]+a[a[i]+1:],a[i])if i<len(a)else a

在线尝试!


令人印象深刻!我有一个65字节的非递归方法(在Python 2中)。


2

Java 8,68字节

此lambda接受可变的List<Integer>remove(int)例如,支持ArrayList)。输出是变异输入。分配给Consumer<List<Integer>>

l->{for(int i=0,f=0;i<l.size();f^=1)i=f>0?l.remove(i)*0+i:l.get(i);}

在线试用

这个问题的控制流程非常烦人。每次迭代时,我们都必须删除一个元素并将其移到下一个位置,并且这两个操作都需要进行范围检查(并且其中任何一个都可能触发程序完成)。一种策略是在单个循环迭代中执行两种操作,并通过其自身的范围检查来保护索引更新。事实证明,这种策略更短一些,它是在每次循环迭代之间交替操作,这就是该解决方案的作用。


1

APL(Dyalog Classic),32字节

1∘{n∇⍣(n≤≢w)⊢w←⍵/⍨(n1+⍺⊃⍵)≠⍳≢⍵}

说明

1∘{                             } bind 1 as starting left argument (⍺)
                             ⍳≢⍵  generate indexes for right argument (⍵)
                   (n1+⍺⊃⍵)      n is 1+item at position  
              w←⍵/⍨              w is  with item at n removed
   n∇⍣(n≤≢w)⊢                     recurse with n as left and w as right arg if n <= length of w

在线尝试!



1

Haskell,99个字节(88个不带缩进)

f x y
 |y>=l=f x$l-1
 |e>=l=x
 |True=f (take e x ++ drop (1+e) x) e
 where e=x!!y
       l=length x

我可能可以使用“ 1 = 1”而不是“ True”保存1个字节,也可以删除“ ++”附近的两个空格
Giacomo Tecya Pigani

1

VI,31 25字节

O@0kdd<C-v><C-a>Y<C-v><C-x>gg@a<Esc>"add<C-a>Y<C-x>@a

<C-?>对应Control + ?,并<Esc>Escape明显。这些每个都计为1个字节(请参见meta)。

输入值

输入文件应在每行中包含1个整数+在末尾包含1个空行,例如:

1
2
3
4
5
⁣

我们可以将输入文件的每一行视为一个数组元素,例如1 :: 2 :: 3 :: 4 :: 5 :: [],在某些语言中(例如caml)。

发射

您可以从以下命令开始vi,然后逐笔输入解笔画:

vi -u NONE input

您还可以使用以下一种代码:

vi -u NONE -c ':exec "norm O@0kdd\<C-v>\<C-a>Y\<C-v>\<C-x>gg@a\<Esc>\"add\<C-a>Y\<C-x>@a"' -c ":w output" -c ':q' input

这应该output从输入文件中产生具有正确结果的文件input

说明

为了介绍该解决方案,我将首先提出一个19字节的解决方案,该解决方案仅适用于不带0的数组。该解决方案使用递归宏,在最终解决方案中几乎没有修改:

Yqa@0ddYgg@aquggY@a

部分解决方案的说明

Y                       # yank first line (first integer + line break) to "0 register
 qa                     # start recording a macro ("a register)
   @0                   # jump n lines, where n is the content of the "0 register
     dd                 # delete the current line (n+1th line)
       Y                # yank current line (integer after the previously deleted line)
        gg              # go back to the first line
          @a            # recurse on macro "a"
            q           # finish recording the macro
             u          # cancel modifications done by the execution of the macro
              gg        # go back to the first line
                Y@a     # apply the recorded macro with first parameter equal to the first integer

这里的技巧是使用"0寄存器存储当前整数(以及换行符,非常重要)。因此,该命令@0允许跳转n行(调用n的值"0)。如果跳转超过文件中的行数,则宏将失败,因此程序将停止(根据需要在数组范围之外)。

但是,如果输入包含,则此解决方案不起作用0。确实,如果"0寄存器值等于0@0则将跳一行(由于换行),而不是0我们喜欢的。因此,下一个命令(dd)不会删除第0个整数,而是第1个(不正确)。

处理的有效解决方案0是始终在拉动整数之前先增加整数,然后再减少整数。因此,该@0命令将跳转n+1行(n是已递增的当前整数)。k然后需要一个命令转到行n(上一行)。使用此技巧,在输入文件的末尾需要一个空行,以避免跳出数组(从而终止程序),因为我们现在总是跳到n+1第几行,然后才跳到上一行。

最终解决方案的说明

O                                                       # insert a new line at the beginning of the file, enter insert mode to write the macro content
 @0                                                     # jump n lines                                                       
   k                                                    # go to the previous line
    dd                                                  # delete this line
      <C-v><C-a>                                        # type Control+A (C-v is needed because we are in insert mode) to increment the current integer
                Y                                       # yank the incremented integer
                 <C-v><C-x>                             # decrement the current integer
                           gg                           # go to the first line
                             @a                         # recurse on macro "a"
                               <Esc>                    # exit insert mode : at this step, the first line of the file contains the macro content @0kdd^AY^Xgg@a
                                    "add                # copy @0kdd^AY^Xgg@a line to the register "a and delete the line
                                        <C-a>           # increment the first integer
                                             Y          # yank it (into "0)
                                              <C-x>     # decrement the first integer
                                                   @a   # apply macro in a" (initial @0 will jump n+1 lines, since we incremented the first integer before calling the macro)

在注册之前在文件中写入宏内容可以节省一些字节:

  • 避免qa...q在注册后写入和撤消所有更改
  • 避免:let @a="..."

编辑

#1

  • 将宏内容写在第一行(而不是最后一行)
  • 更改输入(末尾有1个空行)
  • 在命令行中添加一线测试

0

Pyth,32个字节

VlQIgNlQBK@QNI!K=QYBIgKlQB.(QK;Q

在线尝试


Pyth可以比这更优雅:) #VlQ.(Q@QN;Q以12个字节完成工作,我很确定它可以打更多的高尔夫球
Dave

通过保留传统的Python方法,您可以做到W<Zl=Q+<Q@QZ>Qh@QZ=Z@QZ)Q(25)。Pizzakingme的方法要好得多。

4
@KaranElangovan没什么好抱歉的,他们只是想为您提供帮助。
Leaky Nun

1
固定为最终测试用例,结果为15个字节:#VlQ .(Q@QN)%;Q。欢迎Pyth高尔夫球手提供反馈,我仍然在学习!
戴夫

2
此方法无效。它不仅不会仅打印结果,而且还会使测试用例失败(至少倒数第二个)。您能否删除/解决此问题?

0

C#(.NET Core),74个字节

n=>{for(int i=n[0];i<n.Count;){n.RemoveAt(i);i=i<n.Count?n[i]:n.Count+1;}}

在线尝试!

这将获取一个int列表并对其进行修改。我已经看到一些Java答案,这些答案通过使用Lambda参数定义中的完全限定名称来绕过导入。如果不允许这样做,我可以删除此答案。


如果要在lambda定义中引用参数类型,则可以使用
雅各布

@雅各布我明白。我只是觉得有点脏,System.Collections.Generic.List<int>而不是using System.Collections.Generic将其添加到字节数中。但是我想这与使用数组没有什么不同。
jkelm

原来如此。好吧,using如果需要,您可以使用;只要lambda本身不依赖该语句,就不必将其包括在字节数中。就我个人而言,我总是在测试代码中使用完全限定的名称,以便清楚,容易地验证lambda所使用的导入内容。
雅各布

0

R64 53字节

f=function(a,i=1,d=a[i]+1)"if"(is.na(d),a,f(a[-d],d))

递归函数。有一个必填项,,a跳过的列表。i是要跳过的事物数的索引(默认为1),d是删除了所需值之后下一个项目的索引,这也是要删除的项目的索引。返回numeric(0),一个空向量,用于空输出。

在线尝试!

取消高尔夫:

f <- function(a, i = 1, d = a[i] + 1) {
  if(is.na(d)) {   # d is NA if and only if a[i] is out of bounds
    a
  } else {
    f( a[-d], d, a[d] + 1 )   # a[-d] is a with the item at index d removed
  }
}
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.