I’ve been doing the Perl Weekly
Challenges. The
latest
involved testing for palindromic numbers and building a stack class.
(Note that this is open until 17 January 2021.)
TASK #1 › Palindrome Number
You are given a number $N
.
Write a script to figure out if the given number is Palindrome.
Print 1 if true otherwise 0.
In Perl this is basically trivial, because a number is a string is a
number. (Possibly I use the trinary operator ?:
more than is ideal,
but I think this is a good place for it.)
sub pn {
my $n=shift;
return (join('',reverse split '',$n) eq $n)?1:0;
}
Raku is pretty much the same thing except you can put the methods in a
more sensible order.
sub pn($n) {
if ($n.comb.reverse.join('') eq $n) {
return 1;
} else {
return 0;
}
}
For the other languages, I explicitly converted the number to a string
(ns
) first, and the main difference is in how to reverse the string.
(I find the Python approach needlessly obscurantist, especially as
they're happy to pollute the language's root namespace with things
like len()
so the cost of a reverse()
would seem to be relatively
low.)
def pn(n):
ns='{0}'.format(n)
nr=ns[::-1]
if (nr == ns):
return 1
else:
return 0
Ruby, to be fair, doesn't care about its root namespace.
def pn(n)
ns=n.to_s
if ns==ns.reverse() then
return 1
else
return 0
end
end
And in Rust, as in Python, you can't directly reverse a string (which
is basically a list of chars), but you can reverse a list of chars…
fn pn(n: i64) -> u8 {
let ns=n.to_string();
let nr: String=ns.chars().rev().collect();
if nr == ns {
return 1;
} else {
return 0;
}
}
TASK #2 › Demo Stack
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
Which is a bit fuzzy, but I managed to get some test cases out of the
examples. In Perl and Raku a test is just an assertion and doesn't get
parallelised or anything, so the test setup looked like
my $stack=Local::Stack->new;
$stack->push(2);
$stack->push(-1);
$stack->push(0);
is($stack->pop,0,'test 1');
is($stack->top,-1,'test 2');
$stack->push(0);
is($stack->min,-1,'test 3');
OO Perl is trivial enough, if ugly:
package Local::Stack;
sub new {
my $class=shift;
my $self=[];
bless $self,$class;
}
sub push {
my $self=shift;
my $op=shift;
push @{$self},$op;
}
etc.
The designers of Raku apparently don't object to the main thing
non-Perl people dislike about Perl, the way it looks like a parity
error on your serial line:
#! /usr/bin/perl6
class Local::Stack {
has @!stack;
method push($op) {
@!stack.push($op);
}
etc.
but basically it works the same way; the @! just indicates an instance
variable.
In Python I wrap the function definitions in a class
, in just the
same way, with more self
-references:
class Stack:
def __init__(self):
self.stack=list()
def push(self,op):
self.stack.append(op)
etc.
but the testing wants separate functions, so I end up going over the
setup multiple times (as also in Ruby and Rust):
def test_ex1(self):
stack=Stack()
stack.push(2)
stack.push(-1)
stack.push(0)
self.assertEqual(stack.pop(),0,'example 1')
def test_ex2(self):
stack=Stack()
stack.push(2)
stack.push(-1)
stack.push(0)
stack.pop()
self.assertEqual(stack.top(),-1,'example 2')
etc.
Ruby has the cleanest syntax I looked at, since it assumes that a
method defined in a class is a method to be used on an instance of
that class and makes the rarer option (a method to be used on the
class directly) use the more fiddly code. No mucking about with self
here.
class Stack
def initialize
@stack=Array.new
end
def push(op)
@stack.push(op)
end
etc.
Meanwhile Rust doesn't really want to encapsulate things at all; the
class and instance methods are in a completely separate block from the
instance variables.
pub struct Stack {
stack: Vec<i64>
}
impl Stack {
pub fn new() -> Stack {
Stack { stack: Vec::new() }
}
pub fn push(&mut self,op: i64) {
self.stack.push(op);
}
etc., and for every method I have to name self
explicitly both as a
parameter and when I'm referring to instance variables. I mean, it
works and it's explicit about what you're up to, but I find it verbose
and noisy.
Full code on
github.
Comments on this post are now closed. If you have particular grounds for adding a late comment, comment on a more recent post quoting the URL of this one.