ETOOBUSY 🚀 minimal blogging for the impatient
PWC200 - Arithmetic Slices
TL;DR
Here we are with TASK #1 from The Weekly Challenge #200. Enjoy!
The challenge
You are given an array of integers.
Write a script to find out all
Arithmetic Slices
for the given array of integers.An integer array is called arithmetic if it has at least 3 elements and the differences between any three consecutive elements are the same.
Example 1
Input: @array = (1,2,3,4) Output: (1,2,3), (2,3,4), (1,2,3,4)
Example 2
Input: @array = (2) Output: () as no slice found.
The questions
How does it feel to have arrived to 200 weeks?!? Congratulations manwar, you made it!!!
The solution
Each new item in a sequence triggers the generation of a group of elements with all previous elements… So Raku first:
#!/usr/bin/env raku
use v6;
sub MAIN (*@a) {
put arithmetic-slices(@a ?? @a !! <1 2 3 4>)
.map({ '(' ~ .join(',') ~ ')' }).join(', ');
}
sub arithmetic-slices (@array) {
return if @array < 3;
my $current-rate = @array[1] - @array[0]; # this keeps the growth rate
my $run-length = 1; # this tracks whether we're emitting
return [
gather for 2 ..^ @array -> $i {
my $delta = @array[$i] - @array[$i - 1];
if $current-rate == $delta {
++$run-length;
take [ @array[($i - $_) .. $i].Slip ] for 2 .. $run-length;
}
else {
$current-rate = $delta;
$run-length = 1;
}
}
];
}
Perl’s version is pretty much the same:
#!/usr/bin/env perl
use v5.24;
use warnings;
use experimental 'signatures';
no warnings 'experimental::signatures';
say join ', ', map { '(' . join(',', $_->@*) . ')' }
arithmetic_slices(@ARGV ? @ARGV : qw< 1 2 3 4 >);
sub arithmetic_slices (@array) {
return if @array < 3;
my @retval;
my $current_rate = $array[1] - $array[0];
my $run_length = 1;
for my $i (2 .. $#array) {
my $delta = $array[$i] - $array[$i - 1];
if ($current_rate == $delta) {
++$run_length;
push @retval, [ @array[($i - $_) .. $i] ] for 2 .. $run_length;
}
else {
$current_rate = $delta;
$run_length = 1;
}
}
return @retval;
}
Cheers!