27
\$\begingroup\$

Taken from this question at Stack Overflow. Thanks also to @miles and @Dada for suggesting test inputs that address some corner cases.

The challenge

Given an array of integer values, remove all zeros that are not flanked by some nonzero value.

Equivalently, an entry should be kept either if it's a nonzero or if it's a zero that is immediately close to a nonzero value.

The entries that are kept should maintain in the output the order they had in the input.

Example

Given

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

the values that should be removed are marked with an x:

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

and so the output should be

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

Rules

The input array may be empty (and then the output should be empty too).

Input and output formats are flexible as usual: array, list, string, or anything that is reasonable.

Code golf, fewest best.

Test cases

[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]
\$\endgroup\$
9
  • \$\begingroup\$ Can I use _2 instead of -2? Quite a few languages use that format. \$\endgroup\$
    – Leaky Nun
    Commented Aug 9, 2016 at 9:55
  • \$\begingroup\$ Will we have -0? \$\endgroup\$
    – Leaky Nun
    Commented Aug 9, 2016 at 9:57
  • \$\begingroup\$ @LeakyNun 1 Yes 2 No \$\endgroup\$
    – Luis Mendo
    Commented Aug 9, 2016 at 10:01
  • \$\begingroup\$ Will numbers ever have leading zeros? Like [010 0 0 01 1]? \$\endgroup\$ Commented Aug 9, 2016 at 12:44
  • \$\begingroup\$ @FryAmTheEggman Nope \$\endgroup\$
    – Luis Mendo
    Commented Aug 9, 2016 at 14:32

21 Answers 21

16
\$\begingroup\$

JavaScript (ES6), 35 bytes

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

Works on floats too for two extra bytes.

\$\endgroup\$
10
\$\begingroup\$

Python, 50 bytes

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

A recursive function that takes a tuple. Includes the first element if there's a nonzero value among either the first two elements or the previous value stored from last time. Then, removes the first element and recurses. The previous element is stored in the singleton-list p, which automatically packs to list and starts as empty (thanks to Dennis for 3 bytes with this).


55 bytes:

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

Generates all length-3 chunks of the list, first putting zeroes on the start and end, and takes the middles elements of those that are not all zero.

An iterative approach turned out longer (58 bytes)

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

This doesn't exactly work because b,*l needs Python 3, but Python 3 input gives a string. The initialization is also ugly. Maybe a similar recursive approach would work.

Unfortunately, the indexing method of

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

doesn't work because l[-1:2] interprets -1 as the end of the list, not a point before its start.

\$\endgroup\$
0
10
\$\begingroup\$

Haskell, 55 48 bytes

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

Usage example: h [0,0,0,8,0,1,0,0] -> [0,8,0,1,0].

scanr rebuilds the input list x with an additional 0 at the start and end. In each step we pattern match 3 elements and keep the middle one if there's at least one non-zero element.

Thanks @xnor for 7 bytes by switching from zip3 to scanr.

\$\endgroup\$
2
  • \$\begingroup\$ It would be nice to just do h x=[snd t|t<-zip3(0:x)x$tail x++[0],(0,0,0)/=t], but I guess there's no short way to actually get the second-element of a 3-tuple. \$\endgroup\$
    – xnor
    Commented Aug 9, 2016 at 1:22
  • \$\begingroup\$ Turns out shorter to get the triples out of a scan than a zip3: h x=[b|a:b:c:_<-scanr(:)[0]$0:x,any(/=0)[a,b,c]]. \$\endgroup\$
    – xnor
    Commented Aug 9, 2016 at 1:52
8
\$\begingroup\$

Matlab, 29 27 bytes

The input must consist of a 1*n matrix (where n=0 is possible). (It will throw an error for 0*0 matrices.)

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

Convolution is the key to success.

\$\endgroup\$
7
  • \$\begingroup\$ 's' instead of 'same' <-- :-D \$\endgroup\$
    – Luis Mendo
    Commented Aug 8, 2016 at 23:28
  • \$\begingroup\$ That trick does work a lot of times with builtins=) \$\endgroup\$
    – flawr
    Commented Aug 8, 2016 at 23:30
  • \$\begingroup\$ I've seen that trick, even for non-golfing questions, with the flag 'UniformOutpout' (understandably). But I didn't know about this one \$\endgroup\$
    – Luis Mendo
    Commented Aug 8, 2016 at 23:31
  • 1
    \$\begingroup\$ Could you use ~~a instead of a.*a? \$\endgroup\$
    – feersum
    Commented Aug 9, 2016 at 0:11
  • 2
    \$\begingroup\$ @feersum Matlab unfortunately refuses to convolve logical arrays. This often is a problem for built-ins that are not written in Matlab itself. Otherwise logical arrays behave a lot like numberish ones. It might work in Octave thought, but I do not have it installed at the moment. \$\endgroup\$
    – flawr
    Commented Aug 9, 2016 at 8:39
7
\$\begingroup\$

MATL, 8 bytes

tg3:Z+g)

Output is a string with numbers separated by spaces. An empty array at the output is displayed as nothing (not even a newline).

Try it online! Or verify all test cases.

Explanation

The code converts the input to logical type, i.e. nonzero entries become true (or 1) and zero entries become false (or 0). This is then convolved with the kernel [1 2 3]. A nonzero value causes a nonzero result at that position and at its neighbouring positions. Converting to logical gives true for values that should be kept, so indexing the input with that produces the desired output.

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
\$\endgroup\$
6
\$\begingroup\$

J, 17 14 bytes

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

Saved 3 bytes with help from @Zgarb.

Usage

   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

Explanation

#~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

Try it here.

\$\endgroup\$
3
  • \$\begingroup\$ Would 0< work in place of 0~:? \$\endgroup\$
    – Zgarb
    Commented Aug 9, 2016 at 5:43
  • \$\begingroup\$ @Zgarb The infixes of size 3 can be either positive or negative after processed. \$\endgroup\$
    – miles
    Commented Aug 9, 2016 at 6:20
  • \$\begingroup\$ Ah, I forgot about the negative values. \$\endgroup\$
    – Zgarb
    Commented Aug 9, 2016 at 6:27
5
\$\begingroup\$

Jolf, 14 bytes

Now that I think of it, Jolf is the Java of golfing languages. sighs Try it here.

ψxd||H.nwS.nhS

Explanation

ψ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
\$\endgroup\$
5
\$\begingroup\$

Python 3, 55 bytes

lambda s:[t[1]for t in zip([0]+s,s,s[1:]+[0])if any(t)]
\$\endgroup\$
3
  • 1
    \$\begingroup\$ Wow. I don't know if you saw @xnor answer before this, but you have the exact same code, with the only difference being the name of the lambda. If you did use his code, give him credit, if not, what a crazy coincidence! \$\endgroup\$
    – Theo
    Commented Aug 8, 2016 at 23:39
  • \$\begingroup\$ Did not look at anyone's code. \$\endgroup\$
    – RootTwo
    Commented Aug 8, 2016 at 23:40
  • 3
    \$\begingroup\$ @T.Lukin It's actually not uncommon to come up with the same code. You can see this happen on Anarchy Golf, where code is hidden until the deadline, and multiple people converge on the same solution like this one. \$\endgroup\$
    – xnor
    Commented Aug 8, 2016 at 23:44
4
\$\begingroup\$

Jelly, 9 bytes

0,0jo3\Tị

Try it online! or verify all test cases.

How it works

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.
\$\endgroup\$
4
\$\begingroup\$

Perl, 34 + 1 (-p flag) = 35 bytes

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

Needs -p flag to run. Takes a list of number as imput. For instance :

perl -pe 's/([^1-9]0 |^)\K0 ?(?=0|$)//&&redo' <<< "0 0 0 8 0 1 0 0
0 0 0
-5 0 5"
\$\endgroup\$
2
  • \$\begingroup\$ I get 5 if I input 50 0. \$\endgroup\$
    – feersum
    Commented Aug 9, 2016 at 0:16
  • \$\begingroup\$ @feersum fixed, thanks \$\endgroup\$
    – Dada
    Commented Aug 9, 2016 at 1:48
4
\$\begingroup\$

Haskell, 48 bytes

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

Looks at the previous element p, the first element h, and the element after (if any), and if any are nonzero, prepends the first element h.

The condition any(/=0)$p:h:take 1t is lengthy, in particular the take 1t. I'll look for a way to shorten it, perhaps by pattern matching.

\$\endgroup\$
4
\$\begingroup\$

Retina, 42 35 33 bytes

7 bytes thanks to Martin Ender.

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

 +

^ | $

The last line is necessary.

Verify all testcases at once. (Slightly modified to run all testcases at once.)

Looks like the perfect language to do this in... still got defeated by most of the answers.

\$\endgroup\$
1
  • \$\begingroup\$ I'd just ditch the brackets from the I/O format. \$\endgroup\$ Commented Aug 9, 2016 at 11:54
3
\$\begingroup\$

Mathematica, 43 bytes

ArrayFilter[If[#.#>0,#[[2]],Nothing]&,#,1]&
\$\endgroup\$
3
\$\begingroup\$

C, 96 bytes

Call f() with a pointer to the list of integers, and a pointer to the size of the list. The list and size are modified in-place.

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;}

Try it on ideone.

\$\endgroup\$
1
  • \$\begingroup\$ K&R parameter style is often shorter, but not here - f(int*p,int*n) saves a byte. Or define s as a 3rd parameter (that's not passed. it''s kind-of OK). \$\endgroup\$
    – ugoren
    Commented Aug 9, 2016 at 15:14
3
\$\begingroup\$

Brachylog, 44 38 bytes

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

Try it online!

This language is good as proving things, which is what we will use.

Predicate 0 (main predicate)

,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

Predicate 1 (auxiliary predicate)

~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
\$\endgroup\$
2
\$\begingroup\$

Matlab with Image Processing Toolbox, 27 bytes

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

This is an anonymous function.

Example use:

>> @(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
\$\endgroup\$
1
  • 1
    \$\begingroup\$ I thought of imerode too, but my versions kept being longer than my current one, nice work=) \$\endgroup\$
    – flawr
    Commented Aug 9, 2016 at 8:44
2
\$\begingroup\$

Bash + GNU utils, 25

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

Accepts input as a newline-separated list.

Ideone - with test driver code added to run all testcases together by converting to/from space-separated and newline-separated.

\$\endgroup\$
2
\$\begingroup\$

Cheddar, 78 bytes

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

Test suite.

Cheddar has no filter, so filtering is done by wrapping the elements we want and transforming the elements we don't want into empty arrays, and then concatenate everything.

For example, [0,0,0,8,0,1,0,0] becomes [[],[],[0],[8],[0],[1],[0],[]], and then the concatenated array would be [0,8,0,1,0].

\$\endgroup\$
3
  • \$\begingroup\$ .reduce((+)) -> .sum \$\endgroup\$
    – Downgoat
    Commented Aug 9, 2016 at 18:42
  • \$\begingroup\$ @Downgoat When did you fix that? \$\endgroup\$
    – Leaky Nun
    Commented Aug 9, 2016 at 18:42
  • \$\begingroup\$ oh, sorry nevermind. I thought you were summing the array. not joining the arrays \$\endgroup\$
    – Downgoat
    Commented Aug 9, 2016 at 18:46
1
\$\begingroup\$

APL, 14 bytes

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

Test:

      {⍵/⍨×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

Explanation:

  • 0,⍵,0: add a zero to the beginning and the end of ⍵
  • ×3∨/: find the sign of the GCD of every group of three adjacent numbers (this will be 0 if they are all zero and 1 otherwise).
  • ⍵/⍨: select all the items from ⍵ for which the result was 1.
\$\endgroup\$
1
\$\begingroup\$

Ruby 2.x, 63 bytes

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

Credit where it is due, this is essentially a port of Neil's superior ES6 answer.

It's also my first pcg submission. yay.

\$\endgroup\$
1
\$\begingroup\$

Brain-Flak 142 bytes

Try it online!

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

Explanation

(<()>)                    #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
\$\endgroup\$
4
  • \$\begingroup\$ The link is empty. You can paste code and input, press "save" and use the resulting link \$\endgroup\$
    – Luis Mendo
    Commented Aug 9, 2016 at 16:52
  • \$\begingroup\$ @LuisMendo Unfortunately I cannot use tryitonline so I just linked to the url. \$\endgroup\$
    – Wheat Wizard
    Commented Aug 9, 2016 at 16:54
  • \$\begingroup\$ Why can't you access tryitonline? \$\endgroup\$
    – DJMcMayhem
    Commented Aug 10, 2016 at 21:43
  • \$\begingroup\$ @DJMcMayhem I did not have javascript in my browser. <s>I will fix it now.</s> I see you have already done that thank you. \$\endgroup\$
    – Wheat Wizard
    Commented Aug 10, 2016 at 22:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.