26
\$\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\$
  • \$\begingroup\$ Can I use _2 instead of -2? Quite a few languages use that format. \$\endgroup\$ – Leaky Nun Aug 9 '16 at 9:55
  • \$\begingroup\$ Will we have -0? \$\endgroup\$ – Leaky Nun Aug 9 '16 at 9:57
  • \$\begingroup\$ @LeakyNun 1 Yes 2 No \$\endgroup\$ – Luis Mendo Aug 9 '16 at 10:01
  • \$\begingroup\$ Will numbers ever have leading zeros? Like [010 0 0 01 1]? \$\endgroup\$ – FryAmTheEggman Aug 9 '16 at 12:44
  • \$\begingroup\$ @FryAmTheEggman Nope \$\endgroup\$ – Luis Mendo Aug 9 '16 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\$
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\$
  • \$\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 Aug 9 '16 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 Aug 9 '16 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\$
  • \$\begingroup\$ 's' instead of 'same' <-- :-D \$\endgroup\$ – Luis Mendo Aug 8 '16 at 23:28
  • \$\begingroup\$ That trick does work a lot of times with builtins=) \$\endgroup\$ – flawr Aug 8 '16 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 Aug 8 '16 at 23:31
  • 1
    \$\begingroup\$ Could you use ~~a instead of a.*a? \$\endgroup\$ – feersum Aug 9 '16 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 Aug 9 '16 at 8:39
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\$
  • \$\begingroup\$ Would 0< work in place of 0~:? \$\endgroup\$ – Zgarb Aug 9 '16 at 5:43
  • \$\begingroup\$ @Zgarb The infixes of size 3 can be either positive or negative after processed. \$\endgroup\$ – miles Aug 9 '16 at 6:20
  • \$\begingroup\$ Ah, I forgot about the negative values. \$\endgroup\$ – Zgarb Aug 9 '16 at 6:27
6
\$\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\$
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\$
  • 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 Aug 8 '16 at 23:39
  • \$\begingroup\$ Did not look at anyone's code. \$\endgroup\$ – RootTwo Aug 8 '16 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 Aug 8 '16 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\$
  • \$\begingroup\$ I get 5 if I input 50 0. \$\endgroup\$ – feersum Aug 9 '16 at 0:16
  • \$\begingroup\$ @feersum fixed, thanks \$\endgroup\$ – Dada Aug 9 '16 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\$
  • \$\begingroup\$ I'd just ditch the brackets from the I/O format. \$\endgroup\$ – Martin Ender Aug 9 '16 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\$
  • \$\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 Aug 9 '16 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
    \$\begingroup\$ I thought of imerode too, but my versions kept being longer than my current one, nice work=) \$\endgroup\$ – flawr Aug 9 '16 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\$
  • \$\begingroup\$ .reduce((+)) -> .sum \$\endgroup\$ – Downgoat Aug 9 '16 at 18:42
  • \$\begingroup\$ @Downgoat When did you fix that? \$\endgroup\$ – Leaky Nun Aug 9 '16 at 18:42
  • \$\begingroup\$ oh, sorry nevermind. I thought you were summing the array. not joining the arrays \$\endgroup\$ – Downgoat Aug 9 '16 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\$
  • \$\begingroup\$ The link is empty. You can paste code and input, press "save" and use the resulting link \$\endgroup\$ – Luis Mendo Aug 9 '16 at 16:52
  • \$\begingroup\$ @LuisMendo Unfortunately I cannot use tryitonline so I just linked to the url. \$\endgroup\$ – Sriotchilism O'Zaic Aug 9 '16 at 16:54
  • \$\begingroup\$ Why can't you access tryitonline? \$\endgroup\$ – DJMcMayhem Aug 10 '16 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\$ – Sriotchilism O'Zaic Aug 10 '16 at 22:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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