aboutsummaryrefslogtreecommitdiff
path: root/challenge-059
diff options
context:
space:
mode:
authorPerlMonk Athanasius <PerlMonk.Athanasius@gmail.com>2020-05-10 07:09:30 -0700
committerPerlMonk Athanasius <PerlMonk.Athanasius@gmail.com>2020-05-10 07:09:30 -0700
commit56529d80f94ae3ed2c3f4d3ab7d4cd02bfed1c51 (patch)
tree3a213a9cb1992973fadd973fe63eda49ba345f11 /challenge-059
parentc85f60e27e2b6795a12f1d32f5b597e29eb9d32f (diff)
downloadperlweeklychallenge-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.pl120
-rw-r--r--challenge-059/athanasius/perl/ch-2.pl109
-rw-r--r--challenge-059/athanasius/raku/ch-1.raku132
-rw-r--r--challenge-059/athanasius/raku/ch-2.raku111
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;
+}
+
+################################################################################