by Arne Sommer

# Add the Table (or not) with Raku

[156] Published 28. November 2021.

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

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

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

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

File: add-binary-unloaded ```#! /usr/bin/env raku subset DCB of Int where \$_ ~~ /^1<[01]>*\$/; # [1] unit sub MAIN (DCB \$a, DCB \$b, :v(:\$verbose)); # [1a] my \$length = max(\$a.chars, \$b.chars); # [5a] say ": Max lenght: \$length" if \$verbose; my @a = \$a.comb.reverse; # [2] my @b = \$b.comb.reverse; # [2] my \$carry = 0; # [3] my @result; # [4] for ^\$length -> \$index # [5] { my \$aa = @a.shift // 0; # [6] my \$bb = @b.shift // 0; # [6] my \$sum = \$carry + \$aa + \$bb; # [7] say ": a:\$aa b:\$bb c:\$carry -> \$sum"; if \$sum == 3 { \$sum = 1; \$carry = 1; } # [8] elsif \$sum == 2 { \$sum = 0; \$carry = 1; } # [9] elsif \$sum == 1 { \$carry = 0; } # [10] elsif \$sum == 0 { \$carry = 0; } # [11] @result.push: \$sum; # [12] } @result.push: \$carry if \$carry; # [13] say @result.join.flip; # [14] ```

[1] Set up a custom type (with `subset`) for the input (allowing «0» and «1» only). Note that the first digit must be «1», thus disallowing leading zeroes. (And also disallowing «0» as a value. Oh well.)

See docs.raku.org/language/typesystem#index-entry-subset-subset for more information about `subset`.

[2] Reverse the values, as arrays, as we want to work from the right hand side (because of carrying).

[3] Carrying.

[4] The result goes here, digit by digit.

[5] Iterate over the longest number (as computed in [5a]).

[6] Get the next digit, for both numbers. If none use a zero (to compensate for a situation where they do not have the same lnegth.)

[7] Add them all togeter, incluing the carry(over from the previous digit calculation).

[8] 3 x «1» gives «11» (i.e. a «1» and a carry).

[9] 2 x «1» gives «10» (i.e. a «0» and a carry).

[10] A single «1» gives «1» (and no carry).

[11] «0» gives «0» (and no carry)..

[12] Add the digit to the list.

[13] Do we have a leftover carry? If so, add it.

[14] We reversed the numbers initially (in [2]), so now we have to de-reverisfy the result.

Running it:

```\$ ./add-binary-unloaded 11 1 100 \$ ./add-binary-unloaded 101 1 110 \$ ./add-binary-unloaded 100 11 111 ```

## Challenge #140.2: Multiplication Table

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". ```
File: multab ```#! /usr/bin/env raku subset PosInt of Int where \$_ > 0; # [1] unit sub MAIN (PosInt \$i, PosInt \$j, PosInt \$k, :v(:\$verbose)); # [1a] my @result; # [2] for 1 .. \$i -> \$ii # [3] { for 1 .. \$j -> \$jj # [3] { @result.push: \$ii * \$jj; # [4] } } my @sorted = @result.sort; # [5] say ": Sorted: @sorted[]" if \$verbose; say @sorted[\$k -1] // ""; # [6] ```

[1] Set up a custom type ensuring positive integers, and apply it on the arguments (1a).

[2] We are only interested in the result, not the matrix, so store everything in a simple array.

[3] Iterate over the two dimensions.

[4] • Add the product to the array.

[5] Sort the array.

[6] Print the required element. Note the `-1` to compensate for arrays starting at index 0. The challenge does not say how to handle an out of bounds situation (i.e. `\$k > \$i * \$j`), so we print an empty string in that case.

Running it:

```\$ ./multab 2 3 4 3 \$ ./multab 3 3 6 : Sorted: 1 2 2 3 3 4 6 6 9 4 ```

Looking good.

With verbose mode:

```\$ ./multab -v 2 3 4 : Sorted: 1 2 2 3 4 6 3 \$ ./multab -v 3 3 6 : Sorted: 1 2 2 3 3 4 6 6 9 4 ```

The error situation handled by [6] abvove can be done in [1a] instead:

File: multitab2 ```#! /usr/bin/env raku subset PosInt of Int where \$_ > 0; unit sub MAIN (PosInt \$i, PosInt \$j, PosInt \$k where 1 <= \$k <= \$i * \$j, # [1] :v(:\$verbose)); my @result; for 1 .. \$i -> \$ii { for 1 .. \$j -> \$jj { @result.push: \$ii * \$jj; } } my @sorted = @result.sort; say ": Sorted: @sorted[]" if \$verbose; say @sorted[\$k -1]; # [2] ```

[1] Note the `where` clause, that can be used like this and not only in combination with `subset` as above.

[2] The `//` error handling has gone now.

Running the programs with an out of bounds `\$k` value:

```\$ ./multab 3 3 10 \$ ./multab2 3 3 10 Usage: ./multab2 [-v|--verbose[=Any]] <i> <j> <k> ```

And that's it.