aboutsummaryrefslogtreecommitdiff
path: root/challenge-042
diff options
context:
space:
mode:
authorMohammad S Anwar <mohammad.anwar@yahoo.com>2020-01-12 22:18:46 +0000
committerMohammad S Anwar <mohammad.anwar@yahoo.com>2020-01-12 22:18:46 +0000
commit2fe2152b16e615548c59bd470500f56c87c34496 (patch)
treea8eba3a8cd65ec8d8b33e5d5691178e5a19caa9e /challenge-042
parentf54fa9cffd2a630e7422568129ab4b46c7c7f325 (diff)
downloadperlweeklychallenge-club-2fe2152b16e615548c59bd470500f56c87c34496.tar.gz
perlweeklychallenge-club-2fe2152b16e615548c59bd470500f56c87c34496.tar.bz2
perlweeklychallenge-club-2fe2152b16e615548c59bd470500f56c87c34496.zip
- Added solutions by Colin Crain.
Diffstat (limited to 'challenge-042')
-rw-r--r--challenge-042/colin-crain/perl/ch-1.pl95
-rw-r--r--challenge-042/colin-crain/perl/ch-2.pl89
-rw-r--r--challenge-042/colin-crain/raku/ch-1.p692
-rw-r--r--challenge-042/colin-crain/raku/ch-2.p680
4 files changed, 356 insertions, 0 deletions
diff --git a/challenge-042/colin-crain/perl/ch-1.pl b/challenge-042/colin-crain/perl/ch-1.pl
new file mode 100644
index 0000000000..a333d98c08
--- /dev/null
+++ b/challenge-042/colin-crain/perl/ch-1.pl
@@ -0,0 +1,95 @@
+#! /opt/local/bin/perl
+#
+# octal.pl
+#
+# PWC 42 - Task #1
+# Octal Number System
+# Write a script to print decimal number 0 to 50 in Octal Number System.
+#
+# For example:
+#
+# Decimal 0 = Octal 0
+# Decimal 1 = Octal 1
+# Decimal 2 = Octal 2
+# Decimal 3 = Octal 3
+# Decimal 4 = Octal 4
+# Decimal 5 = Octal 5
+# Decimal 6 = Octal 6
+# Decimal 7 = Octal 7
+# Decimal 8 = Octal 10
+# and so on.
+#
+# method: the algorithm out of the box works for N, as any positive
+# integer can be essentially recounted in a different base. It can
+# be expanded to Z by keeping track of a 'sign bit', converting the
+# absolute value and adding back the sign to the output as
+# required. Rational numbers, Q, are where things get tricky. In
+# cases where the set of prime factors of the two number systems
+# are not the same, repeating fractions become an unfortunate
+# reality.
+#
+# Specifically whether the pet of prime factors of the new base are a
+# subset of that of the old. So any number base8 {2} can be expressed
+# base10 {2,5} but not vice versa.
+#
+# For example 0.1 base10 = 0.0[6314...] base8
+#
+# For this reason we will not consider Q for the moment. And R, Real
+# numbers, including π and e and such, is just right out. Even
+# though it isn't required for the challenge as stated, we will
+# construct an algorithm that will handle negative numbers
+# properly.
+#
+# It follows that any binary representation of a number can be
+# converted into an octal, or hexadecimal, equivalent without losing
+# any precision, as the only factors of these bases are in the set
+# {2}. This is in fact specifically why they are convenient; unique
+# combinations of 4 binary, 2 octal and 1 hexadecimal digits are
+# directly mappable from one system to the other without any
+# knowledge of the number, or part of a number, that they represent.
+# The higher number bases serve as a convenient shorthand for
+# sections of much harder for humans to read binary streams.
+#
+# We will use integer division to divide out the number by 8s. When
+# we realize the graphemes we use to represent a number, no matter
+# what base we use, are not really the number but a rather a
+# representation of that number using marks, we can create the new
+# number much as we would write it on a page. Each time we divide
+# out we reset the number to floor(n/d) and write the remainder to
+# the front of our output. Adding a special case for 0 and we have
+# created a string that Perl can parse as a number, which it is, as
+# much as writing the same on a page is that number. Perl is good
+# like that. Because n is always positive, int(n) == floor(n) so
+# there is no need to import the POSIX floor() function.
+#
+# 2020 colin crain
+## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
+
+
+
+use warnings;
+use strict;
+use feature ":5.26";
+
+## ## ## ## ## MAIN
+
+printf "Decimal %-2d = Octal %-2d\n", $_, octal($_) for (-50..50);
+
+
+
+## ## ## ## ## SUBS
+
+sub octal {
+ my $num = shift;
+ my $sign = ($num >= 0) ? "" : '-';
+ $num = abs($num);
+ my $out = "";
+ my $rem;
+ while ( $num > 0 ) {
+ ($num, $rem) = (int( $num/8 ), $num % 8);
+ $out = $rem . $out;
+ }
+ $out = $sign . $out;
+ return $out ? $out : 0; ## needs to output 0 for 0
+
+}
diff --git a/challenge-042/colin-crain/perl/ch-2.pl b/challenge-042/colin-crain/perl/ch-2.pl
new file mode 100644
index 0000000000..6eea648f11
--- /dev/null
+++ b/challenge-042/colin-crain/perl/ch-2.pl
@@ -0,0 +1,89 @@
+#! /opt/local/bin/perl
+#
+# balanced_brackets.pl
+#
+# PWC 42 - TASK #2
+# Balanced Brackets
+# Write a script to generate a string with random number of ( and )
+# brackets. Then make the script validate the string if it has
+# balanced brackets.
+#
+# For example:
+#
+# () - OK
+# (()) - OK
+# )( - NOT OK
+# ())() - NOT OK
+#
+# method: to make the random string of parens, we take a range of 1 to
+# 10 indexes and, mapping through them, assign either a left or right
+# paren and place on a list, joining that list at the end to make a
+# single string. So far so good.
+#
+# For validation, we will match pairs of parens and eliminate them
+# from the string until no more can be matched. If our string goes
+# away we were good, if not, then things didn't match up. That said,
+# there are a number of short circuits to this process where it no
+# longer pays to continue.
+#
+# • Matched parens come in pairs, by definition, so right out of the
+# gate the length of the random string must be even. So this
+# eliminates one half of the chances. We will check for evenness and
+# exit with a message as required.
+#
+# • If the string under consideration starts with a right paren, that
+# paren can no longer be matched and the validation will fail. One way
+# to detect this is to look for the placement of a valid () match; if
+# the match does not take place at index 0, there must be a paren
+# preceeding it and that paren must be a right paren. So we exit with
+# a note.
+#
+# • Finally if matching has stopped we check for length, if the string
+# still has chars, it is imbalanced and we exit with a note, showing
+# the unbalanced section. If we have no string lenght remaining,
+# against all odds we have succeded at randomly crafting a balanced
+# string of parens.
+#
+# It's obvious this last occurance will in fact rarely happen. The
+# shortest matching sting is 2 chars, (). The odds are .5 any given
+# string is odd-numbered, and .5 the first paren will be right, so our
+# chance of immediately failing is .75
+#
+# After this the odds get complicated, but never better, and worse as
+# the length of the random base grows. So for purposes of this
+# experiment the length has been limited to up to 10 chars.
+
+#
+# 2020 colin crain
+## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
+
+
+
+use warnings;
+use strict;
+use feature ":5.26";
+
+## ## ## ## ## MAIN
+
+my $upper = shift @ARGV // 10;
+$upper = int(rand($upper)) + 1;
+
+my $str = make_string($upper);
+say $str;
+say validate( $str );
+
+
+## ## ## ## ## SUBS
+
+sub make_string {
+ return join '', map { ['(',')']->[int(rand(2))] } (1..$_[0]);
+}
+
+sub validate {
+ my $str = shift;
+ unless (length($str)%2==0) { return "IMBALANCED - odd number of parens"};
+ while ( $str =~ s/ \( (.*?) \) /$1/x) {
+ if ($-[0] != 0){ return "IMBALANCED - remaining group starts with right paren : $str" }
+ }
+ return (length $str == 0) ? "BALANCED" : "IMBALANCED - $str remaining";
+}
diff --git a/challenge-042/colin-crain/raku/ch-1.p6 b/challenge-042/colin-crain/raku/ch-1.p6
new file mode 100644
index 0000000000..f7116ec224
--- /dev/null
+++ b/challenge-042/colin-crain/raku/ch-1.p6
@@ -0,0 +1,92 @@
+use v6;
+
+#
+# octal.p6
+#
+# PWC 42 - Task #1
+# Octal Number System
+# Write a script to print decimal number 0 to 50 in Octal Number System.
+#
+# For example:
+#
+# Decimal 0 = Octal 0
+# Decimal 1 = Octal 1
+# Decimal 2 = Octal 2
+# Decimal 3 = Octal 3
+# Decimal 4 = Octal 4
+# Decimal 5 = Octal 5
+# Decimal 6 = Octal 6
+# Decimal 7 = Octal 7
+# Decimal 8 = Octal 10
+# and so on.
+#
+# method: the algorithm out of the box works for N, as any positive
+# integer can be essentially recounted in a different base. It can
+# be expanded to Z by keeping track of a 'sign bit', converting the
+# absolute value and adding back the sign to the output as
+# required. Rational numbers, Q, are where things get tricky. In
+# cases where the set of prime factors of the two number systems
+# are not the same, repeating fractions become an unfortunate
+# reality.
+#
+# Specifically whether the pet of prime factors of the new base are a
+# subset of that of the old. So any number base8 {2} can be expressed
+# base10 {2,5} but not vice versa.
+# ____
+# For example 0.1 base10 = 0.0[6314] base8
+#
+# For this reason we will not consider Q for the moment. And R, Real
+# numbers, including π and e and such, is just right out. Even
+# though it isn't required for the challenge as stated, we will
+# construct an algorithm that will handle negative numbers
+# properly.
+#
+# It follows that any binary representation of a number can be
+# converted into an octal, or hexadecimal, equivalent without losing
+# any precision, as the only factors of these bases are in the set
+# {2}. This is in fact specifically why they are convenient; unique
+# combinations of 4 binary, 2 octal and 1 hexadecimal digits are
+# directly mappable from one system to the other without any
+# knowledge of the number, or part of a number, that they represent.
+# The higher number bases serve as a convenient shorthand for
+# sections of much harder for humans to read binary streams.
+#
+# We will use integer division to divide out the number by 8s. When
+# we realize the graphemes we use to represent a number, no matter
+# what base we use, are not really the number but a rather a
+# representation of that number using marks, we can create the new
+# number much as we would write it on a page. Each time we divide
+# out we reset the number to floor(n/d) and write the remainder to
+# the front of our output. Adding a special case for 0 and we have
+# created a string that Perl can parse as a number, which it is, as
+# much as writing the same on a page is that number. Perl is good
+# like that.
+
+#
+#
+# 2020 colin crain
+## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
+
+sub MAIN () {
+
+ for -50 .. 50 {
+ printf "Decimal %3d = Octal %3d\n", $_, octal($_) ;
+ }
+}
+
+
+## ## ## ## ## SUBS
+
+sub octal ( $dec is copy ){
+ my $out = "";
+ my $sign = $dec < 0 ?? "-" !! "";
+ $dec .= abs;
+ my $rem;
+ while ( $dec > 0 ) {
+ $rem = $dec % 8;
+ $dec = ($dec/8).floor;
+ $out = $rem ~ $out;
+ }
+ $out = $sign ~ $out;
+ return $out ?? $out !! 0; ## needs to output 0 for 0
+}
diff --git a/challenge-042/colin-crain/raku/ch-2.p6 b/challenge-042/colin-crain/raku/ch-2.p6
new file mode 100644
index 0000000000..711f716f82
--- /dev/null
+++ b/challenge-042/colin-crain/raku/ch-2.p6
@@ -0,0 +1,80 @@
+use v6;
+
+#
+# balanced_brackets.p6
+#
+# PWC 42 - TASK #2
+# Balanced Brackets
+# Write a script to generate a string with random number of ( and )
+# brackets. Then make the script validate the string if it has
+# balanced brackets.
+#
+# For example:
+#
+# () - OK
+# (()) - OK
+# )( - NOT OK
+# ())() - NOT OK
+#
+# method :For validation, we will match pairs of parens and eliminate them
+# from the string until no more can be matched. If our string goes
+# away we were good, if not, then things didn't match up. That said,
+# there is one short circuit to this process where it no
+# longer pays to continue.
+#
+# • Matched parens come in pairs, by definition, so right out of the
+# gate the length of the random string must be even. So this
+# eliminates one half of the chances. We will check for evenness and
+# exit with a message as required.
+#
+# Finally if matching has stopped we check for length, if the string
+# still has chars, it is imbalanced and we exit with a note, showing
+# the unbalanced section. If we have no string lenght remaining,
+# against all odds we have succeded at randomly crafting a balanced
+# string of parens.
+#
+# It's obvious this last occurance will in fact rarely happen. The
+# shortest matching sting is 2 chars, (). The odds are .5 any given
+# string is odd-numbered, and .5 the first paren will be right, hence unmatchable, so our
+# chance of immediately failing is .75
+#
+# After this the odds get complicated, but never better, and worse as
+# the length of the random base grows. So for purposes of this
+# experiment the length has been limited to up to 10 chars.
+#
+# As is, it isn't a very fun game as one almost always loses.
+#
+# 2020 colin crain
+## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
+
+sub MAIN ( Int:D $upper_bound where {$upper_bound > 1} = 10) {
+ my $str_length = (^$upper_bound).pick + 1;
+ my $str = make_string( $str_length );
+
+ say "start: $str";
+ say "val: ", validate( $str );
+
+}
+
+
+## ## ## ## ## SUBS
+
+sub make_string ( Int:D $len){
+ my $str;
+ my @str;
+ for (1..$len) {
+ @str.push: (^2).pick;
+ }
+ @str = map { [ '(' , ')' ][$_] }, @str;
+ return @str.join("");
+}
+
+sub validate (Str:D $orig) {
+ my $str = $orig;
+ unless $str.chars %% 2 { return "IMBALANCED - odd number of parens"};
+
+ while $str ~~ s/\((.*?)\)/$0/ { ; }
+
+ return ($str.chars == 0) ?? "PARENS BALANCED" !! "IMBALANCED - $str unmatched";
+}
+