diff options
| author | Daniel Mantovani <daniel@gmail.com> | 2019-05-18 18:58:40 -0300 |
|---|---|---|
| committer | Daniel Mantovani <daniel@gmail.com> | 2019-05-18 18:58:40 -0300 |
| commit | dfd2342e9a673f42aa2d2a0f1255859172738db3 (patch) | |
| tree | 13b0c2e7292585d4dfcad3ba7d5ecf230645be95 | |
| parent | 48768e4de07ea92f82d71878098d140e5ef230dd (diff) | |
| download | perlweeklychallenge-club-dfd2342e9a673f42aa2d2a0f1255859172738db3.tar.gz perlweeklychallenge-club-dfd2342e9a673f42aa2d2a0f1255859172738db3.tar.bz2 perlweeklychallenge-club-dfd2342e9a673f42aa2d2a0f1255859172738db3.zip | |
my solutions to ch-1 & 2 in perl5
| -rw-r--r-- | challenge-008/daniel-mantovani/perl5/ch-1.pl | 52 | ||||
| -rw-r--r-- | challenge-008/daniel-mantovani/perl5/ch-2.pl | 55 |
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 +# |
