# Perl Weekly Challenge 95

Two pretty simple challenges this week! I tried ot focus on strongly typed subroutines and methods to shake things up.

You are given a number `\$N`.

Write a script to figure out if the given number is a 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
``````

### Solution

See below for explanation and any implementation-specific comments.

``````sub challenge(Int \$N) {
(\$N.Str.flip eq \$N.Str).Int; # [1]
}

sub MAIN(Int \$N) {
say challenge(\$N);
}
``````

This program runs as such:

``````\$ raku ch-1.raku 1221
1
``````

### Explanation

Pretty simple solution here. THe `challenge` subroutine takes the input, casts it to a string, reverses it and compares it to the input argument (returning a boolean). Finally, it casts that boolean to a number to match the challenges output.

1. Casting to a string allows us to account for any negative sign easily.

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

Note: This is shown with Perl 5 syntax.

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

### Solution

See below for explanation and any implementation-specific comments.

``````class Stack {
has @!internal-state of Int;

method push(Int \$elem --> True) {
@!internal-state.push(\$elem);
}

method pop() returns Int {
if @!internal-state.elems == 0 {
warn "Cannot pop an empty stack!";
} else {
@!internal-state.pop;
}
}

method top returns Int {
if @!internal-state.elems == 0 {
warn "Cannot find top of empty stack!";
} else {
@!internal-state.tail;
}
}

method min returns Int {
if @!internal-state.elems == 0 {
warn "Cannot find minimum of empty stack!";
} else {
@!internal-state.min;
}
}

method Str returns Str {
"({@!internal-state.join(', ')}) <-- Top";
}
}

sub MAIN(*@push where all(@push) ~~ Int, Int :\$pop = 2) {
# Can't put a default on "slurpy" args, so this is our work around
@push = @push.elems > 0 ?? @push !! (1, 2, 3, 4);

my \$stack = Stack.new;
for @push -> \$elem {
\$stack.push(\$elem);
}
say "     Stack after pushing: \$stack";
for ^\$pop {
\$stack.pop();
}
say "     Stack after popping: \$stack";
say "    Top element of stack: {\$stack.top}";
say "Minimum element of stack: {\$stack.min}";
}
``````

This program runs as such:

``````# All default
\$ raku ch-2.raku
Stack after pushing: (1, 2, 3, 4) <-- Top
Stack after popping: (1, 2) <-- Top
Top element of stack: 2
Minimum element of stack: 1

# Override pop default
\$ raku ch-2.raku --pop=1
Stack after pushing: (1, 2, 3, 4) <-- Top
Stack after popping: (1, 2, 3) <-- Top
Top element of stack: 3
Minimum element of stack: 1

# Override pop and push defaults
\$ raku ch-2.raku --pop=1 1 2 3
Stack after pushing: (1, 2, 3) <-- Top
Stack after popping: (1, 2) <-- Top
Top element of stack: 2
Minimum element of stack: 1
``````

### Explanation

A stack is a last in, first out (LIFO) structure, where we can only interact with the top. You can think of it like a stack of plates; it’s not easy to grab the middle plate from the stack!

In this case, we decided to make the stack homogenous (i.e., it can only hold integers). A Raku `List` already has a stack-like interface, so we basically just wrap that and add some warnings.

We simply define a class with a private `Array` of integers such that the user can only interact with it via the methods described in the challenge. Then, the `MAIN` subroutine simply demos those methods.

1. Raku classes have something called twigils. The `!` twigil here indicates that this variable is private to the class, and cannot be seen by any outside callers.
2. This could also be written as `has Int @!internal-state`, but I feel that doesn’t read as well. It can be written like this since the `@` sigil already denotes it is a positional variable, so you only need to constrain the members.
3. This is a common pattern for methods and subroutines that don’t actually return anything. Similar to `Unit` in Scala, `void` in Java, or `None` in Python. And of course `-->` is the way we define the return type.
4. The returns type can also be defined using `returns <type>` as shown here. The difference between `-->` and `returns` is that `returns` can only specify abstract types, whereas `-->` can specify both abstract type or specific values, which is why we needed to use `-->` to return the specific value `True`.
5. You’ll notice we don’t add the empty parentheses here. They are optional if there are no arguments to the method. In this case, I am using the Scala convention of having parentheses if the method has side effects, and leaving them off otherwise.
6. `Str` is a magic method, similar to `__str__` in Python or `toString` in Java and Scala. It is called whenever this variable is coerced to a string. So we don’t have to say `"Stack: {\$stack.Str}"`, we can just say `"Stack: \$stack"`.

## Final Thoughts

Strongly typed Raku is much faster than gradually typed Raku, but I find it to be more cumbersome. Scalars are fairly easy (which is the majority of what we dealt with here), but I find positional (`Lists`, `Arrays`, etc.) and associatives (`Hashes`, `Maps`, etc.) to be more challenging. For example, the way you constrain a `List` and an `Array` is slightly different. And `Maps` always have to have string keys, which makes things both cumbersome and slow. In fact, there was some interesting discussion around Raku’s speed (or lack thereof) on the Raku subreddit, and I encourage anyone reading this to spend a little time over there. Anyway, that’s enough rambling from me. Until next time!

Tags:

Categories:

Updated: