获取匹配括号的索引

时间:2019-05-21 13:41:53

标签: arrays perl parentheses

嗨,我正在尝试打印以下括号模式的索引:

((((((...)))(((...))))))

如下:

0 23
1 22
2 21
3 11
4 10
5 9
12 20
13 19
14 18

我尝试使用以下给出的perl代码来实现这一目标:

#!/usr/bin/perl
use strict;
use warnings;

my $string = '((((((...)))(((...))))))';
my @myarray = split('', $string); 
my @stack;
my @stack1;



while (my ($index, $element) = each(@myarray))
{

   if ($element eq '(')
   {
   push(@stack, $index);  
   }

   if ($element eq ')')
   {
   push(@stack1, $index);  
   }  
}


print "$stack[$_]-$stack1[$_]\n" for (0 .. $#stack);

但是上面的代码给了我以下输出,而不是必需的输出:

0-9
1-10
2-11
3-18
4-19
5-20
12-21
13-22
14-23

有什么办法可以做到这一点?

2 个答案:

答案 0 :(得分:6)

将堆栈推入左侧括号,在右侧弹出。

#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };

my $string = '((((((...)))(((...))))))';

my @output;
my @stack;

my $pos = 0;
for my $char (split //, $string) {
    if ($char eq '(') {
        push @stack, $pos;
    } elsif ($char eq ')') {
        push @output, [ pop @stack, $pos ];
    }
    ++$pos;
}
say "@$_" for sort { $a->[0] <=> $b->[0] } @output;

答案 1 :(得分:2)

有趣的问题!可以接受的答案很好,但这是另一种解决方法,因为查看其他解决方案始终具有教育意义。

#!/usr/bin/perl

use strict;
use warnings;

my $string = '((((((...)))(((...))))))';

my (@out, @match);

while ($string =~ m/([()])/g) {
    my $p = pos($string) - 1;
    if ($1 eq '(') {
        push @out, [$p];
        push @match, $#out;
    }
    else {
        die "mismatched paren at char $p\n"
            unless @match;
        $out[pop @match][1] = $p;
    }
}

for (@out) { print "@$_\n" }

exit(0);

输出与您所需的输出完全相同。死于不匹配的括号(choroba的代码也可以在elsif块中进行适当的测试)。不匹配的括号会导致没有第二个数字的行,并且在while循环之后它们也会在@match中残留。

我选择使用Perl的模式进行一些匹配,而不是将字符串分成单个字符并遍历所有字符。相反,我使用“ g”修饰符依次匹配每个打开或关闭括号。因此,循环仅遍历感兴趣的字符。 pos()上的$string函数在最后一个匹配项之后返回 点,因此我需要减去1以获得基于零的输出。

另一个主要区别是,我在@out中累积,并通过注意@out的最后一个索引并将其推向@match来跟踪相应的收盘价。然后,在找到闭合括号时弹出@match,然后在该位置的@out中将第二个元素添加到子数组中。这样就无需对最终结果进行排序,因为@out已经按括号括起来。