I have a code in Perl which takes in a number and adds up all the prime numbers up to that number. I keep on getting the value 0 which means it is not updating my $sum variable, but I don't know what else to do.
sub checkPrime {
my($numb) = #_;
$primeCheck = "prime\n";
if ($numb == 1) {
$primeCheck = "notPrime\n";
}
for ($i = 2; $i < $numb; $i++) {
$mod = $numb % $i;
if ($mod == 0) {
$primeCheck = "notPrime\n"
}
}
return $primeCheck;
}
sub sumOfPrimes {
my($input) = #_;
$sum = 0;
for ($i = 2; $i <= $input; $i++) {
if (checkPrime($i) eq "prime") {
$sum = $sum + $i;
}
}
return $sum;
}
print sumOfPrimes(10);
You are not comparing the correct string. You include a newline character (\n) when you set the value, but not when you compare it. Change:
if (checkPrime($i) eq "prime")
to:
if (checkPrime($i) eq "prime\n")
That is the simplest change, but you probably don't need to have \n in there at all.
To sum prime numbers you need to identify if the number is a prime number. Let's create a function which returns 1 if the number is prime and 0 otherwise.
sub isPrime {
my $n = shift;
return 0 unless $n > 1;
for( my $i = 2; $i < $n; $i++ ) {
return 0 if $n % $i == 0;
}
return 1;
}
Now go through the list of numbers and sum only those which is prime
$sum += $num if isPrime($num);
Related
I tried writing a simple code to find whether a number can be expressed as the sum of primes or not, in Perl. The sample code is as shown:
sub funcIsPrime {
my $num = $_[0];
my $isPrime = 1;
for($i= 2; $i <= $num/2; $i++){
if($num%$i == 0){
$isPrime = 0;
last;
}
}
return $isPrime;
}
#my $num = <>;
my $num = 20;
for($i = 2; $i <= $num/2; $i++){
print "$i\t";
my $j = $num-$i;
print "$j\n";
if(funcIsPrime($i) and funcIsPrime($j)){ # Line x
print "$num = $i + $j\n";
}
}
The function call statements in Line x do not execute. The same line when put outside the loop works fine. What can be the possible solution? Please help. Thank you.
The main issue is missing my in variable declarations. Perl won't let you run the program if you include use warnings; and use strict;:
Global symbol "$i" requires explicit package name (did you forget to declare "my $i"?) at test.pl line 22.
Execution of test.pl aborted due to compilation errors.
Here's simplified working code (you can search for factors up to the square root of n, by the way, although this isn't a perfect or efficient prime test by any means):
use strict;
use warnings;
sub isPrime {
my $num = $_[0];
for (my $i = int sqrt $num; $i > 1; $i--) {
if ($num % $i == 0) {
return 0;
}
}
return 1;
}
my $num = 20;
for (my $i = 2; $i <= $num / 2; $i++) {
my $j = $num - $i;
if (isPrime($i) && isPrime($j)) {
print "$num = $i + $j\n";
}
}
Output
20 = 3 + 17
20 = 7 + 13
The data are stock options. I want to make a 2D array based on days till expiration (int) & normalized distance out of the money (float), with the values being a list of normalized bid and ask prices. If the desired element is not in the array, I want to be able to interpolate between the nearest elements present.
I see 3 possible data structures:
A sparse 2D array, maybe 10000 elements, maybe 1/3 full.
A 2D linked list, ie: 4 listpointers for each data element (so 3000 elements becomes 15000)
A 2D hash (maybe 3000 elements), with 2 sorted lists of the keys (maybe 100 elements each) in each dimension.
The main problem is efficient retrieval when interpolation is required.
Retrieval of existing elements is relatively straight-forward with any method.
I'm currently using choice 3, but retrieval is a bit of a kloodge, since I have to scan along the keylists of each dimension till I find occupied elements, and then do a 2- or 4-way interpolation.
I use moreUtils::firstindx($_ > $desiredKey) to find the keys. The linked lists (choice 2) would spare me the search of the keylist arrays.
Choice 1 would also require scanning, wouldn't need the initial step of keylist lookup, but might need to look at more empty cells. And insertion would be a real hassle.
I would be doing many more searches than insertions.
Does any one have any suggestions for the most efficient data structure.
Since you predominantly perform lookups by lifespan and lookups by distance, and few inserts, I'd use sorted arrays to lookup the records by binary search.
Locating an existing element: O(log N)
Locating the box of a missing element: O(log N)
Inserting: O(N)
Given,
my #data = (
[ $lifespan0, $distance0, $bid0, $ask0 ],
[ $lifespan1, $distance1, $bid1, $ask1 ],
...
);
my $lifespan_search_cmp = sub { $a <=> $data[$b][0] };
my $distance_search_cmp = sub { $a <=> $data[$b][1] };
First, create indexes:
my #by_lifespan = sort { $data[$a][0] <=> $data[$b][0] } 0..$#data;
my #by_distance = sort { $data[$a][1] <=> $data[$b][1] } 0..$#data;
To lookup:
my $i = binsearch_first \&$lifespan_search_cmp, $lifespan, #by_lifespan;
my $j = binsearch_first \&$distance_search_cmp, $distance, #by_distance;
my #lifespan_matching_idxs = get_run_forward \&$lifespan_search_cmp, $lifespan, $i, #by_lifespan;
my #distance_matching_idxs = get_run_forward \&$distance_search_cmp, $distance, $j, #by_distance;
my #cross_match_idxs = do {
my %lifespan_matching_idxs = map { $_ => 1 } #lifespan_matching_idxs;
grep { $lifespan_matching_idxs{$_} }
#distance_matching_idxs
};
if (#cross_match_idxs) {
# Exact match(es) found.
...
} else {
my $lifespan_lowerbracket;
my $lifespan_upperbracket;
if ($i >= 0) {
$lifespan_lowerbracket = $lifespan;
$lifespan_upperbracket = $lifespan;
} else {
die "Can't interpolate" if ~$i == 0 || ~$i >= #by_lifespan;
$lifespan_lowerbracket = $data[~$i ][0];
$lifespan_lowerbracket = $data[~$i - 1][0];
}
my $distance_lowerbracket;
my $distance_upperbracket;
if ($i >= 0) {
$distance_lowerbracket = $distance;
$distance_upperbracket = $distance;
} else {
die "Can't interpolate" if ~$j == 0 || ~$j >= #by_distance;
$distance_lowerbracket = $data[~$j ][1];
$distance_upperbracket = $data[~$j - 1][1];
}
...
}
To insert:
my $i = binsearch_first \&$lifespan_search_cmp, $lifespan, #by_lifespan;
my $j = binsearch_first \&$distance_search_cmp, $distance, #by_distance;
push #data, [ $lifespan, $distance , $bid, $ask ];
splice(#by_lifespan, $i >= 0 ? $i : ~$i, 0, $#data);
splice(#by_distance, $j >= 0 ? $j : ~$j, 0, $#data);
Subs:
sub binsearch_first(&$\#) {
my $compare = $_[0];
#my $value = $_[1];
my $array = $_[2];
my $min = 0;
my $max = $#$array;
return -1 if $max == -1;
my $ap = do { no strict 'refs'; \*{caller().'::a'} }; local *$ap;
my $bp = do { no strict 'refs'; \*{caller().'::b'} }; local *$bp;
*$ap = \($_[1]);
while ($min <= $max) {
my $mid = int(($min+$max)/2);
*$bp = \($array->[$mid]);
my $cmp = $compare->();
if ($cmp < 0) {
$max = $mid - 1;
}
elsif ($cmp > 0) {
$min = $mid + 1;
}
else {
return $mid if $mid == $min;
$max = $mid;
}
}
# Converts unsigned int to signed int.
return unpack('j', pack('J', ~$min));
}
sub get_run_forward(&$\#) {
my $compare = $_[0];
#my $value = $_[1];
my $start = $_[2];
my $array = $_[3];
return if $start < 0;
my $ap = do { no strict 'refs'; \*{caller().'::a'} }; local *$ap;
my $bp = do { no strict 'refs'; \*{caller().'::b'} }; local *$bp;
*$ap = \($_[1]);
my $i = $start;
while ($i <= $#$array) {
*$bp = \($array->[$i]);
my $cmp = $compare->()
and last;
++$i;
}
return wantarray ? ($start..$i-1) : $i-1;
}
You might want to use a tolerance in the floating-point comparions (i.e. in $distance_search_cmp).
I am trying to write a subroutine that determines whether or not the number passed in is prime, and it's not working correctly. The numbers I'm passing in should not be identified as prime. Is there a logic error, or something about Perl that I'm missing?
sub isPrime {
my ( $n ) = #_;
for ( my $i = 3 ; $i < $n ; $i++ ) {
if ( $n % $i == 0 ) {
return 0;
}
else {
return 1;
}
}
}
At the moment your function is checking just if n is not divisible by 3 because it calls return immediately after the fisrt test.
Try to make the function return 0 within the for loop, and return 1 outside it, or set a flag for the number being prime that is initially true and return its value after the loop.
You should also start your for loop at 2, not at 3, otherwise you aren't testing for even numbers.
Here is my code I wrote in about 40 minutes. Don't hate if it is inefficient, I am still learning perl.
print ("This is a prime number checker!\n");
print ("Enter a number below to check it:\n");
$y = 0;
$num = <>;
for ($i = $num; $i > 0; $i--) {
if ($num % $i == 0) {
$y += 1;
}
}
if ($y > 2) {
print ("$num is not a prime!");
} else {
print ("$num is a prime!");
}
I have a Perl program containing the following methods:
det To find the determinant of a matrix.
identityMatrix Return an n by n identity matrix (1s on the main diagnal, rest 0s).
matrixAdd To add two matrices together.
matrixScalarMultiply To multiply an integer by a matrix.
I can easily find the determinant of, for example, a matrix A - I where
(It is 0)
But what if I want to find the determinant of A - RI?
In this case, I want my program to solve for the characteristic polynomial solution (a.k.a. the determinant containing variables) along these lines instead of an integer value:
Any suggestions on how to handle this? Code below:
#!/usr/bin/perl
#perl Solver.pl
use strict;
use warnings;
### solve the characteristic polynomial det(A - RI)
my #A = ( # 3x3, det = -3
[1, 3, -3],
[1, 0, 0],
[0, 1, 0],
);
# test_matrix = A - I
my $test_matrix = matrixAdd( \#A,
matrixScalarMultiply( identityMatrix(3), -1 ) );
print "\nTest:\n";
for( my $i = 0; $i <= $#$test_matrix; $i++ ){
print "[";
for( my $j = 0; $j <= $#$test_matrix; $j++ ){
$j == $#$test_matrix ? print $test_matrix->[$i][$j], "]\n" :
print $test_matrix->[$i][$j], ", ";
}
}
my $dd = det ($test_matrix);
print "det = $dd \n";
# recursively find determinant of a real square matrix
# only call on n by n matrices where n >= 2
#
# arg0 = matrix reference
sub det{
my ($A) = #_;
#base: 2x2 matrix
if( $#$A + 1 == 2 ){ #recall $#$A == last index of A
return $A->[0][0]*$A->[1][1] - $A->[1][0]*$A->[0][1];
}
#cofactor expansion for matrices > 2x2
my $answer = 0;
for( my $col = 0; $col <= $#$A; $col++ ){
my $m = (); #sub matrix
my $multiplier = $A->[0][$col];
if( $col % 2 == 1 ){ #+, -, +, -, ...
$multiplier *= -1;
}
for( my $i = 1; $i <= $#$A; $i++ ){
#j is indexer for A, k for m
for( my ($j, $k) = (0, 0); $j <= $#$A; $j++ ){
$m->[$i-1][$k++] = $A->[$i][$j] unless $j == $col;
}
}
$answer += $multiplier*det( $m );
}#end cofactor expansion
return $answer;
}#end det()
# return reference to an n by n identity matrix
# can do this in Perl!
#
# arg0 = dimension 'n'
sub identityMatrix{
my $n = shift;
my #ret;
for (my $i = 0; $i < $n; $i++ ){
for (my $j = 0; $j < $n; $j++ ){
$ret[$i][$j] = $i == $j ? 1 : 0;
}
}
return \#ret;
}
# return reference to an n by n matrix which is the sum
# of two different n by n matrices, "a" and "b"
#
# arg0, 1 = references to the pair of matrices to add
sub matrixAdd{
my #ret;
my ($a, $b) = ($_[0], $_[1]);
for (my $i = 0; $i <= $#$a; $i++ ){
for (my $j = 0; $j <= $#$a; $j++ ){
$ret[$i][$j] = $a->[$i][$j] + $b->[$i][$j];
}
}
return \#ret;
}
# return reference to a matrix multiplied by a given scalar
#
# arg0 = reference to matrix
# arg1 = scalar to multiply by
sub matrixScalarMultiply{
my #ret;
my ($a, $multiplier) = ($_[0], $_[1]);
for (my $i = 0; $i <= $#$a; $i++ ){
for (my $j = 0; $j <= $#$a; $j++ ){
$ret[$i][$j] = $a->[$i][$j] * $multiplier;
}
}
return \#ret;
}
This is called symbolic math and is in the wheelhouse of tools like Mathematica. For Perl, there are packages like Math::Synbolic but I couldn't tell you how easy they are to use.
On the other hand, if you are just interested in what values of R have a determinant of zero and not that interested in what the characteristic polynomial looks like, then you are looking for the eigenvalues of A. There are some Perl libraries for that, too.
For clarification, if I had a list of 8 elements, i would want to randomly pick 2. If I had a list of 20 elements, I would want to randomly pick 5. I would also like to assure (though not needed) that two elements don't touch, i.e. if possible not the 3 and then 4 element. Rather, 3 and 5 would be nicer.
The simplest solution:
Shuffle the list
select the 1st quarter.
Example implementation:
use List::Util qw/shuffle/;
my #nums = 1..20;
my #pick = (shuffle #nums)[0 .. 0.25 * $#nums];
say "#pick";
Example output: 10 2 18 3 19.
Your additional restriction “no neighboring numbers” actually makes this less random, and should be avoided if you want actual randomness. To avoid that two neighboring elements are included in the output, I would iteratively splice unwanted elements out of the list:
my #nums = 1..20;
my $size = 0.25 * #nums;
my #pick;
while (#pick < $size) {
my $i = int rand #nums;
push #pick, my $num = $nums[$i];
# check and remove neighbours
my $len = 1;
$len++ if $i < $#nums and $num + 1 == $nums[$i + 1];
$len++, $i-- if 0 < $i and $num - 1 == $nums[$i - 1];
splice #nums, $i, $len;
}
say "#pick";
use strict;
use warnings;
sub randsel {
my ($fact, $i, #r) = (1.0, 0);
while (#r * 4 < #_) {
if (not grep { $_ == $i } #r) {
$fact = 1.0;
# make $fact = 0.0 if you really don't want
# consecutive elements
$fact = 0.1 if grep { abs($i - $_) == 1 } #r;
push(#r, $i) if (rand() < 0.25 * $fact);
}
$i = ($i + 1) % #_;
}
return map { $_[$_] } sort { $a <=> $b } #r;
}
my #l;
$l[$_] = $_ for (0..19);
print join(" ", randsel(#l)), "\n";