TL;DR

Here we are with TASK #1 from the Perl Weekly Challenge #091. Enjoy!

# The challenge

You are given a positive number $N. Write a script to count number and display as you read it. # The questions Well wellâ€¦ here I guess my question is whether we really want to consider the input a number, as opposed to a string. I mean, weâ€™re handling it as a string, right? Why constraint it to be a number, with all limitations in terms of integer representation? I guess we can trust our inputs, otherwise the usual care should be taken - e.g. consider something that is not a number, negative stuff, empty string, â€¦ # The solution Letâ€™s start from something that didnâ€™t work, then move onâ€¦ ## The epic fail! My first instinct here was to be clever. How I would love to be clever! Alas, this always seems to be deferred to some distant future. I wanted to do something like this: join '', map { ... } clever_regex_to_capture_sequences($N);


So I thoughtâ€¦ surely something using \1 will help me?

join '', map { ... } ($N =~ m{.\1*}gmxs);  Ehrâ€¦ thereâ€™s no capture there! What is \1 referring to?!? OK, letâ€™s put it: join '', map { ... } ($N =~ m{(.)\1*}gmxs);


AHEM now weâ€™re only capturing the first character in each sequenceâ€¦ we have to take them all:

join '', map { ... } ($N =~ m{((.)\1*)}gmxs);  BUTâ€¦ BUTâ€¦ now the initial character is captured within the second set of round parentheses! Oh myâ€¦ join '', map { ... } ($N =~ m{((.)\2*)}gmxs);


I think itâ€™s better to stop here because now weâ€™re capturing two things and the map is going to have a hard timeâ€¦

## Insisting on regular expression

Now I was in full regex mode, and so I moved on with this:

sub count_number ($N) { my$retval = '';
while (length $N) { my ($sequence, $char) =$N =~ m{((.)\2*)}mxs;
my $n = length$sequence;
$retval .=$n . $char; substr$N, 0, $n, ''; } return$retval;
}


I capture the sequence and the character, count the length of the sequence, add it to the result, then chop it from the start of the string. Oh yes sureâ€¦ the number, the number.

## Maybe itâ€™s a cannon for a mosquito?

I donâ€™t know, the solution with the regular expression was not that compact after all, so I figuredâ€¦ maybe something more readable, although low level?

sub count_number_2 ($N) { my$len = length $N; my ($retval, $previous,$count) = ('', '', 0);
for my $i (0 ..$len) {
my $c =$i < $len ? substr($N, $i, 1) : ''; if ($c eq $previous) { ++$count }
else {
$retval .=$count . $previous if$count;
($previous,$count) = ($c, 1); } } return$retval;
}


This iterates over indices to get one char at a time. Plus one past-the-end character, to make sure the last sequence is properly handled too. Apart from this, itâ€™s just plain old boring counting of sequences, adding something to the \$retval when it makes sense.

# Conclusion

Wellâ€¦ it seems Iâ€™ll have to wait for the next time to try again and feel clever.

Until thenâ€¦ please folks stay safe!

Comments? Octodon, , GitHub, Reddit, or drop me a line!