diff options
| author | PerlMonk Athanasius <PerlMonk.Athanasius@gmail.com> | 2020-05-10 07:09:30 -0700 |
|---|---|---|
| committer | PerlMonk Athanasius <PerlMonk.Athanasius@gmail.com> | 2020-05-10 07:09:30 -0700 |
| commit | 56529d80f94ae3ed2c3f4d3ab7d4cd02bfed1c51 (patch) | |
| tree | 3a213a9cb1992973fadd973fe63eda49ba345f11 /challenge-059 | |
| parent | c85f60e27e2b6795a12f1d32f5b597e29eb9d32f (diff) | |
| download | perlweeklychallenge-club-56529d80f94ae3ed2c3f4d3ab7d4cd02bfed1c51.tar.gz perlweeklychallenge-club-56529d80f94ae3ed2c3f4d3ab7d4cd02bfed1c51.tar.bz2 perlweeklychallenge-club-56529d80f94ae3ed2c3f4d3ab7d4cd02bfed1c51.zip | |
Perl & Raku solutions to Tasks 1 & 2 of the Perl Weekly Challenge #059
On branch branch-for-challenge-059
Changes to be committed:
new file: challenge-059/athanasius/perl/ch-1.pl
new file: challenge-059/athanasius/perl/ch-2.pl
new file: challenge-059/athanasius/raku/ch-1.raku
new file: challenge-059/athanasius/raku/ch-2.raku
Diffstat (limited to 'challenge-059')
| -rw-r--r-- | challenge-059/athanasius/perl/ch-1.pl | 120 | ||||
| -rw-r--r-- | challenge-059/athanasius/perl/ch-2.pl | 109 | ||||
| -rw-r--r-- | challenge-059/athanasius/raku/ch-1.raku | 132 | ||||
| -rw-r--r-- | challenge-059/athanasius/raku/ch-2.raku | 111 |
4 files changed, 472 insertions, 0 deletions
diff --git a/challenge-059/athanasius/perl/ch-1.pl b/challenge-059/athanasius/perl/ch-1.pl new file mode 100644 index 0000000000..31df520db8 --- /dev/null +++ b/challenge-059/athanasius/perl/ch-1.pl @@ -0,0 +1,120 @@ +#!perl + +################################################################################ +=comment + +Perl Weekly Challenge 059 +========================= + +Task #1 +------- +*Linked List* + +*Reviewed by Ryan Thompson* + +You are given a linked list and a value _k_. Write a script to partition the +linked list such that all nodes less than _k_ come before nodes greater than or +equal to _k_. Make sure you preserve the original relative order of the nodes in +each of the two partitions. + +For example: + +Linked List: 1 → 4 → 3 → 2 → 5 → 2 + +_k_ = 3 + +Expected Output: 1 → 2 → 2 → 4 → 3 → 5. + +=cut +################################################################################ + +#--------------------------------------# +# Copyright © 2020 PerlMonk Athanasius # +#--------------------------------------# + +use strict; +use warnings; +use LinkedList::Single; + +#------------------------------------------------------------------------------- +BEGIN +#------------------------------------------------------------------------------- +{ + $| = 1; + print "\n"; +} + +#=============================================================================== +MAIN: +#=============================================================================== +{ + print "Challenge 059, Task #1: Linked List (Perl)\n"; + + while (my $line = <DATA>) + { + my ($k, @values) = split /\s+/, $line; + my $origl_list = LinkedList::Single->new(@values); + my $partd_list = partition($origl_list, $k); + + printf "\nOriginal list: %s\n", sprint_list($origl_list); + printf "Partitioned on k = %d: %s\n", $k, sprint_list($partd_list); + } +} + +#------------------------------------------------------------------------------- +sub partition +#------------------------------------------------------------------------------- +{ + my ($list, $k) = @_; + my $left = LinkedList::Single->new; + my $right = LinkedList::Single->new; + + $list->head; + + while (my @data = $list->each) + { + ($data[0] < $k ? $left : $right)->push( @data ); + } + + $right->head; + + while (my @data = $right->each) + { + $left->push( @data ); + } + + return $left; +} + +#------------------------------------------------------------------------------- +sub sprint_list +#------------------------------------------------------------------------------- +{ + my ($list) = @_; + my @array; + + $list->head; + + while (my @data = $list->each) + { + push @array, @data; + } + + return sprintf '%s', join ' -> ', @array; +} + +################################################################################ + +#------------------------------------------------------------------------------- +# Sample data with format: _k_ followed by the linked list values +#------------------------------------------------------------------------------- + +__DATA__ +3 1 4 3 2 5 2 +4 1 4 3 2 5 2 +5 1 4 3 2 5 2 +3 1 2 3 2 1 +4 5 4 3 2 1 +3 3 6 2 2 1 -1 17 5 +0 5 4 3 2 1 0 -1 -2 -3 -4 -5 +1 5 4 3 2 1 0 -1 -2 -3 -4 -5 diff --git a/challenge-059/athanasius/perl/ch-2.pl b/challenge-059/athanasius/perl/ch-2.pl new file mode 100644 index 0000000000..261b413b6c --- /dev/null +++ b/challenge-059/athanasius/perl/ch-2.pl @@ -0,0 +1,109 @@ +#!perl + +################################################################################ +=comment + +Perl Weekly Challenge 059 +========================= + +Task #2 +------- +*Bit Sum* + +*Reviewed by Ryan Thompson* + +*Helper Function* + +For this task, you will most likely need a function f(_a_,_b_) which returns the +count of different bits of binary representation of _a_ and _b_. + +For example, f(1,3) = 1, since: + +Binary representation of 1 = 01 + +Binary representation of 3 = 11 + +There is only 1 different bit. Therefore the subroutine should return 1. Note +that if one number is longer than the other in binary, the most significant bits +of the smaller number are padded (i.e., they are assumed to be zeroes). + +*Script Output* + +You[r] script should accept _n_ positive numbers. Your script should sum the +result of f(_a_,_b_) for every pair of numbers given: + +For example, given 2, 3, 4, the output would be *6*, since f(2,3) + f(2,4) + +f(3,4) = 1 + 2 + 3 = 6 + +=cut +################################################################################ + +#--------------------------------------# +# Copyright © 2020 PerlMonk Athanasius # +#--------------------------------------# + +use strict; +use warnings; +use feature qw( bitwise ); +use Const::Fast; +use Scalar::Util qw( looks_like_number ); + +const my $USAGE => "Usage:\n $0 [<numbers> ...]\n\n" . + " [<numbers> ...] An even number of positive integers"; + +#------------------------------------------------------------------------------- +BEGIN +#------------------------------------------------------------------------------- +{ + $| = 1; + print "\n"; +} + +#=============================================================================== +MAIN: +#=============================================================================== +{ + print "Challenge 059, Task #2: Bit Sum (Perl)\n\n"; + + scalar @ARGV > 0 or die "ERROR: Missing arguments\n" . $USAGE; + scalar @ARGV % 2 == 0 or die "ERROR: Odd number of arguments\n" . $USAGE; + + for (@ARGV) + { + looks_like_number($_) && int == $_ && $_ >= 0 + or die "ERROR: Invalid number $_\n" . $USAGE; + } + + my ($prob, $soln, $sum, $terms); + + while (scalar @ARGV > 0) + { + my $a_ = shift @ARGV; + my $b_ = shift @ARGV; + my $f = f($a_, $b_); + + $prob .= ' + ' if $terms; + $prob .= "f($a_,$b_)"; + $soln .= ' + ' if $terms++; + $soln .= $f; + $sum += $f; + } + + if ($terms == 1) + { + print "$prob = $sum\n"; + } + else + { + print "$prob = $soln = $sum\n"; + } +} + +#------------------------------------------------------------------------------- +sub f +#------------------------------------------------------------------------------- +{ + return (sprintf '%b', $_[0] ^ $_[1]) =~ tr/1//; +} + +################################################################################ diff --git a/challenge-059/athanasius/raku/ch-1.raku b/challenge-059/athanasius/raku/ch-1.raku new file mode 100644 index 0000000000..17402fc2cd --- /dev/null +++ b/challenge-059/athanasius/raku/ch-1.raku @@ -0,0 +1,132 @@ +use v6d; + +################################################################################ +=begin comment + +Perl Weekly Challenge 059 +========================= + +Task #1 +------- +*Linked List* + +*Reviewed by Ryan Thompson* + +You are given a linked list and a value _k_. Write a script to partition the +linked list such that all nodes less than _k_ come before nodes greater than or +equal to _k_. Make sure you preserve the original relative order of the nodes in +each of the two partitions. + +For example: + +Linked List: 1 → 4 → 3 → 2 → 5 → 2 + +_k_ = 3 + +Expected Output: 1 → 2 → 2 → 4 → 3 → 5. + +=end comment +################################################################################ + +#--------------------------------------# +# Copyright © 2020 PerlMonk Athanasius # +#--------------------------------------# + +# Note: To make the Perl5 module LinkedList::Single work correctly in Raku, I +# found I needed to add a stopper to signify the end of a linked list. I +# chose a value of NaN; Raku has a method Complex::isNaN which I use to +# test for end-of-list in the list-walking loops. + +use LinkedList::Single:from<Perl5>; + +#------------------------------------------------------------------------------- +BEGIN ''.put; +#------------------------------------------------------------------------------- + +#=============================================================================== +sub MAIN() +#=============================================================================== +{ + "Challenge 059, Task #1: Linked List (Raku)".put; + + while my Str $line = data() + { + my Real ($k, @values) = $line.split( /\s+/ ).map: { .Real }; + my $origl-list = LinkedList::Single.new( @values, NaN ); + my $partd-list = partition( $origl-list, $k ); + + "\nOriginal list: %s\n".printf: sprint-list($origl-list); + "Partitioned on k = %d: %s\n".printf: $k, sprint-list($partd-list); + } +} + +#------------------------------------------------------------------------------- +sub partition( $list, Real:D $k ) +#------------------------------------------------------------------------------- +{ + my $left = LinkedList::Single.new; + my $right = LinkedList::Single.new; + + $list.head; + my $data = $list.each; + + until $data.isNaN + { + ($data < $k ?? $left !! $right).push: $data; + $data = $list.each; + } + + $right.push: NaN; + $right.head; + $data = $right.each; + + until $data.isNaN + { + $left.push: $data; + $data = $right.each; + } + + $left.push: NaN; + + return $left; +} + +#------------------------------------------------------------------------------- +sub sprint-list( $list --> Str:D ) +#------------------------------------------------------------------------------- +{ + my Real @array; + + $list.head; + my $data = $list.each; + + until $data.isNaN + { + @array.push: $data; + $data = $list.each; + } + + return '%s'.sprintf: @array.join: ' -> '; +} + +#------------------------------------------------------------------------------- +sub data( --> Str:D ) +#------------------------------------------------------------------------------- +{ + state UInt $index = 0; + state Str @data = + [ + '3 1 4 3 2 5 2', + '4 1 4 3 2 5 2', + '5 1 4 3 2 5 2', + '3 1 2 3 2 1', + '4 5 4 3 2 1', + '3 3 6 2 2 1 -1 17 5', + '0 5 4 3 2 1 0 -1 -2 -3 -4 -5', + '1 5 4 3 2 1 0 -1 -2 -3 -4 -5', + ]; + + return $index < @data.elems ?? @data[ $index++ ] !! Nil; +} + +############################################################################### diff --git a/challenge-059/athanasius/raku/ch-2.raku b/challenge-059/athanasius/raku/ch-2.raku new file mode 100644 index 0000000000..222426368c --- /dev/null +++ b/challenge-059/athanasius/raku/ch-2.raku @@ -0,0 +1,111 @@ +use v6d; + +################################################################################ +=begin comment + +Perl Weekly Challenge 059 +========================= + +Task #2 +------- +*Bit Sum* + +*Reviewed by Ryan Thompson* + +*Helper Function* + +For this task, you will most likely need a function f(_a_,_b_) which returns the +count of different bits of binary representation of _a_ and _b_. + +For example, f(1,3) = 1, since: + +Binary representation of 1 = 01 + +Binary representation of 3 = 11 + +There is only 1 different bit. Therefore the subroutine should return 1. Note +that if one number is longer than the other in binary, the most significant bits +of the smaller number are padded (i.e., they are assumed to be zeroes). + +*Script Output* + +You script should accept _n_ positive numbers. Your script should sum the result +of f(_a_,_b_) for every pair of numbers given: + +For example, given 2, 3, 4, the output would be *6*, since f(2,3) + f(2,4) + +f(3,4) = 1 + 2 + 3 = 6 + +=end comment +################################################################################ + +#--------------------------------------# +# Copyright © 2020 PerlMonk Athanasius # +#--------------------------------------# + +#------------------------------------------------------------------------------- +BEGIN ''.put; +#------------------------------------------------------------------------------- + +#------------------------------------------------------------------------------- +class X::Args is Exception +#------------------------------------------------------------------------------- +{ + has Str $.msg; + + method message( --> Str:D) + { + return 'ERROR: ' ~ $.msg ~ "\n" ~ $*USAGE; + } +} + +#=============================================================================== +sub MAIN +( + *@numbers where { $_.all ~~ UInt:D } #= An even number of positive integers +) +#=============================================================================== +{ + "Challenge 059, Task #2: Bit Sum (Raku)\n".put; + + die X::Args.new(msg => 'Missing arguments') if @numbers.elems == 0; + die X::Args.new(msg => 'Odd number of arguments') if @numbers.elems % 2; + + CATCH + { + when X::Args { .Str.put; } + } + + my Str ($prob, $soln); + my UInt ($sum, $terms); + + while @numbers.elems + { + my UInt $a = @numbers.shift; + my UInt $b = @numbers.shift; + my UInt $f = f($a, $b); + + $prob ~= ' + ' if $terms; + $prob ~= "f($a,$b)"; + $soln ~= ' + ' if $terms++; + $soln ~= $f; + $sum += $f; + } + + if $terms == 1 + { + "$prob = $sum".put; + } + else + { + "$prob = $soln = $sum".put; + } +} + +#------------------------------------------------------------------------------- +sub f( UInt:D $a, UInt:D $b --> UInt:D ) +#------------------------------------------------------------------------------- +{ + return '%b'.sprintf($a +^ $b).trans('0' => '').chars; +} + +################################################################################ |
