Repeat and reverse
Weekly challenge 318 — 21 April 2025
Week 318: 21 Apr 2025
You are given a $string
of lowercase letters.
Write a script to find the position of all groups in the given string. Three or more consecutive letters form a group. Return '' if none found.
Example 1 Input: $str = 'abccccd' Output: 'cccc' Example 2 Input: $str = 'aaabcddddeefff' Output: 'aaa', 'dddd', 'fff' Example 3 Input: $str = 'abcdd' Output: ''
The trick in this challenge is to find a regular expression that will return both the character that forms the group and the length of the group. A little experimentation yielded this:
$string =~ m|(.)(\1\1+)|g
This says 'any character, followed by the same character, followed by the same character
one or more times'. The group is then returned in $1$2
. You need the two bracketed
patterns because the second one is defined using the result of the first.
I believe that doing it that way may mean that the regular expression engine has to be invoked repeatedly at run time, but I can't imagine the effect is substantial.
#!/usr/bin/perl # Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge use v5.26; # The Weekly Challenge - 2025-04-21 use utf8; # Week 318 - task 1 - Group position use warnings; # Peter Campbell Smith binmode STDOUT, ':utf8'; use Encode; group_position('abccccd'); group_position('aaabcddddeefff'); group_position('abcdd'); group_position('xxxooxoxoxoxooo'); group_position('iiwwiiwwiiwwii'); sub group_position { my ($string, $result); $string = shift; $result .= qq['$1$2', ] while $string =~ m|(.)(\1\1+)|g; say qq[\nInput: '$string']; say qq[Output: ] . ($result ? substr($result, 0, -2) : q['']); }
Input: 'abccccd' Output: 'cccc' Input: 'aaabcddddeefff' Output: 'aaa', 'dddd', 'fff' Input: 'abcdd' Output: '' Input: 'xxxooxoxoxoxooo' Output: 'xxx', 'ooo' Input: 'iiwwiiwwiiwwii' Output: ''
Any content of this website which has been created by Peter Campbell Smith is in the public domain