Peter
Peter Campbell Smith

Integggers and keys

Weekly challenge 282 — 12 August 2024

Week 282: 12 Aug 2024

Task 1

Task — 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 has exactly three consecutive matching digits.

Examples


Example 1
Input: $int = 12344456
Output: "444"

Example 2
Input: $int = 1233334
Output: -1

Example 3
Input: $int = 10020003
Output: "000"

Analysis

This is an interesting challenge.

Firstly, we need to be able to cope with the triplicated sequence at the beginning or end of the number as well as its being in the middle, so let's start by sandwiching the number with two non-digits: I used the ¦ character which is on the usual UK keyboard but doesn't mean anything special to Perl.

My first approach was to think that surely there's a one-line regular expression that will do this. It would be great if this worked:

$n = qq[¦$_[0]¦] =~ m|[^\1](\d)\1\1[^\1]|;

but sadly Perl can't cope with a \1 coming before the corresponding (\d).

I then tried

while (qq[¦$_[0]¦] =~ m|(.)(\d)\2\2[^\2]|g)
   next unless $1 ne $2

Strangely, that doesn't work either: the while gets into an infinite loop. I tried a number of variations on that, but all hit the same issue.

So I went for the rather less elegant solution of

while ($int =~ m|(.)(.)\2\2(.)|g) {
   next unless ($1 ne $2 and $2 ne $3);

which thankfully does work.

Try it 

Try running the script with any input:



example: 5677789

Script


#!/usr/bin/perl

# Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge

use v5.26;    # The Weekly Challenge - 2024-08-12
use utf8;     # Week 282 - task 1 - Good integer
use warnings; # Peter Campbell Smith
binmode STDOUT, ':utf8';

# good ones
good_integer('12333456');
good_integer('333456');
good_integer('456333');
good_integer('129934956799998999');

# bad ones
good_integer('123333456');
good_integer('3333456');
good_integer('123333');
good_integer('123345');

sub good_integer {
    
    my $int = $_[0];
    say qq[\nInput:  \$int = $int];
    
    # pad left and right with non-integer
    $int = qq[¦$int¦];
    
    # check for xyyyz pattern
    while ($int =~ m|(.)(.)\2\2(.)|g) {
        next unless ($1 ne $2 and $2 ne $3);
        
        # pattern found!
        say qq[Output: $2$2$2];
        return;
    }
    say qq[Output: -1];
}

Output


Input:  $int = 12333456
Output: 333

Input:  $int = 333456
Output: 333

Input:  $int = 456333
Output: 333

Input:  $int = 129934956799998999
Output: 999

Input:  $int = 123333456
Output: -1

Input:  $int = 3333456
Output: -1

Input:  $int = 123333
Output: -1

Input:  $int = 123345
Output: -1

 

Any content of this website which has been created by Peter Campbell Smith is in the public domain