2012-04-24 16 views
16

Mam plik z listą i konieczność utworzenia pliku, który porównuje każdą linię z drugą. Na przykład, mój plik ma ten:W Perlu, w jaki sposób mogę wygenerować wszystkie możliwe kombinacje listy?

AAA 
BBB 
CCC 
DDD 
EEE

chciałbym ostateczną listę, aby wyglądać tak:

AAA BBB 
AAA CCC 
AAA DDD 
AAA EEE 
BBB CCC 
BBB DDD 
BBB EEE 
CCC DDD 
CCC EEE 
DDD EEE

Staram się zrobić to w Perl, w tym po raz pierwszy i jestem posiadające małe kłopoty. Wiem, że musisz utworzyć tablicę, a następnie podzielić ją, ale po tym mam problemy.

+0

Proszę wysłać dotychczas kod. – tuxuday

Odpowiedz

0
  1. wziąć pierwszego ciągu
  2. iteracyjne nad tablicy z następnej pozycji do końca
    1. dołączyć kolejny ciąg do oryginalnego napisu
  3. wziąć następny ciąg i wróć do kroku 2
7

Spójrz na Math::Combinatorics - Wykonaj kombinacje i permutacje na listach

przykład kopiując z CPAN:

use Math::Combinatorics; 

    my @n = qw(a b c); 
    my $combinat = Math::Combinatorics->new(count => 2, 
              data => [@n], 
             ); 

    print "combinations of 2 from: ".join(" ",@n)."\n"; 
    print "------------------------".("--" x scalar(@n))."\n"; 
    while(my @combo = $combinat->next_combination){ 
    print join(' ', @combo)."\n"; 
    } 

    print "\n"; 

    print "permutations of 3 from: ".join(" ",@n)."\n"; 
    print "------------------------".("--" x scalar(@n))."\n"; 
    while(my @permu = $combinat->next_permutation){ 
    print join(' ', @permu)."\n"; 
    } 

    output: 
combinations of 2 from: a b c 
    ------------------------------ 
    a b 
    a c 
    b c 

    permutations of 3 from: a b c 
    ------------------------------ 
    a b c 
    a c b 
    b a c 
    b c a 
    c a b 
    c b a 
+3

Dlaczego nie używasz przykładowych danych z pytania? – daxim

+1

@daxim: Intensywne było zostawienie trochę pracy dla OP. –

0

Jak o:

#!/usr/bin/perl 
use strict; 
use warnings; 
use Data::Dump qw(dump); 

my @in = qw(AAA BBB CCC DDD EEE); 
my @list; 
while(my $first = shift @in) { 
    last unless @in; 
    my $rest = join',',@in; 
    push @list, glob("{$first}{$rest}"); 
} 
dump @list; 

wyjściowa:

(
    "AAABBB", 
    "AAACCC", 
    "AAADDD", 
    "AAAEEE", 
    "BBBCCC", 
    "BBBDDD", 
    "BBBEEE", 
    "CCCDDD", 
    "CCCEEE", 
    "DDDEEE", 
) 
+5

Globalnej sztuczce zawsze powinny towarzyszyć różne zastrzeżenia, gdy się nie powiedzie. – daxim

+1

@daxim: Masz na myśli "efekt uboczny" dopasowywania plików w bieżącym katalogu roboczym? Jeśli tak, to czy nie jest to całkowicie bezpieczne, ponieważ nie używa "?", "[]" Lub "*"? – flesk

+1

Wszystko to. Jestem teraz zirytowany, zastrzeżenia powinny być jasno przedstawione jako część odpowiedzi, a nie retoryczne pytania dołączone jako komentarz o niskiej widoczności. To nie jest "efekt uboczny", tak naprawdę się dzieje, modalizowanie słowa jest złe. To nie jest bezpieczne: oczywiście użytkownik podał w ankiecie dane anonimowe i będzie zaskoczony w rzeczywistych warunkach. Odpowiedzi SO powinny dążyć do tego, aby nie nastawiać ludzi na porażkę, zawsze powinni być świadomi subtelności i ryzyka; biorąc pod uwagę, że teraz przegłosowałem tę odpowiedź, aby zachęcić M42 do poprawy tej sytuacji. - kontynuacja: – daxim

28

Zastosowanie Algorithm::Combinatorics. Podejście oparte na iteracji jest lepsze niż generowanie wszystkiego na raz.

#!/usr/bin/env perl 

use strict; use warnings; 
use Algorithm::Combinatorics qw(combinations); 

my $strings = [qw(AAA BBB CCC DDD EEE)]; 

my $iter = combinations($strings, 2); 

while (my $c = $iter->next) { 
    print "@$c\n"; 
} 

wyjściowa:

AAA BBB 
AAA CCC 
AAA DDD 
AAA EEE 
BBB CCC 
BBB DDD 
BBB EEE 
CCC DDD 
CCC EEE 
DDD EEE
0

Oto Hack użyciu glob:

my @list = qw(AAA BBB CCC DDD EEE); 

for my $i (0..$#list-1) { 
    print join "\n", glob sprintf "{'$list[$i] '}{%s}", 
      join ",", @list[$i+1..$#list]; 
    print "\n"; 
} 

Wyjście:

AAA BBB 
AAA CCC 
AAA DDD 
AAA EEE 
BBB CCC 
BBB DDD 
BBB EEE 
CCC DDD 
CCC EEE 
DDD EEE 

PS: możesz użyć modułów Text::Glob::Expand lub String::Glob::Permute zamiast zwykłego glob(), aby uniknąć zastrzeżenia pasujących plików w bieżącym katalogu roboczym.

+4

Globalnej sztuczce zawsze powinny towarzyszyć różne zastrzeżenia, gdy się nie powiedzie. – daxim

8

Zapisanie tego za pomocą rekursji jest proste.

Ten przykład kodu pokazuje.

use strict; 
use warnings; 

my $strings = [qw(AAA BBB CCC DDD EEE)]; 

sub combine; 

print "@$_\n" for combine $strings, 5; 

sub combine { 

    my ($list, $n) = @_; 
    die "Insufficient list members" if $n > @$list; 

    return map [$_], @$list if $n <= 1; 

    my @comb; 

    for my $i (0 .. $#$list) { 
    my @rest = @$list; 
    my $val = splice @rest, $i, 1; 
    push @comb, [$val, @$_] for combine \@rest, $n-1; 
    } 

    return @comb; 
} 

Edit

Przepraszam - Byłem generowanie permutacji zamiast kombinacji.

Ten kod jest poprawny.

use strict; 
use warnings; 

my $strings = [qw(AAA BBB CCC DDD EEE)]; 

sub combine; 

print "@$_\n" for combine $strings, 2; 

sub combine { 

    my ($list, $n) = @_; 
    die "Insufficient list members" if $n > @$list; 

    return map [$_], @$list if $n <= 1; 

    my @comb; 

    for (my $i = 0; $i+$n <= @$list; ++$i) { 
    my $val = $list->[$i]; 
    my @rest = @$list[$i+1..$#$list]; 
    push @comb, [$val, @$_] for combine \@rest, $n-1; 
    } 

    return @comb; 
} 

wyjście

AAA BBB 
AAA CCC 
AAA DDD 
AAA EEE 
BBB CCC 
BBB DDD 
BBB EEE 
CCC DDD 
CCC EEE 
DDD EEE 
Powiązane problemy