This is my response to the Perl Weekly Challenge #140.
$a
and $b
.
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
A simple version, without operator overloading.
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
$i
, $j
and $k
.
$k
th element in the sorted multiplication table
of $i
and $j
.
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".
#! /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.