### Perl Weekly Challenge: Week 140

#### Challenge 1:

You are given two decimal-coded binary numbers, `\$a` and `\$b`.

Write a script to simulate the addition of the given binary numbers.

The script should simulate something like `\$a + \$b`. (operator overloading)

##### Example 1
``````Input: \$a = 11; \$b = 1;
Output: 100
``````
##### Example 2
``````Input: \$a = 101; \$b = 1;
Output: 110
``````
##### Example 3
``````Input: \$a = 100; \$b = 11;
Output: 111
``````

Is operator overloading really necessary? Raku atleast has everything needed for binary addition. We could solve this challenge with a one-liner like this:

``````(@*ARGS.parse-base(2) + @*ARGS.parse-base(2)).base(2).say;
``````

However the spec suggests we do in fact overload the `+` operator. I was surprised at how easy (with one caveat) this is to do in Raku.

An overloaded operator is a subroutine which like any other subroutine is created with the `sub` keyword. Because we are overloading an operator which already exists in Raku we also need the `multi` keyword. `infix` indicates what type of operator this is. You can also use `prefix`, `postfix` etc. Then between `<>` you have the actual name of the operator.

``````multi sub infix:<+>(
``````

This is the bit that gave me pause. I was getting errors because my code was calling Rakus' version of `+` in `MAIN()` and converting the operands to `Int`s. By changing the parameters of my subroutine to `IntStr` I ensured that it got called first. I've added a line that prints 'overload!' to verify that it is indeed my operator `+` that is being used. One more thing to point out is that the type specifier has `:D` on the end. I'm not 100% but what I think it is for is to ensure that we get an instance of `IntStr` not the type itself.

``````    IntStr:D \$a,
IntStr:D \$b
) {
``````

The heart of the function is the same as the one-liner above.

``````    return (\$a.parse-base(2) + \$b.parse-base(2)).base(2);
}
``````

(Full code on Github.)

Perl is, as often is the case, a little more difficult. As far as I can tell, there is no way to globally override an operator, only on a per-`package` basis. So my solution introduces a simple class called `Binary`. You would do binary addition with it like this:

``````say Binary->new(\$a) + Binary->new(\$b);
``````

The package uses the `overload` pragma to special `+` for `Binary` values. As we shall see, we will also need to overload the `""` operator in order to make `Binary`s out of strings and to output them again. Each overloaded operator is backed by a subroutine.

``````package Binary;
``````

But first let's look at the constructor. This is plain vanilla Perl OOP. The constructor takes one value which it makes into a binary value by prepending `0b` and stores it.

``````sub new {
my (\$class, \$str) = @_;
my \$self = \"0b\$str";
bless \$self, \$class;
return \$self;
}
``````

The `add()` function takes two parameters. The first is the object itself. This will be the first operand of the addition. The second parameter is a reference to the second operand which should also be a `Binary` object. A real `Binary` type would deal with all kinds of other scenarios such as adding a `Binary` to a scalar, adding it to `undef` etc. but in this small example I haven't bothered with any of that.

Because Perl doesn't have a straightforward method of converting between bases like Raku, I used the combination of `sprintf()` and the woefully misnamed `oct()` functions to convert the operands from strings to decimal numbers. These were added and then `sprintf()` was used again to convert back into a binary string which was then used to create a new `Binary` as the output.

Also as in the Raku version, I am outputting "overload!" to make sure my version of `+` is being used.

``````sub add {
my (\$self, \$other) = @_;
return Binary->new(
sprintf '%b', (sprintf '%d', oct \$\$self) + (sprintf '%d', oct \$\$other)
);
}
``````

This function stringifies the `Binary` object using the `sprintf()`/`oct()` method. It is a little more complex than it needs to be only for the sake of removing the `0b` prefix.

``````sub toString {
my (\$self) = @_;
return sprintf '%b', oct \$\$self;
}
``````

(Full code on Github.)

#### Challenge 2:

You are given 3 positive integers, `\$i`, `\$j` and `\$k`.

Write a script to print the `\$k`th element in the sorted multiplication table of `\$i` and `\$j`.

##### Example 1
``````Input: \$i = 2; \$j = 3; \$k = 4
Output: 3

Since the multiplication of 2 x 3 is as below:

1 2 3
2 4 6

The sorted multiplication table:

1 2 2 3 4 6

Now the 4th element in the table is "3".
``````
##### Example 2
``````Input: \$i = 3; \$j = 3; \$k = 6
Output: 4

Since the multiplication of 3 x 3 is as below:

1 2 3
2 4 6
3 6 9

The sorted multiplication table:

1 2 2 3 3 4 6 6 9

Now the 6th element in the table is "4".
``````

This is another challenge that can be solved with a one-liner in Raku. The `X` operator provides the cross product of two lists. The two lists in question are the range of 1 to `\$i` (or `@*ARGS` as we are taking arguments from the command line.) and the range of 1 to `\$j` (@*ARGS.) The result is a list of two-element lists. `X*` applies the multiplication operator to these lists which, in the case of example 1, would give us `(1 2 3 2 4 6)`. This list is sorted and the `\$k - 1` (`@*ARGS - 1`) is selected and printed. (You have to subtract 1 to get the right answer because arrays start from 0.)

``````(1 .. @*ARGS X* 1 .. @*ARGS).sort({\$^a <=> \$^b})[@*ARGS - 1].say;
``````

(Full code on Github.)

Perl doesn't have `X*` so we simulate it with a double `for` loop.

``````my @table;

for my \$i (1 .. \$ARGV) {
for my \$j (1 .. \$ARGV) {
push @table, \$i * \$j;
}
}

say 0+(sort { \$a <=> \$b } @table)[\$ARGV - 1];
``````

(Full code on Github.)