43
\$\begingroup\$

I can't believe we don't have this already.. It's one of the most important data-structures in programming, yet still simple enough to implement it in a :

Challenge

Your task is to implement a stack that allows pushing and popping numbers, to test your implementation and keep I/O simple we'll use the following setup:

  • Input will be a list of non-negative integers

Every positive integer \$n\$ indicates a \$\texttt{push(}n\texttt{)}\$ and every \$0\$ indicates a \$\texttt{pop()}\$ - discarding the top element.

  • Output will be the resulting stack

Example

For example if we're given \$[12,3,0,101,11,1,0,0,14,0,28]\$:

$$ \begin{aligned} & 12 & [12] \\ & 3 & [3,12] \\ & 0 & [12] \\ & 101 & [101,12] \\ & 11 & [11,101,12] \\ & 1 & [1,11,101,12] \\ & 0 & [11,101,12] \\ & 0 & [101,12] \\ & 14 & [14,101,12] \\ & 0 & [101,12] \\ & 28 & [28,101,12] \end{aligned} $$

Output will be: \$[28,101,12]\$

Rules

  • Input will be a list of non-negative integers in any default I/O format
    • you may use a negative integer to signify the end of a stream of integers
  • Output will be a list/matrix/.. of the resulting stack
    • your choice where the top element will be (at the beginning or end), the output just has to be consistent
    • output is flexible (eg. integers separated by new-lines would be fine), the only thing that matters is the order
    • you may use a negative integer to signify the bottom of the stack
  • You're guaranteed that there will never be a \$0\$ when the stack is empty

Examples

[] -> []
[1] -> [1]
[1,0,2] -> [2]
[4,0,1,12] -> [12,1]
[8,3,1,2,3] -> [3,2,1,3,8]
[1,3,7,0,0,0] -> []
[13,0,13,10,1,0,1005,5,0,0,0] -> [13]
[12,3,0,101,11,1,0,0,14,0,28] -> [28,101,12]
\$\endgroup\$
  • 11
    \$\begingroup\$ It should be noted that, given the conditions, one does not actually need to implement the stack. \$\endgroup\$ – Jeff Zeitlin Jul 27 '18 at 11:35
  • \$\begingroup\$ If you wanted someone to actually implement a stack, you might need to try putting something in the Sandbox. \$\endgroup\$ – mbomb007 Jul 27 '18 at 16:33
  • \$\begingroup\$ @mbomb007: Either is allowed: "your choice where the top element will be (at the beginning or end)" \$\endgroup\$ – BMO Jul 27 '18 at 16:49
  • \$\begingroup\$ @mbomb007: It wouldn't be any more difficult if you had to reverse the input, would it? Besides, if you consider the setup as a stack who defines what's the top and what's the bottom and why should one definition be less arbitrary? \$\endgroup\$ – BMO Jul 27 '18 at 16:57
  • \$\begingroup\$ @OMᗺ Because the input looks quite a bit like a stack/list/array. Now, the entire challenge is basically remove any number followed by a zero. \$\endgroup\$ – mbomb007 Jul 27 '18 at 18:10

76 Answers 76

18
\$\begingroup\$

MATL, 6 bytes

"@?@}x

Input is a row vector of numbers.

The final stack is shown upside down, with the most recent element below.

Try it online! Or verify all test cases.

Explanation

"         % For each element in the input (implicit)
  @       %   Push current element
  ?       %   If non-zero (this consumes the current element)
    @     %     Push current element again
  }       %   Else
    x     %     Delete most recent element
          %   End (implicit)
          % End (implicit)
          % Display (implicit)
\$\endgroup\$
13
\$\begingroup\$

Java (JDK 10), 42 bytes

Since "[the] output is flexible [...], the only thing that matters is the order", this changes the input array into a 0-terminated array. Example : [1,0,2] will return [2,0,2] which is to be interpreted as [2,0,2] = [2].

a->{int s=0;for(int v:a)a[v>0?s++:--s]=v;}

Try it online!

Previous versions:

Java (JDK 10), 60 bytes

l->{for(int i;(i=l.indexOf(0))>0;l.remove(i))l.remove(--i);}

Try it online!

Credits:

If I can end the program with errors: 55 bytes

(though everything is properly modified)

l->{for(int i;;l.remove(--i))l.remove(i=l.indexOf(0));}

Try it online!

\$\endgroup\$
  • 4
    \$\begingroup\$ This is rather impressive. You can lose 1 byte by using >0 since there will never be a zero at the start of the list (that would imply the top of the stack was at -1). \$\endgroup\$ – O.O.Balance Jul 28 '18 at 1:07
  • \$\begingroup\$ @O.O.Balance Indeed, I hadn't thought about that., thanks! \$\endgroup\$ – Olivier Grégoire Jul 28 '18 at 7:31
12
\$\begingroup\$

Sed, 17 Bytes

:;s/[0-9]\+,0//;t

-3 bytes thanks to @OMᗺ, -1 thanks to @eggyal

Because you're guaranteed to never pop an empty list, you don't need anything more than an iterated finite state machine. Regular expressions are a tool for building finite state machines, and sed can iterate. It's a match made in heaven.

Takes input from stdin, like so:

echo '[12,3,0,101,11,1,0,0,14,0,28]' | sed ':;s/[0-9]\+,0,//;t'

Outputs the stack in reverse:

[12,101,28]

Could be smaller by two bytes if my local sed inherently understood character classes like \d, but it doesn't for some reason.

\$\endgroup\$
  • 1
    \$\begingroup\$ Welcome to PPCG! Nice, mine was longer (using different input format).. Btw. you can use an empty label since you only use 1 and since you iterate the process the g is redundant - saving you 4 bytes: Try it online! \$\endgroup\$ – BMO Jul 27 '18 at 15:36
  • \$\begingroup\$ The g isn't redundant! It makes the worst case runtime complexity depend on the depth of sequential pops, instead of the number of pops! Not that efficiency matters in code golf :) \$\endgroup\$ – Tacroy Jul 27 '18 at 15:43
  • 1
    \$\begingroup\$ Your last sentence answers the question about redundancy :P Btw. how did you count the bytes? I get 18, probably you included a new-line at the end or something. \$\endgroup\$ – BMO Jul 27 '18 at 16:06
  • \$\begingroup\$ Yup, it was a newline. \$\endgroup\$ – Tacroy Jul 27 '18 at 16:20
  • 1
    \$\begingroup\$ If the final element of the input is a 0 then it won’t get matched by your regex. \$\endgroup\$ – eggyal Jul 28 '18 at 4:38
11
\$\begingroup\$

C (gcc), 62 60 56 55 bytes

-2 -6 bytes thanks to l4m2

-1 byte thanks to ceilingcat.

Uses the permitted notion of -1 terminated arrays. f() calls itself recursively, until fully wound, and then backtracks through the list. r keeps track of how many numbers to discard before printing something. Increases if current item is 0, decreases otherwise. If 0, we need not discard, and can print the number.

r;f(int*l){~*l?f(l+1),*l?r?r--:printf("%d ",*l):r++:0;}

Try it online!

\$\endgroup\$
  • \$\begingroup\$ f(l)int*l; => f(int*l)? \$\endgroup\$ – l4m2 Jul 28 '18 at 12:39
  • \$\begingroup\$ @l4m2 Ah, cheers! Probably a remnant from earlier, more variable-laden days. \$\endgroup\$ – gastropner Jul 28 '18 at 13:10
  • \$\begingroup\$ the r=0 seems useless \$\endgroup\$ – l4m2 Jul 28 '18 at 15:52
  • \$\begingroup\$ @l4m2 Aye, good catch. \$\endgroup\$ – gastropner Jul 28 '18 at 16:11
11
\$\begingroup\$

PowerShell, 46 41 40 bytes

$args|%{$x,$a=&({1,$_+$a},{$a})[!$_]};$a

Try it online!

Takes input via splatting, e.g., $z=@(12,3,0,101,11,1,0,0,14,0,28); .\implement-stack.ps1 @z, which on TIO manifests as separate arguments.

$args|%{$x,$a=&({1,$_+$a},{$a})[!$_]};$a    # Full program
$args                                       # Take input via splatting
     |%{                            };      # Loop through each item
              &(              )[!$_]        # Pseudo-ternary, if input is 0 this is 1
        $x,$a=            {$a}              # ... which will pop the first item into $x
           $a=  { ,$_+$a}                   # Else, we append the first item
        $x   =   1                          # ... and drop a dummy value into $x
                                      $a    # Leave $a on pipeline; implicit output

-5 bytes thanks to mazzy.
-1 byte swapping $_ to 1

\$\endgroup\$
  • \$\begingroup\$ Does a splatting save 3 bytes on $agrs? :) \$\endgroup\$ – mazzy Jul 27 '18 at 17:21
  • \$\begingroup\$ -2 bytes $args|%{$x,$a=&({$_,$_+$a},{$a})[!$_]};$a? \$\endgroup\$ – mazzy Jul 27 '18 at 17:48
  • 1
    \$\begingroup\$ @mazzy Yes, and we had just talked about splatting! I forgot already! lol Thanks! \$\endgroup\$ – AdmBorkBork Jul 27 '18 at 19:22
  • \$\begingroup\$ Wouldn't splatting be .\implement-stack.ps1 @z (not $z), otherwise you're just passing an array as the first/only argument \$\endgroup\$ – pinkfloydx33 Jul 31 '18 at 22:23
  • \$\begingroup\$ @pinkfloydx33 Yep. Typo on my part. \$\endgroup\$ – AdmBorkBork Aug 1 '18 at 12:27
10
\$\begingroup\$

Haskell, 28 bytes

foldl(#)[]
(_:s)#0=s
s#n=n:s

Try it online!

\$\endgroup\$
  • \$\begingroup\$ How main function is named? I don't know, how to run it) \$\endgroup\$ – Евгений Новиков Aug 11 '18 at 17:12
  • \$\begingroup\$ @ЕвгенийНовиков: see the "try it online" link for an example of how to run the code. \$\endgroup\$ – nimi Aug 11 '18 at 23:26
10
\$\begingroup\$

R, 45 bytes

o={};for(e in scan())o="if"(e,c(e,o),o[-1]);o

Try it online!

  • -4 byte thanks to @Giuseppe
\$\endgroup\$
  • 1
    \$\begingroup\$ 48 bytes -- abusing F will also get you to 48 bytes but this is cleaner imho \$\endgroup\$ – Giuseppe Jul 27 '18 at 14:33
  • \$\begingroup\$ I don't know how I missed the if-else inversion :facepalm: ... thanks ! \$\endgroup\$ – digEmAll Jul 27 '18 at 16:46
  • \$\begingroup\$ 45 bytes \$\endgroup\$ – Giuseppe Aug 1 '18 at 14:55
  • 1
    \$\begingroup\$ A R+pryr and Reduce solution is 44 bytes \$\endgroup\$ – JayCe Aug 10 '18 at 18:51
  • \$\begingroup\$ @JayCe: to be honest, I prefer to keep it a "base-R" solution... but feel free to post it as your own answer ! ;) \$\endgroup\$ – digEmAll Aug 10 '18 at 20:40
9
\$\begingroup\$

Python 2, 59 57 51 bytes

s=[]
for x in input():s=(s+[x],s[:-1])[x<1]
print s

Try it online!

\$\endgroup\$
9
\$\begingroup\$

Jelly, 6 bytes

ṣ0Ṗ;¥/

Try it online!

How it works

ṣ0Ṗ;¥/  Main link. Argument: A (array)

ṣ0      Split A at zeroes.
    ¥/  Left-reduce the resulting 2D array by this dyadic chain:
  Ṗ       Pop; discard the last element of the left argument.
   ;      Concatenate the result with the right argument.
\$\endgroup\$
  • \$\begingroup\$ Will this emulate three pops if there are three consecutive zeros? \$\endgroup\$ – WGroleau Jul 28 '18 at 5:29
  • \$\begingroup\$ Yes. [1,3,7,0,0,0], e.g., gets split into [[1,3,7],[],[],[]], and each step of the left-reduce pops on element of the left array. \$\endgroup\$ – Dennis Jul 28 '18 at 15:44
9
\$\begingroup\$

Brain-Flak, 40 36 bytes

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

Try it online!

Thanks to @Nitrodon for -4 bytes.

Since Brain-Flak already uses stacks, this is a good puzzle for Brain-Flak.

([]){   while items on stack
    {}      pop stack count
    {       if top element is non-zero
        ({}<>)<> push it on the other stack
    }
    if we're here the stack is either empty or there's a 0 on the stack

    ([])    so, count the stack again
    {{}<>{}<>} if there are items left on the stack, pop the stack count and the last item of the other stack
    {} pop the zero or the stack count
    ([]) count the stack again for next round
}
<>  go to the output stack
\$\endgroup\$
  • 2
    \$\begingroup\$ In this particular case, {{}<>{}<>} can be shortened to {{}<>}. \$\endgroup\$ – Nitrodon Jul 27 '18 at 19:46
  • \$\begingroup\$ @Nitrodon Thank you. Can you explain, why this still works? It doesn't switch back to the input stack in the loop. \$\endgroup\$ – Dorian Jul 28 '18 at 17:09
  • 1
    \$\begingroup\$ The top of the output stack is guaranteed to be nonzero, so the shortened loop executes either 0 or 2 times. \$\endgroup\$ – Nitrodon Jul 29 '18 at 18:39
8
\$\begingroup\$

Python 2, 48 bytes

s=[]
for x in input():s=([x]+s)[2*0**x:]
print s

Try it online!

\$\endgroup\$
  • \$\begingroup\$ Any chance you can explain how this works? I have been trying to work it out for the last half hour! Surely 2*0**x is always going to be 0. I'm obviously missing something. \$\endgroup\$ – ElPedro Jul 28 '18 at 22:12
  • 1
    \$\begingroup\$ @ElPedro It's not zero when x=0, in which case it's 2. \$\endgroup\$ – xnor Jul 28 '18 at 22:20
  • \$\begingroup\$ Ah, I see what you mean. Guess I was looking too hard and missing the obvious! Thanks and great answer. \$\endgroup\$ – ElPedro Jul 28 '18 at 22:25
7
\$\begingroup\$

Whitespace, 89 bytes

[N
S S N
_Create_Label_LOOP_1][S S S N
_Push_0][S N
S _Duplicate_0][T   N
T   T   _Read_STDIN_as_integer][T   T   T   _Retrieve][S N
S _Duplicate_input][N
T   T   S 
_If_neg_Jump_to_Label_EXIT][S N
S _Duplicate_input][N
T   S T N
_If_0_Jump_to_Label_DROP][N
S N
N
_Jump_to_Label_LOOP_1][N
S S S N
_Create_Label_EXIT][S N
N
_Discard_top][N
S S S S N
_Create_Label_LOOP_2][T N
S T _Print_as_integer][S S S T  S T S N
_Push_10_newline][T N
S S _Print_as_character][N
S T S S N
_Jump_to_Label_LOOP_2][N
S S T   N
_Create_Label_DROP][S N
N
_Discard_top][S N
N
_Discard_top][N
S N
N
_Jump_to_Label_LOOP_1]

Letters S (space), T (tab), and N (new-line) added as highlighting only.
[..._some_action] added as explanation only.

Takes the input-list new-line separated with -1 to indicate we're done with the inputs.

Try it online.

Explanation in pseudo-code:

Start LOOP_1:
  Integer i = STDIN as integer
  If(i is negative):
    Call function EXIT
  If(i is 0):
    Call function DROP
  Go to next iteration of LOOP_1

function EXIT:
  Start LOOP_2:
    Pop and print top as integer
    Print newline
    Go to next iteration of LOOP_2

function DROP:
  Drop the top of the stack
  Go to next iteration of LOOP_1
\$\endgroup\$
7
\$\begingroup\$

Wolfram Language (Mathematica), 28 bytes

#//.{a___,b_,0,c___}:>{a,c}&

Try it online!

\$\endgroup\$
  • \$\begingroup\$ (this only works because "The default is to have earlier patterns match shortest sequences", so there is no need to ensure that b is nonzero.) \$\endgroup\$ – user202729 Jul 27 '18 at 13:23
  • \$\begingroup\$ @user202729 Yep. Mathematica's pattern-matching is non-greedy, so it tries to match the shortest possible a___ first. One can see that by trying ReplaceList[#, {a___, b_, 0, c___} :> {a, c}] &. On a related note, StringReplace is actually greedy, so this submission wouldn't work with StringReplace (with pattern like a___~~b_~~"0"~~c___) \$\endgroup\$ – JungHwan Min Jul 27 '18 at 13:26
7
\$\begingroup\$

Python 2, 60 59 57 56 bytes

l=input()
while 0in l:i=l.index(0);l[i-1:i+1]=[]
print l

Try it online!


Saved:

  • -1 byte, thanks to pushkin
\$\endgroup\$
  • \$\begingroup\$ You can save a byte by removing the space between 0 and in \$\endgroup\$ – pushkin Jul 27 '18 at 17:48
  • 2
    \$\begingroup\$ Congrats on the 10K \$\endgroup\$ – ElPedro Jul 28 '18 at 9:10
6
\$\begingroup\$

JavaScript, 40 bytes

Outputs in reverse order.

a=>a.map(x=>x?o.push(x):o.pop(),o=[])&&o

Try it online

1 byte saved thanks to Herman L.

\$\endgroup\$
  • \$\begingroup\$ a=>a.map(x=>x?o.push(x):o.pop(),o=[])&&o is one byte shorter \$\endgroup\$ – Herman L Jul 27 '18 at 12:27
  • \$\begingroup\$ @HermanL: D'oh! Of course it is! Thanks. Was using (un)shift before I spotted output could be reversed. \$\endgroup\$ – Shaggy Jul 27 '18 at 12:40
  • \$\begingroup\$ This works because o is referenced in the callback after it's defined in the second argument. \$\endgroup\$ – MattH Jul 27 '18 at 13:48
6
\$\begingroup\$

05AB1E, 9 bytes

vy>i¨ëy)˜

Try it online or verify all test cases.

Explanation:

v        # For-each of the items in the input-list:
 y>i     #  If the current item is 0:
  ¨      #   Pop the top item of the list
 ë       #  Else:
  y      #   Push the current item to the stack
   )     #   Wrap the entire stack into a list
         #    i.e. 12 → [12]
         #    i.e. [12] and 3 → [[12], 3]
    ˜    #   Flatten the stack
         #    i.e. [[12], 3] → [12, 3]
         # (and output the list implicitly after the loop)

9 bytes alternative:

vy_i\ëy])

Try it online of verify all test cases.

Explanation:

v        # For-each of the items in the input-list:
 y_i     #  If the current item is 0:
  \      #   Discard top item of the stack
 ë       #  Else:
  y      #   Push the current item to the stack
]        # Close both the if-else and for-each (short for `}}`)
 )       # Wrap the entire stack into a list (and output implicitly)

PS: If the output should have been reversed to match the test cases in the challenge description, we can add a trailing R to the second version (so 10 bytes), which reverses the list. Try it online or verify all test cases.

\$\endgroup\$
5
\$\begingroup\$

Retina 0.8.2, 18 bytes

^
,
+1`,\d+,0

^,

Try it online! Link includes test cases. Explanation:

^
,

Prefix an extra ,.

+1`,\d+,0

Process all pop operations.

^,

Remove the , if it's still there.

Reversing the numbers would cost an extra 8 bytes:

O^$`\d+
\$\endgroup\$
  • \$\begingroup\$ Which simply replaces all <number>, 0 sublist by nothing. \$\endgroup\$ – user202729 Jul 27 '18 at 12:53
5
\$\begingroup\$

Ruby, 36 bytes

->a{b=[];a.map{|x|x>0?b<<x:b.pop};b}

Try it online!

Anonymous lambda. Outputs in reverse order.

\$\endgroup\$
5
\$\begingroup\$

Brain-Flak, 36 bytes

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

Try it online!

#Let's call the two stacks in and out

([]){{}                      ([])}    # while not in.empty()
       {        (  )}{}               # if in.peek() != 0
        (({}<>)) <>                   # a = in.pop; out.push(a); out.push(a)
                       <>{}<>         # out.pop()
                                  <>  # switch to out to be printed
\$\endgroup\$
5
\$\begingroup\$

Brain-Flak, 32 bytes

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

Try it online!

Uses -1 to signify the end of the array (but any number will do really).

\$\endgroup\$
5
\$\begingroup\$

V, 10 bytes

ò/ 0⏎b2dw0

Try it online!

Explanation

ò           " run the following, until an error occurs
 / 0⏎       " | goto next zero with space in front (errors if none)
     b      " | jump one word back (to the beginning of element to pop)
      2     " | twice (element & zero itself)
       dw   " | | delete word
         0  " | goto beginning of line

Equivalent in Vim, 16 bytes

qq/ 0⏎b2dw0@qq@q

Try it online!

Explanation

Pretty much the same, except recording a macro q and recursively call it:

qq                " record macro q
  / 0⏎b2dw0       " same as in V
           @q     " recursively call q (aborts on error)
             q    " quit recording
              @q  " execute the macro q
\$\endgroup\$
5
\$\begingroup\$

Java 10, 75 72 bytes

n->{var s="";for(int i:n)s=(s+","+i).replaceAll(",\\d+,0","");return s;}

Outputs separated by a comma. Top of the stack is last. Try it online here.

Thanks to Olivier Grégoire for golfing 2 bytes.

Please check out Kevin Cruijssen's and Olivier Grégoire's Java answers as well. They take a list-based approach instead, with the latter beating mine by a tidy margin.

Ungolfed:

n -> { // lambda taking an integer array as argument and returning a String
    var s = ""; // we'll be using a String to implement and output the stack
    for(int i : n) // loop through the array
        s = (s + "," + i) // append the next number
               .replaceAll(",\\d+,0", ""); // remove any number followed by a zero
    return s; // output the resulting stack
}
\$\endgroup\$
  • \$\begingroup\$ Nice approach with Strings. Better than my naive approach with an actual Stack-object. +1 from me. \$\endgroup\$ – Kevin Cruijssen Jul 27 '18 at 13:20
  • 1
    \$\begingroup\$ n->{var s="";for(int i:n)s=(s+","+i).replaceAll(",\\d+,0$","");return s;} (73 bytes), but puts the , before numbers, not after. \$\endgroup\$ – Olivier Grégoire Jul 28 '18 at 0:19
  • 1
    \$\begingroup\$ n->{var s=""+n;for(int x:n)s=s.replaceFirst("\\d+, 0,? ?","");return s;} (72 bytes), uses a list rather than an array and messes with the output because it can return things like "[, 2]" \$\endgroup\$ – Olivier Grégoire Jul 28 '18 at 0:35
  • \$\begingroup\$ @OlivierGrégoire Nice. We can drop the $ to save an additional byte, since each 0 we add is removed right away. \$\endgroup\$ – O.O.Balance Jul 28 '18 at 0:41
  • \$\begingroup\$ @OlivierGrégoire Your second approach is interesting as well, but I think the inconsistent output format may invalidate the solution. \$\endgroup\$ – O.O.Balance Jul 28 '18 at 1:00
5
\$\begingroup\$

GolfScript, 14 12 bytes

~{.{;}if}/]`

Try it online!

~{.{;}if}/]` Full program, implicit input
~            Eval input
 {      }/   Foreach:
      if       If the value is truthy (!= 0):
  .              Push itself
   {;}         Else: pop the top value
          ]` Push as array representation
             Implicit output
\$\endgroup\$
5
\$\begingroup\$

Perl 5 -p, 17 bytes

Thanks @sundar and @DomHastings

s/\d+ 0 ?//&&redo

Try it online!

\$\endgroup\$
  • 1
    \$\begingroup\$ -2 bytes (with slightly mankier output): Try it online! \$\endgroup\$ – sundar Jul 27 '18 at 22:29
  • \$\begingroup\$ Further to @sundar's comment, another slight simplification: Try it online! \$\endgroup\$ – Dom Hastings Jul 28 '18 at 7:08
  • \$\begingroup\$ Doesn't that fail if there's a number like 0942 input? \$\endgroup\$ – Xcali Jul 29 '18 at 3:28
  • 1
    \$\begingroup\$ You can safely assume there will not be any leading zeros. \$\endgroup\$ – O.O.Balance Jul 29 '18 at 9:11
5
\$\begingroup\$

><>, 25 bytes

i:?\~~
(0:/:^?
!?l:!<oan;

Try it online! (input must be written in ascii. otherwise use this one)

How it works

i:?\~~ checks for 0, continues to ~~ to delete previous entry. otherwise go down to:

(0:/:^? which checks for -1 (no more input), then wrap up to delete -1 and loop:

!?l:!<oan; which outputs each number with a newline, then ends when stack emptied

\$\endgroup\$
5
\$\begingroup\$

Husk, 6 bytes

Since there's no Husk answer already and it's my favourite golfing-lang:

F`?:tø

Try it online!

Explanation

F`?:tø  --
F    ø  -- foldl (reduce) with [] as the initial accumulator
 `      -- | flip arguments of
  ?:    -- | | if truthy: apply cons (prepend) to it
    t   -- | | else: return tail
        -- | : returns a function, either prepending the element or dropping 1 element

Alternative solution, 6 bytes

Instead of flipping, we can also just reverse the list and then use a right-fold: Ḟ?:tø↔

\$\endgroup\$
5
\$\begingroup\$

Brachylog, 21 bytes

~c₃Ckt[İ,0]≠∧C⟨hct⟩↰|

Try it online!

-1 byte, and more importantly this feels like a much less clunky way of doing this.

~c₃                     % Partition the input into 3 subarrays
   C                    % Call that array-of-arrays C
    kt[İ,0]             % Its second element should be of the form [Integer, 0]
           ≠            % And its elements shouldn't be equal (i.e. 
                        %   the Integer shouldn't be 0)
            ∧C⟨hct⟩     % Then, remove that [İ, 0] element from C
                   ↰    % And call this predicate recursively
                    |   % When the above fails (when it can't find a partition with 
                        %  [İ, 0] in it), then just output the input

Alternate 21 byter: ∋0∧ℕ₁;0;P↺c;Qc?∧P,Q↰| Try it online!


Older code:

22 bytes

∋0&b,1;?z{=|¬∋0&}ˢtᵐ↰|

Try it online!

∋0           If input contains a 0, 
&b           Remove input's first element, getting list of "next" elements
,1           Append 1 to that to handle last element
;?z          Zip that with input
{      }ˢ    Select only zipped pairs where
 =|          both elements are equal (to keep 0s followed by 0s)
   ¬∋0&      or the pair doesn't contain a 0
             this removes both the (pairs containing the) value
              that is followed by a 0, and the 0 itself
tᵐ           Recover back the (filtered) input array elements from the zip
↰            Call this predicate recursively 
|            If input contains no 0s, input is the output 
\$\endgroup\$
4
\$\begingroup\$

Red, 64 bytes

func[b][a: copy[]foreach n b[either n > 0[insert a n][take a]]a]

Try it online!

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

Attache, 35 bytes

{y.=[]_:>{If[_>0,Push&_!y,Pop!y]}y}

Try it online!

Actually implements a stack! For the most part.

54 bytes for a "stackless" approach: Fixpoint!{Flat!{#_=1or _@1>0}\Chop[_,1+Rotate[_=0,1]]}. Didn't spend much time golfing it tho.

Explanation

y.=[] defines an array and _:>{...} iterates over the input array. For each element, we either push it if its > 0 or pop the last element. We return y at the end.

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

Lua, 141 124 bytes

loadstring'p=loadstring("return "..(...))()r={}t=table for i=1,#p do (0<p[i]and t.insert or t.remove)(r,1,p[i])end return r'

Try it online!


Explanation

p=loadstring("return "..(...))() -- deserializes the input ('{1, 2, 3}' becomes a table with 3 elements)
r={} -- initializes the result table
t=table -- just to decrease the number of bytes used
for i=1,#p do -- for each element on the input list (table)
  (0<p[i] and t.insert or t.remove)(r, 1, p[i])
   0<p[i] and t.insert   -- if the element (p[i]) is greater than 0 then 'y' is going to be the function table.insert
                       or t.remove -- else it's going to be the remove function
  (                               ) -- this defines which function will be called (insert or remove)

                                   (          ) -- these are the arguments
                                    r, 1, p[i] -- 'r' is the table, 1 is the position, p[i] is the element
                                    -- the insert function receives 3 arguments, the table which to insert, the position and the value
                                    -- the remove function only receives 2, the table and the position
                                    -- There's no problem with that because the third argument will be ignored
end
return r -- returns the 'r' table

This is an anonymous function.

I hope I did a decent job of explaining how it works hahah

\$\endgroup\$

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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