This is my response to The Weekly Challenge #304.
$n
.
$n
digits
with 1
in the given list so that no two consecutive digits are 1
otherwise return
false.
Input: @digits = (1, 0, 0, 0, 1), $n = 1
Output: true
Re-arranged list: (1, 0, 1, 0, 1)
Example 2:
Input: @digits = (1, 0, 0, 0, 1), $n = 2
Output: false
#! /usr/bin/env raku
unit sub MAIN (*@ints is copy where @ints.elems > 0
&& all(@ints) eq any(0,1), # [1]
Int :$n where $n > 0, # [2]
:v(:$verbose));
if @ints.join ~~ /11/ # [3]
{
say ':Found neighbourly 1s in the input' if $verbose;
say 'false'; # [3a]
exit; # [3b]
}
my $replaced = 0; # [4]
for 0 .. @ints.end -> $index # [5]
{
if @ints[$index] == 0 # [6]
{
if $index == 0 || @ints[$index -1] == 0 # [7]
{
if $index == @ints.end || @ints[$index +1] == 0 # [8]
{
@ints[$index] = 1; # [9]
$replaced++; # [10]
say ": Replaced #$replaced at index $index: [{ @ints.join(",") }]"
if $verbose;
}
}
}
}
say $replaced >= $n ?? 'true' !! 'false'; # [11]
[1] At least one element, all of which must be either 0 or 1.
This is set up as an any
junction. Note the is copy
so that
the program can change the values (in [9]).
See docs.raku.org/routine/any for more information about any
.
See docs.raku.org/type/Parameter#method_copy for more information about is copy
.
[2] A named argument for the $n
value, which must be a positive
integer.
[3] We are not allowed to have two consecutive 1s, and should check that this is not the case initially. In which case we cannot replace anything.
[4] The number of replacements will end up here.
[5] Iterate over the indices in the input. end
gives
the index of the last item. (for ^@ints -> $index
would do the
same, and is shorter.)
See docs.raku.org/routine/end for more information about end
.
[6] Is the current value zero?
[7] Is the current index zero (i.e. no left value) or the value to the left is also zero?
[8] Is the current index the end or the value to the right is also zero?
[9] Replace the current zero with one.
[10] Increase the count.
[11] Did we manage to replace at least $n
zeroes?.
Running it:
$ ./arrange-binary -n=1 1 0 0 0 1
true
$ ./arrange-binary -n=2 1 0 0 0 1
false
Looking good.
With verbose mode:
$ ./arrange-binary -n=1 -v 1 0 0 0 1
: Replaced #1 at index 2: [1,0,1,0,1]
true
$ ./arrange-binary -n=2 -v 1 0 0 0 1
: Replaced #1 at index 2: [1,0,1,0,1]
false
@ints
and an integer, $n
which is less than or equal to
total elements in the given array.
$n
, and has the
maximum average. It should return the average.
Input: @ints = (1, 12, -5, -6, 50, 3), $n = 4
Output: 12.75
Subarray: (12, -5, -6, 50)
Average: (12 - 5 - 6 + 50) / 4 = 12.75
Example 2:
Input: @ints = (5), $n = 1
Output: 5
#! /usr/bin/env raku
unit sub MAIN (*@ints where @ints.elems > 0 && all(@ints) ~~ Int, # [1]
Int :$n where $n > 0 && $n <= @ints.elems, # [2]
:v(:$verbose));
my $max-avg = -Inf; # [3]
for 0 .. @ints.elems - $n -> $start # [4]
{
my $avg = @ints[$start .. $start + $n -1].sum / $n; # [5]
if $avg > $max-avg # [6]
{
$max-avg = $avg; # [7]
say ": New maximum average $max-avg at index $start to \
{ $start + $n -1 }" if $verbose;
}
elsif $verbose
{
say ": Not a new maximum average $max-avg at index $start to \
{ $start + $n -1 }";
}
}
say $max-avg; # [8]
[1] At least one element, all of which must be integers.
[2] A named integer argument, which must be in the range 1 .. number of elements in @ints.
[3] The maximum value, starting at -Inf
- the absolutely lowest
value possible.
[4] Iterate over the starting positions of the possible subarrays.
Note the -$n
so that the last one is long enough (has length
$c
.)
[5] Get the average of the subarray. Note the use of
sum
to add the entire subarray together.
See docs.raku.org/routine/sum for more information about sum
.
[6] Do we have a higher average than the previous one?
[7] Set the new average.
[8] Print the average value.
Running it:
$ ./maximum-average -n=4 1 12 -5 -6 50 3
12.75
$ ./maximum-average -n=1 5
5
Looking good.
With verbose mode:
$ ./maximum-average -n=4 -v 1 12 -5 -6 50 3
: New maximum average 0.5 at index 0 to 3
: New maximum average 12.75 at index 1 to 4
: Not a new maximum average 12.75 at index 2 to 5
12.75
$ ./maximum-average -n=1 -v 5
: New maximum average 5 at index 0 to 0
5
And that's it.