Questions are good
Weekly challenge 328 — 30 June 2025
Week 328: 30 Jun 2025
You are given a string containing only lower case English letters and '?'s. Write a script to replace every '?' in the given string so that the string doesn’t contain consecutive repeating characters.
Example 1 Input: $str = 'a?z' Output: 'abz' There can be many strings, one of them is 'abz'. The choices are 'a' to 'z' but we can't use either 'a' or 'z' to replace the '?'. Example 2 Input: $str = 'pe?k' Output: 'peak' Example 3 Input: $str = 'gra?te' Output: 'grabte'
Let's look for all the '?' characters, noting what character comes immediately
before and after them - call those $a
and $b
. To avoid creating a doubled
letter we have to substitute a new letter in place of the '?', and in every case
we can use 'a', 'b' or 'c'. Specifically, we can use 'a' if neither of the surrounding
letters is 'a', or use 'b' if neither is 'b', or in the cases where one is 'a' and the other is
'b' we can insert 'c'.
To do that with a regular expression we have a slight problem if the string starts or ends with a '?', and to get round that I added a non-letter ('*') to the start and end of the string before searching it for '?'s and then stripped them off the resulting string.
Note that the challenge is silent as to what happens if the input string already contains doubled letter, such as 'abbc?d', and my algorithm will leave them unchanged.
#!/usr/bin/perl # Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge use v5.26; # The Weekly Challenge - 2025-06-30 use utf8; # Week 328 - task 1 - Replace all ? use warnings; # Peter Campbell Smith binmode STDOUT, ':utf8'; use Encode; replace_all_queries('abc?def?ghi'); replace_all_queries('?a?a?a?a?a?a?a?'); replace_all_queries('a?????b'); replace_all_queries('?????'); replace_all_queries('?br?c?d?br?'); replace_all_queries('a??????b'); replace_all_queries('a?b?a?b?c?a'); sub replace_all_queries { my ($string, $z); # initialise - add '*' to start and end $string = qq[*$_[0]*]; # loop while string contains a '?' while ($string =~ m|^(.*?)(.)\?(.?)(.*)|) { # replace ? with a, b or c for $z ('a', 'b', 'c') { if ($z ne $2 and $z ne $3) { $string = qq[$1$2$z$3$4]; last; } } } say qq[\nInput: $_[0]]; say qq[Output: ] . substr($string, 1, -1); }
Input: abc?def?ghi Output: abcadefaghi Input: ?a?a?a?a?a?a?a? Output: bababababababab Input: a?????b Output: ababacb Input: ????? Output: ababa Input: ?br?c?d?br? Output: abracadabra Input: a??????b Output: abababab Input: a?b?a?b?c?a Output: acbcacbacba
Any content of this website which has been created by Peter Campbell Smith is in the public domain