diff options
| author | Mohammad S Anwar <mohammad.anwar@yahoo.com> | 2020-01-12 22:18:46 +0000 |
|---|---|---|
| committer | Mohammad S Anwar <mohammad.anwar@yahoo.com> | 2020-01-12 22:18:46 +0000 |
| commit | 2fe2152b16e615548c59bd470500f56c87c34496 (patch) | |
| tree | a8eba3a8cd65ec8d8b33e5d5691178e5a19caa9e /challenge-042 | |
| parent | f54fa9cffd2a630e7422568129ab4b46c7c7f325 (diff) | |
| download | perlweeklychallenge-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.pl | 95 | ||||
| -rw-r--r-- | challenge-042/colin-crain/perl/ch-2.pl | 89 | ||||
| -rw-r--r-- | challenge-042/colin-crain/raku/ch-1.p6 | 92 | ||||
| -rw-r--r-- | challenge-042/colin-crain/raku/ch-2.p6 | 80 |
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"; +} + |
