This is my response to The Weekly Challenge #309.
@ints
, increasing
order.
Input: @ints = (2, 8, 10, 11, 15)
Output: 11
8 - 2 => 6
10 - 8 => 2
11 - 10 => 1
15 - 11 => 4
11 is where we found the min gap.
Example 2:
Input: @ints = (1, 5, 6, 7, 14)
Output: 6
5 - 1 => 4
6 - 5 => 1
7 - 6 => 1
14 - 7 => 7
6 and 7 where we found the min gap, so we pick the first instance.
Example 3:
Input: @ints = (8, 20, 25, 28)
Output: 28
8 - 20 => 14
25 - 20 => 5
28 - 25 => 3
28 is where we found the min gap.
#! /usr/bin/env raku
unit sub MAIN (*@ints where all(@ints) ~~ Int # [1]
&& ( [<] @ints ) # [1a]
&& @ints.elems > 1, # [1b]
:v(:$verbose));
my $left = @ints.shift; # [2]
my $min-gap = Inf; # [3]
my $at = Inf; # [4]
while (@ints.elems) # [5]
{
my $right = @ints.shift; # [6]
my $gap = $right - $left; # [7]
my $is-smallest = $gap < $min-gap; # [8]
$min-gap = $gap if $is-smallest; # [9]
$at = $right if $is-smallest; # [10]
say ": $right - $left => $gap { $is-smallest ?? "(smallest)" !! ""}"
if $verbose;
$left = $right; # [11]
}
say $at; # [12]
[1] An array of integers,
in ascending order [1a] (courtesy of the Reduction Metaoperator
[]
in combination with <
(a normal
«less than»)), and at least two elements [1b].
See
docs.raku.org/language/operators#Reduction_metaoperators for more
information about the Reduction Metaoperator []
.
[2] Get the first value, the left hand one in the upcoming comparisons.
[3] The minimum gap value, starting at the absolute maximum.
[4] The index of the minimum gap value.
[5] As long as we have unfinished business.
[6] Get the next value, the right hand one in the comparisons.
[7] Calculate the gap
[8] Do we have a smaller gap than already registred?
[9] If so, set the new minimum gap value
[10] - and the index.
[11] Prepare for the next iteration of the loop.
[12] Print the index.
Running it:
$ ./min-gap 2 8 10 11 15
11
$ ./min-gap 1 5 6 7 14
6
$ ./min-gap 8 20 25 28
28
Looking good.
With verbose mode:
$ ./min-gap -v 2 8 10 11 15
: 8 - 2 => 6 (smallest)
: 10 - 8 => 2 (smallest)
: 11 - 10 => 1 (smallest)
: 15 - 11 => 4
11
$ ./min-gap -v 1 5 6 7 14
: 5 - 1 => 4 (smallest)
: 6 - 5 => 1 (smallest)
: 7 - 6 => 1
: 14 - 7 => 7
6
$ ./min-gap -v 8 20 25 28
: 20 - 8 => 12 (smallest)
: 25 - 20 => 5 (smallest)
: 28 - 25 => 3 (smallest)
28
@ints
.
Input: @ints = (1, 5, 8, 9)
Output: 1
1, 5 => 5 - 1 => 4
1, 8 => 8 - 1 => 7
1, 9 => 9 - 1 => 8
5, 8 => 8 - 5 => 3
5, 9 => 9 - 5 => 4
8, 9 => 9 - 8 => 1
Example 2:
Input: @ints = (9, 4, 1, 7)
Output: 2
9, 4 => 9 - 4 => 5
9, 1 => 9 - 1 => 8
9, 7 => 9 - 7 => 2
4, 1 => 4 - 1 => 3
4, 7 => 7 - 4 => 3
1, 7 => 7 - 1 => 6
This program is very similar to «min-gap» from the first part.
File: min-diff
#! /usr/bin/env raku
unit sub MAIN (*@ints where all(@ints) ~~ UInt # [1]
&& @ints.elems > 1, # [1a]
:v(:$verbose));
my @sorted = @ints.sort; # [2]
my $left = @sorted.shift; # [3]
my $min-diff = Inf; # [4]
while (@sorted.elems) # [5]
{
my $right = @sorted.shift; # [6]
my $diff = $right - $left; # [7]
my $is-smallest = $diff < $min-diff; # [8]
$min-diff = $diff if $is-smallest; # [9]
say ": $right - $left => $diff { $is-smallest ?? "(smallest)" !! ""}"
if $verbose;
$left = $right; # [10]
}
say $min-diff; # [11]
[1] An array of unsigned integers (the UInt
type),
with at least 1 element.
See
docs.raku.org/type/UInt
for more information about the UInt
type.
[2] Sort the values, as the minimum difference between any given value will always be lowest when compared to the nearest value (value wise). When we sort them, those values will also be nearest index wise.
[3] Get the left hand value.
[4] The minimum difference.
[5] As long as we have unfinished business.
[6] Get the right hand value.
[7] Compute the difference.
[8] Do we have a new smallest difference?
[9] If so, update the difference.
[10] Preparfe for the next iteration.
[11] Print the value, the lowest difference.
Running it:
$ ./min-diff 1 5 8 9
1
$ ./min-diff 9 4 1 7
2
Looking good.
With verbose mode:
$ ./min-diff -v 1 5 8 9
: 5 - 1 => 4 (smallest)
: 8 - 5 => 3 (smallest)
: 9 - 8 => 1 (smallest)
1
$ ./min-diff -v 9 4 1 7
: 4 - 1 => 3 (smallest)
: 7 - 4 => 3
: 9 - 7 => 2 (smallest)
2
And that's it.