08 December 2021

Clarity versus brevity

PWC 142 task 1: You are given positive integers, $m and $n. Write a script to find total count of divisors of $m having last digit $n.

Tasks such as this always raise a dilemma.  Do I write something ingenious and compact, or should I write code which someone else (or me in 10 years) can easily understand.

My submission falls in the second category. I simply loop $j from 1 to $m, checking whether $m / $j is an integer, in which case $j is a divisor. I add that to my list of divisors, and if it ends in $n, to my list of divisors ending in $n.

This is - in once sense - quite inefficient, because once $j exceeds $m/2 the only remaining divisor is $m itself so I've wasted more-or-less half my time.

I could get round that by looping $j from 1 to int($m/2), and every time I found a divisor $d I could add $d and $m/$d to my list of divisors. But then I would have to sort the list, or possibly make two lists, reverse one of them and concatenate, remembering that if $m is even, $m/2 will be in my list twice.

Even faster would be to check only for prime divisors, and then there would be quite a limited set of combinations of those which would need to be tested for last-digit matching.

So I went with the simple version, and even my little Raspberry Pi easily deals with, for example, 1048575 in a couple of seconds.

No doubt someone - probably many people - will have come up with a more elegant solution, and of course if my solution had been very slow I would have done that too.

One of the failings of Perl code which is often mentioned is its maintainability.  I've been at both ends of that - writing code which I know will need to be maintained to meet changing business needs long after I'm gone, and being tasked with maintaining code that some long-gone person wrote.

I know which approach I prefer.


PWC 142 task 2: Write a script to implement SleepSort.

This is of course a bit of a joke, but you can do it in Perl, of course.  I found that delaying $n seconds worked, but much less, for example $n/10 seconds did not: the Linux scheduler clearly doesn't use a fifo queue.

There is a slightly less jokey way of sorting in Perl without actually sorting:

@list = (1, 9, 76, 3, 99, 4, 22);

for $j  (@list) {
$sorted[$j] = 1;
$max = $j if $j > $max;
}

for $j  (0 .. $max) {
say qq[$j] if $sorted[$j];
}



No comments:

Post a Comment