From 6145ce7249758b1eaea8d240e3d6e02ad3e4fa3c Mon Sep 17 00:00:00 2001 From: Duane Powell Date: Tue, 27 Aug 2019 08:49:51 -0500 Subject: Commit solutions for perl weekly challenge 023 --- challenge-023/duane-powell/perl5/ch-1.pl | 56 +++++++++++++++++++++ challenge-023/duane-powell/perl5/ch-2.pl | 86 ++++++++++++++++++++++++++++++++ 2 files changed, 142 insertions(+) create mode 100755 challenge-023/duane-powell/perl5/ch-1.pl create mode 100755 challenge-023/duane-powell/perl5/ch-2.pl diff --git a/challenge-023/duane-powell/perl5/ch-1.pl b/challenge-023/duane-powell/perl5/ch-1.pl new file mode 100755 index 0000000000..d17b0b95b9 --- /dev/null +++ b/challenge-023/duane-powell/perl5/ch-1.pl @@ -0,0 +1,56 @@ +#!/usr/bin/perl +use Modern::Perl; + +# Create a script that prints nth order forward difference series. You should be a able to pass +# the list of numbers and order number as command line parameters. Let me show you with an example. + +# Suppose we have list (X) of numbers: 5, 9, 2, 8, 1, 6 and we would like to create 1st order +# forward difference series (Y). So using the formula Y(i) = X(i+1) - X(i), we get the following +# numbers: (9-5), (2-9), (8-2), (1-8), (6-1). In short, the final series would be: 4, -7, 6, -7, 5. +# If you noticed, it has one less number than the original series. Similary you can carry on 2nd +# order forward difference series like: (-7-4), (6+7), (-7-6), (5+7) => -11, 13, -13, 12. +# +my ($order, @series) = @ARGV; +($order and @series > 1) || die "Usage:\n$0 order list-of-space-separated-ints\n"; + +# No point in order being larger than series size - 1 +$order = scalar(@series)-1 if ($order >= @series); + +say "order:\tseries:"; +for (1 .. $order) { + my @num; + # we need two numbers to continue + if (@series > 1) { + my $x = shift @series; + foreach my $n (@series) { + push @num, $n-$x; + $x = $n; + } + say "$_:\t" . join(",",@num); + } + @series = @num; +} + +__END__ + +./ch-1.pl 5 5 9 2 8 1 6 +order: series: +1: 4,-7,6,-7,5 +2: -11,13,-13,12 +3: 24,-26,25 +4: -50,51 +5: 101 + +./ch-1.pl 10 1 2 3 4 5 6 7 8 9 10 10000 +order: series: +1: 1,1,1,1,1,1,1,1,1,9990 +2: 0,0,0,0,0,0,0,0,9989 +3: 0,0,0,0,0,0,0,9989 +4: 0,0,0,0,0,0,9989 +5: 0,0,0,0,0,9989 +6: 0,0,0,0,9989 +7: 0,0,0,9989 +8: 0,0,9989 +9: 0,9989 +10: 9989 + diff --git a/challenge-023/duane-powell/perl5/ch-2.pl b/challenge-023/duane-powell/perl5/ch-2.pl new file mode 100755 index 0000000000..72abe7aacc --- /dev/null +++ b/challenge-023/duane-powell/perl5/ch-2.pl @@ -0,0 +1,86 @@ +#!/usr/bin/perl +use Modern::Perl; +use Math::Prime::Util qw(is_prime); +use bigint; + +# Create a script that prints Prime Decomposition of a given number. +# The prime decomposition of a number is defined as a list of prime +# numbers which when all multiplied together, are equal to that number. +# For example, the Prime decomposition of 228 is 2,2,3,19 as 228 = 2 x 2 x 3 x 19. + +my @num = @ARGV; +(@num) || die "Usage:\n$0 list-of-space-separted-ints;\n$0 test\n"; +@num = (228,864,1008,1024,130321,823543,3894380348208432032,7102345678999999999) if ($ARGV[0] eq 'test'); +prime_fact($_) foreach (@num); +exit; + +sub prime_fact { + my $p = shift; + if ($p < 2 or $p =~ m/\D/) { + say "$p? Input must be an integer greater than 1"; + return; + } + + my %out; + my $fac = 2; + my $n = $p; + while ($n >=2) { + if (is_prime($n)) { + $out{$n}++; + last; + } else { + if ($n % $fac) { + # Remainder exists, try next factor. + $fac++; + } else { + # No remainder, $fac is a factor. + # Continue with smaller $n + $out{$fac}++; + $n = $n/$fac; + } + } + } + + # We got all factors and their counts, make the output human + # readable with commify() and powers, eg 2 x 2 x 2 = (2^3) + my @out; + foreach (sort {$a <=> $b} (keys %out)) { + if ($out{$_} > 1) { + push @out, "($_^" . commify($out{$_}) . ")"; + } else { + push @out, commify($_); + } + } + # If input $p was a prime then display output as p=1xp by unshifting 1 into front of @out + unshift @out, 1 if (@out == 1 and $out[0] !~ m/\(/); + $p = commify($p); + say "$p = ", join(" x ", @out); +} + +# From the Perl Cookbook +sub commify { + my $n = reverse shift; + $n =~ s/(\d\d\d)(?=\d)(?!\dx\.)/$1,/g; + return scalar reverse $n; +} + +__END__ + +./ch-2.pl 999999999 +999,999,999 = (3^4) x 37 x 333,667 + +./ch-2.pl 256 500 1001 +256 = (2^8) +500 = (2^2) x (5^3) +1,001 = 7 x 11 x 13 + +./ch-2.pl test +228 = (2^2) x 3 x 19 +864 = (2^5) x (3^3) +1,008 = (2^4) x (3^2) x 7 +1,024 = (2^10) +130,321 = (19^4) +823,543 = (7^7) +3,894,380,348,208,432,032 = (2^5) x 47 x 136,373 x 18,987,252,871 +7,102,345,678,999,999,999 = 661 x 45,600,991 x 235,627,549 + -- cgit