递归调用不打印 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向上级调用等

注意 - 我还:

  • 打开 strictwarnings - 这在编写代码时非常重要。
  • 未在子调用中使用 & 前缀。这很少是您想要做的。
  • 未引用 $_[0] - 作为样式点,您应该避免在不必要的情况下 显式 使用隐式变量。为您的参数命名,并为它们命名以明确发生了什么。