diff options
| author | Mohammad S Anwar <mohammad.anwar@yahoo.com> | 2019-04-06 07:52:34 +0100 |
|---|---|---|
| committer | Mohammad S Anwar <mohammad.anwar@yahoo.com> | 2019-04-06 07:52:34 +0100 |
| commit | 40c3105b0efc48ab8177cda4f31794dc0b0e7d7f (patch) | |
| tree | 8fdd3b717fc1a8855afac6715b339ee0ba854608 | |
| parent | 925d874768478e39c1d2db725f5ca43087c76ed3 (diff) | |
| download | perlweeklychallenge-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.sh | 86 | ||||
| -rw-r--r-- | challenge-002/joelle-maslak/perl5/ch-2.pl | 140 | ||||
| -rw-r--r-- | challenge-002/joelle-maslak/perl6/ch-2.p6 | 89 |
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; +} + + |
