2012-02-03 4 views
0

배열의 모든 순열을 생성하는 간단한 재귀 Perl 루틴을 작성하려고합니다. 나는 이것을하기위한 루틴을 제공하는 모듈을 가지고 있지 않으며 그것들을 설치할 수도 없다.Perl을 사용하는 순열

sub permute 
{ 
    my @array = @_; 
    if (@array == 0) 
    { 
     return; 
    } 
    else 
    { 
     my $accum = ""; 
     my $result = permute_with_accumulator($accum, @array); 
     return $result; 
    } 
} 

sub permute_with_accumulator 
{ 
    my ($accum, @array) = @_; 
    if (@array == 1) 
    { 
     my $element = $array[0]; 
     $accum .= "$element,"; 
    } 
    else 
    { 
     my $i; 
     for ($i = 0; $i <= $#array; $i++) 
     { 
     $accum .= "$array[$i] "; 
     my @new_array =(); 
     if ($i == 0) 
     { 
      @new_array = @array[1..$#array]; 
     } 
     elsif ($i == $#array) 
     { 
      @new_array = @array[0..$#array-1]; 
     } 
     else 
     { 
      my $lower = $i - 1; 
      my $upper = $i + 1; 
      @new_array = @array[1..$lower, $upper..$#array]; 
     } 
     permute_with_accumulator($accum, @new_array); 
     } 
    } 
    return $accum; 
} 

을하지만 @array = QW (E1, E2, E3 E4 E5)을 할 때 실행 :

my $perms = permute(@array); 
print ("$perms\n"); 

출력이 단지

e1 e2 e3 e4 e5 
여기 코드는 내가 지금까지 가지고있다

모든 조언을 주시면 감사하겠습니다.

감사합니다.

+4

당신이 CPAN 모듈을 설치할 수없는 경우 '재미라고 생각 Perl의 절반을 잃어 버리고 작업 부하가 3 배가됩니다. 나는 그것을 고칠 것을 권합니다. 그렇지 않으면 더 많은 바퀴를 재발견하고 유지해야 할 것입니다. local :: lib와 같은 것을 사용하여 root없이 모듈을 설치하거나 perlbrew를 사용하여 자신의 Perl 복사본을 컴파일하십시오. – Schwern

+8

그래서 StackOverflow에 코드를 게시하면 괜찮습니다.하지만 CPAN에 게시하면 그렇지 않습니다. – ikegami

+0

저는 랩 컴퓨터에서 일하고 있는데 설치 한 것에 국한됩니다. 나는 아무것도 설치할 수 없다. 내가 할 수있는 한, 순열을위한 루틴을 제공하는 모든 모듈을 "사용"하려고했지만 아무도 사용할 수 없다는 것을 알 수 있습니다. – Schemer

답변

8

사실, 이것은 FAQ를 볼 수 있습니다 : 붙여 넣기위한 몇 가지 멋진 코드와 함께

How do I permute N elements of a list?

:이 코드는 독립형 스크립트로 사용하도록되어

#!/usr/bin/perl -n 
# Fischer-Krause ordered permutation generator 

sub permute (&@) { 
     my $code = shift; 
     my @idx = 0..$#_; 
     while ($code->(@_[@idx])) { 
       my $p = $#idx; 
       --$p while $idx[$p-1] > $idx[$p]; 
       my $q = $p or return; 
       push @idx, reverse splice @idx, $p; 
       ++$q while $idx[$p-1] > $idx[$q]; 
       @idx[$p-1,$q][email protected][$q,$p-1]; 
     } 
} 

permute { print "@_\n" } split; 

, 하지만 함께 직접 하위를 사용할 수 있습니다

sub permute (&@); # predeclare sub, paste sub at bottom 
my @a; 
permute { push @a, "@_" } @some_array; 
+0

사실, 그 줄은 항상있었습니다. 내가 편집으로 수정 한 것은 매개 변수의 순서였습니다. 그 방법은 루틴을 다른 방식으로 돌리고 있었기 때문입니다. – Schemer

+0

@Schemer하지만 아무 것도 반환하지 않습니다. 또한 배열 인덱스 인'$ accum'에'$ i'를 추가하고 요소는 추가하지 않습니다. – TLP

+0

고마워, 방금 배열 요소를 추가하지 않는 것으로 나타났습니다. : P 오타.나는'return $ accum'을 기본 케이스에서 꺼내서 루틴의 끝으로 옮겼습니다. 하지만 이제는 e1, e2, e3, e4 및 e5가 포함 된 배열에서 permute를 호출하면 출력은 단순히 'e1 e2 e3 e4 e5'입니다. – Schemer

3

Stanford 프로그래밍 패러다임 시리즈에서 Scheme의 재귀 및 이중 매핑으로 순열을 수행하는 것에 대한 YouTube 강의가 있습니다. 펄, 나는 알고리즘에 대해 다음 구현 해낸 :

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

my @array = qw(e1 e2 e3); 

sub permute { 
    return ([]) unless (@_); 
    return map { 
     my @cdr = @_; 
     my $car = splice @cdr, $_, 1; 
     map { [$car, @$_]; } &permute(@cdr); 
    } 0 .. $#_; 
} 

print "@$_\n" foreach (&permute (@array)); 

매우 비효율적 일 수도 있지만, 나는 그것이 & 우아한 :