Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

adding n-tuples

by kwatts59 (Initiate)
on May 16, 2019 at 13:35 UTC ( #11100080=perlquestion: print w/replies, xml ) Need Help??

kwatts59 has asked for the wisdom of the Perl Monks concerning the following question:

There are two arrays, each with n numbers. How do I calculate the sum of all the possible n-tuples.

For example, array @A has 4 numbers and array @B has 4 numbers as follows:

@A = ($a1,$a2,$a3,$a4); @B = ($b1,$b2,$b3,$b4);

How do I calculate the sum of all 4-tuples?

$E = b1*a2*a3*a4 + a1*b2*a3*a4 + a1*a2*b3*a4 + a1*a2*a3*b4 + b1*b2*a3*a4 + b1*a2*b3*a4 + b1*a2*a3*b4 + a1*b2*b3*a4 + a1*b2*a3*b4 + a1*a2*b3*b4 + b1*b2*b3*a4 + b1*b2*a3*b4 + b1*a2*b3*b4 + a1*b2*b3*b4 + b1*b2*b3*b4;
Note that there are no duplicate numbers or positions. Ex. a1*a1*a2*a2 or a1*b1*a2*b2 are not counted.

Edit: I forgot the last 4-tuple b1*b2*b3*b4

2019-05-17 Athanasius added code tags

Replies are listed 'Best First'.
Re: adding n-tuples
by choroba (Bishop) on May 16, 2019 at 14:38 UTC
    Use math first before programming.

    Note that you can factor out a1 and b1 from the formula, you'll get

    (a1 + b1) * (a2 * a3 * a4 + a2 * a3 * b4 + ...)
    In the second factor, you can use the same technique to factor out a2 + b2, and so on. In the end, you'll get
    (a1 + b1) * (a2 + b2) * (a3 + b3) * (a4 + b4)

    So, the solution is

    $sum = 1; for my $i (0 .. 3) { $sum *= $A[$i] + $B[$i]; } say $sum;

    And it gives the same result as

    my $sum = 0; for my $pattern (map unpack('b4', pack 's', $_), 0 .. 15) { my $prod = 1; for my $i (0 .. 3) { $prod *= (\@A, \@B)[substr $pattern, $i, 1][$i]; } $sum += $prod; } say $sum;

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
Re: adding n-tuples
by WoodyWeaver (Monk) on May 16, 2019 at 13:44 UTC
    Quick clue: your friend is Math::Combinatorics or Algorithm::Combinatorics. This is just fiddly enough to not write your own. Its not clear from your question what you are looking for (it sounds like you have 2N data points and you want all sums of N tuples, so its probably the Algorithm::Combinatorics::variations() you want, but I'm sure you'll get it from that man page.
Re: adding n-tuples
by LanX (Archbishop) on May 16, 2019 at 14:51 UTC
    Just for fun.

    When hacking this on my mobile I hoped using a "magic" solution might need less keystrokes.

    use strict; use warnings; $\ = "\n"; my @a = map {int rand 10} 0..3; my @b = map {int rand 10} 0..3; print "IN: (@a) (@b)"; print eval join '+' , glob join '\*' , map "{$a[$_],$b[$_]}", 0..3; __END__ perl mult_tuple.pl IN: (9 8 8 9) (3 1 7 3) 19440

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

Re: adding n-tuples
by tybalt89 (Parson) on May 16, 2019 at 15:08 UTC
    #!/usr/bin/perl -l # https://perlmonks.org/?node_id=11100080 use strict; use warnings; use List::Util qw( sum ); my @A = (1, 1, 1, 1); my @B = (2, 2, 2, 2); print sum map eval tr/x/*/r, glob join 'x', map "{$A[$_],$B[$_]}", 0 . +. $#A;

        LOL

Re: adding n-tuples
by QM (Parson) on May 16, 2019 at 15:23 UTC
    Reading all of the replies, I'm really surprised that "n-tuple" somehow means "product", when it could as easily mean concatenation or something else entirely.

    I would have liked to see a simple example worked out (which might have helped the OP in the first place). :D

    -QM
    --
    Quantum Mechanics: The dreams stuff is made of

      It's most likely homework.

      The canonic solution are 4 nested loops with an $sum += $c1*$c2*$c3*$c4 as the last step.

      Feel free to demonstrate it.

      update

      like here: Re: adding n-tuples

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

Re: adding n-tuples
by BillKSmith (Parson) on May 16, 2019 at 14:41 UTC
    I assume that you want all tuples in which each column contains the corresponding column from either A or B. Here is one way to do it:
    use strict; use warnings; my @A = qw(1 10 100 1000); my @B = qw(2 20 200 2000); my $sum = 0; foreach my $fac1 ($A[0], $B[0]) { foreach my $fac2 ($A[1], $B[1]) { foreach my $fac3 ($A[2], $B[2]) { foreach my $fac4 ($A[3], $B[3]) { my $prod = $fac1 * $fac2 * $fac3 * $fac4; $sum += $prod; printf "%5d %5d %5d %5d: %.0f\n", $fac1, $fac2, $fac3, + $fac4, $prod; } } } } print $sum;

    Update: Corrected computation of products. Added print for debugging.

    Bill

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://11100080]
Approved by marto
Front-paged by haukex
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chanting in the Monastery: (4)
As of 2019-05-25 06:01 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Do you enjoy 3D movies?



    Results (151 votes). Check out past polls.

    Notices?
    • (Sep 10, 2018 at 22:53 UTC) Welcome new users!