by Arne Sommer

# Palindromic Stack with Raku and Perl

 Published 16. January 2021.

This is my response to the Perl Weekly Challenge #095.

## Challenge #095.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`.

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 ```

Note that the challenge does not actually say how we should treat non-numeric values. I have chosen to let the program reject them, but printing `0` could be an alternative.

Multiple dispatch is fun, so let us have a go at it:

File: palindrome-number-multi ```#! /usr/bin/env raku multi sub MAIN (Numeric \$N where \$N >= 0 && \$N eq \$N.flip) #  { say 1; } multi sub MAIN (Numeric \$N) #  { say 0; } ```

 This version is used if the input parameter is numeric (the `Numeric` type), it is positive (see the second example above), and the number equals itself if we reverse it (with `flip`). Note the string comparison (with `eq`), so that we keep the reversed value as is.

 All other numbers (after  has declined them) results in a `0`.

Running it on the examples:

```\$ ./palindrome-number-multi 1221 1 \$ ./palindrome-number-multi -101 0 \$ ./palindrome-number-multi 90 0 \$ ./palindrome-number-multi 0110 1 ```

Complex numbers do not work:

```\$ ./palindrome-number-multi 1+2i Cannot convert 1+2i to Real: imaginary part not zero in sub MAIN at ./palindrome-number-multi line 3 in block <unit> at ./palindrome-number-multi line 3 ```

We do string comparison, but prior to that the comparison with zero coerces the number to a Real - which fails. The remedy is removing that comparison, as the string comparison takes care of negative numbers for us.

This time, using a ternary if:

File: palindrome-number-if ```#! /usr/bin/env raku unit sub MAIN (Numeric \$N); say \$N eq \$N.flip #  ?? 1 !! 0; ```

 The ternary if, whith a single `say` up front.

```\$ ./palindrome-number-if 1+2i 0 ```

The ternary if is actually redundant. We can coerce the Boolean value to Numeric value (with the Prefix `+` Operator), and save some code:

File: palindrome-number ```#! /usr/bin/env raku unit sub MAIN (Numeric \$N); say + (\$N eq \$N.flip); #  ```

 Ensure a numeric value (instead of `True` and `False`).

See docs.raku.org/routine/+ for more information about the Prefix Operator `+`.

Boolean values are built in, but are implemented as an `enum` (enumeration). You can inspect the real (or numeric, rather) values like this:

```> Bool.enums Map.new((False => 0, True => 1)) ```

See docs.raku.org/language/typesystem#enum for more information about the `enum` type.

See docs.raku.org/routine/enums for more information about the `enums` method.

### A Perl Version

This is straight forward translation of «palindrome-number».

File: palindrome-number-perl ```#! /usr/bin/env perl use strict; use warnings; use feature 'say'; use Scalar::Util qw(looks_like_number); #  my \$N = \$ARGV // die "Specify a number"; die "Not a number" unless looks_like_number(\$N); #  say 0 + (\$N eq reverse(\$N)); #  ```

 Deciding if a value is numeric is hard. But the «Scalar::Util» module is helpful.

 Complain for non-numeric values.

 Ensure that we get a `0` for non-palindromic values by adding zero. (As we will get an empty string otherwise.)

Running it gives the same result as the Raku version, except for complex numbers (but that is probably ok, as the yare not built in):

```\$ ./palindrome-number-perl 1221 1 \$ ./palindrome-number-perl -101 0 \$ ./palindrome-number-perl 90 0 \$ ./palindrome-number-perl AA 1 \$ ./palindrome-number-perl 1+2i Not a number at ./palindrome-number-perl line 9. ```

## Challenge #095.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 ```

It is boring to duplicate the example code, so I have written an interactive program where the user specifies the commands.

File: demo-stack ```#! /usr/bin/env raku unit sub MAIN; class stack { has @.values is rw; #  method push (\$value) #  { @.values.push: \$value; } method pop #  { return @.values.pop; } method top #  { return @.values; } method min #  { return @.values.min; } method all #  { return @.values.join(" -> "); } } my \$stack = stack.new; #  loop #  { given prompt 'stack> ' #  { when /^push\s+(.*)\$/ { \$stack.push: \$_ for \$0.Str; } # [2a] when 'pop' { \$stack.pop; } # [3a] when 'top' { say \$stack.top; } # [4a] when 'min' { say \$stack.min; } # [5a] when 'all' { say \$stack.all; } # [6a] when 'exit' | 'quit' { exit; } #  } ```

 Just one element in the class, the stack.

 A method to add one element. Note the trailing `.Str` in [2a] to coerce the match object to a string.

 A method to remove one element. The method returns the elment, but the code in [3a] does not print it.

 A method to show the top eleement on the stack.

 A method to show the smallest element on the stack. Note that this will fail if we add non-numeric values to the stack - which is permissible.

 A method to show the content of the stack. The top is to the right. This method is not specified in the challenge, but I have added it as it is useful for debugging.

 Set up an initial (empty) stack.

 An eternal loop. Note the exit strategy (in ).

 Print the text and wait for user input.

 We need an exit strategy, and these commands fit the bill. Using Control-C works as well.

See docs.raku.org/routine/prompt for more information about `prompt`.

Running it:

```\$ ./demo-stack stack> push 2 stack> push -1 stack> push 0 stack> all 2 -> -1 -> 0 stack> pop stack> top 2 stack> push 0 stack> min -1 stack> all 2 -> -1 -> 0 stack> quit ```

Looking good.

We can support several values in one «push»:

File: demo-stack-list (changes only) ``` when /^push\s+(.*)\$/ { \$stack.push: \$_ for \$0.words; } ```

Running it:

```\$ ./demo-stack-list stack> push 1 2 3 4 stack> all 1 -> 2 -> 3 -> 4 stack> quit ```

### Perl

This is a straight forward translation of «demo-stack-list», but requires about 50% more code due to the unique (not meant as a compliment) object system in Perl.

File: demo-stack-perl ```#! /usr/bin/env perl use strict; use warnings; use feature 'say'; use List::Util; package stack { sub new { my \$class = shift; my \$self = { 'values' => [] }; bless \$self, \$class; return \$self; } sub push { my (\$self, \$value) = @_; push(@{\$self->{values}}, \$value); } sub pop { my \$self = shift; return pop(@{\$self->{values}}); } sub top { my \$self = shift; return \${\$self->{values}}; } sub min { my \$self = shift; my @values = @{\$self->{values}}; return List::Util::min @values; } sub all { my \$self = shift; return join(" -> ", @{\$self->{values}}); } } my \$stack = stack->new(); my \$input; while (1) { print 'stack> '; \$input = ; chomp(\$input); if (\$input =~ /^push\s+(.*)\$/) { \$stack->push(\$_) #  for split(/\s+/, \$1); } elsif (\$input eq 'pop') { \$stack->pop; } elsif (\$input eq 'top') { say \$stack->top; } elsif (\$input eq 'min') { say \$stack->min; } elsif (\$input eq 'all') { say \$stack->all; } elsif (\$input eq 'exit' || \$input eq 'quit') { exit; } } ```

 Note that the first match is at `\$1`, and not `\$0` as in Raku.

Running it gives the same result as the Raku version:

```./demo-stack-perl stack> push 2 -1 0 stack> all 2 -> -1 -> 0 stack> pop stack> top 2 stack> push 0 stack> min -1 stack> all 2 -> -1 -> 0 stack> exit ```

I used «exit» instead of «quit» this time.

And that's it.