保持非零及其邻居


26

摘自Stack Overflow的这个问题。也感谢@miles和@Dada为解决某些极端情况提供建议的测试输入。

挑战

给定一个整数值数组,请删除所有不包含某个非零值的零。

等效地,如果条目为非零或为立即接近于非零值的零,则应保留该条目。

保留的条目应在输出中保持其在输入中的顺序。

给定

[2 0 4 -3 0 0 0 3 0 0 2 0 0]

应删除的值用标记x

[2 0 4 -3 0 x 0 3 0 0 2 0 x]

所以输出应该是

[2 0 4 -3 0 0 3 0 0 2 0]

规则

输入数组可能为空(然后输出也应该为空)。

输入和输出格式像往常一样灵活:数组,列表,字符串或任何合理的格式。

打高尔夫球,最少。

测试用例

[2 0 4 -3 0 0 0 3 0 0 2 0 0] -> [2 0 4 -3 0 0 3 0 0 2 0]
[] -> []
[1] -> [1]
[4 3 8 5 -6] -> [4 3 8 5 -6]
[4 3 8 0 5 -6] -> [4 3 8 0 5 -6]
[0] -> []
[0 0] -> []
[0 0 0 0] -> []
[0 0 0 8 0 1 0 0] -> [0 8 0 1 0]
[-5 0 5] -> [-5 0 5]
[50 0] -> [50 0]

我可以_2代替使用-2吗?相当多的语言都使用该格式。
Leaky Nun

我们要-0吗?
Leaky Nun

@LeakyNun 1是2否
路易斯·门多

数字会以零开头吗?喜欢[010 0 0 01 1]吗?
FryAmTheEggman'8

@FryAmTheEggman Nope
Luis

Answers:


16

JavaScript(ES6),35个字节

a=>a.filter((e,i)=>e|a[i-1]|a[i+1])

在浮点数上也可以使用两个额外的字节。


10

Python,50个字节

f=lambda l,*p:l and l[:any(l[:2]+p)]+f(l[1:],l[0])

带元组的递归函数。如果前两个元素或上次存储的前一个值之间存在非零值,则包含第一个元素。然后,删除第一个元素并递归。前一个元素存储在singleton-list中p,后者会自动打包到list并开始为空(这要归功于Dennis 3个字节)。


55个字节:

lambda l:[t[1]for t in zip([0]+l,l,l[1:]+[0])if any(t)]

生成列表的所有长度为3的块,首先在开头和结尾处添加零,并获取不全为零的中间元素。

迭代方法的结果更长(58个字节)

a=0;b,*l=input()
for x in l+[0]:a|b|x and print(b);a,b=b,x

这并不是完全有效,因为b,*l需要Python 3,但是Python 3 input提供了一个字符串。初始化也很丑陋。也许可以使用类似的递归方法。

不幸的是,索引方法

lambda l:[x for i,x in enumerate(l)if any(l[i-1:i+2])]

之所以无效,是因为它l[-1:2]解释-1为列表的末尾,而不是列表的开头。


10

Haskell,55 48字节

h x=[b|a:b:c:_<-scanr(:)[0]$0:x,any(/=0)[a,b,c]]

用法示例:h [0,0,0,8,0,1,0,0]-> [0,8,0,1,0]

scanr重新构建输入列表x0并在开头和结尾处添加其他内容。在每个步骤中,我们都会对3个元素进行模式匹配,如果至少有一个非零元素,则将中间的元素保留下来。

感谢@xnor通过从切换zip3到7个字节scanr


这样做会很不错h x=[snd t|t<-zip3(0:x)x$tail x++[0],(0,0,0)/=t],但是我想没有一种捷径可以真正获得3元组的第二个元素。
xnor

结果scan比a 更短使三元组消失zip3h x=[b|a:b:c:_<-scanr(:)[0]$0:x,any(/=0)[a,b,c]]
xnor

8

Matlab,29 27字节

输入必须包含一个1*n矩阵(如果n=0可能)。(这将为0*0矩阵引发错误。)

@(a)a(conv(a.*a,1:3,'s')>0) 

卷积是成功的关键。


's'代替'same'<-:-D
路易斯·门多

这个技巧在内置方法上确实可以使用很多次=)
更加糟糕的

我已经看到带有标志的技巧,即使对于非高尔夫问题也是如此'UniformOutpout'(可以理解)。但是我不知道这件事
路易斯·门多

1
您能~~a代替使用a.*a吗?
feersum

2
不幸的是,@ feersum Matlab拒绝卷积logical数组。对于不是用Matlab本身编写的内置程序,这通常是一个问题。否则逻辑数组的行为很像数字数组。它可能以Octave的方式工作,但我目前尚未安装。
瑕疵的

6

J,17 14字节

#~0<3+/\0,~0,|

在@ Zgarb的帮助下节省了3个字节

用法

   f =: #~0<3+/\0,~0,|
   f 2 0 4 _3 0 0 0 3 0 0 2 0 0
2 0 4 _3 0 0 3 0 0 2 0
   f ''

   f 0 0 0 8 0 1 0 0
0 8 0 1 0

说明

#~0<3+/\0,~0,|  Input: array A
             |  Get the absolute value of each in A
           0,   Prepend a 0
        0,~     Append a 0
    3  \        For each subarray of size 3, left to right
     +/           Reduce it using addition to find the sum
  0<            Test if each sum is greater than one
                (Converts positive values to one with zero remaining zero)
#~              Select the values from A using the previous as a mask and return

在这里尝试。


0<在地方工作0~:
Zgarb

@Zgarb处理后,大小为3的后缀可以是正数或负数。
2016年

啊,我忘了负值。
Zgarb '16

6

MATL,8字节

tg3:Z+g)

输出是一个数字,字符串之间用空格分隔。输出处的空数组不显示任何内容(甚至不显示换行符)。

在线尝试!验证所有测试用例

说明

代码将输入转换为逻辑类型,即非零条目变为true(或1),零条目变为false(或0)。然后将其与内核进行卷积[1 2 3]。非零值会在该位置及其相邻位置导致非零结果。转换为逻辑给出true了应保留的值,因此使用该索引编制输入将生成所需的输出。

t    % Input array implicitly. Duplicate
g    % Convert to logical: nonzero becomes true, zero becomes false
3:   % Push array [1 2 3]
Z+   % Convolution, keeping size of first input
g    % Convert to logical
)    % Index into original array. Implicitly display

5

Jolf,14个字节

现在我想到了,Jolf是高尔夫语言的Java。叹息 在这里尝试。

ψxd||H.nwS.nhS

说明

ψxd||H.nwS.nhS
ψxd             filter input over this function
   ||           or with three args
     H           the element
      .nwS       the previous element
          .nhS   or the next element

5

Python 3,55个字节

lambda s:[t[1]for t in zip([0]+s,s,s[1:]+[0])if any(t)]

1
哇。我不知道您是否在此之前看到@xnor答案,但是您有完全相同的代码,唯一的区别是lambda的名称。如果您确实使用了他的代码,请给他功劳,如果没有,那就太疯狂了!
西奥,

没有看任何人的代码。
RootTwo 2016年

3
@ T.Lukin提出相同的代码实际上并不少见。您可以在Anarchy Golf上看到这种情况,在该代码中,代码一直隐藏到最后期限,并且许多人都在同一个解决方案上汇聚,就像这样
xnor

4

果冻,9 个字节

0,0jo3\Tị

在线尝试!验证所有测试用例

怎么运行的

0,0jo3\Tị  Main link. Argument: A (array)

0,0        Yield [0, 0].
   j       Join, separating with A. This prepends and appends a 0 to A.
    o3\    Reduce each group of three adjacent integers by logical OR.
       T   Truth; get the indices of all truthy results.
        ị  At-index; retrieve the elements of A at those indices.

4

Perl,34 + 1(-p标志)= 35个字节

s/([^1-9]0 |^)\K0 ?(?=0|$)//&&redo

需要-p标志来运行。以数字列表作为输入。例如 :

perl -pe 's/([^1-9]0 |^)\K0 ?(?=0|$)//&&redo' <<< "0 0 0 8 0 1 0 0
0 0 0
-5 0 5"

5如果输入,我就知道了50 0
feersum'8

@feersum已修复,谢谢
Dada

4

Haskell,48个字节

p%(h:t)=[h|any(/=0)$p:h:take 1t]++h%t
p%e=e
(0%)

查看前一个元素p,第一个元素h和之后的元素(如果有),并且如果有非零元素,则在第一个元素前添加h

条件any(/=0)$p:h:take 1t是漫长的,特别是take 1t。我会寻找一种方法来缩短它,也许是通过模式匹配。


4

视网膜42 35 33字节

感谢Martin Ender提供7个字节。

(?<= ^ | \ b0)0(?= $ | 0)

 +

^ | $

最后一行是必需的。

一次验证所有测试用例。(稍作修改即可一次运行所有测试用例。)

看起来像是在其中完成此操作的理想语言...仍然被大多数答案所击败。


我只是放弃了I / O格式的括号。
Martin Ender

3

Mathematica,43个字节

ArrayFilter[If[#.#>0,#[[2]],Nothing]&,#,1]&

3

C,96字节

f()用指向整数列表的指针和指向列表大小的指针进行调用。列表和大小就地修改。

i,t,e,m;f(int*p,int*n){int*s=p;for(i=m=e=0;i++<*n;s+=t=m+*s||i<*n&&p[1],e+=t,m=*p++)*s=*p;*n=e;}

在ideone上尝试一下


K&R参数样式通常更短,但不是在这里- f(int*p,int*n)保存一个字节。或将其定义s为第三个参数(未传递。有点确定)。
ugoren '16

3

Brachylog44 38字节

,0gL:?:Lc:1fzbh.
~c[A:.:B],[0:0:0]'.l3

在线尝试!

这种语言可以很好地证明事物,这就是我们将要使用的语言。

谓词0(主谓词)

,0gL:?:Lc:1fzbh.
 0gL               [0] = L    (assignment works both ways)
   L:?:Lc          [L:input:L] = temp
         :1f       find all solutions of predicate 1 with temp as input
            zbh.   then transpose and take the middle row and assign to output

谓词1(辅助谓词)

~c[A:.:B],[0:0:0]'.l3
~c[A:.:B]                 input is in the form of [A:output:B]
         ,                and
          [0:0:0]'.       output is not [0:0:0]
                  .l3     and length of output is 3

2

带图像处理工具箱的Matlab,27字节

@(a)a(~imerode(~a,~~(1:3)))

这是一个匿名函数。

使用示例:

>> @(a)a(~imerode(~a,~~(1:3)))
ans = 
    @(a)a(~imerode(~a,~~(1:3)))
>> ans([0 0 0 8 0 1 0 0])
ans =
     0     8     0     1     0

1
我想到imerode过,但我的版本一直比我目前的一个更长的时间,好工作=)
flawr

2

Bash + GNU utils,25

grep -vC1 ^0|grep -v \\-$

接受输入作为以换行符分隔的列表。

Ideone-添加了测试驱动程序代码,可以通过以空格分隔和换行分隔来回转换所有测试用例。


2

切达 78字节

a->([[]]+a.map((e,i)->e|(i?a[i-1]:0)|(i-a.len+1?a[i+1]:0)?[e]:[])).reduce((+))

测试套件。

Cheddar没有过滤器,因此过滤是通过包装所需元素并将不想要的元素转换为空数组,然后将所有内容连接起来完成的。

例如,[0,0,0,8,0,1,0,0]变为[[],[],[0],[8],[0],[1],[0],[]],然后串联数组为[0,8,0,1,0]


.reduce((+))->.sum
Downgoat

@Downgoat你什么时候解决的?
Leaky Nun

哦,对不起,没关系。我以为您正在对数组求和。不加入阵列
Downgoat

1

APL,14个字节

{⍵/⍨×3∨/0,⍵,0}

测试:

      {⍵/⍨×3∨/0,⍵,0}2 0 4 ¯3 0 0 0 3 0 0 2 0 0
2 0 4 ¯3 0 0 3 0 0 2 0

说明:

  • 0,⍵,0:在the的开头和结尾加上零
  • ×3∨/:找到每组三个相邻数字的GCD符号(如果全为零,则为0,否则为1)。
  • ⍵/⍨:从select中选择所有结果为1的项目。

1

Ruby 2.x,63个字节

f=->(x){x.select.with_index{|y,i|x[i-1].to_i|y|x[i+1].to_i!=0}}

值得一提的是,这实质上是Neil出色的ES6答案的一部分。

这也是我第一次提交pcg。好极了。


1

Brain-Flak 142字节

在线尝试!

(<()>)(()){{}([]<([]){{}({}<>)<>({}<>)<>({}<>)<>(<>({}<>)<>({}<>)<>({})<>){{}((<()>))}{}{}([][()])}{}{}<>{}([]){{}({}<>)<>([])}{}<>>[[]])}{}{}

说明

(<()>)                    #Pad the top with an extra zero
(()){{}([]<...>[[]])}{}   #Until the stack height remains the same
 ([]){{}...([][()])}{}    #Until the stack height is one
  ({}<>)<>                #Move the top three to the other stack
  ({}<>)<>
  ({}<>)<>
  (...)                   #Push the sum of the top three
   <>({}<>)               #Move the second and third back
   <>({}<>)
   <>({})<>               #Leave the top of the stack
  {{}...}{}               #If the sum is not zero
   ((<()>))               #Add a buffer to the top of the stack
  {}                      #Pop the buffer/middle value
 {}                       #Remove extra zero
 <>                       #Switch to the off stack
 {}                       #Remove extra zero
 ([]){{}({}<>)<>([])}{}<> #Move the entire off stack back

链接为空。您可以粘贴代码和输入,按“保存”并使用出现的链接
Luis Mendo

@LuisMendo不幸的是,我不能使用tryitonline,所以我只是链接到URL。
小麦巫师

为什么不能使用Tryitonline?
DJMcMayhem

@DJMcMayhem我的浏览器中没有javascript。<s>我现在将修复它。</ 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.