ETOOBUSY 🚀 minimal blogging for the impatient
PWC135 - Middle 3-digits
TL;DR
Here we are with TASK #1 from The Weekly Challenge #135. Enjoy!
The challenge
You are given an integer.
Write a script find out the middle 3-digits of the given integer, if possible otherwise throw sensible error.
Example 1
Input: $n = 1234567 Output: 345
Example 2
Input: $n = -123 Output: 123
Example 3
Input: $n = 1 Output: too short
Example 4
Input: $n = 10 Output: even number of digits
The questions
The specification is terse but also reasonably complete: the input specification is clear (an integer) and the expected correct output too (the three digits in the middle).
Examples help though:
- the sign has to be ignored;
- integers whose representation has an even number of digits have to be disregarded.
I honestly can’t think of other corner cases than those in the examples… so I guess it’s a fantastic TDD challenge!
The solution
There are some checks to be done, and we will do them the boring way, starting with Raku:
#!/usr/bin/env raku
use v6;
sub middle-three-digits (Int:D $x is copy) {
$x = -$x if $x < 0;
my $l = $x.chars;
die "too short\n" if $l < 3;
die "even number of digits\n" if $l %% 2;
$x.substr(($l - 3) / 2, 3);
}
put middle-three-digits((@*ARGS[0] || 1234567).Int);
Ignoring the sign means flipping it if the input is negative. Then, we consider the number of digits and do our checks.
If everything is OK, we take the middle digits. The length $l
is
decreased by 3 because:
- 1 takes into account that function
substr
deals with 0-based indexes - other 2 takes into account that we have to take 3 characters overall, so we want to move one character ahead (there’s a division by 2, so that 2 will become 1 after the division).
The same, in Perl:
#!/usr/bin/env perl
use v5.24;
use warnings;
use experimental 'signatures';
no warnings 'experimental::signatures';
sub middle_three_digits ($x) {
die "not an integer\n" unless $x =~ m{\A(?: 0 | -? [1-9]\d* )\z}mxs;
$x = -$x if $x < 0;
my $l = length $x;
die "too short\n" if $l < 3;
die "even number of digits\n" unless $l % 2;
return substr $x, ($l - 3) / 2, 3;
}
say middle_three_digits(shift // 1234567);
There is some additional check at the beginning to validate the input, but apart from this it’s a direct translation (in some cases, copy) of the Raku counterpart.
This is all, I guess!