Peter’s blog ✴ Week 275 ✴ 24 June 2024

THE WEEKLY CHALLENGE
Broken digits

The Perl Camel

Task 2

Replace digits

You are given an alphanumeric string, $str, where each character is either a letter or a digit. Write a script to replace each digit in the given string with the value of the previous letter plus (digit) places.

Examples


Example 1
Input: $str = 'a1c1e1'
Output: 'abcdef'
shift('a', 1) => 'b'
shift('c', 1) => 'd'
shift('e', 1) => 'f'

Example 2
Input: $str = 'a1b2c3d4'
Output: 'abbdcfdh'
shift('a', 1) => 'b'
shift('b', 2) => 'd'
shift('c', 3) => 'f'
shift('d', 4) => 'h'

Example 3
Input: $str = 'b2b'
Output: 'bdb'

Example 4
Input: $str = 'a16z'
Output: 'abgz'

Analysis

For this one I decided to forgo the concise 1- or 2-line answer in favour of something more readable. I simply loop over the characters in $str and do what the task says - output the chracater if alphabetic and output the previous character shifted that number of places along the alphabet if it's numeric.

There are a few unspecified cases:

  • First character is numeric (2abc)
  • Two consecutive numbers (ab34cd)
  • Shifted character goes beyond z (xy9)

In production code I would of course check for those, but I didn't in my submission.

Perl Weekly’s review

from PW issue 675

DIY tool with detailed task analysis is bonus. You are going to love it, I am confident.

This review may cover either or both challenges for this week.

I am sorry that the 'Try it' feature is currently working very slowly or not at all owing to some issue with my web hosting provider.

Try it 

Try running the script with any input:



example: exc2l0en6

Script


#!/usr/bin/perl

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

use v5.26;    # The Weekly Challenge - 2024-06-24
use utf8;     # Week 275 - task 2 - Replace digits
use warnings; # Peter Campbell Smith
binmode STDOUT, ':utf8';

replace_digits('a9c9e9');
replace_digits('a1b2c3d4');
replace_digits('a2c6d1n6');

sub replace_digits {
    
    my ($j, $char, $str, $result, $prev);
    
    $str = shift;
    
    # loop over characters in $str
    for $j (0 .. length($str)) {
        $char = substr($str, $j, 1);
        
        # if it's a digit do the magic
        if ($j > 0 and $char =~ m|([0-9])|) {
            $result .= chr(ord($prev) + $char);
            
        # else don't
        } else {
            $result .= $char;
        }
        $prev = $char;
    }
    
    printf(qq[\nInput:  \@str = '%s'\n], $str);
    printf(qq[Output: '%s'\n], $result);
}

12 lines of code

Output from script


Input:  @str = ('a9c9e9')
Output: 'ajclen'

Input:  @str = ('a1b2c3d4')
Output: 'abbdcfdh'

Input:  @str = ('a2c6d1n6')
Output: 'accident'

 

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