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.

Leave a comment

About laurent_r

user-pic I am the author of the "Think Perl 6" book (O'Reilly, 2017) and I blog about the Perl 5 and Raku programming languages.