Using perl's reduce to compute dot-product - perl

Suppose I have the following two equal-sized arrays in my perl program:
my #arr1 = 1..5;
my #arr2 = 6..10;
I'm trying to get their dot-product using the reduce function defined in the List::Util core module but the following is not working for me:
my $dot_prod = reduce { $arr1[$a] * $arr2[$a] + $arr1[$b] * $arr2[$b] }0..$#arr1;
I get 50 as my output instead of the expected 130.

The documentation describes the behavior of reduce as follows:
The first call will be with $a and $b set to the first two elements of
the list, subsequent calls will be done by setting $a to the result of
the previous call and $b to the next element in the list.
Thus, in this case, on the first iteration reduce will set $a = 0 and $b = 1, and hence, execute
$arr1[0] * $arr2[0] + $arr1[1] * $arr2[1]
This temporary result happens to be 20.
Now, for the second iteration, $a is set to the result of the previous iteratrion and so $a = 20 and $b = 2. Thus, the following will be executed
$arr1[20] * $arr2[20] + $arr1[2] * $arr2[2]
which is not what we want.
A possible workaround:
prepend an initial 0 to the list provided as input to reduce as follows:
my $dot_prod = reduce { $a + $arr1[$b] * $arr2[$b] } 0, 0..$#arr1;
This gives us the desired result since on the first iteration $a = $b = 0 and we'll compute
0 + $arr[0] * $arr[0]
whose result will be 6.
Then in the second iteration, we'll have $a = 6 $b = 1 and so we'll compute
6 + $arr1[1] * $arr2[1]
etc.

Honestly,
my $dot_prod = reduce { $a + $arr1[$b] * $arr2[$b] } 0, 0..$#arr1;
isn't the most readable. There is this:
my $dot_prod = sum map { $arr1[$_]*$arr2[$_] } 0..$#arr1;
But that doesn't use reduce. Well, we could simply implement sum in terms of reduce instead of using List::Util's, and perhaps even inline it:
my $dot_prod = reduce { $a+$b } map { $arr1[$_]*$arr2[$_] } 0..$#arr1;

Here are the previously posted solutions in a runnable program:
my #arr1 = 1..3;
my #arr2 = 6..8;
use List::Util qw(reduce sum) ;
my $dot_prod0 = reduce { $a + $arr1[$b] * $arr2[$b] } 0,0..$#arr1; #reduce
print "Dot product0 = ".$dot_prod0."\n";
my $dot_prod1 = sum map { $arr1[$_]*$arr2[$_] } 0..$#arr1; #sum map
print "Dot product1 = ".$dot_prod1."\n";
my $dot_prod2 = reduce { $a+$b } map { $arr1[$_]*$arr2[$_] } 0..$#arr1; #reduce map
print "Dot product2 = ".$dot_prod2."\n";

Related

adding numbers returned from function in powershell

I have the following basic code in powershell where I'm calculating the value of x
function add3([int]$num) {
return ($num + 3);
}
[String]$argA = "AB";
[int]$x = (add3($argA.Length) + 2);
Write-Host($x)
Running this in ISE I'm getting the value 5 instead of 7.
In PowerShell, you call functions by listing the arguments separated by spaces, not commas, and parentheses are not used. This is a common source of confusion. Your expression:
[int]$x = (add3($argA.Length) + 2);
Is a call to the function add3 with three arguments: ($argA.Length) and the strings + and 2. Since your function has only one argument, the result is 2 + 3 = 5 and the other two are discarded (calling a function with extraneous parameters is not an error in PowerShell). You can verify this is what's happening by changing your function:
function add3([int]$num, $y, $z) {
Write-Host $y;
Write-Host $z;
return ($num + 3);
}
The solution is to parenthesize the expression properly:
$x = (add3 $argA.Length) + 2;
You're getting the correct output.
Try to use this approach instead:
[int]$x = (add3($argA.Length)) + 2
function add3($num) {
return ($num + 3);
}
[String]$argA = "AB";
$x = (add3($argA.Length)) +2
Write-Host($x)

Can someone explain the logic of the recursion code and when it's best to use?

I'm learning perl and I want to understand the logic better so I can improve in programming. I was wondering if anyone could explain it part by part. I think I have a good grasp of what's happening instead of this line $num = $val * fact($val-1); ?
#!/usr/bin/perl
use warnings;
use strict;
print "Enter in a number\n";
my $input = <>;
my $num = fact($input);
print "The factorial of $input is $num\n";
sub fact {
my $val = $_[0];
if ( $val > 1 ) {
$num = $val * fact( $val - 1 );
}
else {
$num = 1;
}
}
exit;
The first line is the shebang, which specifies which version of Perl to use.
#!/usr/bin/perl
The next two lines will help you catch mistakes in your program and make sure you are coding properly. See Why use strict and warnings?
use warnings;
use strict;
print will print the message in quotes.
print "Enter in a number\n";
The diamond operator, <>, used in this context, is the same as calling readline. It will read the input from STDIN.
my $input=<>;
The next line is calling the subroutine fact with $input as an argument.
my $num= fact($input);
Printing the result. $input and $num will be interpolated because you are using double quotes.
print "The factorial of $input is $num\n";
Finally, the part you are most interested in.
sub fact{
my $val = $_[0];
if ($val > 1) {
$num = $val * fact($val-1);
} else {
$num = 1;
}
}
The first line of this subroutine my $val = $_[0];, is setting $val equal to the value you call it with. The first time through, you call is with $input, so $val will be set to that value.
Next, we have this if else statement. Suppose you enter 5 on the command line, so $input was 5. In that case, it is greater than 1. It will execute the statement $num = $val * fact($val-1);. Seeing as the value of $val is 5, it would be the same as calling $num = 5 * fact(4);.
If we were going to continue looking at the what code is executing, you'll see that now we are calling fact(4);. Since 4 > 1 it will pass the if statement again, and then call fact(3).
Each time we are multiplying the number by that number minus one, such as $val = 5 * 4 * 3 * 2 * 1.
From perlsub
If no return is found and if the last statement is an expression, its
value is returned. If the last statement is a loop control structure
like a foreach or a while , the returned value is unspecified. The
empty sub returns the empty list.
So this is why we don't have to return $num at the end of your fact subroutine, but it may be useful to add to increase readability.
Just to break down what this is doing.
$num = 5 * fact(4);
fact(4) is equivalent to 4 * fact(3).
$num = 5 * (4 * fact(3));
fact(3) is equivalent to 3 * fact(2).
$num = 5 * (4 * (3 * fact(2)));
fact(2) is equivalent to 2 * fact(1).
$num = 5 * (4 * (3 * (2 * fact(1)));
fact(1) is equivalent to 1.
$num = 5 * (4 * (3 * (2 * 1));
Search recursion on Google for another example (did you mean recursion?).
As a wise man once said: "To understand recursion, you must first understand recursion."
Anyway - there are a bunch of algorithms that can work recursively. Factorial is one.
A factorial of 5! = 5*4*3*2*1. This makes it quite a good case for recursion, because you could also say it's 5 * 4!. This is what the code is doing. When you supply a number to the subroutine 'fact' it calculates the factorial of one number lower, then multiplies by the original number. Except when it gets a value of 1 or less.
So give your fact "3" to start off. (same applies to bigger numbers, but the example is longer!)
It sets val to '3'.
Then, because '3 > 1' it goes and gets 'fact(2)'.
which because 2 > 1, goes and runs 'fact(1)'.
which because it isn't >1, returns '1'.
which is returned to the 'fact(2)' sub, multiple by '2' (giving 2) and returned as a result
to the 'fact(3) sub, which multiplies the returned result by 3, to give 6.
Personally I find recursion is a good way to confuse anyone who's reading your code. It's suitable for problems that are implicitly recursive - such as factorials, fibonnaci sequences and directory traversals - and generally should be avoided otherwise.
The reason you're having trouble learning from that code is because it's poorly designed:
The subroutine needlessly uses a lexical variable ($num) from outside the subroutine. Don't do this!
The subroutine relies on implied return values instead of specifying return explicitly.
Fixing these issues clarifies the functionality a lot:
sub fact {
my $val = $_[0];
if ( $val > 1 ) {
return $val * fact( $val - 1 );
}
else {
return 1;
}
}
And then using a ternary to reduce more:
sub fact {
my $val = shift;
return $val > 1 ? $val * fact( $val - 1 ) : 1;
}
As for when recursion is good to use? The answer is when you need it.
The factorial is an obvious example of where recursion could be used, but it's better to avoid using it when one has a choice. This is for both readability and functional reasons:
sub fact {
my $val = shift;
my $fact = 1;
while ($val > 1) {
$fact *= $val--;
}
return $fact;
}

Add an element at the end of a vector

I would like to add at the end of a vector that presents already a number of elements the numbers "1" or "0". Let's say that I have 2D vectors with different lenghts like
vector[0][0] = 1
vector[0][1] = 3
vector[1][0] = 2
vector[1][1] = 4
vector[1][2] = 5
I would like to add at the end of each vector the numbers 1 or 0 (based on an if command); the output sould be:
vector[0][0] = 1
vector[0][1] = 3
vector[0][2] = 1
vector[1][0] = 2
vector[1][1] = 4
vector[1][2] = 5
vector[1][3] = 0
in which the new elements added are vector[0][2] = 1 and vector[1][3]=0.
I thought of somenthing like:
for my $i (0..$#vector) {
for my $j (0..$#{ $vector[$i] }) {
if($prob_friendship > (my $random_number=rand()) ) {
push #{ $vector[$i][$j] }, 1;
}
else {
push #{ $vector[$i][$j] }, 0;
}
}
}
but it gives me the error Can't use string ("1") as an ARRAY ref while "strict refs" in use at distribuzione2.pl line 42, <STDIN> line 5.
Any help?
The $prob_friendship value is given in input by keyborad
There's no need for the nested loop, you only need to iterate over the first array index.
You can just iterate using $i as you are now and then use push #{$vector[$i]}, ...
Alternatively, if you don't actually need to know the array index (and with props to #TLP's answer) you can iterate directly over the individual references stored in the first dimension of #vector and do the whole thing in three lines:
for my $ref (#vector) {
push #$ref, ($prob_friendship > rand()) ? 1 : 0;
}
You can just use the array refs as they are:
for my $aref (#vector) { # will iterate over array refs
if ($prob > rand()) {
push #$aref, 1; # dereferencing the aref
} else {
push #$aref, 0;
}
}

Perl - Returning the maximum value in a data set

I have never delved into the world of Perl before and I find it pretty confusing and could use some help. In the code below the calc() section returns a running average of an'input' over 'count' samples. I would like to modify that so the calc() returns the maximum value within the sample set. Thanks in advance for the help!
sub calc
{
my ($this, $dim, $input, $count) = #_;
if ($count < 1)
{
warn "count=$count is less than 1.";
return undef;
}
my $inputsum_in = $this->{inputsum};
my ($inputcumsum, $inputsum_out) = PDL::CumulativeSumOver2($input, $inputsum_in);
my $inputdelay = $this->delay('inputhistory', $input);
my $inputdelaysum_in = $this->{inputdelaysum};
my ($inputdelaycumsum, $inputdelaysum_out) = PDL::CumulativeSumOver2($inputdelay, $inputdelaysum_in);
$this->{inputsum} = $inputsum_out;
$this->{inputdelaysum} = $inputdelaysum_out;
my $sampleno = $this->{sampleno};
my $divider = $count;
if($sampleno < $count)
{
my $last = $dim - 1;
$divider = sequence($dim) + ($sampleno + 1);
my $start = $count - $sampleno;
$divider->slice("$start:$last") .= $count if $start <= $last;
$this->{sampleno} = $sampleno + $dim;
}
return ($inputcumsum - $inputdelaycumsum) / $divider;
}
How about
$max = max($input);
PDL Primitives
If you want to find the maximum of a certain list of values, you do not need to write your own subroutine. There is already a function that comes shipped with perl v5.7.3 or higher:
use List::Util qw(max); # core module since v5.7.3
use strict;
use warnings;
print max(1 .. 10); # prints 10
EDIT: Here is the loop I take it you need.
Read input data from sensor
append new data to stored data
Throw away excess data
Evaluate
Here's how I'd do it.
my $storedData = pdl;
# $storedData is now a vector containing one element, 0
while (! stopCondition()) {
my $input = readSensorData(); # step 1
$storedData = $storedData->append($input); # step 2
if ($storedData->nelem > $count) { # step 3
$storedData = $storedData->slice("-$count:-1");
# note that -1 points to the last element in a piddle and -X refers to
# the element X-1 away from the end (true for piddles and native arrays)
}
my ($max, $min) = evaluate($storedData); # step 4
}
I'm not sure if this answers your question, but your comment below seems pretty different from the question you have above. Consider editing the above to better reflect what you're having trouble with or asking a new question.
An easy way to get a running average is with a finite impulse response filter, aka convolution. Convolve any signal with a (normalized) rectangular impulse and you get running average.
my $filter = ones($count) / $count;
my $runningAve = convolveND($input, $filter);
my $max = $runningAve->max`;
Or in one line
my $max = convolveND($input, ones($count) / $count)->max;
convolveND is documented here.
There is one thing to be careful of with this method, which is that the values at the beginning and end of the $runningAve piddle aren't really running averages. To ensure that the output is the same size as the input convolveND (by default) effectively concatenates zeroes to the beginning and end of the input, the result being that the first and last few elements of $runningAve are lower than actual running averages. (Note that a running average should have N - (window - 1) elements in principle, N being the size of $input.) Since these "bad" values will necessarily be lower than the actual running average values, they won't disturb the maximum that you want. (Re "by default": convolveND has other ways of handling edges, as you will see in the documentation linked to above.)
(NB: I am not a PDL expert. There may be a cheaper way to get the running average that's cheaper than convolveND, something like $ra = $input->range(...)->sumover(0) / $count, but I don't know what you'd put in the ... and the above is readable. See also http://search.cpan.org/~jlapeyre/PDL-DSP-Iir-0.002/README.pod#moving_average)

Multiplication large numbers in perl

i have a problem with a scripts below and How to make multification results equals to 1332521814089765.
#!/usr/bin/perl
my $divide = 1332521814089765/1332521809;
my $results1 = int $divide;
print "After Divide: $results1 \n";
my $multiplication = $results1*1332521809;
my $results2 = $multiplication;
print "After Multiplication: $results2 \n"; #How to make multification results equals to 1332521814089765
after searching and make a test here the results but still not get my expected results
my $divide = 1332521814089765/1332521809;
my $multiplication = $divide*1332521809;
my $results = $multiplication/10;
print "My Results: $results\nExpect Results: 1332521814089765\n";
1000000 * 1332521809 is equal to 1332521809000000. Why would you expect 1332521814089765?
Maybe you are multiplying the wrong numbers, which is to say you meant to use
my $multiplication = $divide*1332521809;
instead of
my $multiplication = $results1*1332521809;
Another possibility is that you are trying to find the inverse function of
$y = int($x/$k)
Unfortunately, there is none because there are multiple values of $x that give the same $y.
int(1332521809000000/1332521809) = 1000000
...
int(1332521814089764/1332521809) = 1000000
int(1332521814089765/1332521809) = 1000000
int(1332521814089766/1332521809) = 1000000
...
int(1332523141521808/1332521809) = 1000000