Perl Weekly Challenge 282: Good Integer

These are some answers to the Week 281, Task 1, of the Perl Weekly Challenge organized by Mohammad S. Anwar.

Spoiler Alert: This weekly challenge deadline is due in a few days from now (on August 18, 2024, at 23:59). This blog post provides some solutions to this challenge. Please don’t read on if you intend to complete the challenge on your own.

Task 1: Good Integer

You are given a positive integer, \$int, having 3 or more digits.

Write a script to return the Good Integer in the given integer or -1 if none found.

A good integer is exactly three consecutive matching digits.

Example 1

Input: \$int = 12344456
Output: "444"

Example 2

Input: \$int = 1233334
Output: -1

Example 3

Input: \$int = 10020003
Output: "000"

Good Integer in Raku

I first tried with a single regex using lookaround assertions such as <!before \$0> and <!after \$O> to prevent matches when there is a sequence of more than 3 identical digits, but it appears that it is not possible to combine lookaround assertions with a previous captured match special variable (\$0 or \$/[0]), or, at least, that I did not find the proper syntax (but it seems to me that there are some good reasons for this not to be possible).

So I decided to simply use two successive regexes, one to exclude the cases with 4 (or more) identical digits, and the second one to match three identical digits.

sub good-integer (\$in) {
return -1 if \$in ~~ / (\d) \$0 ** 3 /;    # 4 digits
return  ~\$/ if \$in ~~ / (\d) \$0 ** 2 /;  # 3 digits
return -1;
}

my @tests = 12344456, 123444456, 1233334, 10020003;
for @tests -> \$test {
printf "%-10s => ", \$test;
say good-integer \$test;
}

This program displays the following output:

\$ raku ./good-integer.raku
12344456   => 444
123444456  => -1
1233334    => -1
10020003   => 000

Good Integer in Perl

I suspect that Perl's look-ahead and look-behind assertions will have the same behavior as Raku's lookaround assertions. So, I used the same strategy as in Raku, and this is actually a port to Perl of the previous Raku program.

use strict;
use warnings;
use feature 'say';

sub good_integer {
my \$in = shift;
return -1 if \$in =~ /(\d)\1{3}/;
return  \$1 x 3 if \$in =~ /(\d)\1{2}/;
return -1;
}

my @tests = (12344456, 123444456, 1233334, 10020003);
for my \$test (@tests) {
printf "%-10s => ", \$test;
say good_integer \$test;
}

This program displays the following output:

\$ perl ./good-integer.pl
12344456   => 444
123444456  => -1
1233334    => -1
10020003   => 000

Wrapping up

The next week Perl Weekly Challenge will start soon. If you want to participate in this challenge, please check https://perlweeklychallenge.org/ and make sure you answer the challenge before 23:59 BST (British summer time) on August 25, 2024. And, please, also spread the word about the Perl Weekly Challenge if you can.