YarNik
YarNik

Reputation: 139

Perl combinations without 3 words

I have a set of 15 words, but 3 of them are not needed. I need to get all the combinations. These words are sorted, do not mix them.

I try to remove from the array, but the script reports an error.

@words_orig = qw(Home Pronunciation Symbols Help About Mobile Apps Shop Dictionary API Privacy Policy Terms About2 Contact);
@words = (@words_orig);

for $w1 ( 0 .. $#words ) {
    delete @words[$w1];
    for $w2 ( 0 .. $#words ) {
        delete @words[$w2];
        for $w3 ( 0 .. $#words ) {
            delete @words[$w3];
            print join(' ', @words) . "\n";
            @words = (@words_orig);
        }
    }
}

Upvotes: 0

Views: 60

Answers (2)

ikegami
ikegami

Reputation: 385839

There should be C(15, 15-3) = (15*14*13)/(3*2*1) = 455 solutions.

That can be found using the following:

for my $i00 (0      .. $#words) {
for my $i01 ($i00+1 .. $#words) {
for my $i02 ($i01+1 .. $#words) {
for my $i03 ($i02+1 .. $#words) {
for my $i04 ($i03+1 .. $#words) {
for my $i05 ($i04+1 .. $#words) {
for my $i06 ($i05+1 .. $#words) {
for my $i07 ($i06+1 .. $#words) {
for my $i08 ($i07+1 .. $#words) {
for my $i09 ($i08+1 .. $#words) {
for my $i10 ($i09+1 .. $#words) {
for my $i11 ($i10+1 .. $#words) {
   say "@words[$i00, $i01, $i02, $i03, $i04, $i05,
               $i06, $i07, $i08, $i09, $i10, $i11]";
}}}}}}}}}}}}

The above can also be written as follows:

use Algorithm::Loops qw( NestedLoops );

my $iter = NestedLoops([
   [ 0..$#words ],
   ( sub { [ $_+1..$#words ] } ) x ( @words - 3 - 1 ),
]);

while ( my @indexes = $iter->() ) {
   say "@words[@indexes]";
}

Note that the provided solutions consider duplicate words to be different words. This should be fine since the OP indicated the presence of a duplicate word was a mistake.

Upvotes: 1

choroba
choroba

Reputation: 241898

In this case, it's probably better to work with the indices of the words:

#! /usr/bin/perl
use warnings;
use strict;
use feature qw{ say };

my @words = qw( Home Pronunciation Symbols Help About Mobile Apps Shop
                Dictionary API Privacy Policy Terms About Contact );
for my $i (0 .. $#words) {
    for my $j ($i + 1 .. $#words) {
        for my $k ($j + 1 .. $#words) {
            say join ' ', @words[ grep $_ != $i && $_ != $j && $_ != $k,
                                  0 .. $#words ];
        }
    }
}

Note that "About" is mentioned twice, so comparing the words by string comparison would return a different list:

#! /usr/bin/perl
use warnings;
use strict;
use feature qw{ say };

my @words = qw( Home Pronunciation Symbols Help About Mobile Apps Shop
                Dictionary API Privacy Policy Terms About Contact );

for my $i (@words) {
    for my $j (@words) {
        next if $i le $j;

        for my $k (@words) {
            next if $j le $k || $i le $k;

            say join ' ', grep $_ ne $i && $_ ne $j && $_ ne $k, @words;
        }
    }
}

Upvotes: 1

Related Questions