Something which is divisible by 5 and 3 is divisible by 15, so your logic is more straight forward as...
- Divisible by 15
- Divisible by 5
- Divisible by 3
- Not divisible by 5 nor 3
I'd also take advantage of say
.
I'd also replace the awkward until
with a for
and not bother with $i.
Avoid using $a and $b because these are special variables used by sort
.
Turn on strict and warnings.
Strip the newline off $a. Technically not necessary if you're going to use it as a number, but if you don't printing it will have an extra newline.
A non-number %
anything is 0. Unless we validate the input, if you input nothing or "bananas" you'll get SPOKOKOKO
. We can check if the input looks like something Perl considers a number with Scalar::Util::looks_like_number. If it isn't a number, throw an exception; it isn't the function's job to figure out what to do with a non-number. Perl doesn't really have exceptions, but we can get close with a die
and eval
.
And put the logic inside a subroutine. This separates the details of the input and output from the logic. The logic can now be named, documented, tested, and reused. This also avoids the redundant say
.
use strict;
use warnings;
use Scalar::Util qw(looks_like_number);
use v5.10;
sub whatever_this_is_doing {
my $num = shift;
# Validate input early to keep the rest of the logic simple.
if( !looks_like_number($num) ) {
die "'$num' is not a number";
}
if($num % 15 == 0) {
"SPOKOKOKO";
}
elsif($num % 5 == 0) {
"SPOKO";
}
elsif($num % 3 == 0) {
"KOKO";
}
else {
$num; # Note there's no need to quote a single variable.
}
}
for(1..99) {
my $num = <>;
chomp($num);
eval {
say whatever_this_is_doing($num);
} or say "'$num' is not a number.";
}
I'm sure there's some very clever math thing one can do to reduce the number of calls to %
, but %
is extremely unlikely to be a bottleneck, especially in Perl, so I'd leave it there.