Perl Weekly Challenge 95.
My solutions (task 1, task 1a, and task 2) to the The Weekly Challenge - 095.
Task 1: Palindrome Number
Submitted by: Mohammad S Anwar
You are given a number $N
.
Write a script to figure out if the given number is Palindrome. Print 1 if true otherwise 0.
Example 1:
Input: 1221
Output: 1
Example 2:
Input: -101
Output: 0, since -101 and 101- are not the same.
Example 3:
Input: 90
Output: 0
Instead of checking if a number is a palindrome, I will test if an arbitrary string is a palindrome. I simply reverse the string and compare it to the original.
# Perl weekly challenge 095
# Task 1: Palindrome number.
# Figure out if a number is a palindrome.
# See https:/wlmb.github.io/2021/01/11/PWC95/#task-1-palindrome-number
use v5.12;
use strict;
use warnings;
say("Input: $_\nOutput:", ("$_" eq reverse "$_")?1:0) foreach @ARGV;
./ch-1.pl 1221 -101 90
Results:
Input: 1221
Output:1
Input: -101
Output:0
Input: 90
Output:0
This is small enough to be made into a oneliner.
perl -E 'say("Input: $_\nOutput:", ("$_" eq reverse "$_")?1:0) foreach @ARGV' 1221 -101 90;
Results:
Input: 1221
Output:1
Input: -101
Output:0
Input: 90
Output:0
Finally, I make a small variation to remove all punctuation and use
lowercase before making the comparison, to test actual palindromes. In this case, I
receive the text from STDIN
.
# Perl weekly challenge 095
# Task 1: Palindrome number. Alternative solution
# Figure out if a string is a palindrome after stripping punctuation.
# See https:/wlmb.github.io/2021/01/11/PWC95/#task-1-palindrome-number
use v5.12;
use strict;
use warnings;
use English;
undef $INPUT_RECORD_SEPARATOR;
my $input=<>;
(my $clean_input=lc $input)=~s/\W//g;
say("Input:\n$input\nOutput:", ("$clean_input" eq reverse "$clean_input")?1:0);
Example: A children’s palindrome in Spanish:
./ch-1a.pl <<FIN
Anita
lava la
tina.
FIN
Results:
Input:
Anita
lava la
tina.
Output:1
Example: One of Merlina Acevedo’s recent palindromes.
./ch-1a.pl <<EOF
Evil alive's in a man
is a fool, an aloof,
as in a man, is evil
lives in a bar,
a wall
a wiz
a nazi wall,
as in a tan,
ill in a dumb mob
as a bomb
Mud,
an ill in a tan is all:
a wiz
a nazi wall,
a war
a ban
Is evil,
lives in a man,
is a fool, an aloof,
As in a man,
Is evil alive?
EOF
Results:
Input:
Evil alive's in a man
is a fool, an aloof,
as in a man, is evil
lives in a bar,
a wall
a wiz
a nazi wall,
as in a tan,
ill in a dumb mob
as a bomb
Mud,
an ill in a tan is all:
a wiz
a nazi wall,
a war
a ban
Is evil,
lives in a man,
is a fool, an aloof,
As in a man,
Is evil alive?
Output:1
I found that \W
gets confused by some punctuation marks, such as the
opening question mark ‘¿’ or some quotes ‘´’. I guess I would have to
set the adequate locale for it to work with these characters.
Task 2: Demo Stack
Submitted by: Mohammad S Anwar
Write a script to demonstrate Stack operations like below:
push($n)
- add $n to the stack
pop()
- remove the top element
top()
- get the top element
min()
- return the minimum element
Example:
my $stack = Stack->new;
$stack->push(2);
$stack->push(-1);
$stack->push(0);
$stack->pop; # removes 0
print $stack->top; # prints -1
$stack->push(0);
print $stack->min; # prints -1
I make a stack class using Moo and an array for the data. I prints the stack everytime it changes and I print the on-going operation.
# Perl weekly challenge 095
# Task 2: Demo stack.
# Demonstrate Stack operations.
# See https:/wlmb.github.io/2021/01/11/PWC95/#task-2-demo-stack
package Stack;
use List::Util;
use v5.12;
use Moo;
has _stack=>(is=>'ro', default=>sub{[]}, init_arg=>undef);
sub push {
my $self=shift;
my $x=shift;
say "Push:\t$x";
my $s=$self->_stack;
push @$s, $x;
$self->show;
}
sub pop {
my $self=shift;
my $s=$self->_stack;
die "Empty stack" unless defined $s;
my $top=pop @$s;
say "Pop:\t$top";
$self->show;
return $top;
}
sub top {
my $self=shift;
my $top=$self->_stack->[-1];
say "Top:\t$top";
return $top;
}
sub exch {
my $self=shift;
my $x=$self->pop;
my $y=$self->pop;
say "Exch:\t$x <-> $y";
$self->push($x);
$self->push($y);
}
sub min {
my $self=shift;
my $s=$self->_stack;
my $min=List::Util::min @$s;
say "Min:\t$min";
$self->push($min);
}
sub max {
my $self=shift;
my $s=$self->_stack;
my $max=List::Util::max @$s;
say "Max:\t$max";
$self->push($max);
}
sub add {
my $self=shift;
my ($x, $y)=($self->pop,$self->pop);
my $res=$x+$y;
say "Add:\t$x + $y -> $res";
$self->push($res);
}
sub sub {
my $self=shift;
my ($x, $y)=($self->pop,$self->pop);
my $res=$y-$x;
say "Sub:\t$y - $x -> $res";
say "Sub:\t$res";
$self->push($res);
}
sub mul {
my $self=shift;
my ($x, $y)=($self->pop,$self->pop);
my $res=$x*$y;
say "Mul:\t$x * $y -> $res";
$self->push($res);
}
sub div {
my $self=shift;
my ($x, $y)=($self->pop,$self->pop);
my $res=$y/$x;
say "Div:\t$y / $x -> $res";
$self->push($res);
}
sub cs {
my $self=shift;
my $x=$self->pop;
my $res=-$x;
say "CS:\t$x -> $res";
$self->push($res);
}
sub inv {
my $self=shift;
my $x=$self->pop;
my $res=1/$x;
say "Inv:\t1/$x -> $res";
$self->push($res);
}
sub show {
my $self=shift;
my $s=$self->_stack;
say "Stack:\t", join " ", reverse @$s;
}
Drive the package from STDIN
. I use a simple RPN notation to make a
primitive calculator. Numbers are pushed, operators operate on the top
operands of the stack.
package main;
use Scalar::Util qw(looks_like_number);
my $s=Stack->new;
while(<>){
chomp;
$s->push($_), next if looks_like_number($_);
$s->pop, next if lc $_ eq "pop";
$s->top, next if lc $_ eq "top";
$s->exch, next if lc $_ eq "exch";
$s->min, next if lc $_ eq "min";
$s->max, next if lc $_ eq "max";
$s->add, next if $_ eq "+";
$s->sub, next if lc $_ eq "-";
$s->mul, next if lc $_ eq "*";
$s->div, next if lc $_ eq "/";
$s->cs, next if lc $_ eq "cs"; # change sign
$s->inv, next if lc $_ eq "inv"; # invert
$s->show, next if lc $_ eq "show";
die "Unrecognized op";
}
Example:
./ch-2.pl <<EOF
2
-1
0
pop
top
0
min
EOF
Results:
Push: 2
Stack: 2
Push: -1
Stack: -1 2
Push: 0
Stack: 0 -1 2
Pop: 0
Stack: -1 2
Top: -1
Push: 0
Stack: 0 -1 2
Min: -1
Push: -1
Stack: -1 0 -1 2
Another example:
./ch-2.pl <<EOF #5/2*2-5=0
2
5
exch
/
2
*
5
-
EOF
Results:
Push: 2
Stack: 2
Push: 5
Stack: 5 2
Pop: 5
Stack: 2
Pop: 2
Stack:
Exch: 5 <-> 2
Push: 5
Stack: 5
Push: 2
Stack: 2 5
Pop: 2
Stack: 5
Pop: 5
Stack:
Div: 5 / 2 -> 2.5
Push: 2.5
Stack: 2.5
Push: 2
Stack: 2 2.5
Pop: 2
Stack: 2.5
Pop: 2.5
Stack:
Mul: 2 * 2.5 -> 5
Push: 5
Stack: 5
Push: 5
Stack: 5 5
Pop: 5
Stack: 5
Pop: 5
Stack:
Sub: 5 - 5 -> 0
Sub: 0
Push: 0
Stack: 0
Yet another example:
./ch-2.pl <<EOF # -1/(1+5-4)*4/2)*4=-1
1
5
+
4
-
4
*
2
/
inv
cs
4
*
EOF
Results:
Push: 1
Stack: 1
Push: 5
Stack: 5 1
Pop: 5
Stack: 1
Pop: 1
Stack:
Add: 5 + 1 -> 6
Push: 6
Stack: 6
Push: 4
Stack: 4 6
Pop: 4
Stack: 6
Pop: 6
Stack:
Sub: 6 - 4 -> 2
Sub: 2
Push: 2
Stack: 2
Push: 4
Stack: 4 2
Pop: 4
Stack: 2
Pop: 2
Stack:
Mul: 4 * 2 -> 8
Push: 8
Stack: 8
Push: 2
Stack: 2 8
Pop: 2
Stack: 8
Pop: 8
Stack:
Div: 8 / 2 -> 4
Push: 4
Stack: 4
Pop: 4
Stack:
Inv: 1/4 -> 0.25
Push: 0.25
Stack: 0.25
Pop: 0.25
Stack:
CS: 0.25 -> -0.25
Push: -0.25
Stack: -0.25
Push: 4
Stack: 4 -0.25
Pop: 4
Stack: -0.25
Pop: -0.25
Stack:
Mul: 4 * -0.25 -> -1
Push: -1
Stack: -1