aboutsummaryrefslogtreecommitdiff
path: root/challenge-008
diff options
context:
space:
mode:
authorMohammad S Anwar <Mohammad.Anwar@yahoo.com>2019-05-19 00:14:14 +0100
committerGitHub <noreply@github.com>2019-05-19 00:14:14 +0100
commit1d61345cef518e4d7dd1666eb5eae2da376f845e (patch)
tree00a1bb377b8d9afced06c99baf77df85ecfa2b1e /challenge-008
parent323f6fb1bb7f08767d0e2f5a8f8af36fba6d6785 (diff)
parentdfd2342e9a673f42aa2d2a0f1255859172738db3 (diff)
downloadperlweeklychallenge-club-1d61345cef518e4d7dd1666eb5eae2da376f845e.tar.gz
perlweeklychallenge-club-1d61345cef518e4d7dd1666eb5eae2da376f845e.tar.bz2
perlweeklychallenge-club-1d61345cef518e4d7dd1666eb5eae2da376f845e.zip
Merge pull request #158 from dmanto/branch-for-challenge-008
my solutions to ch-1 & 2 in perl5
Diffstat (limited to 'challenge-008')
-rw-r--r--challenge-008/daniel-mantovani/perl5/ch-1.pl52
-rw-r--r--challenge-008/daniel-mantovani/perl5/ch-2.pl55
2 files changed, 107 insertions, 0 deletions
diff --git a/challenge-008/daniel-mantovani/perl5/ch-1.pl b/challenge-008/daniel-mantovani/perl5/ch-1.pl
new file mode 100644
index 0000000000..237514adf6
--- /dev/null
+++ b/challenge-008/daniel-mantovani/perl5/ch-1.pl
@@ -0,0 +1,52 @@
+# Write a script that computes the first five perfect numbers.
+# A perfect number is an integer that is the $sum of its positive proper divisors (all divisors except itself).
+# Please check Wiki for more information. This challenge was proposed by Laurent Rosenfeld.
+
+use strict;
+use warnings;
+use v5.10;
+
+# we start by defining a sub that checks if a number is perfect (i.e is equal lo the sum of all its divisors):
+
+sub is_perfect {
+ my $x = shift;
+ my $sum = 0;
+ for my $d ( 1 .. $x - 1 ) {
+ $sum += $d unless $x % $d;
+ }
+ return $sum == $x;
+}
+
+# as using this formula to test all integers (or even restricted to odd numbers) will take forever, we
+# use other property of perfect numbers. They have the binary form of x ones (1) followed by x-1 zeros (0)
+# note that 2 ^ x - 1 will give you a binary number of x ones, and if you multiply this number for
+# 2 ^ (x-1) yow will be adding x - 1 zeros to the right.
+
+sub get_candidate {
+ my $p = shift;
+ return undef unless ( $p && $p > 0 && $p < 33 );
+ my $pwr2 = 1;
+ $pwr2 *= 2 while --$p; # $pwr2 will be 2 ^ ($p-1)
+ return ( $pwr2 * 2 - 1 ) * $pwr2;
+
+ # this will be '1' x $p . '0' x ($p-1) in binary
+}
+
+# now we calculate all perfect number cases starting on get_candidate(2) until we get 5
+
+my $q = 5; # we need five perfect numbers
+my $ones = 2; #start with 2 ones and a 0 (110, i.e, 6)
+while ($q) {
+ my $candidate = get_candidate($ones);
+ $q-- && say $candidate if is_perfect($candidate);
+ $ones++;
+}
+
+# note that 5 is the maximum amount of perfect numbers that you can get with 32 bit arithmetics, as the 6th
+# one is 0b111111111111111110000000000000000 (17 ones and 16 zeros)
+#
+# calculating the first 5 takes 1.8 secs on my machine, if you want to get up to the sixth you can change $q
+# assignement to 6 in line 34 (provided that your perl has 64 bit arithmetics) , but the time to complete the
+# calculations increases to almost 8 min. This is because the is_perfect function has to as many divisions as
+# the number is checking minus one, so for the 6 perfect number that will be 858,986,056 divisions only for
+# the last check
diff --git a/challenge-008/daniel-mantovani/perl5/ch-2.pl b/challenge-008/daniel-mantovani/perl5/ch-2.pl
new file mode 100644
index 0000000000..4875a51070
--- /dev/null
+++ b/challenge-008/daniel-mantovani/perl5/ch-2.pl
@@ -0,0 +1,55 @@
+
+use strict;
+use warnings;
+use v5.10;
+use utf8;
+use open qw(:std :utf8);
+
+# Write a function, ‘center’, whose argument is a list of strings, which will be lines of text. The function
+# should insert spaces at the beginning of the lines of text so that if they were printed, the text would be
+# centered, and return the modified lines.
+
+# For example,
+
+# center("This", "is", "a test of the", "center function");
+# should return the list:
+
+# " This", " is", " a test of the", "center function"
+# because if these lines were printed, they would look like:
+
+# This
+# is
+# a test of the
+# center function
+
+sub center {
+ my @list = @_;
+
+ # size of bigger line (in chars, not in bytes):
+ my $sz;
+
+ # iterate over the list replacing chars in the list, and actualize max chars
+ for my $i ( 0 .. $#list ) {
+
+ # get rid of undefined lines
+ $list[$i] //= '';
+
+ # now actualize max size
+ $sz = !defined $sz || length $list[$i] > $sz ? length $list[$i] : $sz;
+ }
+
+ # nothing to do if $sz was not defined
+ return @list unless defined $sz;
+
+ # pad spaces in front in each line, to center the text
+
+ return map { ' ' x int( ( $sz - length ) / 2 ) . $_ } @list;
+}
+my @list = <>;
+chomp @list;
+say for center @list;
+
+#
+# you can test the example case with the following command executed in the script directory:
+# $> echo -e "This\nis\na test of the\ncenter function"|perl ch-2.pl
+#