aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohammad S Anwar <mohammad.anwar@yahoo.com>2019-04-06 07:52:34 +0100
committerMohammad S Anwar <mohammad.anwar@yahoo.com>2019-04-06 07:52:34 +0100
commit40c3105b0efc48ab8177cda4f31794dc0b0e7d7f (patch)
tree8fdd3b717fc1a8855afac6715b339ee0ba854608
parent925d874768478e39c1d2db725f5ca43087c76ed3 (diff)
downloadperlweeklychallenge-club-40c3105b0efc48ab8177cda4f31794dc0b0e7d7f.tar.gz
perlweeklychallenge-club-40c3105b0efc48ab8177cda4f31794dc0b0e7d7f.tar.bz2
perlweeklychallenge-club-40c3105b0efc48ab8177cda4f31794dc0b0e7d7f.zip
- Added more sultions by Joelle Maslak.
-rw-r--r--challenge-002/joelle-maslak/perl5/ch-1.sh86
-rw-r--r--challenge-002/joelle-maslak/perl5/ch-2.pl140
-rw-r--r--challenge-002/joelle-maslak/perl6/ch-2.p689
3 files changed, 315 insertions, 0 deletions
diff --git a/challenge-002/joelle-maslak/perl5/ch-1.sh b/challenge-002/joelle-maslak/perl5/ch-1.sh
new file mode 100644
index 0000000000..85e4eb5cd7
--- /dev/null
+++ b/challenge-002/joelle-maslak/perl5/ch-1.sh
@@ -0,0 +1,86 @@
+#!/bin/bash
+
+# Challenge:
+# Write a script or one-liner to remove leading zeros from positive
+# numbers.
+#
+# Assumptions:
+# The first question was, "What do you do about non-positive numbers?
+#
+# I assumed we just wanted to print non-numbers or non-positive
+# numbers "as-is", without removing anything. But we still wanted to
+# handle them, otherwise this would be a shorter program.
+#
+# Zero is neither postiive or negative.
+#
+# Likewise, what is a number?
+#
+# I assumed any number that is provided in decimal format is a
+# number. Numbers expressed in scientific notation, non-latan
+# script, or fractions (1/2) are not treated as positive numbers, so
+# they are printed without modification.
+#
+# Example input/output
+#
+# INPUT OUTPUT
+# 0 0
+# 0.0 0.0
+# 00.00 00.00
+# -1 -1
+# -01 -01
+# 1.0 1.0
+# 1.0000 1.0000
+# 00. 00. (not a standard-formatted number)
+# 0.0 .0 (leading zero removed)
+# 001 1
+# abc abc
+# 01a 01a
+# 001 2 001 2
+#
+# Implementation:
+# "perl -E" simply executes the first argument, the script. We'll
+# describe the script later. The "--" argument just tells Perl to not
+# treat any following arguments as Perl runtime arguments (I.E.
+# instaed of perl trying to interpret -1 as a command line argument,
+# we want to just pass it to the script. The final argument, "$*", is
+# just the arguments passed to this shell script, passed as the first
+# argument to the one-liner.
+#
+# The script used takes the first command line parameter (shift) and
+# does a substitution on it. The regex substitution uses the "rsxx"
+# modifiers. The "a" modifier says to treat character classes as if
+# they only match ASCII characters - thus \d becomes equivilent to
+# [0-9] rather than 0-9 plus all digits in other scripts. The "r"
+# modifier says to not modify the input argument, just return the
+# modified result. The "s" says to treat this as a single line
+# statement (it either matches or it doesn't with the complete
+# string). The "xx" allows us to use whitespace to make the regex
+# more readable.
+#
+# The regex basically removes zeros at the front of one of two
+# different patterns - this pattern could be simplified as two
+# regexes:
+#
+# s/ ^ 0+ ( \d* \. \d+ ) $ /$1/arsxx
+#
+# - and -
+#
+# s/ ^ 0+ ( [1-9] \d* ) $ /$1/arsxx
+#
+# The first one handles numbers with a decimal point. It removes all
+# leading zeros in front of the decimal point, in a pretty
+# straightforward way. Note that 0.0 would become .0, removing the
+# leading zero.
+#
+# The second regex above handles non-zero positive numbers without a
+# decimal point. But we don't want to remove leading zeros for zero
+# itself. I.E. 00 is not a positive number (it's zero, it's neither
+# positive or negative), so it should stay 00. So any number starting
+# with a zero must have at least one non-zero digit for leading zeros
+# to be removed.
+#
+# These two regexes were then combined form what is in the one-liner
+# below.
+#
+perl -E 'say shift =~ s/ ^ 0+ ( ( \d* \. \d+ ) | ( [1-9] \d* ) ) $ /$1/arsxx' -- "$*"
+
diff --git a/challenge-002/joelle-maslak/perl5/ch-2.pl b/challenge-002/joelle-maslak/perl5/ch-2.pl
new file mode 100644
index 0000000000..2960a33f1f
--- /dev/null
+++ b/challenge-002/joelle-maslak/perl5/ch-2.pl
@@ -0,0 +1,140 @@
+#!/usr/bin/env perl
+use v5.26;
+use strict;
+use warnings;
+
+# Turn on method signatures
+use feature 'signatures';
+no warnings 'experimental::signatures';
+
+# Challenge:
+# Write a script that can convert integers to and from a base35
+# representation, using the characters 0-9 and A-Y. Dave Jacoby came
+# up with nice description about base35, in case you needed some
+# background.
+#
+# Assumptions:
+# * This should be case-insensitive on input
+# * This should use only upper case on output
+# * Negative numbers should be accepted.
+# * Only integers are handled
+#
+# Example input/output:
+# perl 2.pl encode 10 --> A
+# perl 2.pl encode 100 --> 2U
+# perl 2.pl encode -10 --> -A
+# perl 2.pl decode A --> 10
+# perl 2.pl decode 2U --> 100
+# perl 2.pl decode -A --> -10
+#
+#
+# Implementation:
+# This is essentially two programs, one to convert decimal integer to
+# a base 35 integer, the other to do the reverse.
+#
+# We start by parsing the arguments on the command line. The first
+# argument is used to determine if we "encode" (convert decimal -->
+# Base35) or "decode" (convert Base35 --> Decimal).
+#
+# ENCODE:
+#
+# We validate the second parameter is a valid decimal integer.
+#
+# We normalize the input, and store a sign character ('' for a
+# positive number, '-' for a negative number).
+#
+# We then build an array by adding values to the front of the array as
+# we process the input value. We take the modul0 35 of the input,
+# convert that to 0 through Y, and add it to the front of the array
+# until our input value has become 0.
+#
+# We then print the sign value followed by the array elements.
+#
+# DECODE:
+#
+# This is similar, although the input string is checked with a regex
+# that ensures that the string, matched case insensitively contains
+# the base 35 characters.
+#
+# We normalize the input, converting it to lower case and storing the
+# sign character (if any).
+#
+# We then loop over each character in the string. On each iteration,
+# we multiply an accumulator by 35 and add the character's value to
+# the accumulator (we add 0 through 34 depending on the character).
+#
+# We then print the sign and the accumulator.
+#
+# USAGE:
+#
+# This is self-explanatory and is the usage message for this script.
+
+if (@ARGV != 2) { USAGE(); }
+if ($ARGV[0] eq 'encode') {
+ encode($ARGV[1]);
+} elsif ($ARGV[0] eq 'decode') {
+ decode($ARGV[1]);
+}
+
+sub encode($input) {
+ USAGE() unless $input =~ m/^ \-? [0-9]+ $/sx;
+
+ # Set sign based on input
+ my $sign = $input < 0 ? '-' : '';
+
+ # We want an absolute value to start with
+ $input = abs($input);
+
+ # Main loop to do the conversion. We stick the output in array @out.
+ my @out;
+ while ($input) { # Loop while input > 0
+ # Add the digit to the front of the array
+ my $digit = $input % 35;
+ if ($digit < 10) {
+ unshift @out, $digit;
+ } else {
+ unshift @out, chr($digit - 10 + ord('A'));
+ }
+
+ # Move to the next digit in $input
+ $input = int($input / 35);
+ }
+
+ say $sign . join('', @out); # Output digits
+}
+
+sub decode($input) {
+ USAGE() unless $input =~ m/^ \-? [A-Y0-9]+ $/isx;
+
+ # Get sign
+ my $sign = ($input =~ m/^ \-/x) ? '-' : '';
+
+ # Remove sign from variable we are parsing & convert to lowercase
+ $input =~ s/^ \-//x;
+ $input = lc($input);
+
+ # Parse each digit
+ my $output = 0;
+ foreach my $char (split //, $input) {
+ $output *= 35;
+ if ($char =~ m/[0-9]/) {
+ $output += $char;
+ } else {
+ # It's not a straight number
+ $output += 10 + ord($char) - ord('a'); # Add value of letters
+ }
+ }
+
+ say $sign . $output;
+}
+
+sub USAGE() {
+ say STDERR "Usage: ";
+ say STDERR " $0 <op> <num>";
+ say STDERR " <op> 'encode' to convert to Base35 or 'decode' to convert from Base35";
+ say STDERR " <num> A number in the proper format for the operation";
+ say STDERR "";
+ exit 1;
+}
+
+
diff --git a/challenge-002/joelle-maslak/perl6/ch-2.p6 b/challenge-002/joelle-maslak/perl6/ch-2.p6
new file mode 100644
index 0000000000..f8410e3210
--- /dev/null
+++ b/challenge-002/joelle-maslak/perl6/ch-2.p6
@@ -0,0 +1,89 @@
+#!/usr/bin/env perl6
+use v6;
+
+# Challenge:
+# Write a script that can convert integers to and from a base35
+# representation, using the characters 0-9 and A-Y. Dave Jacoby came
+# up with nice description about base35, in case you needed some
+# background.
+#
+# Assumptions:
+# * This should be case-insensitive on input
+# * This should use only upper case on output
+# * Negative numbers should be accepted.
+# * Only integers are handled
+#
+# Example input/output:
+# perl6 2.pl6 encode 10 --> A
+# perl6 2.pl6 encode 100 --> 2U
+# perl6 2.pl6 encode -10 --> -A
+# perl6 2.pl6 decode A --> 10
+# perl6 2.pl6 decode 2U --> 100
+# perl6 2.pl6 decode -A --> -10
+#
+#
+# Implementation:
+# This is essentially two programs, one to convert decimal integer to
+# a base 35 integer, the other to do the reverse.
+#
+# Perl 6 allows multi-dispatch, including of the MAIN routine. This
+# means you can define two (or more) MAIN routines, and the one that
+# gets executed will be the one where the command line parameters
+# satisfy all requirements of the parameter definition. For these two
+# MAINs, we have a "where" clause on the first (anonymous) parameter.
+# If neither where condition matches, the program will give an error.
+#
+# ENCODE:
+#
+# For the encode version, the second parameter is an Int:D - that is,
+# a defined integer. Perl 6 automatically converts a base 10 integer
+# on the command line to an Int with this style of parameter
+# definition, if it can be converted to an Int. If it can't be (for
+# instance, it contains invalid chracters), then this multi sub won't
+# match the parameters and eventually (assuming no others match) will
+# throw an error.
+#
+# The actual encoding routine is simple in Perl 6 - it has a built-in
+# base conversion function. Part of knowing the language is knowing
+# about built-ins.
+#
+# DECODE:
+#
+# This is similar, although the input string is checked with a regex
+# that ensures that the string, matched case insensitively (:i does
+# that) contains an optional - followed by 1 or more base 36
+# characters.
+#
+# The actual decoding is using Str.parse-base, which returns a number
+# by parsing the string.
+#
+# USAGE:
+#
+# I've overriden the default usage method to provide some help to the
+# user. This is
+
+multi sub MAIN(
+ Str:D $ where 'encode',
+ Int:D $input
+) {
+ say $input.base(35);
+
+}
+
+multi sub MAIN(
+ Str:D $ where 'decode',
+ Str:D $input where $input ~~ m:i/^ '-'? <[0..9 A..Y]>+ $/
+) {
+ say $input.parse-base(35);
+}
+
+sub USAGE() {
+ $*ERR.say("Usage: ");
+ $*ERR.say(" {$*PROGRAM-NAME} <op> <num>");
+ $*ERR.say(" <op> 'encode' to convert to Base35 or 'decode' to convert from Base35");
+ $*ERR.say(" <num> A number in the proper format for the operation");
+ $*ERR.say("");
+ exit 1;
+}
+
+