# Keep nonzeros and their neighbours

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]

• Can I use _2 instead of -2? Quite a few languages use that format. Aug 9 '16 at 9:55
• Will we have -0? Aug 9 '16 at 9:57
• @LeakyNun 1 Yes 2 No Aug 9 '16 at 10:01
• Will numbers ever have leading zeros? Like [010 0 0 01 1]? Aug 9 '16 at 12:44
• @FryAmTheEggman Nope Aug 9 '16 at 14:32

## JavaScript (ES6), 35 bytes

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


Works on floats too for two extra bytes.

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

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. • 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.
– xnor
Aug 9 '16 at 1:22
• 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]]. – xnor Aug 9 '16 at 1:52 # 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. • 's' instead of 'same' <-- :-D Aug 8 '16 at 23:28 • That trick does work a lot of times with builtins=) Aug 8 '16 at 23:30 • I've seen that trick, even for non-golfing questions, with the flag 'UniformOutpout' (understandably). But I didn't know about this one Aug 8 '16 at 23:31 • Could you use ~~a instead of a.*a? Aug 9 '16 at 0:11 • @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. Aug 9 '16 at 8:39 # 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. • Would 0< work in place of 0~:? Aug 9 '16 at 5:43 • @Zgarb The infixes of size 3 can be either positive or negative after processed. Aug 9 '16 at 6:20 • Ah, I forgot about the negative values. Aug 9 '16 at 6:27 # 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). ### 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  # 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  # Python 3, 55 bytes lambda s:[t[1]for t in zip([0]+s,s,s[1:]+[0])if any(t)]  • 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! – Theo Aug 8 '16 at 23:39 • Did not look at anyone's code. Aug 8 '16 at 23:40 • @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. – xnor Aug 8 '16 at 23:44 # Jelly, 9 bytes 0,0jo3\Tị  ### 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.  ## 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"  • I get 5 if I input 50 0. Aug 9 '16 at 0:16 • @feersum fixed, thanks – Dada Aug 9 '16 at 1:48 ## 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. # Retina, 4235 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. • I'd just ditch the brackets from the I/O format. Aug 9 '16 at 11:54 # Mathematica, 43 bytes ArrayFilter[If[#.#>0,#[[2]],Nothing]&,#,1]&  # 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;}  • 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). Aug 9 '16 at 15:14 # 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  # 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  • I thought of imerode too, but my versions kept being longer than my current one, nice work=) Aug 9 '16 at 8:44 # 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.

# 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].

• .reduce((+)) -> .sum Aug 9 '16 at 18:42
• @Downgoat When did you fix that? Aug 9 '16 at 18:42
• oh, sorry nevermind. I thought you were summing the array. not joining the arrays Aug 9 '16 at 18:46

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

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

# 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

• The link is empty. You can paste code and input, press "save" and use the resulting link Aug 9 '16 at 16:52
• @LuisMendo Unfortunately I cannot use tryitonline so I just linked to the url. Aug 9 '16 at 16:54
• Why can't you access tryitonline? Aug 10 '16 at 21:43
• @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. Aug 10 '16 at 22:04