递归调用不打印 perl 中字符串的预期组合
Recursive call is not printing the expected combinations of a string in perl
下面的程序是打印字符串所有可能的排列。我在 Perl 中试过这个。但是输出似乎不是预期的。有人可以帮忙吗?
print "Enter string ";
chomp( $str = <STDIN> );
$n = length($str);
&combi( $str, 0, ( $n - 1 ) );
sub combi {
$l = $_[1];
$r = $_[2];
if ( $l == $r ) {
print( $_[0], "\n" );
}
else {
@char = split( "", $_[0] );
for ( $i = $l; $i <= $r; $i++ ) {
&swap( $char[ $_[1] ], $char[$i] );
$res = join( "", @char );
&combi( $res, ( ( $_[1] ) + 1 ), $r );
&swap( $char[ $_[1] ], $char[$i] );
}
}
}
sub swap {
$temp = $_[0];
$_[0] = $_[1];
$_[1] = $temp;
}
程序输出:
Enter String: abc
abc
acb
您可以使用 CPAN 模块 List::Permutor 打印所有可能的排列。
例如:
use List::Permutor;
my $perm = new List::Permutor qw/ fred barney betty /;
while (my @set = $perm->next) {
print "One order is @set.\n";
}
另一个模块是 Algorithm::Permute - 使用面向对象的界面方便快捷地排列。
我很难理解你的代码,但我认为你的问题是 - 你正在尝试以一种相当重量级的方式来处理它,但是重要的是 - 你不是 实际上 'unwinding' 你递归的尾部。
递归算法的要点是深入遍历并整理结果。
所以我会这样处理你的问题:
#!/usr/bin/env perl
use strict;
use warnings;
my $str = 'abcde';
sub combinations {
my ($string) = @_;
print "Starting combinations with \"$string\"\n";
if ( length($string) == 1 ) {
return ($string);
}
my @combinations;
for my $index ( 0 .. length($string) - 1 ) {
my @chars = split( //, $string );
my $firstletter = splice( @chars, $index, 1 );
print "Keeping: $firstletter combining @chars\n";
foreach my $combination ( combinations( join( "", @chars ) ) ) {
print "Got for @chars $combination\n";
push( @combinations, $firstletter . $combination );
}
}
return (@combinations);
}
print join( "\n", combinations($str) );
我们有一个递归例程,它是 'given' 一个字符串。它迭代该字符串中的每个字母 - 挑选出 'first letter' 并将剩余的字母交给递归调用以执行相同的操作。
但是接下来是 'sticking back together' 调用的结果,列出 'results' - 因为每个 'level' 调用都应该生成一些答案,它然后returns向上级调用等
注意 - 我还:
- 打开
strict
和 warnings
- 这在编写代码时非常重要。
- 未在子调用中使用
&
前缀。这很少是您想要做的。
- 未引用
$_[0]
- 作为样式点,您应该避免在不必要的情况下 显式 使用隐式变量。为您的参数命名,并为它们命名以明确发生了什么。
下面的程序是打印字符串所有可能的排列。我在 Perl 中试过这个。但是输出似乎不是预期的。有人可以帮忙吗?
print "Enter string ";
chomp( $str = <STDIN> );
$n = length($str);
&combi( $str, 0, ( $n - 1 ) );
sub combi {
$l = $_[1];
$r = $_[2];
if ( $l == $r ) {
print( $_[0], "\n" );
}
else {
@char = split( "", $_[0] );
for ( $i = $l; $i <= $r; $i++ ) {
&swap( $char[ $_[1] ], $char[$i] );
$res = join( "", @char );
&combi( $res, ( ( $_[1] ) + 1 ), $r );
&swap( $char[ $_[1] ], $char[$i] );
}
}
}
sub swap {
$temp = $_[0];
$_[0] = $_[1];
$_[1] = $temp;
}
程序输出:
Enter String: abc
abc
acb
您可以使用 CPAN 模块 List::Permutor 打印所有可能的排列。
例如:
use List::Permutor;
my $perm = new List::Permutor qw/ fred barney betty /;
while (my @set = $perm->next) {
print "One order is @set.\n";
}
另一个模块是 Algorithm::Permute - 使用面向对象的界面方便快捷地排列。
我很难理解你的代码,但我认为你的问题是 - 你正在尝试以一种相当重量级的方式来处理它,但是重要的是 - 你不是 实际上 'unwinding' 你递归的尾部。
递归算法的要点是深入遍历并整理结果。
所以我会这样处理你的问题:
#!/usr/bin/env perl
use strict;
use warnings;
my $str = 'abcde';
sub combinations {
my ($string) = @_;
print "Starting combinations with \"$string\"\n";
if ( length($string) == 1 ) {
return ($string);
}
my @combinations;
for my $index ( 0 .. length($string) - 1 ) {
my @chars = split( //, $string );
my $firstletter = splice( @chars, $index, 1 );
print "Keeping: $firstletter combining @chars\n";
foreach my $combination ( combinations( join( "", @chars ) ) ) {
print "Got for @chars $combination\n";
push( @combinations, $firstletter . $combination );
}
}
return (@combinations);
}
print join( "\n", combinations($str) );
我们有一个递归例程,它是 'given' 一个字符串。它迭代该字符串中的每个字母 - 挑选出 'first letter' 并将剩余的字母交给递归调用以执行相同的操作。
但是接下来是 'sticking back together' 调用的结果,列出 'results' - 因为每个 'level' 调用都应该生成一些答案,它然后returns向上级调用等
注意 - 我还:
- 打开
strict
和warnings
- 这在编写代码时非常重要。 - 未在子调用中使用
&
前缀。这很少是您想要做的。 - 未引用
$_[0]
- 作为样式点,您应该避免在不必要的情况下 显式 使用隐式变量。为您的参数命名,并为它们命名以明确发生了什么。