实现堆栈


44

我不敢相信我们还没有这个。.它是编程中最重要的数据结构之一,但仍然足够简单,可以在

挑战

您的任务是实现允许压入和弹出数字的堆栈,以测试实现并保持I / O简单,我们将使用以下设置:

  • 输入将是非负整数列表

每个正整数表示一个,每个表示一个 -丢弃顶部元素。push( n 0 pop()npush(n)0pop()

  • 输出将是结果堆栈

例如,如果我们得到:[12,3,0,101,11,1,0,0,14,0,28]

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]

输出将是:[28,101,12]

规则

  • 输入将是任何默认I / O格式的非负整数列表
    • 您可以使用负整数来表示整数流的结尾
  • 输出将是结果堆栈的列表/矩阵/ ..
    • 您可以选择顶部元素的位置(在开头还是结尾),输出必须保持一致
    • 输出是灵活的(例如,用换行符分隔的整数就可以了),唯一重要的是顺序
    • 您可以使用负整数来表示堆栈的底部
  • 您可以保证堆栈为空时永远不会为0

例子

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

12
应该注意的是,给定条件,实际上并不需要实现堆栈。
杰夫·齐特林'18

如果希望某人实际实现堆栈,则可能需要尝试将某些内容放入沙箱中。
mbomb007 '18

@ mbomb007:要么是正确的:“你的选择,其中顶元素将是(在开头或结尾)”
ბიმო

@ mbomb007:如果您不得不撤消输入,这不会再困难了吗?此外,如果您将设置看作是一个堆栈,它定义了什么是顶部,什么是底部,为什么一个定义应该没有那么随意?
ბიმო

@OMᗺ因为输入看起来有点像堆栈/列表/数组。现在,整个挑战基本上是删除任何数字,然后删除零。
mbomb007 '18

Answers:


19

MATL,6个字节

"@?@}x

输入是数字的行向量。

最终的堆栈显示为上下颠倒,下面是最新的元素。

在线尝试!验证所有测试用例

说明

"         % 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)

13

Java(JDK 10),42字节

由于“输出是灵活的,唯一重要的是顺序”,因此这会将输入数组更改为以- 0结尾的数组。示例:[1,0,2]将返回[2,0,2],将其解释为= 。[2,0,2][2]

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

在线尝试!

之前的版本:

Java(JDK 10),60字节

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

在线尝试!

学分:

如果我可以以错误结束程序:55个字节

(尽管一切都已正确修改)

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

在线尝试!


4
这是相当令人印象深刻的。您可以使用丢失1个字节,>0因为列表的开头永远不会为零(这意味着堆栈的顶部位于-1)。
OOBalance

@OOBalance的确,我没有考虑过。,谢谢!
奥利维尔·格雷戈尔

12

Sed,17字节

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

@OMᗺ-3个字节,@ eggyal -1

因为可以保证永远不会弹出一个空列表,所以除了迭代有限状态机外,您只需要其他内容。正则表达式是用于构建有限状态机的工具,并且sed可以进行迭代。这是天造地设的一场比赛。

接受来自stdin的输入,如下所示:

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

反向输出堆栈:

[12,101,28]

如果我本地本地sed理解的字符类(例如)可以缩小两个字节\d,但这不是出于某种原因。


1
欢迎来到PPCG!很好,我的更长(使用不同的输入格式)。您可以使用一个空标签,因为您只使用1,并且由于您重复了该过程,因此g是多余的-为您节省了4个字节:在线尝试!
ბიმო

g不是多余的!这使得最坏情况下的运行时复杂性取决于连续弹出的深度,而不是弹出的数量!在代码高尔夫中,效率并不重要:)
Tacroy

1
您的最后一句话回答了有关冗余:P Btw的问题。您如何计算字节数?我18岁,可能您在末尾加上了换行符。
ბიმო

是的,这是换行符。
Tacroy

1
如果输入的最后一个元素为0,那么您的正则表达式将不会匹配它。
eggyal '18

12

PowerShell46 41 40字节

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

在线尝试!

通过拼写输入,例如,$z=@(12,3,0,101,11,1,0,0,14,0,28); .\implement-stack.ps1 @z在TIO上显示为单独的参数。

$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个字节,感谢mazzy。
-1字节交换$_1


splatting是否保存3个字节$agrs?:)
mazzy

-2个字节$args|%{$x,$a=&({$_,$_+$a},{$a})[!$_]};$a
mazzy

1
@mazzy是的,我们刚才谈到飞溅!我已经忘了!哈哈谢谢!
AdmBorkBork

不会.\implement-stack.ps1 @z(不是$z),否则,您只是将数组作为第一个/唯一的参数传递
pinkfloydx33 '18

@ pinkfloydx33是的。我是错别字。
AdmBorkBork '18年

11

C(gcc)62 60 56 55字节

-2 -6个字节,得益于l4m2

-1个字节,感谢ceilingcat

使用-1终止数组的允许概念。f()递归调用自身,直到完全结束,然后在列表中回溯。r跟踪打印某些东西之前要丢弃多少个数字。如果当前项目为0,则增加;否则,则减少。如果为0,则无需丢弃,可以打印数字。

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

在线尝试!


f(l)int*l;=> f(int*l)
l4m2 '18年

@ l4m2啊,干杯!可能是更早,负载更多的日子的残余。
gastropner

r=0好像没用
l4m2

@ l4m2是的,很好。
gastropner


10

R,45个字节

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

在线尝试!

  • -4字节感谢@Giuseppe

1
48字节 -滥用F也将使您达到48字节,但这是更干净的恕我直言
Giuseppe

我不知道我如何错过if-else反转:facepalm:...谢谢!
digEmAll


1
R+pryrReduce溶液是44个字节
JayCe

@JayCe:说实话,我更喜欢将其保留为“ base-R”解决方案……但随时可以将其发布为您自己的答案!;)
digEmAll


9

果冻,6字节

ṣ0Ṗ;¥/

在线尝试!

这个怎么运作

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

如果存在三个连续的零,这会模拟三个爆破声吗?
WGroleau '18

是。[1,3,7,0,0,0],例如,被拆分为[[1,3,7],[],[],[]],则left-reduce的每一步都会弹出left数组的元素。
丹尼斯

9

Brain-Flak40 36字节

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

在线尝试!

感谢@Nitrodon提供了-4个字节。

由于Brain-Flak已经使用堆栈,因此这对于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

2
在这种特殊情况下,{{}<>{}<>}可以缩短为{{}<>}
Nitrodon

@Nitrodon谢谢。您能解释一下,为什么这仍然有效?它不会在循环中切换回输入堆栈。
多里安

1
确保输出堆栈的顶部为非零,因此缩短的循环执行0或2次。
Nitrodon

8

Wolfram语言(Mathematica),28个字节

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

在线尝试!


(这仅是有效的,因为“默认设置是使较早的模式匹配最短的序列”,因此无需确保该b值不为零。)
user202729

@ user202729是的。Mathematica的模式匹配是非贪婪的,因此它尝试首先匹配最短的可能a___。通过尝试可以看到这一点ReplaceList[#, {a___, b_, 0, c___} :> {a, c}] &。与此相关的是,StringReplace实际上是贪婪的,因此此提交不适用于StringReplace(格式如下a___~~b_~~"0"~~c___
JungHwan Min

8

Python 2,48个字节

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

在线尝试!


您是否有机会解释其工作原理?在过去的半小时内,我一直在努力解决问题!肯定2*0**x会一直如此0。我显然缺少了一些东西。
ElPedro

1
@ElPedro时不为零x=0,在这种情况下为2。–
xnor

啊,我明白你的意思了。猜猜我看起来太努力了,却没有发现明显的东西!谢谢,很好的答案。
ElPedro '18年

7

空格,89字节

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

字母S(空格),T(制表符)和N(换行符)仅作为突出显示而添加。
[..._some_action]仅作为说明添加。

将输入列表换行用分隔,-1以表明我们已完成输入。

在线尝试

伪代码中的解释:

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


6

JavaScript,40个字节

以相反的顺序输出。

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

在线尝试

感谢Herman L节省了1个字节。


a=>a.map(x=>x?o.push(x):o.pop(),o=[])&&o是一个字节短
Herman L

@HermanL:天哪!当然是的!谢谢。(un)shift在我发现输出可以反转之前正在使用。
毛茸茸的

之所以有效,o是因为在第二个参数中定义了回调之后,在回调中对其进行了引用。
MattH '18

6

05AB1E,9 个字节

vy>i¨ëy)˜

在线尝试验证所有测试用例

说明:

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 字节替代:

vy_i\ëy])

在线试用验证所有的测试用例

说明:

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:如果输出应该被颠倒以匹配质询描述中的测试用例,我们可以R在第二个版本中添加尾随(所以10 个字节),从而将列表颠倒。在线尝试验证所有测试用例


5

视网膜0.8.2,18字节

^
,
+1`,\d+,0

^,

在线尝试!链接包括测试用例。说明:

^
,

附加一个前缀,

+1`,\d+,0

处理所有弹出操作。

^,

,如果仍然存在,请删除。

反转数字将花费额外的8个字节:

O^$`\d+

它只是简单地将所有<number>, 0子列表替换为空。
user202729


5

Brain-Flak,36个字节

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

在线尝试!

#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


5

V,10字节

ò/ 0⏎b2dw0

在线尝试!

说明

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

相当于Vim,16字节

qq/ 0⏎b2dw0@qq@q

在线尝试!

说明

几乎相同,除了记录一个宏q并递归调用它:

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

5

Java 10,75 72字节

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

输出以逗号分隔。栈顶是最后一个。在这里在线尝试。

感谢OlivierGrégoire打高尔夫球2字节。

请同时查看Kevin CruijssenOlivierGrégoire Java答案。他们取而代之的是基于列表的方法,后者以可观的优势击败了我的公司。

取消高尔夫:

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
}

字符串的好方法。比我对实际对象的幼稚方法要好Stack。向我+1。
凯文·克鲁伊森

1
n->{var s="";for(int i:n)s=(s+","+i).replaceAll(",\\d+,0$","");return s;}(73个字节),但放在,前面的数字,而不是后面的数字。
奥利维尔·格雷戈尔

1
n->{var s=""+n;for(int x:n)s=s.replaceFirst("\\d+, 0,? ?","");return s;}(72字节),使用列表而不是数组,并弄乱了输出,因为它可以返回“ [,2]”之类的东西
OlivierGrégoire18年

@OlivierGrégoire尼斯。我们可以删除$来保存另一个字节,因为0我们添加的每个字节都会立即删除。
OOBalance

@OlivierGrégoire您的第二种方法也很有趣,但是我认为不一致的输出格式可能会使解决方案无效。
OOBalance

5

GolfScript14 12字节

~{.{;}if}/]`

在线尝试!

~{.{;}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


5

> <>,25个字节

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

在线尝试!(输入必须用ascii编写。否则请使用输入)

这个怎么运作

i:?\~~检查0,继续~~删除上一个条目。否则请转到:

(0:/:^? 它检查-1(没有更多输入),然后结束删除-1并循环:

!?l:!<oan; 它用换行符输出每个数字,然后在清空堆栈时结束



5

外壳,6个字节

既然还没有Husk的答案,那是我最喜欢的golfing-lang:

F`?:tø

在线尝试!

说明

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

替代解决方案,6字节

除了翻转之外,我们还可以反转列表,然后使用右对齐: Ḟ?:tø↔


5

brainfuck214个 150字节

>>,[>++++++[-<-------->]+<[>+++++[-<++++++++>]]>[-<<<[[-]<],[-]>>>>-<<]>>+[<<+<,----------[++++++++++>-]>[->>-<]>[->+<]>]<<<,]<<[[<]++++++++++<]>>[.>]

将输入读取为以换行符分隔的数字。这必须包含一个尾随换行符。还希望每个数字都没有前导零。输出为类似的换行符分隔列表

在线尝试!

解释并不是真正的解释,而实际上只是我正在处理的评论和内容的版本,可能实际上对任何人都没有用

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

5

Brachylog,21个字节

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

在线尝试!

-1个字节,更重要的是,这样做感觉不太麻烦。

~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↰| 在线试用!


较旧的代码:

22字节

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

在线尝试!

∋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 

5

警告:随之而来的是许多行。你被警告了。


CJam,17个字节

最危险的代码
(假设堆栈元素只能在输出中用空格隔开,并且输入数组可以是我们希望的任何形式)

q~{X0={;}X?}fX]S*

在线尝试!

说明

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

备用代码#
1,27 字节(假定堆栈元素必须以问题中显示的格式输出,并且输入数组可以是我们希望的任何形式)

q~{X0={;}X?}fX]',S+*'[\+']+

在线尝试!

说明

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

备用代码#
2,24 字节(假定可以在输出中整理堆栈元素,并且输入数组必须采用问题中显示的确切格式)

q',/~]S*~{X0={;}X?}fX]S*

在线尝试!

说明

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

最安全的代码,为34个字节
(假定必须以问题中所示的格式输出堆栈元素,并且输入数组必须以问题中所示的准确格式)

q',/~]S*~{X0={;}X?}fX]',S+*'[\+']+

在线尝试!

说明

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

由于@Jo国王的指出与逐份输出的那些是因为像无效[12],并[1,2]会区分。

还感谢@Jo King为整理后的输出提供了一个非常合适的替代选择,并减少了9个字节!


1
因为你不能告诉之间的区别第一个是无效[12][1,2]。但是,尽管您可以摆脱18字节
Jo King

哦,我当然非常傻了
海伦(Helen)'18

但是,用空格而不是逗号来分隔数字可能更容易理解,因为空格使用]S*(3)而逗号使用]',*(4)
Helen

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.