This is my response to The Weekly Challenge #355.
$int.
, and return
as string.
Input: $int = 123
Output: "123"
Example 2:
Input: $int = 1234
Output: "1,234"
Example 3:
Input: $int = 1000000
Output: "1,000,000"
Example 4:
Input: $int = 1
Output: "1"
Example 5:
Input: $int = 12345
Output: "12,345"
#! /usr/bin/env raku
unit sub MAIN (Int $int where $int > 0); # [1]
$int.flip.comb.rotor(3, :partial)>>.join.join(",").flip.say;
# [2] [3] [4] ############# [5] ### [6] ##### [7] [8]
[1] Ensure a positive integer.
[2] Reverse the string with flip. (And not
with reverse, as the that one works on arrays. Reversing
a string (which in this case is an array with one element) does
not actually do anything.)
See docs.raku.org/routine/flip for more information about flip.
[3] Split the string into an array of individual digits.
[4] Use rotor to group three and three
digits in subarrays. (This is from the end, remember, courtesy
of flip.) The :partial adverb tells the function
to return the remainder digits as a final subarray.
E.g.
> say <1 2 3 4 5 6 7 8>.rotor(3); # -> ((1 2 3) (4 5 6))
> say <1 2 3 4 5 6 7 8>.rotor(3, :partial); # -> ((1 2 3) (4 5 6) (7 8))
See docs.raku.org/routine/rotor for more information about rotor.
[5] Join each subarray into a string for each one.
[6] Join the strings, separated by a comma.
[7] Flip the string.
[8] And print it.
Running it:
$ ./thousand-separator 123
123
$ ./thousand-separator 1234
1,234
$ ./thousand-separator 1000000
1,000,000
$ ./thousand-separator 1
1
$ ./thousand-separator 12345
12,345
Looking good.
No verbose mode for this one.
@ints.
An array is mountain if and only if:
1) arr.length >= 3
and
2) There exists some i with 0 < i < arr.length - 1 such that:
arr[0] < arr[1] < ... < arr[i - 1] < arr[i]
arr[i] > arr[i + 1] > ... > arr[arr.length - 1]
Example 1:
Input: @ints = (1, 2, 3, 4, 5)
Output: false
Example 2:
Input: @ints = (0, 2, 4, 6, 4, 2, 0)
Output: true
Example 3:
Input: @ints = (5, 4, 3, 2, 1)
Output: false
Example 4:
Input: @ints = (1, 3, 5, 5, 4, 2)
Output: false
Example 5:
Input: @ints = (1, 3, 2)
Output: true
#! /usr/bin/env raku
unit sub MAIN (*@ints where @ints.elems >= 3 && all(@ints) ~~ Int, # [1]
:a(:$show-all), # [2]
:v(:$verbose) = $show-all); # [2a]
my $is-ok = False; # [3]
for 1 .. @ints.end -1 -> $i # [4]
{
my @left = @ints[0..$i]; # [5]
my @right = @ints[$i..*]; # [6]
my $ok = ( [<] @left ) && ( [>] @right ); # [7]
say ": i:$i : @left[] <-> @right[] = $ok" if $verbose;
if $ok # [8]
{
$is-ok = True; # [8a]
last unless $show-all; # [8b]
}
}
say $is-ok; # [9]
[1] All the values must be integers, and there must be at least 3 of them.
[2] Use the «-a» command line option to show all the possible partitions (mountain tops), even after a successful match. This option enables verbose mode as well, courtesy of the default value on the latter [2a].
[3] Assume failure by default.
[4] Iterate over the starting indices.
[5] Get the left mountain side,
[6] and the right one. Note that the (potential) top is included in both.
[7] Use the Reduction Metaoperator []
with < on the left and > on the right to ensure that the values
are sorted in increasing (left) and decreasing (right) order.
See docs.raku.org/language/operators#Reduction_metaoperators for more information about the Reduction Metaoperator [].
[8] Do we have a mountain array? If so, set the flag [8a] and exit the loop (unless we used the «-a» command line option).
[9] Print the Boolean result.
Running it:
$ ./mountain-array 1 2 3 4 5
False
$ ./mountain-array 0 2 4 6 4 2 0
True
$ ./mountain-array 5 4 3 2 1
False
$ ./mountain-array 1 3 5 5 4 2
False
$ ./mountain-array 1 3 2
True
Looking good.
With verbose mode:
$ ./mountain-array -v 1 2 3 4 5
: i:1 : 1 2 <-> 2 3 4 5 = False
: i:2 : 1 2 3 <-> 3 4 5 = False
: i:3 : 1 2 3 4 <-> 4 5 = False
False
$ ./mountain-array -v 0 2 4 6 4 2 0
: i:1 : 0 2 <-> 2 4 6 4 2 0 = False
: i:2 : 0 2 4 <-> 4 6 4 2 0 = False
: i:3 : 0 2 4 6 <-> 6 4 2 0 = True
True
$ ./mountain-array -v 5 4 3 2 1
: i:1 : 5 4 <-> 4 3 2 1 = False
: i:2 : 5 4 3 <-> 3 2 1 = False
: i:3 : 5 4 3 2 <-> 2 1 = False
False
$ ./mountain-array -v 1 3 5 5 4 2
: i:1 : 1 3 <-> 3 5 5 4 2 = False
: i:2 : 1 3 5 <-> 5 5 4 2 = False
: i:3 : 1 3 5 5 <-> 5 4 2 = False
: i:4 : 1 3 5 5 4 <-> 4 2 = False
False
$ ./mountain-array -v 1 3 2
: i:1 : 1 3 <-> 3 2 = True
True
Only the second example gets more verbose output if we use the «-a» command line option. Note that the new information is pretty useless...
$ ./mountain-array -v 0 2 4 6 4 2 0
: i:1 : 0 2 <-> 2 4 6 4 2 0 = False
: i:2 : 0 2 4 <-> 4 6 4 2 0 = False
: i:3 : 0 2 4 6 <-> 6 4 2 0 = True
True
$ ./mountain-array -a 0 2 4 6 4 2 0
: i:1 : 0 2 <-> 2 4 6 4 2 0 = False
: i:2 : 0 2 4 <-> 4 6 4 2 0 = False
: i:3 : 0 2 4 6 <-> 6 4 2 0 = True
: i:4 : 0 2 4 6 4 <-> 4 2 0 = False
: i:5 : 0 2 4 6 4 2 <-> 2 0 = False
True
And that's it.