RabbitFarm
2025-07-06
A Good String Is Irreplaceable
The examples used here are from the weekly challenge problem statement and demonstrate the working solution.
Part 1: Replace all ?
You are given a string containing only lower case English letters and ?. Write a script to replace all ? in the given string so that the string doesn’t contain consecutive repeating characters.
The core of the solution is contained in a single subroutine. The resulting code can be contained in a single file.
The approach we take is to randomly select a new letter and test to make sure that it does not match the preceding or succeeding letter.
-
sub replace_all{
my($s) = @_;
my @s = split //, $s;
my @r = ();
{
my $c = shift @s;
my $before = pop @r;
my $after = shift @s;
my $replace;
if($c eq q/?/){
push @r, $before, $replace if $before;
push @r, $replace if
!$before;
}
else{
push @r, $before, $c if $before;
push @r, $c if
!$before;
}
unshift @s, $after if $after;
redo if $after;
}
return join q//, @r;
}
◇
Finding the replacement is done in a loop that repeatedly tries to find a relacement that does not match the preceding or following character. Since the number of potential conflicts is so small this will not (most likely require many iterations.
Just to make sure things work as expected we’ll define a few short tests.
-
MAIN:{
say replace_all q/a?z/;
say replace_all q/pe?k/;
say replace_all q/gra?te/;
}
◇
-
Fragment referenced in 1.
Sample Run
$ perl perl/ch-1.pl atz peck graqte
Part 2: Good String
You are given a string made up of lower and upper case English letters only. Write a script to return the good string of the given string. A string is called good string if it doesn’t have two adjacent same characters, one in upper case and other is lower case.
We’ll define a subroutine for detecting and returning non-good pairs of letters. We know we’re done when this subroutine returns undef.
We’ll call these pairs of letters bad pairs. To see if we have a matching pair we’ll just compare the ascii values.
-
sub bad_pair{
my($s) = @_;
my @s = split q//, $s;
return undef if
!@s;
{
my($x, $y) = (ord shift @s, ord shift @s);
if($x == $y + 32 || $x == $y - 32){
return chr($x) . chr($y);
}
unshift @s, chr($y);
redo unless @s == 1;
}
return undef;
}
◇
-
Fragment referenced in 5.
We use that bad_pair subroutine repeatedly in a loop until all bad pairs are removed.
-
sub make_good{
my($s) = @_;
{
my $bad_pair = bad_pair $s;
$s =~ s/$bad_pair// if $bad_pair;
redo if bad_pair $s;
}
return $s;
}
◇
-
Fragment referenced in 5.
The main section is just some basic tests.
-
MAIN:{
say make_good q/WeEeekly/;
say make_good q/abBAdD/;
say make_good q/abc/;
}
◇
-
Fragment referenced in 5.
Sample Run
$ perl perl/ch-2.pl Weekly abc
References
posted at: 17:39 by: Adam Russell | path: /perl | permanent link to this entry