This is my response to The Weekly Challenge #344.
@ints and an integer, $x.
$x to the integer in the array-form.
Input: @ints = (1, 2, 3, 4), $x = 12
Output: (1, 2, 4, 6)
Example 2:
Input: @ints = (2, 7, 4), $x = 181
Output: (4, 5, 5)
Example 3:
Input: @ints = (9, 9, 9), $x = 1
Output: (1, 0, 0, 0)
Example 4:
Input: @ints = (1, 0, 0, 0, 0), $x = 9999
Output: (1, 9, 9, 9, 9)
Example 5:
Input: @ints = (0), $x = 1000
Output: (1, 0, 0, 0)
#! /usr/bin/env raku
unit sub MAIN (Int :$x, # [1]
*@ints where @ints.elems > 0 # [2]
&& all(@ints) ~~ /^<[0..9]>$/); # [2a]
say "({ (@ints.join + $x).comb.join(", ") })"; # [3]
[1] A named integer argument. It should probably be an unsigned int
(UInt), though. Just as the array of integers really is an array
of single digits. We do not want any negativity, no(w)?
[2] A slurpy array for the integers, with at least one element.
[3] Glue the integers together to a single value, add x, split
the new value into single digits and print them as a comma separated
list.
Running it:
$ ./array-form-compute -x=12 1 2 3 4
(1, 2, 4, 6)
$ ./array-form-compute -x=181 2 7 4
(4, 5, 5)
$ ./array-form-compute -x=1 9 9 9
(1, 0, 0, 0)
$ ./array-form-compute -x=9999 1 0 0 0 0
(1, 9, 9, 9, 9)
$ ./array-form-compute -x=1000 0
(1, 0, 0, 0)
Looking good.
No verbose mode for this one.
@source and @target.
@target by
putting these smaller lists from @source together in some
order. You cannot break apart or change the order inside any of
the smaller lists in @source.
Input: @source = ([2,3], [1], [4])
@target = (1, 2, 3, 4)
Output: true
Use in the order: [1], [2,3], [4]
Example 2:
Input: @source = ([1,3], [2,4])
@target = (1, 2, 3, 4)
Output: false
Example 3:
Input: @source = ([9,1], [5,8], [2])
@target = (5, 8, 2, 9, 1)
Output: true
Use in the order: [5,8], [2], [9,1]
Example 4:
Input: @source = ([1], [3])
@target = (1, 2, 3)
Output: false
Missing number: 2
Example 5:
Input: @source = ([7,4,6])
@target = (7, 4, 6)
Output: true
Use in the order: [7, 4, 6]
We could have used recursive descent (depth first) here, but why
bother with all that manual work when the built-in permutations can
do it for us absolutely free of hard work (i.e. programming). The downside
is that permutations gives us absolutely all permutations to try,
even if the already selected values (to the left) do not fit.
#! /usr/bin/env raku
unit sub MAIN (*@rows where @rows.elems > 0 # [1]
&& all(@rows) ~~ /^ <[0..9,]>+ $/, # [1a]
:t(:$target) where $target ~~ /^ <[0..9,]>+ $/, # [2]
:v(:$verbose));
my @source = @rows>>.split(',')>>.Int; # [3]
my @target = $target.split(',')>>.Int; # [4]
for @source.permutations -> @combo # [5]
{
my @flat = @combo[*;*]; # [6]
my $equal = @flat eqv @target; # [7]
say ": ({ @combo.map({ "[{ $_.join(",")}]" }).join(", ") }) \
eq ({ @target.join(",") }): { $equal }" if $verbose;
if $equal # [8]
{
say 'true'; # [8a]
exit; # [8b]
}
}
say 'false'; # [9]
[1] A slurpy array of arrays, with at least one of them. Each element (array) consits of commas and digits only.
[2] The target as a named argument. This is also a comma separated list of integers.
[3] Split the source into a list of lists.
[4] Split the target into a (single) list.
[5] Iterate over the permutations of the
source array.
See docs.raku.org/routine/permutations for more information about permutations.
[6] Flatten the subarrays in the array.
[7] Are the current permutation equal to the target? We
use the equivalence operator eqv, that checks if the two arguments
have the same types and values.
See docs.raku.org/routine/eqv for more information about eqv.
[8] Are they equal? If so, say so [8a] and finish [8b].
[9] We have failed to find equality in the loop if we reach this point. Say so.
Running it:
$ ./array-formation -t=1,2,3,4 2,3 1 4
true
$ ./array-formation -t=1,2,3,4 1,3 2,4
false
$ ./array-formation -t=5,8,2,9,1 9,1 5,8 2
true
$ ./array-formation -t=1,2,3 1 3
false
$ ./array-formation -t=7,4,6 7,4,6
true
Looking good.
With verbose mode:
$ ./array-formation -v -t=1,2,3,4 2,3 1 4
: ([2,3], [1], [4]) eq (1,2,3,4): False
: ([2,3], [4], [1]) eq (1,2,3,4): False
: ([1], [2,3], [4]) eq (1,2,3,4): True
true
$ ./array-formation -v -t=1,2,3,4 1,3 2,4
: ([1,3], [2,4]) eq (1,2,3,4): False
: ([2,4], [1,3]) eq (1,2,3,4): False
false
$ ./array-formation -v -t=5,8,2,9,1 9,1 5,8 2
: ([9,1], [5,8], [2]) eq (5,8,2,9,1): False
: ([9,1], [2], [5,8]) eq (5,8,2,9,1): False
: ([5,8], [9,1], [2]) eq (5,8,2,9,1): False
: ([5,8], [2], [9,1]) eq (5,8,2,9,1): True
true
$ ./array-formation -v -t=1,2,3 1 3
: ([1], [3]) eq (1,2,3): False
: ([3], [1]) eq (1,2,3): False
false
$ ./array-formation -v -t=7,4,6 7,4,6
: ([7,4,6]) eq (7,4,6): True
true
And that's it.