获取匹配括号的索引
Getting indices of matching 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
有什么办法可以实现吗?
左边括号入栈,右边出栈。
#!/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;
有趣的问题!接受的答案很好,但这里有另一种方法,因为看到另一个解决方案总是有教育意义的。
#!/usr/bin/perl
use strict;
use warnings;
my $string = '((((((...)))(((...))))))';
my (@out, @match);
while ($string =~ m/([()])/g) {
my $p = pos($string) - 1;
if ( 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" 修饰符依次匹配每个左括号或右括号。因此,循环只迭代感兴趣的字符。 $string
returns 点 在 最后一场比赛之后的 pos()
函数,所以我需要减去一个以获得 zero-based 输出。
另一个关键区别是我在 @out
中累积,并通过记录 @out
的最后一个索引跟踪相应的收盘价,将其推到 @match
。然后,当我找到右括号时,我弹出 @match
,并将第二个元素添加到 @out
中的 sub-array 那个位置。这消除了对最终结果进行排序的需要,因为 @out
已经按照左括号的顺序排列。
您好,我正在尝试打印以下括号模式的索引:
((((((...)))(((...))))))
如下:
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
有什么办法可以实现吗?
左边括号入栈,右边出栈。
#!/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;
有趣的问题!接受的答案很好,但这里有另一种方法,因为看到另一个解决方案总是有教育意义的。
#!/usr/bin/perl
use strict;
use warnings;
my $string = '((((((...)))(((...))))))';
my (@out, @match);
while ($string =~ m/([()])/g) {
my $p = pos($string) - 1;
if ( 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" 修饰符依次匹配每个左括号或右括号。因此,循环只迭代感兴趣的字符。 $string
returns 点 在 最后一场比赛之后的 pos()
函数,所以我需要减去一个以获得 zero-based 输出。
另一个关键区别是我在 @out
中累积,并通过记录 @out
的最后一个索引跟踪相应的收盘价,将其推到 @match
。然后,当我找到右括号时,我弹出 @match
,并将第二个元素添加到 @out
中的 sub-array 那个位置。这消除了对最终结果进行排序的需要,因为 @out
已经按照左括号的顺序排列。