text:
Is this a straight flush?
Related: Name the poker hand

A straight flush is a poker hand containing five cards of sequential rank, all of the same suit. As part of a straight flush, an ace can rank either above a king or below a two. An ace can rank either high (e.g. A♥ K♥ Q♥ J♥ 10♥ is an ace-high straight flush) or low (e.g. 5♦ 4♦ 3♦ 2♦ A♦ is a five-high straight flush), but cannot rank both high and low in the same hand (e.g. Q♣ K♣ A♣ 2♣ 3♣ is an ace-high flush, not a straight flush).

Challenge
Given N cards (in any reasonable format) output a truthy value if a straight flush is contained in the poker hand.
Input

N numbers of cards. (In any reasonable format)

There are four suits; hearts, spades, diamonds, and clubs (H, S, D, C).
Each suit has one card for the numbers 2 to 10, plus 4 'picture' cards, Ace, Jack, Queen, and King (A, J, Q, K)
Note: You can take 10 as T
Output

Truthy/Falsy value

Test case
["AS", "2S", "3S", "4S", "5S"] => true

["3D", "9C", "4S", "KH", "AD", "AC"] => false

["5D", "6D", "7D", "8H", "9D", "10D", "JD"] => false

["JC", "7C", "5D", "8C", "AC", "10C", "9C", "5S"] =>true

[] => false

["AS", "2S", "3S"] => false

["JC", "QC", "KC", "AC", "2C"] => false

[ "2H", "3H", "4H", "5H", "6H", "7H"] => true

Standard code-golf rules apply.
Winning criteria: Shortest code in each lang

May we assume that there won't be two of the same card in the hand?

@JoKing yep, you wont have the same card twice or more

May we take 10 as T?

@JoKing I don't think that can happen IRL. ;-)

@EriktheOutgolfer I literally have about 5 packs of mixed cards less then a meter away from me

@JoKing I think you are not allowed to play with more than 1 pack of cards, at least on a poker game ;)

Python 2, 95 bytes
lambda a:any(set('A234567891JQKA'[i/4:][:5])<={r['HCSD'[i%4]in r]for r in a}for i in range(40))

Try it online!
There are 40 possible straight flushes, and this simply checks them all. Chas Brown saved 2 bytes; Jo King saved 4 more.

There are 40, you used A at both ends so I believe changing 36 to 40 should fix it.

Oops, aren't I good at counting. I fixed it!

99 bytes.

Swap the suit-value order and move the if condition to the index?

95 bytes

R, 128 126 94 91 bytes
function(x,r=rle(outer(y<-chartr("J-X","A2-9TJQKAS",LETTERS),y,paste0)%in%x))any(r$l>4&r$v)

Try it online!
Original logic shortened considerably by @J.Doe.
Makes a 26 by 26 matrix with mostly nonsense but all the cards (with the Aces repeated at the bottom) contained in rows 10 to 23 of columns 3,4,8 and 24. The matrix is created by concatenating all combinations of the upper case alphabet with letters J through X replaced by A,2-9,T,J,Q,K,A,S via chartr. We get C, D, H for free!
The %in% flattens the matrix column-wise into a vector. Then see if run-length encoding is greater than 4 for any run of TRUE matches.

Clever use of rle AND outer ! This saves two bytes

94 bytes.  Two changes: using a symmetric outer call that produces many invalid cards, and using the vector coercion of in to avoid apply. They both have to be in place for this to work!

Very nice! Changed the answer and made it a community wiki.

JavaScript (ES6), 116 bytes
a=>[...'CDHS'].some(s=>a.map(c=>m|=c.match(s)&&2<<"234567891JQKA".search(c[0]),m=0)|(g=k=>k&&1+g(k&k/2))(m|m>>13)>4)

Try it online!
How?
For each suit \$s\$, we convert all cards \$c\$ of suit \$s\$ into a 14-bit bitmask \$m\$, duplicate bit #13 (Ace) to bit #0 to handle the steel wheel (A,2,3,4,5) and count the number of consecutive bits. If it's greater than 4, we have a straight flush.

I've gotten so used to your "currying notation" introductory line that I miss it when it's not needed.

Brachylog, 31 bytes
tᵍkᵐ²cᵐ{ps₅~s"A23456789TJQKA"}ᵉ

Try it online!
 ᵍ                    Group input by
t                     each element's "tail" (i.e. suit)
kᵐ²                   Knife off the suit character from each element in each array
cᵐ                    Concatenate the elements of each suit array into a string
{               }ᵉ    There exists at least one string in that such that
 p                    it has a permutation
 s₅                   which has a substring of length 5
 ~s                   which is also a substring of
 "A23456789JQKA"

Retina 0.8.2, 66 bytes
J
11
Q
12
K
13
A
1$%'¶14
\d+(.)
$1$&$*
O`
^
¶
((?(1)\1.|¶.+)){5}\b

Try it online! Explanation:
J
11
Q
12
K
13

Convert the picture cards into their values.
A
1$%'¶14

A can be 1 or 14.
\d+(.)
$1$&$*
O`

Convert the value to unary, and suffix it so that the cards sort properly.
^
¶
((?(1)\1.|¶.+)){5}\b

Match 5 cards that increase by 1 each time, and ensure that the last increase was exactly 1.

Java 10, 189 167 165 164 160 157 156 bytes
s->{int i=10;for(;i-->0;)i=s.matches("AKQJT98765432A".substring(i,i+5).replaceAll(".","(?=.*$0\\\\1)").replaceFirst(".1","([HSDC])")+".*")?-2:i;return-1>i;}

Takes the input as a single space-delimited String
(i.e. "AS 2S 3S 4S 5S").
-22 bytes thanks to @OlivierGrégoire.
-1 byte thanks to @AlexRacer.
Try it online.
Golfed version of the code that I've used for Project Euler #54, which I primarily did with regexes (for fun and to learn more about regexes). Without regexes it would probably have been better for performance and easier (probably also applies for golfing this answer; will take a look later on).
Explanation:
s->{                    // Method with String parameter and boolean return-type
  int i=10;for(;i-->0;) //  Loop `i` in the range (10,0]:
    i=s.matches(        //   If the input matches the following regex:
        "AKQJT98765432A".substring(i,i+5)
                        .replaceAll(".","(?=.*$0\\\\1)")
                        .replaceFirst(".1","([HSDC])")
                        //    Five adjacent cards
        +".*")?         //    With optionally zero or more other characters
         -2             //     Set `i` to -2, which also stops the loops at the same time
      :i;               //   Else: leave `i` unchanged to continue
  return-1>i;}          //  Return whether `i` is not -2 (so whether the loop has finished)

Additional regex explanation:

"AKQJT98765432A".substring(i,i+5) takes five adjacent cards based on i
.replaceAll(".","(?=.*$0\\\\1)") replaces each of those cards with "(?=.*c\\1)" (where c is the card-character)
.replaceFirst(".1","([HSDC])") will then replace the first \\1 with ([HSDC]).

I.e. the total regex to check the Straight Flush for cards in the value-range [9,5] will become:
^(?=.*9([HSDC]))(?=.*8\\1)(?=.*7\\1)(?=.*6\\1)(?=.*5\\1).*$
(NOTE: String#matches implicitly adds the trailing/leading ^...$ to check the entire String.) This regex will:
^(?=.*9([HSDC]))(?=.*8\\1)(?=.*7\\1)(?=.*6\\1)(?=.*5\\1).*$
^                                                         $ Match the entire string
 (?=           )(?=      )(?=      )(?=      )(?=      )    Do positive lookaheads to check
                                                            each card
    .*             .*        .*        .*        .*         With optional leading characters
                                                            in front of every card
                                                        .*  And any trailing characters at
                                                            the end of the entire hand
      9              8         7         6         5        The five adjacent values
        [HSDC]                                              With a suit
       (      )       \\1       \\1       \\1       \\1     which is the same for all cards

172 bytes. I only golfed the regex generation: it's still your algorithm.

167 bytes. I removed the unnecessary ".*"+ prefix.

@OlivierGrégoire Thanks! Nice golfs.

-1 byte if you break out of loop instead of using f

@AlexRacer Smart, thanks! And been able to golf 2 more bytes by changing the break to i=-2 and the return to return-1>i; using your approach (and 2 more changing (.) to . and $1 to $0). :)

JavaScript (ES6), 106 bytes
h=>h.map(([r,s])=>[..."HSDCA23456789TJQKA"].map(c=>i+=c==s?i*15:c==r?d[i]=1:1,i=0),d=[])|/(,1){5}/.test(d)

Accepts an array of string representations of cards, replacing 10 with T.
Try it online!
Explanation
Iterates over each card and sets a flag in an array of booleans using an index
computed from the unique combination of its rank and suit. This array is then
stringified to permit matching a pattern of 5 consecutive truthy values.
For example, a hand with a straight flush may produce the following as a
substring of the full string representation of the boolean array: ,,,,1,1,1,1,1,,,,
Because the first rank value (i.e. A) is offset from the
start of the string, there will always be empty values
preceding all 1's in the array, ensuring the string
representation will begin with a ,
h =>
    h.map(([r, s]) =>                         // destructure card value, e.g. "JH" => ["J", "H"]
        [..."HSDCA23456789TJQKA"].map(c =>    // mapping accounts for both positions of 'A'
            i +=                              // increment index value
            c == s                            // if found index of suit...
                ? i * 15                      // buffer so that cards from different suits cannot be confused
            : c == r                          // if found index of rank...
                ? d[i] = 1                    // set flag to denote card is in hand
            : 1,
            i = 0
        ),
        d = []
    ) |
    /(,1){5}/.test(d)                         // implicitly converts to string joined with a ,

Nice.  This deserves more votes, but folks tend to lose interest in challenges a couple days after the initial posting.

Clean, 145 135 bytes
import StdEnv,Data.List
?l=or[isInfixOf(map hd h)['A234567891JQKA']\\a<-l,b<-l,c<-l,d<-l,e<-l,h<-[[a,b,c,d,e]]|tl(nub(map last h))==[]]

Try it online!
Simplified:
? l                                             // function ? taking argument l
  = or [                                        // is at least one of these true
        isInfixOf (map hd h) ['A234567891JQKA'] // do the first characters of a hand appear in this string, in order
        \\ a <- l                               // loop level 1, assigns `a`
           , b <- l                             // loop level 2, assigns `b`
             , c <- l                           // loop level 3, assigns `c`
               , d <- l                         // loop level 4, assigns `d`
                 , e <- l                       // loop level 5, assigns `e`
                   , h <- [[a,b,c,d,e]]         // trick to assign `h`, because it's cheaper than let .. in ..
        | tl (nub (map last h)) == []           // only take the loop iterations where all the suits are the same
       ]

Japt, 37 bytes
Takes input as a 2D array.
"AJQKA"i1Aò2 q)øUñÌòÏÌ¦XÌÃËmÎ¬ú5 á5Ãc

Try it

Explanation
"AJQKA"                                   :String literal
       i1                                 :Insert at (0-based) index 1
         Aò2                              :  Range [2,10]
             q                            :  Join
              )                           :End insert
               ø                          :Does that string contain any element in the following array?
                U                         :Input
                 ñ                        :Sort
                  Ì                       : By last element (grouping suits together)
                   òÏ                     :Partition between X & Y where
                     Ì                    :  Last element of Y
                      ¦                   :  Does not equal
                       XÌ                 :  Last element of X
                         Ã                :End partition
                          Ë               :Map
                           m              :  Map
                            Î             :   First elements (card values)
                             ¬            :  Join
                              ú5          :  Right pad with spaces to length 5
                                 á5       :  Permutations of length 5
                                   Ã      :End map
                                    c     :Flatten

Jelly, 18 bytes
Ṣœc5Uµ13R;1wṪ€ȧEµƇ

Try it online!
Actual input format: list ([..., ...]) of lists of 2 integers each; the first is an integer in \$[1,13]\$, for \$A23456789TJQK\$ respectively, and the second is in \$[1,4]\$, for \$CDHS\$ respectively. The TIO link accepts input in the format of the test cases.
Output format: empty list as falsy, non-empty list as truthy.

I don't see anything in the specs suggesting that integers can be substituted for the suits and picture cards - did I miss something?

@Shaggy I assume that's within "any reasonable format", I don't think we have defaults regarding inputting playing cards.

PHP, 264 bytes
It echos 1 if it is a straight flush and 0 or null if not.
If you name the file 1X then you can save 11 bytes as you don't need to change $argv[0]. Not sure at the moment why the filename can break it.
For some reason the strings :;<=> get sorted before the strings 0123456789 by asort in TIO even though :;<=> have ASCII values 58-62 and 0123456789 have ASCII values 48-57. So if you take the code from the TIO link or below and use PHPTester with the following test suite it works.
$argb[0] = [".code.tio", "AS", "2S", "3S", "4S", "5S"]; // => true
$argb[1] = [".code.tio", "3D", "9C", "4S", "KH", "AD", "AC"]; // => false
$argb[2] = [".code.tio", "5D", "6D", "7D", "8H", "9D", "TD", "JD"]; // => false
$argb[3] = [".code.tio", "JC", "7C", "5D", "8C", "AC", "TC", "9C", "5S"]; // => true
$argb[4] = [".code.tio", ]; // => false
$argb[5] = [".code.tio", "AS", "2S", "3S"]; // => false
$argb[6] = [".code.tio", "JC", "QC", "KC", "AC", "2C"]; // => false
$argb[7] = [".code.tio", "TC", "JC", "QC", "KC", "AC", "2C"]; // => true
$argb[8] = [".code.tio", "2H", "3H", "4H", "5H", "6H", "7H"]; // => true

for ($z=0; $z<9;$z++){
    $argv=$argb[$z];
    array_shift($argv);
    unset($a,$b,$c,$d,$e,$f,$g,$h,$i);
    $f=false; // not needed, just removes several notices

    // TIO code here

    echo "<br>";

TIO Code
for($b=count($a=$argv);$b;){$a[0]='1X';$a[--$b]=strtr($a[$b],'ATJQK','1:;<=');$a[]=($a[$b][0]==1?">".$a[$b][1]:1);}asort($a);foreach($a as$c){$d[$c[1]][]=$c[0];}foreach($d as$e){if(4<$g=count($e)){for($h=0;$g>$i=4+$h;){$f|=(ord($e[$i])-ord($e[$h++])==4);}}}echo$f;

Try it online!

Kotlin, 226 bytes
Used T for 10 so all cards are 2 characters in length.
{h:List<String>->val m=List(4){mutableSetOf<Int>()}
for(c in h)m["CDHS".indexOf(c[1])].add("A23456789TJQK".indexOf(c[0]))
var r=0>1
for(b in m){if(b.contains(0))b.add(13)
for(i in 0..9)r=b.containsAll((i..i+4).toList())||r}
r}

Try it online!

Pascal (FPC), 223 216 210 209 bytes
var a,b:char;c:set of byte;i:byte;begin repeat readln(a,b);i:=pos(b,'HDC')*14+pos(a,'23456789TJQK');c:=c+[i];if a='A'then c:=c+[i+13]until eof;i:=0;while not([i..i+4]<=c)or(i mod 14>9)do i:=i+1;write(i<52)end.

Try it online!
Uses T for 10. Input contains 1 card per line.
Now I golfed it so much that I don't know how it works anymore...
Explanation:
var a,b:char; //for reading cards
    c:set of byte; //this set is for remembering which cards are present in the input
                   //14 numbers used for each suit
    i:byte;
begin
  repeat
    readln(a,b);             //read rank into a, suit into b and a newline
    i:=pos(b,'HDC')*14+pos(a,'23456789TJQK');
        //temporary use i to calculate corresponding number for the card
        //pos() gives 0 if b is not found
        //1st pos() is for the group of numbers for that suit, 2nd pos() is for offset
    c:=c+[i];                //include i into set
    if a='A'then c:=c+[i+13] //if rank is A, include the number at the end of group as well
  until eof;
  i:=0;
  while not(
    ([i..i+4]<=c) //if NOT 5 cards in a row are present...
    and           //while the check is started from 10 (T)...
    (i mod 14<10) //(otherwise, it is checking across 2 different suits)
  )do i:=i+1;     //increment i, otherwise stop
  write(i<52) //if i<=51, there is a straight flush starting at the card corresponding to i
              //(if there isn't a straight flush, i stops at 252 due to i..i+4, I don't know why)
end.


text:
Implementing a stack
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 code-golf:
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]

It should be noted that, given the conditions, one does not actually need to implement the stack.

If you wanted someone to actually implement a stack, you might need to try putting something in the Sandbox.

@mbomb007: Either is allowed: "your choice where the top element will be (at the beginning or end)"

@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?

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

@mbomb007: It's not though, what about [1,2,0,0]?

Look at my answer in Retina. In pseudo-code: Loop: remove the first #,0 and you're done. So you remove 2,0, then remove 1,0.

Let us continue this discussion in chat.

Related

We don't usually like to make different rules for different languages. Your spec says "if your language doesn't […] support […] lists, …" – would you consider opening this option to all languages? As @Titus pointed out, Python has perfectly good support for lists, yet you seem OK with a Python answer using negatives.

@O.O.Balance: I completely forgot that I restricted it, sorry about that.. (updated)

Is a terminating character allowed for the output? For the given example, is [28, 101, 12, 0] allowed?

@JonClaus: Why did you change your question after I allowed it (something else)? That's not cool! I'll allow a negative integer marking the bottom of the stack, as was originally asked for since it's also allowed to mark end of input. Also, welcome to PPCG!

@OMᗺ Sorry about the switch from -1 to 0. I figured both were equivalent for the purposes of an answer because neither is a possible value in the stack, which can only contain positive integers.

May we use unary for the input and output?

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)

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:

-1 byte thanks to O.O.Balance

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!

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

@O.O.Balance Indeed, I hadn't thought about that., thanks!

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

Does a splatting save 3 bytes on $agrs? :)

-2 bytes $args|%{$x,$a=&({$_,$_+$a},{$a})[!$_]};$a?

@mazzy Yes, and we had just talked about splatting! I forgot already! lol Thanks!

Wouldn't splatting be .\implement-stack.ps1 @z (not $z), otherwise you're just passing an array as the first/only  argument

@pinkfloydx33 Yep. Typo on my part.

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.

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!

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 :)

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.

Yup, it was a newline.

If the final element of the input is a 0 then it won’t get matched by your regex.

Similar to the Retina answer.

(as pointed out above) this fails for [1,0].

ya, I just hope nobody tries to use numbers in octal.

You can use \w instead of [0-9] and you may be able to cut down the \+ to *

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!

f(l)int*l; => f(int*l)?

@l4m2 Ah, cheers! Probably a remnant from earlier, more variable-laden days.

the r=0 seems useless

@l4m2 Aye, good catch.

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

48 bytes -- abusing F will also get you to 48 bytes but this is cleaner imho

I don't know how I missed the if-else inversion :facepalm: ... thanks !

45 bytes

A R+pryr and Reduce solution is 44 bytes

@JayCe: to be honest, I prefer to keep it a "base-R" solution... but feel free to post it as your own answer ! ;)

I totally understand... I don't post non-base R very often either... will do!

Haskell, 28 bytes
foldl(#)[]
(_:s)#0=s
s#n=n:s

Try it online!

How main function is named? I don't know, how to run it)

@ЕвгенийНовиков: see the "try it online" link for an example of how to run the code.

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.

Will this emulate three pops if there are three consecutive zeros?

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.

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

In this particular case, {{}<>{}<>} can be shortened to {{}<>}.

@Nitrodon Thank you. Can you explain, why this still works? It doesn't switch back to the input stack in the loop.

The top of the output stack is guaranteed to be nonzero, so the shortened loop executes either 0 or 2 times.

Python 2, 59 57 51 bytes
s=[]
for x in input():s=(s+[x],s[:-1])[x<1]
print s

Try it online!

Wolfram Language (Mathematica), 28 bytes
#//.{a___,b_,0,c___}:>{a,c}&

Try it online!

(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.)

@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___)

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

Try it online!

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.

@ElPedro It's not zero when x=0, in which case it's 2.

Ah, I see what you mean. Guess I was looking too hard and missing the obvious! Thanks and great answer.

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

You can save a byte by removing the space between 0 and in

Congrats on the 10K

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

brainfuck, 214 150 bytes
>>,[>++++++[-<-------->]+<[>+++++[-<++++++++>]]>[-<<<[[-]<],[-]>>>>-<<]>>+[<<+<,----------[++++++++++>-]>[->>-<]>[->+<]>]<<<,]<<[[<]++++++++++<]>>[.>]

Reads input as numbers separated by newlines. This must include a single trailing newline. Also expects no leading zeros on each number. Output as a similar newline separated list
Try it online!
Explanation that isn't really an explanation but is actually just the version I was working on with the comments and stuff which may or may not actually be useful to anyone
Stack format:
0 (0 \d*)*

>>,[
    Setup digit == '0' conditional
    >++++++
    [-<-------->]
    +
    <[
        Read digit != '0'
        Restore the char code
        cond1 is already 1 at this stage
        >+++++
        [-<++++++++>]
    ]>[
        Read digit == '0'
        -
        Pop previous value
        <<<[
            [-]<
        ]
        Skip next input (assumed to be newline)
        ,[-]
        Skip following loop by unsetting loop flag
        >>>>-
        <<
    ]

    Move to next stack frame
    >
    Set loop flag
    >+[
        Set bit used for conditional
        <<+
        Read next character
        <,
        Compare with '\n'
        ----------[
            Not '\n': restore the char code
            ++++++++++

            >-
        ]>[
            -
            == '\n': Leave as 0
            Unset loop flag
            >>-
            <
        ]

        Copy loop flag along
        >
        [- > + <]

        Move to loop flag of next stack frame
        >
    ]

    <<<
,]

Fill in with newlines
<<[
    Skip to the cell before this value
    [<]
    Put a newline in there
    ++++++++++
    Move to next value
    <
]

Now the tape has the exact values we need to output
>>[.>]

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.

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

@HermanL: D'oh! Of course it is! Thanks. Was using (un)shift before I spotted output could be reversed.

This works because o is referenced in the callback after it's defined in the second argument.

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.

Brain-Flak, 32 bytes
([]){{}{({}<>)<>}{}<>{}<>([])}<>

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

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

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

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+

Which simply replaces all <number>, 0 sublist by nothing.

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
}

Nice approach with Strings. Better than my naive approach with an actual Stack-object. +1 from me.

n->{var s="";for(int i:n)s=(s+","+i).replaceAll(",\\d+,0$","");return s;} (73 bytes), but puts the , before numbers, not after.

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]"

@OlivierGrégoire Nice. We can drop the $ to save an additional byte, since each 0 we add is removed right away.

@OlivierGrégoire Your second approach is interesting as well, but I think the inconsistent output format may invalidate the solution.

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

Try it online!
Anonymous lambda. Outputs in reverse order.

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

><>, 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

22 bytes

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ø↔

Perl 5 -p, 17 bytes
Thanks @sundar and @DomHastings
s/\d+ 0 ?//&&redo

Try it online!

-2 bytes (with slightly mankier output): Try it online!

Further to @sundar's comment, another slight simplification: Try it online!

Doesn't that fail if there's a number like 0942 input?

You can safely assume there will not be any leading zeros.

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

Warning: Lots of lines ensue. You have been warned.

CJam, 17 bytes
Most dangerous code
(Assumes the stack elements can be separated by only spaces in the output and that the input array can be whatever form we wish)
q~{X0={;}X?}fX]S*

Try it online!
Explanation
q                                    Reads input string
 ~                                   Instantly convert to array since the string is in the CJam format
  {        }fX                       For loop
   X0=                               If X (the array element currently being checked) is equal to 0
      {;}                            Pop the top element from the stack
         X                           Else push X onto the top of the stack
          ?                          If-Else flag
              ]                      Collate all stack elements into an array
               S*                    Put a space between each array element

Alternate Code #1, 27 bytes
(Assumes stack elements have to be output in the format shown in the question and that the input array can be whatever form we wish)
q~{X0={;}X?}fX]',S+*'[\+']+

Try it online!
Explanation
q                                    Reads input string
 ~                                   Instantly convert to array since the string is in the CJam format
  {        }fX                       For loop
   X0=                               If X (the array element currently being checked) is equal to 0
      {;}                            Pop the top element from the stack
         X                           Else push X onto the top of the stack
          ?                          If-Else flag
              ]                      Collate stack items into an array
               ',S+                  Add together a comma and a space to create a delimiter
                   *                 Apply the delimiter to the stack
                    '[\+             Append left bracket to the left of the stack text
                        ']+          Append right bracket to the right of the stack text

Alternate Code #2, 24 bytes
(Assumes the stack elements can be collated in the output and that the input array has to be in the exact format shown in the question)
q',/~]S*~{X0={;}X?}fX]S*

Try it online!
Explanation
q                        Read input string
 ',/                     Separate by commas (since commas are an invalid array delimiter in CJam)
    ~                    Turn string into an array of substrings that make up the array
     ]S*                 Add spaces in between input numbers to prevent collation in the array
        ~                Turn the string into a valid array representative of the original
         {        }fX    For loop
          X0=            If X (the array element currently being checked) is equal to 0
             {;}         Pop the top element from the stack
                X        Else push X onto the top of the stack
                 ?       If-Else flag
                     ]   Collate all stack elements into an array
                      S* Add a space between each element

Safest code for this, 34 bytes
(Assumes stack elements have to be output in the format shown in the question and that the input array has to be in the exact format shown in the question)
q',/~]S*~{X0={;}X?}fX]',S+*'[\+']+

Try it online!
Explanation
q                                      Read input string
 ',/                                   Separate by commas (since commas are an invalid array delimiter in CJam)
    ~                                  Turn string into an array of substrings that make up the array
     ]S*                               Add spaces in between input numbers to prevent collation in the array
        ~                              Turn the string into a valid array representative of the original
         {        }fX                  For loop
          X0=                          If X (the array element currently being checked) is equal to 0
             {;}                       Pop the top element from the stack
                X                      Else push X onto the top of the stack
                 ?                     If-Else flag
                     ]                 Collate stack items into an array
                      ',S+             Add together a comma and a space to create a delimiter
                          *            Apply the delimiter to the stack
                           '[\+        Append left bracket to the left of the stack text
                               ']+     Append right bracket to the right of the stack text

Thanks to @Jo King for pointing out that the ones with the collated output are invalid since things like [12] and [1,2] would be indistinguishable.
Thanks also to @Jo King providing a very suitable alternative for the collated outputs and cutting off 9 bytes!

The first one isn't valid since you can't tell the difference between [12] and [1,2]. However, the 27 byte version seems alright, though you can get rid of the whitespace and brackets for 18 bytes

oh of course I'm so dumb many thanks

However it would probably be more golfy to separate numbers by spaces rather than commas since spaces uses ]S* (3) whereas commas use ]',* (4)

Red, 64 bytes
func[b][a: copy[]foreach n b[either n > 0[insert a n][take a]]a]

Try it online!

Java 10, 83 76 75 74 bytes
a->{for(int i=0;i<a.size();)if(a.get(i++)<1){a.remove(i-=2);a.remove(i);}}

-7 bytes thanks to @O.O.Balance.
-1 byte thanks to @OlivierGrégoire.
Modifies the input-List instead of returning a new one to save bytes.
Try it online.
Explanation:
a->{                        // Method with List parameter and no return-type
  for(int i=0;i<a.size();)  //  Loop `i` in the range [0, size)
    if(a.get(i++)<1){       //   If the current item is 0:
      a.remove(i-=2);       //    Remove the previous item
      a.remove(i);}}        //    As well as the current 0

76 bytes using your suggestion of taking a List and modifying it: https://bit.ly/2AeKMTb

@O.O.Balance Thanks. Been able to golf one more byte by changing the position of the i++.

My answer is similar to this one, but 61 bytes only.

a->{for(int i=0;i<a.size();)if(a.get(i++)<1){a.remove(i-=2);a.remove(i);}} (74 bytes)

MarioLANG, 51 47 bytes
> ;+[!>(
"====#"
 (![-<:[
 =#=="!<
!)<   #=
#="

Try it online!
Uses -1 as mark for EOF. Explanation follows:
> ;+[!>     Mario walks to the left, reads an integer, adds 1 and checks if it's 0.
"====#"     If the value is not 0 Mario takes the elevator and starts walking to the left.
 (![-<      Mario takes 1 from the value and checks again if it's 0.
 =#=="      If so Mario skips the elevator and moves the pointer to the left, otherwise he
!)<         takes the elevator down and moves the pointer to the right. Either case
#="         Mario ends up taking the elevator to the start of the level.

>(    This is a loop to print what's left in the data values. Mario walks
"     to the right and falls, moving the pointer to the left and checking
:[    if the value pointed is 0. If it is, Mario skips the command to walk to the left and
!<    falls to end the level. Otherwise he walks to the left and takes the elevator,
#=    printing the value pointed as integer and continuing the loop.

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.

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

Japt, 14 bytes
;NË¥0?Ao:ApDÃA

Try it online!
Actual TIO doesn't work for some reason (it exits with an error, see here) so I've given a page to the ETHproductions' online Japt interpreter.

11 bytes and in the right order.

@Shaggy are you planning to post it as your own answer?

TIO is fixed now :-)

C, 138 bytes
int main(int _,char**v){int n=0,*s=0,i;for(;*++v;){i=atoi(*v);if(i){s=realloc(s,n*4+4);s[n++]=i;}else n--;}while(n--)printf("%i ",s[n]);}

Taking advantage of implicit definitions for printf, atoi, etc, and saving an 'int' by declaring i with the other variables.
202 bytes
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int _,char**v){int n=0,*s=NULL;for(;*++v;){int i=atoi(*v);if(i){s=realloc(s,n*4+4);s[n++]=i;}else n--;}while(n--)printf("%i ",s[n]);}

Takes input as command line args, outputs to stdout.

123 bytes: https://bit.ly/2LEvBXR

Why are include guards not included in your total?

Because gcc does not require them for this program. If you want to keep them, you can still remove the spaces. But here on PPCG we define a language by its implementation; my golf would thus be C (gcc).

Save 1 more byte by replacing else n--; with else--n;

Submissions don't necessarily need to be full programs, a function saves you some bytes: Try it online!

Save a byte by swapping the variable declarations to int*s=0,n=0,i;, and since this is C89, save a further 4 bytes by not specifying main()'s return type, defaulting to int.

104 bytes

TIS, 75 bytes
Code:
@0
MOV UP ACC
JGZ U
JLZ Q
ADD ANY
JRO -4
Q:MOV ANY DOWN
JMP Q
U:MOV ACC ANY

Layout:
1 2 CS
I0 NUMERIC -
O0 NUMERIC - 32

Try it online!
This implementation requires negative numbers for termination, and all values to be delimited by whitespace. Output is delimited by whitespace as well.
Explanation:
I have one regular computation node. Numeric input comes from above, and numeric output is sent below. To the right, there is a stack node.
Here's the code, with more verbose (and additional) labels:
@0
START: MOV UP ACC     # Get input
       JGZ PUSH       # If input is positive, jump to PUSH
       JLZ STOP       # If input is negative, jump to STOP
                      # Else input is zero, continue at POP
POP:   ADD ANY        # Consume one value from the stack, by adding it to the accumulator
       JRO -4         # Jump back up to the top (new input will overwrite the accumulator)
STOP:  MOV ANY DOWN   # Move one value from the stack to output
       JMP STOP       # Just loop this bit forever
PUSH:  MOV ACC ANY    # Push the value we just read onto the stack
                      # Implicitly jump back to the top

You may have noticed that we use ANY to access the stack instead of RIGHT. We can depend on this to go to the correct place because of a quirk in the implementation of both the original game, and this emulator. Replacing all the ANYs by explicit RIGHTs will give the same solution.
I go into more detail about this behavior in note 2 of this other answer.
Limitations:
TIS has some inherent limitations, which limit the abilities of this implementation quite directly.
First, the numeric datatype only accepts values from -999 to 999. Any values outside this range will be clamped to either -999 or 999.
Additionally, TIS stack nodes only allow a maximum depth of 15 items. Some implementations may deadlock when hitting that limit. Others, like this one, will behave in perhaps-unexpected ways. This specific implementation will just dump any overflow values to the output. (Changing the last line to U:MOV ACC RIGHT will make it do the deadlock thing instead).

Kotlin, 90 bytes
{l:List<Int>->var c=0
l.reversed().filter{if(it<1){c++
0>1}else if(c>0){c--
0>1}else 1>0}}

Try it online!

Haskell, 51 43 bytes
run s function
Try it online
(#)[]
(_:r)#(0:s)=r#s
r#(x:s)=(x:r)#s
r#_=r

C, 86 Bytes
c;f(a,n)int*a;{if(!n)c=0;else{f(a+1, n-1);!c&&*a&&printf("%d ",*a)||(c+=2*!*a-1,0);};}

Solution based on recursion. Simply load whole array on a system stack and count number of zeroes from the end and either skip current number (if count is positive) or print it. The resulting stack is printed from left to right, ie. head is on the beggining of the line.
Ungolfed version:
int counter;
void goo(int * a, int n){
        if (!n) {     // end of the array
            counter = 0;
            return;
        }
        goo(a+1, n-1); // try next number
        if (!*a) { cnt++; return;} //increase number of zeroes;
        if (cnt) { cnt--; return;} //skip current number
        printf("%d ", *a); //print it otherwise
    }

Try it on Ideone!

This is nice! You can save 3 bytes: https://bit.ly/2NQUCMZ

73 bytes

Befunge-93, 37 bytes
v<
 |   :<
 $
 $
>>&:1+|
>:v :$<
^._@

Try it online!
My first answer in Befunge!
Uses -1 as EOF. As Befunge already uses a stack internally, I just need to do the push and pop operations given the values at the input.

Befunge can be a lot more compact then that. 17 bytes

@JoKing I've been trying to understand your code all day... now I think I did at last.

Ruby, 36 bytes
->a{b=[];a.map{|i|i>0?b<<i:b.pop};b}

Try it online!

dc, 24 bytes
[*+]sP[?d0=Pd0<l]dslxsxf

Try it online!
Input is one number per line and terminate with a negative number but remember that negative numbers are input with a leading underscore not a dash. There's something punny about implementing this in a stack based language and using the operand stack as the data structure. I'm especially happy about the *+ to "pop" the zero and the previous input.

Rust, 66 bytes
Takes a vector and returns a vector. The head of the stack comes last in the output.
|l|{let mut r=vec!();for&e in&l{if e>0{r.push(e)}else{r.pop();}}r}

Try It Online

Stax, 8 bytes
âΦε∙GφN²

Run and debug it

another 8

Chip -o, 53 bytes
)))))))}v9
ABCDEFGH`~8
0123456`v~S
)))))))~]T
abcdefg

Try it online!
For the TIO here, I use a Bash wrapper to allow "easier" number inputs. Numbers are given as values like \x3f, so that printf can do the conversion to the actual byte values for us. However, this is only a wrapper, or test harness, or whatever, and as such it is technically unnecessary.
This treats each byte of input as a 'signed byte', meaning that it will accept values 0 (0x00) through 127 (0x7f) as input, and anything else is a terminator (by virtue of being negative).
However, thanks to the -o flag, we don't need to provide an explicit terminator, since the interpreter will provide an infinite series of -1 (0xff) values upon exhaustion of STDIN.
Explanation:
Chip is a 2D language, so the various elements seen generally interact with their four neighbors. Here's the highlights of the structure:
)))))))}v9      This chunk will, given a positive value, push it onto the stack,
ABCDEFGH`~8     and given zero, pop a value off the stack. Only the low 7 bits are
0123456         stored, since we never need to push/pop negatives.

The stack push control (9) is set from the result of ORing ()) the low 7 bits of the input together (A - G), and XORing (}) the result with the high bit of the input (H). The stack pop control (8) is set by that same calculation, but inverted (~).
The end result is that 1 - 127 cause a push, and -128 - 0 cause a pop.
The stack bits (0-6) push/pop based on what the control values resolve to. If pushing, they will read from the corresponding input bits (A - G).
       H
0123456`v~S   This chunk will pop values to the output (or to the void if we
)))))))~]T    had a zero), and terminate the program if the stack is empty.
abcdefg

When the stack (0 - 6) is popped, we want to send that data to the output bits (a - g). Actually, we always send a value to the output, because in Chip you are either peeking or popping, and difference is only whether the value is kept for the future.
If the input was non-negative, due to the high bit (H) being unset, we want to suppress the output (S), preventing anything from being written to STDOUT.
On the way to the output, we also OR all the bits together again ()) to see if the stack has been emptied. If all bits are zero, it's empty, so we terminate (T). To prevent premature termination (since on the first cycle the stack is empty, and we always either peek or pop), we also use an AND (]) to ensure that we have a negative input value.

Scala, 50 bytes
(List[Int]()/:v)((x,i)=>if (i==0)x.tail else i::x)

Usage in the REPL
scala> val v = List(12,3,0,101,11,1,0,0,14,0,28)
v: List[Int] = List(12, 3, 0, 101, 11, 1, 0, 0, 14, 0, 28)

scala> (List[Int]()/:v)((x,i)=>if (i==0)x.tail else i::x)
res0: List[Int] = List(28, 101, 12)

scala>

Japt -g, 9 bytes
;®?AiZ:Av

Try it online!

R+pryr, 44 bytes
Reduce(pryr::f("if"(b,c(b,a),a[-1])),scan())

Try it online!
Heavily inspired by digEmAll's answer.

ReRegex, 19 bytes
[^0,]\d*,0,//#input

Very simple solution, Looks for a non-zero number, followed by a zero, and removes both of them.
Takes input in the form of ,1,2,3,
Try it online!
Test Battery

MathGolf, 7 bytes
Æ_╜Å;;]

Try it online!
Explanation
I wish I could do something clever to save a byte, it seems as if it should be possible.
Æ        For-each over the input with the next 5 operators
 _       Duplicate TOS
  ╜      Else without if, executes the next block if TOS is false
   Å;;   Discard two elements
      ]  Wrap everything in array

This answer has the opposite order compared to the examples in the challenge.

I don't know MathGolf, but I don't think that ] is necessary. Relevant.

@BMO I'm always unsure on how to interpret that, since MathGolf implicitly joins the stack into a single string. Thus, a stack consisting of [123, 456] would be printed as 123456, which has been used in this answer. I'll ask in the chatroom and try to get some consensus.

Yeah, I'm not sure about it either. But I would argue that as a function in MathGolf it would be fine (which is most of the time - as here too - fine), however as a full program it's not since it outputs a joined string.

@BMO MathGolf doesn't really have "functions" as of now. I don't know if I'll implement it later. However, the general consensus seems to be that the ] should be included in the byte count, with the reasoning that "The principle that languages are defined by their implementations overrides most others".

Vyxal W, 6 bytes
0\_VṄĖ

Try it Online!
-2 thanks to Aaron Miller

6 bytes

dang it you ninja'd me. Very well done.

I did ninja you

Or more accurately, Makonede dug up this question, other people started answering, then you took notice.

Charcoal, 12 bytes
ＦＡ¿ι⊞υι¬⊟υＩυ

Try it online! Link is to verbose version of code. Explanation:
ＦＡ

Loop over the input list.
¿ι

Test for zero.
⊞υι

If non-zero, push to the predefined empty list.
¬⊟υ

Otherwise pop the value, and ignore it by taking the logical negation which is always zero and therefore prints an empty line.
Ｉυ

Print each element of the list on its own line.

Small Basic, 218 bytes
A Script that takes input as a series of integers and outputs to the TextWindow object.
Note, terminal "s are not required for code to function and do not contribute to the bytecount.
n=" "
x=""
While n<>""
If n=0Then
k=Stack.PopValue(x)
Else
Stack.PushValue(x,n)
EndIf
n=TextWindow.Read()
EndWhile
o=Stack.PopValue(x)
k=Stack.GetCount(x)
For i=2To k
o=o+","+Stack.PopValue(x)
EndFor
TextWindow.Write(o)

Try it at SmallBasic.com! Requires IE/Silverlight
-8 bytes thanks to
@OMᗺ for removing [ and ]
Input / Output

Ruby, 53 bytes
l=[];gets.split.map{|s|a=s.to_i;a>0?l<<a:l.pop};$><<l

The input needs to be separated by spaces. I'm working on a solution with gsub, but it does not re-run matching when it gets to the end. I would be happy if someone could help me fix this:
gets.gsub(/\d+ 0\s*/,'')

I can't get it to work with empty input, how does it work?

@OMᗺ I think this should work on empty input and TIO normalizes it to nil for some reason. If you enter a whitespace, it still works. Running in command line should not yield an error I think (I'll check that later).

@PeterLenkefi You might be able to implement a loop with gsub!, which returns the string if modifications were made and nil otherwise.

Retina, 13 bytes
Takes the input list separated by newlines.
+0`\b\d+¶0¶?

Try it online!
Repeatedly remove the first occurrence of a number followed by a zero. Stack is returned upside-down.
Reversing the order of the lines is 4 more bytes (add to end of program). To avoid a possible leading newline, surround the input with newlines, similar to how the input in the examples uses brackets.

G^`

Java 8, 65 bytes
flexible output permitting... the output stack is stored in the input array, with zero or more terminating -1 values
a->{int x=0,y=0;for(int e:a){a[y++]=-1;a[e>0?x++:--x]=e>0?e:-1;}}

all the remaining numbers on the stack are placed at the front of the array. Reaching -1 in the array indicates the end of the stack.

Clojure, 139 bytes
(defn t[q](loop[c(rest q)n(first q)s '()](if(not(nil? n))(if(= n 0)(recur(rest c)(first c)(rest s))(recur(rest c)(first c)(cons n s)))s)))

Try it online!
Ungolfed
(defn stacktest [col]
  (loop [c  (rest col)
         n  (first col)
         s  '()]
    (if (not (nil? n))
      (if (= n 0) ; then
        (recur (rest c) (first c) (rest s))    ; then - pop
        (recur (rest c) (first c) (cons n s))) ; else - push
      s)))        ; else

Octave, 56 bytes
s=[];for i=input(''),if i,s=[i s];else s(1)=[];end,end,s

Try it online!
Implementation is simple.  Create an empty stack / array s, then declare a list of values (i.e. [12, 3, 0, 101, 11, 1, 0, 0, 14, 0, 28]), iterate through each element and if the element is non-zero, simply place the element at the front.  Otherwise, remove the first value inside the stack.  Once we're done, show the result to the screen.

PHP (>=5.4), 68 66 bytes
(-2 bytes by fixing a condition, thanks to Titus)
<?for(;null!=$n=$argv[++$i];)$n?$a[]=$n:array_pop($a);print_r($a);

To run it:
php -n <filename> <int_1> <int_2> ... <int_n>

Example:
php -n stack.php 12 3 0 101 11 1 0 0 14 0 28

Or Try it online!
Using r option per Titus's suggestion, this can be counted as 64 bytes:
Example:
php -nr "for(;null!=$n=$argv[++$i];)$n?$a[]=$n:array_pop($a);print_r($a);" 12 3 0 101 11 1 0 0 14 0 28

Anything positive is truthy and there is no negative input -> no need for >0. And you can also run it with php -nr '<code>' <int_1> <int_2> ... <int_n> - without the <? tag.

But you need NULL!== or it will take zero as end of input. (see your TiO)

@Titus: Thanks for the tips! Do you have any link to show confirmation that an option like -r <code> can be valid? I'm new to PPCG and am not sure what options and methods I can use for PHP golfing!

-r is free; see this thread in meta. You still have to fix the NULL condition.

The inputs are in string form and '0' is not equal to null as a string. Please see this: Try it online! Not sure why I should use strict comparison in that case.

Oh right. I misread the TiO output.

Bash, 81 , 50 bytes
for i;{ ((i))&&o+=($i)||unset o[-1];};echo ${o[@]}

Try it online!
Packed in function because, tio doesn't show output without it for some reason.

A few tips: 1. A full program would be shorter. 2. in $@ is implicit and can be removed. 3. The if statement can be shortened to ((i))&&o+=($i)||unset o[-1].

Scala, 61 bytes 48 bytes
(Seq[Int]()/:z)((z,b)=>if(b!=0)b+:z else z.tail)

Usage in the REPL
val z = Seq(1,2,3,4,0,3,2,5,0,1)

(Seq[Int]()/:z)((z,b)=>if(b!=0)b+:z else z.tail)

res0: Seq[Int] = List(1, 2, 3, 3, 2, 1)

Uses shorthand .foldLeft notation/: and .tail for popping items.

F#, 84 bytes
let t v=
 let mutable s=List.empty
 for i in v do s<-if i=0 then s.Tail else i::s
 s

Try it online!
Takes advantage of the fact that in F# a List is a single-linked-list. Popping from the stack just takes the tail of the list (that is, everything after the first element). Pushing to the stack makes the individual value i the head of the list (that is, pre-appends it to the list).

Lua, 115 bytes
t,a,s=table,arg,{}for i=1,#a do v=0+a[i]if v>0 then t.insert(s,1,v)else t.remove(s,1)end end print(t.concat(s,","))

quite simple iterates the arguments pushes and pops them to a table
Try it online!

You might want to add a TIO-link, I have no idea how to test this.

Added a try it online link, sorry for the inconvenience I forget it most of the time :)

Scheme, 115 bytes
Like all lisp variants, scheme is based around linked lists.  Linked Lists are often used to implement stacks.  So I thought scheme might be a competitive language for this challenge.  However, I failed to find a way to leverage Scheme's easily accessible built-ins for stack building to overcome Scheme's sheer verbosity.  I love scheme, but sometimes its just too long...
(define(g c)(define(f l s)(cond((null? l)s)((= 0(car l))(f(cdr l)(cdr s)))(else(f(cdr l)(cons(car l)s)))))(f c'()))

Try it Online!

Prolog (SWI), 47 bytes
R-L:-append(A,[_,0|T],L),append(A,T,M),R-M;R=L.

Try it online! Call as output-input.
Explanation
R-L:-
     append(A,[_,0|T],L),                       % if list contains _,0
                         append(A,T,M),R-M;     % then remove it and recurse
                                           R=L. % else we're done, output = input

Ahead, 23 bytes
~$k*2!:Ivj~
~oNO@k!d<~#

Try it online!

Lua, 99 Bytes
I started looking for improvements for this answer, but ended with a solution that I find sufficently different to be an answer on its own.
As usual, you can Try it online!
It takes input as a list of arguments, and outputs each number separated by commas.
The top of the stack (first element to pop()) is the last one printed
r={}for i=1,#arg
do
a=arg[i]+0s=a>0 and a or x
r[#r+(s and 1or 0)]=s
end
print(table.concat(r,","))

Ungolfed
r={}          -- Define our output array
for i=1,#arg  -- iterate over the argument
do
a=arg[i]+0    -- shorthand for the current argument, add 0 to coerce it into a number
s=a>0         -- s define the operation to do in the current loop
    and a     -- if a>0, then s=a
  or x        -- else, s=x, x isn't initialiazed, so it's equivalent to s=nil

r[#r+         -- modify the end of the array
  (s          -- if s is true (which means not nil)
      and 1   -- add 1 to the current index to perform a push
    or 0)]    -- else, let it alone, which means we overwrite the last value of the table
  =s          -- attrib s to that index

  --[[
    if s is nil, it gives us, ungolfed, r[r.length+0]=nil, which erase the last value we have
    if s is a number, it's equivalent to r[r.length+1]=arg[i], or table.push(r, arg[i])
  ]]
end

print(table.concat(r,",")) -- outputs the table separating each element by commas

97 bytes. I think you could also save bytes by using an anonymous function with loadstring, but that's up to you if you want that

Dart, 69 bytes
f(l){var m=[];l.forEach((n){n>0?m.add(n):m.removeLast();});return m;}

Alternative
f(l,{m=List}){l.forEach((n){n>0?m.add(n):m.removeLast();});return m;}
Try it online!
Naive answer until I find a better way.

Common Lisp, 54 bytes
(let(s)(dolist(x(read)s)(if(= 0 x)(pop s)(push x s))))

Ultra-straightforward implementation!
Try it online!

Burlesque - 27 bytes
%f={Jz?{vvvv}if}ps(%f!)[]e!

But this is rather bad to be honest. Anyway:
%f={Jz?{vvvv}if}             defines f
                ps           parse
                  (%f!)      quoted call to f
                       []    intersperse
                         e!  eval

This essentially inserts a call to f between the numbers.
J            duplicate
 z?          zero?
   {vvvv}    pop two elemnets
         if  if

05AB1E, 8 bytes
0'\‡».V)

Try it online!
0'\‡».V)  # full program
     .V   # run...
          # implicit input...
   ‡      # with all digits of...
0         # literal...
   ‡      # replaced with corresponding characters in...
 '\       # literal...
    »     # joined by newlines...
     .V   # as 05AB1E code
       )  # push stack
          # implicit output

Pxem, filename only: 51 bytes.
Emulating stack with stack-based language. \001 is unprintable character 0x01.
.w._.c.w.cXXX.-.a.s.s.c\001.+.a.sL.w.n.c.c.z.d.a,.oL.a

Try it online!
Usage

Input as strings of decimal integers, from stdin.
Separate each item of list with one or more blank characters, from begining to end.
Append -1 to indicate end of list.
Output is to stdout, separated with a comma.

How it works
XX.z
# while stack is empty or pop!=0; do
.a.wXX.z
 # get integer from stdin, and push it
 .a._XX.z
 # dup; while pop!=0; do
 .a.c.wXX.z
  # dup; push dummy item; break; done
  .a.cXXX.-.aXX.z
 # pop twice and discard them
 .a.s.sXX.z
# dup; add one; done
.a.c\001.+.aXX.z
# pop
.a.sXX.z
# while :; do
# NOTE L is for dummy
.aL.wXX.z
 # pop and print it as an integer
 .a.nXX.z
 # dup; dup; while size<2||pop!=pop; do exit; done
 # NOTE dup is not done if empty
 .a.c.c.z.d.aXX.z
 # print a comma; done
 .a,.oL.a

JavaScript (Node.js), 53 bytes
(l,n=[])=>(l.map(t=>t?n.push(t):n.pop()),n.reverse())

Try it online!
More readable version
(list, stack=[]) =>
    (list.map(t =>
        t ? stack.push(t) : stack.pop()
    ), stack.reverse())

APL (Dyalog APL), 37 36 bytes
{{t←1-⍨o←⍵⍳0⋄o<≢⍵:⍵[t o~⍨⍳≢⍵]⋄⍵}⍣≡⍵}

Attempt This Online!
Whew this took me hours. 99% sure can still be golfed.
{{t←1-⍨o←⍵⍳0⋄o<≢⍵:⍵[t o~⍨⍳≢⍵]⋄⍵}⍣≡⍵}
{                                     } ⍝ Define a function
                                   ⍣≡   ⍝ Iterate until fixed point
                                     ⍵  ⍝ Starting with the input
 {                                }     ⍝ The function to iterate
         ⍵⍳0                            ⍝ Find the 1st 0
       o←                               ⍝ Store it in the variable 'o'
    1-⍨                                 ⍝ Subtract 1
  t←                                    ⍝ Store it in the variable 't'
            ⋄                           ⍝ <statement separator>
             o<                         ⍝ Is o less than
               ≢⍵                      ⍝ The length of the input?
                  :                     ⍝ If true
                   ⍵[         ]        ⍝ Keep the following indexes:
                           ⍳≢⍵            ⍝ Generate the indexes of the input array
                          ~               ⍝ Remove from ^
                      t o                 ⍝ The values in t and o
                                ⋄      ⍝ If false
                                 ⍵     ⍝ Return the input

Python 2, 65 bytes
def f(p,s=[]):
 for i in p:
  if i:s+=i,
  else:s.pop()
 return s

Try it online!

Actually, when written this way the function is non-reusable.

@user202729 What does non-reusable mean?

https://codegolf.meta.stackexchange.com/questions/4939/do-function-submissions-have-to-be-reusable

@user202729 Oh, I didn't realise

JavaScript (Node.js), 63 bytes
a=>{let b=[];a.map(x=>x?b.push(x):b.pop());return b.reverse();}

Try it online!
Can probably be improved

49 bytes in right order  a=>a.reduce((r,i)=>i?[i].concat(r):r.slice(1),[]). Reverse order I see nothing beating @Shaggy's answer

@AlexisFacques 44 bytes: a=>a.reduce((r,i)=>i?[i,...r]:r.slice(1),[])

JavaScript (ES6), 44 bytes
This code works directly on the original array rather than creating a new one. This is however longer than @Shaggy's answer.
a=>a.reverse(x=0).filter(n=>n?x?!x--:1:!++x)

Try it online!

Python 3, 186 bytes
l = list()
while True:
    one = int(input())
    if one<0:
        break
    elif one==0:
        if len(l)>0:
            l.pop()
    else:
        l.append(one)

l.reverse()
print(l)

Try it online!

You place the language and byte code in your actual answer, not in the comments.

Welcome to PPCG! This seems to be erroring. Also you need to add a byte-count and provide the language name in the answer itself.

@OMᗺ That's because the answer requires a negative integer to indicate EOF (I believe you permitted this in the spec).

94 bytes: https://bit.ly/2uRGQmj

Ah that works! Yes, I did indeed. I took the freedom of editing the answer, if you're not happy with my edit, feel free to format it differently (however language name and byte-count should still be present) and incorporate the suggested golfs.

13 bytes off of the golf suggested by O.O.Balance: Try it online!

@O.O.Balance if you're language doesn't has native support for lists ... I think that Python does.

@Titus we don't usually make different rules for different languages – but you are right, that is what it says. OP does not seem to mind – I'll ask them to clarify.

@Titus OP has now clarified that all languages may take input this way.

Python 3, 60 bytes
def f(L,r=[]):
 for n in L:r=[n]+r if n else r[1:]
 return r

Try it online!

Pepe, 57 bytes
rrEEReRerEerEEEEerEERrERREeEreErEEEEereeRrErEEReEEReeEree

Try it online!
Requires the input to end with -1. Note that "Separated by" option must be enabled. You might prefer to change the separator to , (it's a ; by default). Also, putting ,-1 on a newline might help you not accidentally remove the ,-1, preventing infinite loops and browser crashes.
Explanation
Text in brackets [] are values taken from the stack, r is the control-flow stack, R is the data stack
# prepare (11 bytes)
rrEE           # Define [implicit 0] as
  Re Re          # Double pop from R
rEe            # Return

# main (29 bytes)
rEEEEe         # Decrement [implicit 0], always returns -1
rEE            # Create label [-1]
  RrE            # Prepend 0 to r
  RREeE          # Prepend input to R
  reE            # Execute 0 (double pop) if [input] was 0
  rEEEEe         # Decrement [0] in r, always returns -1
ree           # If [input] wasn't -1, goto label -1

# output (17 bytes)
RrE           # Prepend 0 to r
rEE           # Create label [0]
  ReEE ReeE     # Output [pop R] and a newline
ree           # If there's anything on the stack (non-zero), goto [0]

sed, 42 bytes
s/^/%/
:l
s/!+,%0,/%/;tl
s/%(!+),/\1,%/;tl

Try it online!
The top of the stack is on the right. Input and output are in unary, separated by a comma. Zeroes are represented by the digit 0.

Pyth, 13 bytes
 m?daYd.)YQ_Y

Try it online!

Go, 90 bytes
func f(i[]int)(o[]int){for _,e:=range i{if e>0{o=append(o,e)}else{o=o[:len(o)-1]}}
return}

Attempt This Online!
Implements a stack where the last element is the top of the stack.

Vyxal W, 8 bytes
(n¨in_)^

Try it Online!
A no-eval approach
Explained
(n¨in_)^
(     )   # For each item in the input
 n        # Push n
  ¨in_    # if that's truth, push n again, else pop top
       ^  # reverse the stack for outputting with W flag

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

authors: Евгений Новиков

sort: votes


text:
Remove surrounding zeroes of a 2d array
This is a 2-dimensional version of this question.
Given a non-empty 2-dimensional array/matrix containing only non-negative integers:
$$ \begin{bmatrix}
{\color{Red}0} & {\color{Red}0} & {\color{Red}0} & {\color{Red}0} & {\color{Red}0} \\
{\color{Red}0} & {\color{Red}0} & 0 & 1 & 0 \\
{\color{Red}0} & {\color{Red}0} & 0 & 0 & 1 \\
{\color{Red}0} & {\color{Red}0} & 1 & 1 & 1 \\
{\color{Red}0} & {\color{Red}0} & {\color{Red}0} & {\color{Red}0} & {\color{Red}0}
\end{bmatrix} $$
Output the array with surrounding zeroes removed, i.e. the largest contiguous subarray without surrounding zeroes:
$$ \begin{bmatrix}
0 & 1 & 0 \\
0 & 0 & 1 \\
1 & 1 & 1
\end{bmatrix} $$
Examples:
$$ \begin{bmatrix}
{\color{Red}0} & {\color{Red}0} & {\color{Red}0} & {\color{Red}0} & {\color{Red}0} \\
{\color{Red}0} & {\color{Red}0} & 0 & 1 & 0 \\
{\color{Red}0} & {\color{Red}0} & 0 & 0 & 1 \\
{\color{Red}0} & {\color{Red}0} & 1 & 1 & 1 \\
{\color{Red}0} & {\color{Red}0} & {\color{Red}0} & {\color{Red}0} & {\color{Red}0}
\end{bmatrix}
\mapsto
\begin{bmatrix}
0 & 1 & 0 \\
0 & 0 & 1 \\
1 & 1 & 1
\end{bmatrix}
$$
Input:
[[0, 0, 0, 0, 0], [0, 0, 0, 1, 0], [0, 0, 0, 0, 1], [0, 0, 1, 1, 1], [0, 0, 0, 0, 0]]

Output:
[[0, 1, 0], [0, 0, 1], [1, 1, 1]]

$$ \begin{bmatrix}
{\color{Red}0} & {\color{Red}0} & {\color{Red}0} & {\color{Red}0} \\
{\color{Red}0} & 0 & 0 & 3 \\
{\color{Red}0} & 0 & 0 & 0 \\
{\color{Red}0} & 5 & 0 & 0 \\
{\color{Red}0} & {\color{Red}0} & {\color{Red}0} & {\color{Red}0}
\end{bmatrix}
\mapsto
\begin{bmatrix}
0 & 0 & 3 \\
0 & 0 & 0 \\
5 & 0 & 0
\end{bmatrix}
$$
Input:
[[0, 0, 0, 0], [0, 0, 0, 3], [0, 0, 0, 0], [0, 5, 0, 0], [0, 0, 0, 0]]

Output:
[[0, 0, 3], [0, 0, 0], [5, 0, 0]]

$$ \begin{bmatrix}
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9
\end{bmatrix}
\mapsto
\begin{bmatrix}
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9
\end{bmatrix}
$$
Input:
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

Output:
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

$$ \begin{bmatrix}
{\color{Red}0} & {\color{Red}0} & {\color{Red}0} & {\color{Red}0} \\
{\color{Red}0} & {\color{Red}0} & {\color{Red}0} & {\color{Red}0} \\
{\color{Red}0} & {\color{Red}0} & {\color{Red}0} & {\color{Red}0}
\end{bmatrix}
\mapsto
\begin{bmatrix}
\end{bmatrix}
$$
Input:
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

Output:
[]

$$ \begin{bmatrix}
{\color{Red}0} & {\color{Red}0} & {\color{Red}0} & {\color{Red}0} \\
1 & 1 & 1 & 1 \\
{\color{Red}0} & {\color{Red}0} & {\color{Red}0} & {\color{Red}0}
\end{bmatrix}
\mapsto
\begin{bmatrix}
1 & 1 & 1 & 1
\end{bmatrix}
$$
Input:
[[0, 0, 0, 0], [1, 1, 1, 1], [0, 0, 0, 0]]

Output:
[[1, 1, 1, 1]]

$$ \begin{bmatrix}
{\color{Red}0} & 1 & {\color{Red}0} & {\color{Red}0} \\
{\color{Red}0} & 1 & {\color{Red}0} & {\color{Red}0} \\
{\color{Red}0} & 1 & {\color{Red}0} & {\color{Red}0}
\end{bmatrix}
\mapsto
\begin{bmatrix}
1 \\
1 \\
1
\end{bmatrix}
$$
Input:
[[0, 1, 0, 0], [0, 1, 0, 0], [0, 1, 0, 0]]

Output:
[[1], [1], [1]]

$$ \begin{bmatrix}
1 & 1 & 1 & 1 \\
1 & 2 & 3 & 1 \\
1 & 1 & 1 & 1
\end{bmatrix}
\mapsto
\begin{bmatrix}
1 & 1 & 1 & 1 \\
1 & 2 & 3 & 1 \\
1 & 1 & 1 & 1
\end{bmatrix}
$$
Input:
[[1, 1, 1, 1], [1, 2, 3, 1], [1, 1, 1, 1]]

Output:
[[1, 1, 1, 1], [1, 2, 3, 1], [1, 1, 1, 1]]

This is very difficult in JavaScript. I'm looking forward to a concise answer in that language.

@MattH Nothing is difficult in a non-esoteric language. :) Just difficult to make it short.

Can we give a falsey output instead of an empty matrix, for the last test case?

Also, if output can be a non-square matrix, please add a test case for that.

A test case that broke my earlier submission: [[0, 0, 0, 0], [0, 0, 0, 0], [1, 1, 1, 1], [0, 0, 0, 0]] (the result having a width/height of 1)

@sundar What does that falsey value look like? If it is just false, I think it is OK.

Hey, is it possible to add the test case $$\begin{bmatrix}1&1&1&1\1&2&3&1\1&1&1&1\end{bmatrix}$$

I would suggest adding a test case like this as well:
$$ \begin{bmatrix}
{\color{Red}0} & 1 & {\color{Red}0} & {\color{Red}0} \
{\color{Red}0} & 1 & {\color{Red}0} & {\color{Red}0} \
{\color{Red}0} & 1 & {\color{Red}0} & {\color{Red}0}
\end{bmatrix}
$$

MATL, 3 bytes
JYa

Try it online! Or verify all test cases.
Explanation
J      % Push 1j
Ya     % With complex 2nd input, this unpads the matrix in the
       % 1st input (implicit). The unpad value is 0 by default
       % Display (implicit)

"JYa JYa JYa JYa"

I like how half the code is just (implicit).

Wolfram Language (Mathematica), 42 bytes
#&@@CellularAutomaton[{,{},0{,}},{#,0},0]&

Try it online!
Cellular automata are indeed the answer to life, the universe, and everything.1
How?
CellularAutomaton accepts an input array and an optional background value. Thus, {#,0} specifies that a cellular automaton rule should be applied to the input, assuming a background of 0s.
A neat thing here is that CellularAutomaton crops the output so that no border of background cells is present (because otherwise the output lies on an infinite plane).
The code applies the rule {Null, {}, {0, 0}} -- applying the head Null to the 0-radius neighbor of each cell (i.e. only the center: the cell itself) -- exactly 0 times. The result of this is the original input, but with background removed (i.e. cropping out surrounding 0s).

1. See the bytecount of my answer? ;)

Nice builtin abuse... well Mathematica has a built-in, just not exposed directly.

No XKCD 505 reference?

+1 for Cellular Automata & the Ultimate Answer.

JavaScript (ES6), 98 bytes
(a,z)=>(g=A=>A.slice(A.map(m=M=(r,i)=>M=(z?a:r).some(n=>z?n[i]:n)?1/m?i:m=i:M)|m,M+1))(a).map(z=g)

Try it online!
How?
To overcome the lack of a zip built-in, we define a function g() that is able to operate on either the rows or the columns of the input matrix a[ ], depending on the value of the global flag z.
g() looks for the minimum index m and maximum index M of either non-empty rows (if z is undefined) or non-empty columns (if z is defined) and returns the corresponding slice of either the matrix itself or a given row of the matrix.
To summarize:

we first remove rows by invoking g() on the matrix with z undefined
we then remove columns by invoking g() on each row with z defined, which leads to this rather unusual .map(z=g)

Commented
(a, z) => (               // a[] = input matrix; z is initially undefined
  g = A =>                // g() = function taking A = matrix or row
    A.slice(              //   eventually return A.slice(m, M + 1)
      A.map(m = M =       //     initialize m and M to non-numeric values
        (r, i) =>         //     for each row or cell r at position i in A:
        M = (z ? a : r)   //       iterate on either the matrix or the row
        .some(n =>        //       and test whether there's at least one
          z ? n[i] : n    //       non-zero cell in the corresponding column or row
        ) ?               //       if so:
          1 / m ? i       //         update the maximum index M (last matching index)
                : m = i   //         and minimum index m (first matching index)
        :                 //       otherwise:
          M               //         let M (and m) unchanged
      ) | m,              //     end of map(); use m as the first parameter of slice()
      M + 1               //     use M+1 as the second parameter of slice()
    )                     //   end of slice()
  )(a)                    // invoke g() on the matrix with z undefined
  .map(z = g)             // invoke g() on each row of the matrix with z defined

That is impressive.

@Jek, Arnauld lives in a whole different dimension.  But if you're extremely lucky, you can occasionally find a trick that he missed and post a shorter solution.  In the process, you'll develop a very deep understanding of JavaScript.

@RickHitchcock I'm not that good at code pattern recognition and I'm regularly missing a lot of things, even if I've seen them before. In this particular example, I was focused on the reusability of g() and missed quite an obvious optimization on the way to update m and M (-9 bytes). I fully agree that code-golfing is a great (and fun) way to learn a lot about the subtleties of a language.

Haskell, 62 61 bytes
f.f.f.f
f=reverse.foldr(zipWith(:))e.snd.span(all(<1))
e=[]:e

Try it online!
foldr(zipWith(:))e with e=[]:e is a slightly shorter transpose, and snd.span(all(<1)) drops leading lists of zeros from a list of list. As transpose followed by reverse on a 2D list equals an rotation by 90°, the code f.f.f.f is just four times drop leading lists of zeros and rotate.

Pyth, 13 bytes
V2=.sCQ]m0Q;Q

Try it online!

I think =_CQ would work in place of =Q_CQ.

R, 96 100 97 bytes
function(m)m[~m,~t(m),drop=F]
"~"=function(x,z=seq(r<-rowSums(x)))z>=min(y<-which(r>0))&z<=max(y)

Try it online!
The ~ helper takes a non-negative vector and returns a vector with FALSE for the "exterior" 0s of the vector and TRUE for positives and any "interior" 0s. This function is applied to the row and column sums of the input matrix.
~ and ! use R's parser treatment of operators.
Corrected as per @DigEmAll's comment, but with some bytes golfed back from @J.Doe

I think you should add drop=F as I did, otherwise these 2 tests will return a vector instead of row and column : Try it online!

97 bytes with drop=F. Still under a ton!

Jelly, 10 bytes
œr€0z0Uµ4¡

Try it online!

Brachylog, 24 22 20 19 bytes
{s.h+>0∧.t+>0∧}\↰₁\

Try it online!
Outputs the result matrix as an array of arrays, or false for empty output.
(Thanks to @Fatalize for suggesting inline predicate and saving 1 byte.)
Explanation
Predicate 0 (Main):
{...}     Define and call predicate 1 to remove all-zero rows
  \       Transpose the result
   ↰₁     Call pred 1 again, now to remove all-zero columns
     \    Transpose the result to have correct output orientation

Predicate 1:
?s.h+>0∧.t+>0∧
  .           output is
 s              a subsequence of the rows of
?              the input (implicit)
   h          also, output's head element (first row)
    +>0        has a sum > 0 (i.e. has at least one non-zero value)
       ∧.t+>0  and similarly the output's tail element (last row)
∧              (don't implicitly unify that 0 with the output)

Writing the first predicate inline is 1 byte shorter: {s.h+>0∧.t+>0∧}\↰₁\ . (this is true for pretty much any Brachylog answer, predicates on new lines is really only implemented if you want to write more readable things).

@Fatalize Thanks, updated (finally!). I never thought about how inline predicate syntax is both a definition and predicate application, pretty cool.

R, 89 79 bytes
function(m,y=apply(which(m>0,T),2,range)){y[!1/y]=0;m[y:y[2],y[3]:y[4],drop=F]}

Try it online!
Thanks to @ngm for the test cases code, and @J.Doe for saving 10 bytes !

I had to add drop=F parameter due to the default R behavior turning single row/col matrix into vectors...

I didn't notice that my previous code was failing the all-zero cases... now it's fixed unfortunately with a lot more bytes :(

I wish i could +2 this. Really nice use of fivenum.

79 bytes using range and tweaking the indexation

@J.Doe: range, of course ! great idea thanks !

APL (Dyalog Classic), 17 15 bytes
{⍉⌽⍵⌿⍨∨\∨/×⍵}⍣4

Try it online!

Wolfram Language (Mathematica), 66 bytes
If[Max@#>0,ImageCrop@Image[#~ArrayPad~1,r="Real"]~ImageData~r,{}]&

Try it online!
Now works by padding the array with zeroes (thanks @JungHwanMin)!
A second thanks to @JungHwanMin for saving 4 bytes

Python 2, 71 bytes
Returns by modifying the input. A list should be passed as input.
def f(a):exec'while a and 1>sum(a[-1]):a.pop()\na[:]=zip(*a)[::-1]\n'*4

Try it online!

Python 2, 77 bytes
This also modifies the input, but it works....
def f(a):exec'while a and 1>sum(a[-1]):a.pop()\na=zip(*a)[::-1]\n'*4;return a

Try it online!

J, 24 bytes
(|.@|:@}.~0=+/@{.)^:4^:_

Try it online!
Explanation
(|.@|:@}.~0=+/@{.)^:4^:_
            +/                sum
              @               of
               {.             the first row
          0=                  is zero? (1 = true, 0 = false)
       }.~                    chop off that many rows from the front
 |.@|:@                       rotate by 90 deg (transpose then reverse)
(                )^:4         repeat this process 4 times (rotating a total of 360 deg)
                     ^:_      fixpoint - repeat until no change

Python 2, 118 116 bytes
f=lambda a,n=4,s=sum:n and f(zip(*a[max(i for i in range(len(a))if s(s(a[:i],()))<1):][::-1]),n-1)or(s(s(a,()))>0)*a

Try it online!

Saved:

-2 bytes, thanks to shooqie

You can save two bytes by assigning s=sum in lambda definition

Jelly, 12 bytes
Ṗ§Ṫ¬ȧƲ¿UZµ4¡

Try it online!
As a function.

Wolfram Language (Mathematica), 48 bytes
Nest[Reverse@Thread@#//.{{0..},a___}->{a}&,#,4]&

Try it online!
Doing it the normal way.

Unfortunately \[Transpose] can't work here.

Ruby, 73 63 bytes
->a{4.times{_,*a=a while a[0]&.sum==0;a=a.reverse.transpose};a}

Try it online!
Edit: simplified, also the previous version crashed for all 0s
How it works:

do 4 times:

remove the first line while there is a first line and it's full of 0s
rotate the array clockwise by 90°

return the array

The link is correct, but your answer in the code block says &.sum<0 instead of &.sum<1.

@ConorO'Brien my bad, new version didn't work for empty array (nil<1). Thanks for noticing anyway

Octave, 48 49 bytes
@(a)sparse(1-min([x y v]=find(a))+x,1-min(y)+y,v)

Try it online!
Find nonzero points and rearrange them in a new sparse matrix.

@alephalpha Answer updated!

K (ngn/k), 22 19 bytes
4{+|(+/&\~+/x)_'x}/

Try it online!

Husk, 11 bytes
!5¡(T0mo↔↓¬

Try it online!
I feel like some bytes could be shaved off by shortening the !5¡ part.
How it works
!5¡(

Repeatedly apply the function explained below, collecting the results in an infinite list. Then, retrive the \$5^{\text{th}}\$ element. In other words, apply the function to the input 4 times.
mo↔↓¬

Map over the current version of the input and: reverse each, after having dropped the longest prefix consiting of zeroes only (dropping this prefix is performed by using Husk's ↓, which is a function that crops the longest run of consecutive elements from the beginning of the list that yield truthy results when ran through a function, namely ¬, logical not).
T0

Transpose, replacing missing entries with 0.

Retina, 87 bytes
/.\[(?!0,)/^+`\[0,
[
/(?<! 0)]./^+`, 0]
]
\[(\[0(, 0)*], )+
[
(, \[0(, 0)*])+]|\[0]]
]

Try it online! Explanation:
/.\[(?!0,)/^+`

Until at least one row doesn't begin with zero...
\[0,
[

... remove the leading zero from each row.
/(?<! 0)]./^+`

Until at least one row doesn't end with zero...
, 0]
]

... remove the trailing zero from each row.
\[(\[0(, 0)*], )+
[

Remove leading rows of zeros.
(, \[0(, 0)*])+]|\[0]]
]

Remove trailing rows of zeros, or the last remaining zero.

@RickHitchcock It's format sensitive, add in the spaces: Try it online!

Charcoal, 48 bytes
Ｆ⁴«Ｗ∧θ¬Σ§θ±¹Σ⊟θ¿θ≔⮌Ｅ§θ⁰Ｅθ§§θνλθ»⪫[]⪫Ｅθ⪫[]⪫ι, ¦,

Try it online! Link is to verbose version of code. Includes 15 bytes for formatting. Explanation:
Ｆ⁴«

Repeat 4 times.
Ｗ∧θ¬Σ§θ±¹

Repeat while the array is not empty but its last row sums to zero...
Σ⊟θ

Remove the last row from the array and print a line of the length of its sum, i.e. nothing.
¿θ≔⮌Ｅ§θ⁰Ｅθ§§θνλθ»

If the array isn't empty then transpose it.
⪫[]⪫Ｅθ⪫[]⪫ι, ¦,

Format the array nicely for display. (Standard output would be Ｉθ instead.)

JavaScript, 144 140 129 127 bytes
w=>(t=w=>(q=(s=w=>w.some((r,j)=>r.find(e=>e,i=j))?w.slice(i).reverse():[[]])(s(w)))[0].map((e,j)=>q.map((e,i)=>q[i][j])))(t(w))

140 -> 129 bytes, thanks @Arnauld
Algorithm

Do twice:

Find first non-zero row
Slice off preceding rows
Reverse
Find first non-zero row
Slice off preceding rows
Reverse
Transpose

f = w=>(t=w=>(q=(s=w=>w.some((r,j)=>r.find(e=>e,i=j))?w.slice(i).reverse():[[]])(s(w)))[0].map((e,j)=>q.map((e,i)=>q[i][j])))(t(w));

w1 = [[0, 0, 0, 0, 0], [0, 0, 0, 1, 0], [0, 0, 0, 0, 1], [0, 0, 1, 1, 1], [0, 0, 0, 0, 0]];
w2 = [[0, 0, 0, 0], [0, 0, 0, 3], [0, 0, 0, 0], [0, 5, 0, 0], [0, 0, 0, 0]];
w3 = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
w4 = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]];

console.log(f(w1).join("\n"));
console.log(f(w2).join("\n"));
console.log(f(w3).join("\n"));
console.log(f(w4));

You can save 7 bytes by using some/some instead of findIndex/find and rearranging the helper function declarations to get rid of the parenthesis around the (now single) main function argument.

I think you can save 4 more bytes by having s return [[]] so that t is guaranteed to be able to operate on w[0].

PHP (>=5.4), 200 194 186 184 bytes
(-6 bytes by returning null instead of empty array)
(-8 bytes thanks to Titus)
(-2 bytes with calling by reference thanks to Titus)
function R(&$a){$m=$n=1e9;foreach($a as$r=>$R)foreach($R as$c=>$C)if($C){$m>$r&&$m=$r;$M>$r||$M=$r;$n>$c&&$n=$c;$N>$c||$N=$c;}for(;$m<=$M;)$o[]=array_slice($a[$m++],$n,$N-$n+1);$a=$o;}

Try it online!
How?
Finds min and max index for rows ($m & $M) and columns ($n & $N) and replaces the input with a sub array from $m,$n to $M,$N (this is a call by reference).

Save 6 bytes with if($C){$m>$r&&$m=$r;$M>$r||$M=$r;$n>$c&&$n=$c;$N>$c||$N=$c;}

... and two bytes with while($m<=$M)$o[]=array_slice($a[$m++],$n,$N-$n+1);

@Titus: Thanks for the great tips. Loved the trick of using && and || and I'm sure I will be able to use that trick in other places as well.

You can save another two bytes with call by reference: $a= instead of return.

Octave, 78 74 bytes
function x=f(x)
for k=1:nnz(~x)*4,x=rot90(x);x=x(:,~~cumsum(any(x,1)));end

Try it online!
Explanation
This rotates the matrix by 90 degrees (x=rot90(x)) a sufficient number of times (for k=1:... end). The number of rotations is a multiple of 4, so the final matrix has the original orientation. Specifically, the number of rotations is 4 times the number of zeros in the matrix (nnz(~x)*4).
For each rotation, if there are one or more columns on the left consisting of only zeros they are removed (x=x(:,~~cumsum(any(x,1)))).
What remains of the matrix after this process is output by the function (function x=f(x)).

Japt -h, 23  11 bytes
4Æ=sUb_dÃ z

Try it

Explanation
                :Implicit input of 2D-array U
4Æ              :Map the range [0,4)
   s            :  Slice U from
    Ub          :   The first index in U where
      _dÃ       :    Any element is truthy (not zero)
          z     :  Rotate 90 degrees
  =             :  Reassign to U for the next iteration
                :Implicitly output the last element

Clean, 73 bytes
import StdEnv,StdLib
$ =dropWhile(all((>)1))o reverse o transpose

$o$o$o$

Try it online!
Very similar to Laikoni's Haskell answer.

Attache, 40 bytes
Fixpoint[{Flip!_[N[0=Sum!_@0]...#_]}//4]

Try it online! Same business as below, just a bit smarter, splitting the process into four steps instead of two.
Alternatives
47 bytes: Fixpoint[{Reverse=>Tr!_[N[0=Sum!_@0]...#_]}//4]
48 bytes: Fixpoint[{MatrixRotate!_[N[0=Sum!_@0]...#_]}//4]

Attache, 68 bytes
Fixpoint[{n.=Dim@_@-1Tr[{_@1!in~-n'0or Sum!_@0}\Enumerate@_<:0]}//2]

Try it online!
Twice: This removes any first or last row whose sum is 0, then transposes the array. Then, this process is repeated until the result does not change.

Stax, 14 bytes
Ç·W≈y§╗♦º{¬║8•

Run and debug it
Alternative, also 14 bytes
Ç·W≈x≈ƒHq♣☻»íÅ

Run and debug it

PHP, 188 bytes
function f(&$a){for($s=array_shift;!max($a[0]);)$s($a);for($p=array_pop;!max(end($a));)$p($a);for($w=array_walk;!max(($m=array_map)(reset,$a));)$w($a,$s);while(!max($m(end,$a)))$w($a,$p);}

call by reference.
breakdown
// call by reference
function f(&$a)
{
    // while first row is all zeroes, remove it
    while(!max($a[0]))array_shift($a);
    // while last row is all zeroes, remove it
    while(!max(end($a)))array_pop($a);
    // while first column is all zeroes, remove it
    while(!max(array_map(reset,$a)))array_walk($a,array_shift);
    // while last column is all zeroes, remove it
    while(!max(array_map(end,$a)))array_walk($a,array_pop);
}

05AB1E (legacy), 13 bytes
2Fζ2FRDv¬O_i¦

Try it online or verify all test cases.
Explanation:
2F                    # Loop two times:
  ζ                   #  Zip/transpose; swapping rows/columns
                      #  (takes the input-matrix implicitly in the first iteration)
   2F                 #  Inner loop two times:
     R                #  Reverse the rows
      Dv              #  Inner loop over the rows:
        ¬             #   Get the first row (without popping the matrix)
         O_i          #   If the row consists only of 0s:
            ¦         #    Remove this first row from the matrix
                      # (output the result implicitly)

The 2nd test case should output [[0, 0, 3], [0, 0, 0], [5, 0, 0]].

@Shaggy Almost 5 months later, but it's fixed now (and 1 byte smaller in the process). xD

Python 2, 86 bytes
lambda a,l=1:a if l>4else([a.pop()for b in a if sum(a[-1])<1],f(zip(*a[::-1]),l+1))[1]

Try it online!
Takes a list of lists, returns a list of tuples.
Explanation
Abuses the heck out of list comprehension. This is the equivalent expanded code:
def f(a,l=1):
    # after 4 rotations, the list is back in its original orientation, return
    if l > 4:
        return a
    else:
        # helper variable to store return values
        ret = []
        # "trim" all rows from "bottom" of list that only contain 0s
        # since we are always checking le that item in the list, don't need range(len(a))
        # since we are only removing at most one item per iteration, will never try to remove more than len(a) items
        # brackets surrounding generator force it to be consumed make a list, and therefore actually pop() list items
        ret.append([a.pop() for b in a if sum(a[-1]) < 1])
        # rotate the array, increase the number of rotations, and recursively call this function on the new array/counter
        ret.append(f(zip(*a[::-1]), l + 1)))
        # we only put both items in a list in order to stay in the one-line lambda format
        # discard the popped items and return the value from the recursive call
        return ret[1]

JavaScript (Node.js), 100 bytes
f=(a,i=4,b=a[0])=>b&&i?/[1-9]/.test(b)?f([...b].map((c,j)=>a.map(d=>d.pop())),i-1):f(a.slice(1),i):a

Try it online!

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/