Peter’s blog ✴ Week 372 ✴ 4 May 2026

THE WEEKLY CHALLENGE
Strings of strings

The Perl Camel

Task 1

Rearrange spaces

You are given a string of words and spaces. Write a script to rearrange the spaces so that there is an equal number of spaces between every pair of adjacent words and that number is maximised. If you can’t distribute all the spaces, place the extra ones at the end of the string.

Examples


Example 1
Input: $str = '  challenge  '
Output: 'challenge    '
We have 4 spaces and 1 word. So all spaces go to the end.

Example 2
Input: $str = 'coding  is  fun'
Output: 'coding  is  fun'
We have 4 spaces and 3 words (2 gaps). So 2 spaces per gap.

Example 3
Input: $str = 'a b c  d'
Output: 'a b c d '
We have 4 spaces and 4 words (3 gaps). So 1 space per gap and 
   1 remainder.

Example 4
Input: $str = '  team      pwc  '
Output: 'team          pwc'
We have 10 spaces and 2 words (1 gap). So 10 spaces per gap.

Example 5
Input: $str = '   the  weekly  challenge  '
Output: 'the    weekly    challenge '
We have 9 spaces and 3 words (2 gaps). So 4 spaces per gap and
   1 remainder.

Analysis

Well, this should be easy. And it is quite easy, but there are several edge cases, such as no words, no spaces, a single word, an empty string.

My algorithm:

  • Collect the words and count the spaces
  • Find the largest number of spaces available to go between each pair of words
  • ... and the number of extra spaces
  • Build the output

And I think that covers all the possibilities.

Perl Weekly’s review

from PW issue 772

Peter has given two stylish implementations of the weekly challenge using Perl's native string functions to produce very compact code. For Rearrange Spaces he worked out precisely what gaps were needed to recreate the string using join, and for the Largest Substring solution he had one loop with a hash to keep track of where each character was seen first so that the answer was determined with one cycle through the original string.

Try it 

Try running the script with any input:



example: the cat  sat  on   the   mat

Script


#!/usr/bin/perl

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

use v5.26;    # The Weekly Challenge - 2026-05-04
use utf8;     # Week 372 - task 1 - Rearrange spaces
use warnings; # Peter Campbell Smith
binmode STDOUT, ':utf8';
use Encode;

rearrange_spaces('aa bb cc bb ee      ');
rearrange_spaces('aa bb cc bb ee        ');
rearrange_spaces('  aa bb cc bb ee  ');
rearrange_spaces('abcde');
rearrange_spaces('abcde     ');
rearrange_spaces('     abcde');
rearrange_spaces('     ');
rearrange_spaces('');
rearrange_spaces('one two three four      ');

sub rearrange_spaces {
    
    my ($string, $rest, @words, $spaces, $fill, $extra, $word, $output);
    
    # initialise
    $string = $rest = $_[0];
    $spaces = 0;
    
    # collect words and count spaces
    while ($rest) {
        if ($rest =~ m|(^[^\s]+)(.*)|) {
            push @words, $1;
        } elsif ($rest =~ m|^(\s+)(.*)|) {
            $spaces += length $1;
        }
        $rest = $2;
    }
    
    # calculate inter-word spaces
    $fill = @words > 1 ? int($spaces / (@words - 1)) : 0;
    $extra = $spaces - $fill * (@words - 1);
    
    # build the output
    for $word (@words) {
        $output .= $word . (' ' x $fill);
    }
    $output = substr($output, 0, -$fill) if @words > 1;
    $output .= ' ' x $extra;
    
    # report
    say qq[\nInput:  '$string'];
    say qq[Output: '$output'];
}

18 lines of code

Output from script


Input:  'aa bb cc bb ee      '
Output: 'aa  bb  cc  bb  ee  '

Input:  'aa bb cc bb ee        '
Output: 'aa   bb   cc   bb   ee'

Input:  '  aa bb cc bb ee  '
Output: 'aa  bb  cc  bb  ee'

Input:  'abcde'
Output: 'abcde'

Input:  'abcde     '
Output: 'abcde     '

Input:  '     abcde'
Output: 'abcde     '

Input:  '     '
Output: '     '

Input:  ''
Output: ''

Input:  'one two three four      '
Output: 'one   two   three   four'

 

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