Perl Weekly Challenge 95: Palindrome Numbers and Demo Stack

These are some answers to the Week 95 of the Perl Weekly Challenge organized by Mohammad S. Anwar.

Spoiler Alert: This weekly challenge deadline is due in a few of days (January 17, 2021). This blog post offers some solutions to this challenge, please don’t read on if you intend to complete the challenge on your own.

Task 1: Palindrome Numbers

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

A palindrome is a word, number, phrase, or other sequence of characters which reads the same backward as forward, like “noon”, “madam”, or “redivider”.

Palindrome Numbers in Raku

This is fairly simple. We just compare the input with its reversed version:

use v6;

my $num = @*ARGS[0] // 1221;
say "$num: ", +($num eq $num.flip);

Note that the + sign in the second code line is aimed at numifying the value of the Boolean expression $num eq $num.flip (False or True) into 0 or 1.

This is the output with a few input values:

$ raku palindrome.raku
1221: 1

$ raku palindrome.raku 7337
7337: 1

$ raku palindrome.raku 8765
8765: 0

$ raku palindrome.raku -1221
-1221: 0

This is so simple that we can also do it as a one-liner script:

$ raku -e 'my $n = @*ARGS[0]; say "$n: ", +($n eq $n.flip);' 7337
7337: 1

Palindrome Numbers in Perl

Again, we just compare the input with its reversed version:

use strict;
use warnings;
use feature "say";

my $num = shift // 1221;
say "$num: ", $num eq (reverse $num) ? 1 : 0;

This is the output with a few input values:

$ perl palindrome.pl
1221: 1

$ perl palindrome.pl 7337
7337: 1

$ perl palindrome.pl 5678
5678: 0

$ perl palindrome.pl -101
-101: 0

We can also do a Perl one-liner:

$ perl -E '$n = shift; say "$n: ", $n eq (reverse $n) ? 1 : 0;' 1221
1221: 1

Palindrome Numbers in Scala

The Scala version uses essentially the same idea:

object Main {
  def main(args: Array[String]): Unit = {
    val num = args(0).toString
    if (num == num.reverse) {
      println(1)
    } else {
      println(0)
    }
  }
}

This Scala program produces the same results as the above Raku and Perl programs.

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

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

There are already push and pop built-in functions in both Raku and Perl, so we will give our stack operations different names. The stack will be implemented as a simple array with the relevant stack operations.

Demo Stack in Raku

Functional Implementation

Implementing a stack is typical of a job for object-oriented programming. However, I will start with a more functional approach (as I prefer that). The push and pop stack operations are renamed put-in-stack and take-from-stack:

use v6;

sub put-in-stack (@stack, *@new-items) {
    push @stack, |@new-items;
}
sub take-from-stack (@stack where @stack.elems > 0) {
    return pop @stack;
}
sub top (@stack where @stack.elems > 0) {
    return @stack.tail;
}
sub minimum (@stack where @stack.elems > 0) {
    return @stack.min;
}
my @a-stack = 1..5;
say @a-stack;
put-in-stack @a-stack, 6..8;
say @a-stack;
say "Min: ", minimum @a-stack; 
say "Top: ", top @a-stack;
say "Take: ", take-from-stack @a-stack;
say @a-stack;

This displays the following output:

$ raku stack_oo.raku
[1 2 3 4 5]
[1 2 3 4 5 6 7 8]
Min: 1
Top: 8
Take: 8
[1 2 3 4 5 6 7]

Object-Oriented Implementation

If you prefer an object-oriented version, it could look like this:

use v6;

class Stack {
    has @.stack is rw;
    method is-empty {
        @!stack.elems > 0 ?? False !! True;
    }
    method put-in-stack (*@new-items) {
        push @!stack, |@new-items;
    }
    method take-from-stack {
        return pop @!stack;
    }
    method top {
        return @!stack.tail;
    }
    method minimum {
        return @!stack.min;
    }
}
my $a-stack = Stack.new( stack => 1..5);
say $a-stack.stack;
$a-stack.put-in-stack: 6..8;
say $a-stack.stack;
say "Min: ", $a-stack.minimum; 
say "Top: ", $a-stack.top;
say "Take: ", $a-stack.take-from-stack ;
say $a-stack.stack;

The code using the Stack class should really check that the stack is not empty (with the is-empty method) before calling the take-from-stack, top, or minimum methods to avoid an unhandled exception, and we may in that case raise an ad-hoc exception or print an error message or do something else, but since we have no specification on what to do in such a case, this is left as an exercise to the reader.

Output:

$ raku  stack_oo.raku
[1 2 3 4 5]
[1 2 3 4 5 6 7 8]
Min: 1
Top: 8
Take: 8
[1 2 3 4 5 6 7]

Demo Stack in Perl

In Perl, we will implement only the functional version:

#!/usr/bin/perl
use strict;
use warnings;
use feature qw/say/;

sub is_empty {
    my $stack = shift;
    return @$stack > 0 ? 0 : 1;
}

sub put_in_stack {
    my ($stack, @new_items) = @_;
    push @$stack, @new_items;
}
sub take_from_stack  {
    my $stack = shift;
    return undef if is_empty $stack;
    return pop @$stack;
}
sub top {
    my $stack = shift;
    return undef if is_empty $stack;
    return $stack->[-1];
}
sub minimum {  # assuming stack of numeric values
    my $stack = shift;
    return undef if is_empty $stack;
    my $min = $stack->[0];
    for my $item (@$stack) {
        $min = $item if $item < $min;
    }
    return $min;
}
my $a_stack = [1..5];
say "@$a_stack";
put_in_stack $a_stack, 6..8;
say "@$a_stack";
say "Min: ", minimum $a_stack; 
say "Top: ", top $a_stack;
say "Take: ", take_from_stack $a_stack;
say "@$a_stack";

This displays the following output:

$ perl stack.pl
1 2 3 4 5
1 2 3 4 5 6 7 8
Min: 1
Top: 8
Take: 8
1 2 3 4 5 6 7

Demo Stack in Scala

Being a beginner in Scala, I don’t yet master passing function parameters by value or by reference. So I’ll make my stack a global variable to enable in-place modification. You don’t need to tell me it’s bad, I know. At this point, I’m only trying to make a program that works properly, I’ll hopefully implement better practices and write more idiomatic Scala code in a few months from now.

object stack extends App {
  var stack = Array(1, 2, 3, 4, 5)
  print_stack("Original stack") 
  push(Array(6, 7, 8))
  print_stack("Pushed stack")
  val popped = pop
  println(s"Popped: $popped")
  print_stack("Popped stack")
  val topped = top
  println(s"Top: $topped")
  val minimum = min
  println(s"Min: $minimum")
  def print_stack(caption: String) : Unit = {
    print(s"$caption: "); println( stack.mkString(" "))
  }
  def push(newItems: Array[Int]): Unit = {
    stack ++= newItems
  }
  def pop: Int = {
    val lastItem = stack.last
    stack = stack.dropRight(1)
    return lastItem
  }
  def top: Int = {
    return stack.last
  }
  def min: Int = {
    var min = stack(0);
    for (i <- 1 to (stack.length - 1)) {
      if (stack(i) < min) min = stack(i)
    }
    return min
  }
}

This displays the following output:

Original stack: 1 2 3 4 5
Pushed stack: 1 2 3 4 5 6 7 8
Popped: 8
Popped stack: 1 2 3 4 5 6 7
Top: 7
Min: 1

Wrapping up

The next week Perl Weekly Challenge will start soon. If you want to participate in this challenge, please check https://perlweeklychallenge.org/ and make sure you answer the challenge before 23:59 BST (British summer time) on Sunday, January 17, 2021. And, please, also spread the word about the Perl Weekly Challenge if you can.

Leave a comment

About laurent_r

user-pic I am the author of the "Think Perl 6" book (O'Reilly, 2017) and I blog about the Perl 5 and Raku programming languages.