Peter’s blog ✴ Week 336 ✴ 25 August 2025

THE WEEKLY CHALLENGE
Grouping and scoring

The Perl Camel

Task 1

Equal group

You are given an array of integers. Write a script to return true if the given array can be divided into one or more groups: each group must be of the same size as the others, with at least two members, and with all members having the same value.

From example 3 we can see that if several group sizes are possible, we are to return the largest.

Examples


Example 1
Input: @ints = (1,1,2,2,2,2)
Output: true
Groups: (1,1), (2,2), (2,2)

Example 2
Input: @ints = (1,1,1,2,2,2,3,3)
Output: false
Groups: (1,1,1), (2,2,2), (3,3)

Example 3
Input: @ints = (5,5,5,5,5,5,7,7,7,7,7,7)
Output: true
Groups: (5,5,5,5,5,5), (7,7,7,7,7,7)

Example 4
Input: @ints = (1,2,3,4)
Output: false

Example 5
Input: @ints = (8,8,9,9,10,10,11,11)
Output: true
Groups: (8,8), (9,9), (10,10), (11,11)

Analysis

I have solved this in a straightforward way:

  • Loop down over possible group sizes - ie integer submultiples of the array size, and
  • check to see if all the members of each group are identical.

And that's it.

Perl Weekly’s review

from PW issue 736

Solutions are more mathematically elegant, while they are more explicit about verifying the actual grouping conditions. Both approaches have merit depending on the specific requirements!

Try it 

Try running the script with any input:



example: 5, 5, 5, 9, 9, 9, 0, 0, 0

Script


#!/usr/bin/perl

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

use v5.26;    # The Weekly Challenge - 2025-08-25
use utf8;     # Week 336 - task 1 - Equal group
use warnings; # Peter Campbell Smith
binmode STDOUT, ':utf8';
use Encode;

equal_group(1, 1, 2, 2, 2, 2);
equal_group(1, 1, 1, 2, 2, 2, 3, 3);
equal_group(5, 5, 5, 5, 5, 5, 7, 7, 7, 7, 7, 7);
equal_group();
equal_group(42);
equal_group(77, 77);
equal_group(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1);

sub equal_group {
    
    my (@array, $result, $size, $groups, $group, $start, $member, $output);
    
    # initialise
    @array = @_;
    $result = 'false';
    
    # loop down over possible group sizes
    SIZE: for ($size = scalar @array; $size >= 2; $size --) {
        
        # check for integral number of groups
        $groups = scalar @array / $size;
        next SIZE unless $groups == int($groups);
        
        # check each group
        $output = '(';
        for $group (0 .. $groups - 1) {
            $start = $group * $size;
            
            # check each member
            for $member (0 .. $size - 1) {
                next SIZE unless $array[$start + $member] == $array[$start];
                $output .= qq[$array[$start + $member], ];
            }
            $output = substr($output, 0, -2) . '), (';
        }
        $result = qq[true - ] . substr($output, 0, -3);
        last;
    }
    
    say qq[\nInput:  (] . join(', ', @array) . ')';
    say qq[Output: $result];
}

18 lines of code

Output from script


Input:  (1, 1, 2, 2, 2, 2)
Output: true - (1, 1), (2, 2), (2, 2)

Input:  (1, 1, 1, 2, 2, 2, 3, 3)
Output: false

Input:  (5, 5, 5, 5, 5, 5, 7, 7, 7, 7, 7, 7)
Output: true - (5, 5, 5, 5, 5, 5), (7, 7, 7, 7, 7, 7)

Input:  ()
Output: false

Input:  (42)
Output: false

Input:  (77, 77)
Output: true - (77, 77)

Input:  (-1, -1, -1, -1, -1, -1, -1, -1, -1, -1)
Output: true - (-1, -1, -1, -1, -1, -1, -1, -1, -1, -1)

 

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