This is my response to The Weekly Challenge #310.
Input: $list = ( [1, 2, 3, 4], [4, 5, 6, 1], [4, 2, 1, 3] )
Output: (1, 4)
Example 2:
Input: $list = ( [1, 0, 2, 3], [2, 4, 5] )
Output: (2)
Example 3:
Input: $list = ( [1, 2, 3], [4, 5], [6] )
Output: ()
#! /usr/bin/env raku
unit sub MAIN ($arrays-as-string, :v(:$verbose)); # [1]
my @list = $arrays-as-string.split(" ")>>.split(","); # [2]
say ": List: { @list.raku }" if $verbose; # [3a]
say "(" ~ ([(&)] @list).keys.sort.join(",") ~ ")"; # [3]
[1] Specify the values with comma as the separator, and the arrays with space as the separtator. See «Running it» below for clarification.
I could have used my normal slurpy array with one string for each array here, and used the space as separator in the strings. But this is more compact, at the cost of reduced legibility.
[2] Split the arrays on a space, and each array individually on a comma.
[3]
Use the intersection operator
(&)
- in combination with the Reduction Metaoperator
[]
- to get the intersection of all the arrays.
See
docs.raku.org/routine/(&),%20infix%20%E2%88%A9
for more information about the intersection operator (&)
.
See
docs.raku.org/language/operators#Reduction_metaoperators for more
information about the Reduction Metaoperator []
.
The intersection is of the Set
persuation, datatype wise
that is. So we use the keys
method to get the actual values, the
keys. Then we sort them, as a Set
is unsorted, thus resorting to
random order when we extract the content.
See
docs.raku.org/type/Set
for more information about the Set
type.
Note the use of string concatenation (the ~
thingy)
on the last row, instead of my preferred code interpolation block
as used in [3a]. The next part of the challenge will stick to
interpolation...
Running it:
$ ./arrays-intersection "1,2,3,4 4,5,6,1 4,2,1,3"
(1,4)
$ ./arrays-intersection "1,0,2,3 2,4,5"
(2)
$ ./arrays-intersection "1,2,3 4,5 6"
()
Looking good.
With verbose mode:
$ ./arrays-intersection -v "1,2,3,4 4,5,6,1 4,2,1,3"
: List: [("1", "2", "3", "4").Seq, ("4", "5", "6", "1").Seq,
("4", "2", "1", "3").Seq]
(1,4)
$ ./arrays-intersection -v "1,0,2,3 2,4,5"
: List: [("1", "0", "2", "3").Seq, ("2", "4", "5").Seq]
(2)
$ ./arrays-intersection -v "1,2,3 4,5 6"
: List: [("1", "2", "3").Seq, ("4", "5").Seq, ("6",).Seq]
()
Input: @ints = (4, 1, 2, 3)
Output: (2, 3, 4, 1)
Even index elements: 4, 2 => 2, 4 (increasing order)
Odd index elements : 1, 3 => 3, 1 (decreasing order)
Example 2:
Input: @ints = (3, 1)
Output: (3, 1)
Example 3:
Input: @ints = (5, 3, 2, 1, 4)
Output: (2, 3, 4, 1, 5)
Even index elements: 5, 2, 4 => 2, 4, 5 (increasing order)
Odd index elements : 3, 1 => 3, 1 (decreasing order)
#! /usr/bin/env raku
unit sub MAIN (*@ints where @ints.elems > 1 && all(@ints) ~~ Int, # [1]
:v(:$verbose));
my @even = @ints.shift; # [2]
my @odd = @ints.shift; # [3]
while @ints.elems # [4]
{
@even.push: @ints.shift; # [5]
@odd.push: @ints.shift if @ints.elems; # [6]
}
say ": Even: @even[]\n: Odd: @odd[]" if $verbose;
say "({ (roundrobin(@even.sort, @odd.sort(-*))).flat.join(", ") })"; # [7]
[1] A slurpy array of 2 or more integers.
[2] Get the first value with an even index (i.e. 0), and place it in this aptly named array.
[3] And the first one with an odd index (i.e. 1).
[4] As long as we have additional values to sort,
[5] • get the next one, having an even index.
[6] • get the next one, if present.
[7] We sort the even indiced array the normal way, and
the odd one the other way round (the -*
argument to sort
).
Then we merge the two arrays with roundrobin
which gives us one
element from each list each time. The result is a two dimentional array,
so we flatten it with flat
. All of this is wrapped up in some
pretty printing code.
See docs.raku.org/routine/roundrobin for more information about roundrobin
.
Running it:
$ ./sort-odd-even 4 1 2 3
(2, 3, 4, 1)
$ ./sort-odd-even 3 1
(3, 1)
$ ./sort-odd-even 5 3 2 1 4
(2, 3, 4, 1, 5)
Looking good.
With verbose mode:
$ ./sort-odd-even -v 4 1 2 3
: Even: 4 2
: Odd: 1 3
(2, 3, 4, 1)
$ ./sort-odd-even -v 3 1
: Even: 3
: Odd: 1
(3, 1)
$ ./sort-odd-even -v 5 3 2 1 4
: Even: 5 2 4
: Odd: 3 1
(2, 3, 4, 1, 5)
And that's it.