Peter
Peter Campbell Smith

Last digit sleeps

Weekly challenge 142 — 6 December 2021

Week 142 - 6 Dec 2021

Task 1

Task — Divisor last digit

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

Examples


Example 1:
Input: $m = 24, $n = 2
Output: 2
The divisors of 24 are 1, 2, 3, 4, 6, 8 and 12.
There are only 2 divisors having last digit 2 are 2 
   and 12.

Example 2:
Input: $m = 30, $n = 5
Output: 2
The divisors of 30 are 1, 2, 3, 5, 6, 10 and 15.
There are only 2 divisors having last digit 5 are 5 
   and 15.

Analysis

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 (1 .. $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 (1 .. 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.

Try it 

Try running the script with any input:



example: 45



example: 5

Script


#!/usr/bin/perl

# Peter Campbell Smith - 2021-12-08
# PWC 142 task 1

use v5.20;
use warnings;
use strict;

my ($test, @tests, $m, $n, $string1, $string2, $divisor, $dividend, $count, $s);

# inputs - pairs of $m and $n
@tests = ([24, 2], [30, 5], [24, 7], [37, 0], [45, 5], [1048575, 5], [1048576, 2]);

# loop over tests
for $test (@tests) {
    ($m, $n) = @$test;
    say qq[\nInput:  \$m = $m, \$n = $n];
    $count = 0;
    $string1 = $string2 = '';

    # loop over potential divisors
    for $divisor (1 .. $m) {
        $dividend = $m / $divisor;

        # if it is a divisor
        if ($dividend eq int($dividend)) {
            $string1 .= qq[$divisor, ];   # list of all divisors
            if ($divisor % 10 == $n) {
                $string2 .= qq[$divisor, ];   # list of divisors with last digit $n
                $count ++;
            }
        }
    }

    # tidy the ends of the strings
    for $s ($string1, $string2) {
        $s =~ s|, (\d+), $| and $1|;
    }
    
    # say the answers
    say qq[Output: $count];
    say qq[The divisors of $m are $string1];
    if ($string2) {
        say qq[There are only $count divisors with last digit $n: $string2];
    } else {
        say qq[There are no divisors with last digit $n];
    }

}

Output


Input:  $m = 24, $n = 2
Output: 2
The divisors of 24 are 1, 2, 3, 4, 6, 8, 12 and 24
There are only 2 divisors with last digit 2: 2 and 12

Input:  $m = 30, $n = 5
Output: 2
The divisors of 30 are 1, 2, 3, 5, 6, 10, 15 and 30
There are only 2 divisors with last digit 5: 5 and 15

Input:  $m = 24, $n = 7
Output: 0
The divisors of 24 are 1, 2, 3, 4, 6, 8, 12 and 24
There are no divisors with last digit 7

Input:  $m = 37, $n = 0
Output: 0
The divisors of 37 are 1 and 37
There are no divisors with last digit 0

Input:  $m = 45, $n = 5
Output: 3
The divisors of 45 are 1, 3, 5, 9, 15 and 45
There are only 3 divisors with last digit 5: 5, 15 and 45

Input:  $m = 1048575, $n = 5
Output: 32
The divisors of 1048575 are 1, 3, 5, 11, 15, 25, 31, 33, 
41, 55, 75, 93, 123, 155, 165, 205, 275, 341, 451, 465, 
615, 775, 825, 1023, 1025, 1271, 1353, 1705, 2255, 2325, 
3075, 3813, 5115, 6355, 6765, 8525, 11275, 13981, 19065, 
25575, 31775, 33825, 41943, 69905, 95325, 209715, 349525 
and 1048575
There are only 32 divisors with last digit 5: 5, 15, 25, 
55, 75, 155, 165, 205, 275, 465, 615, 775, 825, 1025, 
1705, 2255, 2325, 3075, 5115, 6355, 6765, 8525, 11275, 
19065, 25575, 31775, 33825, 69905, 95325, 209715, 349525 
and 1048575

Input:  $m = 1048576, $n = 2
Output: 5
The divisors of 1048576 are 1, 2, 4, 8, 16, 32, 64, 128, 
256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 
131072, 262144, 524288 and 1048576
There are only 5 divisors with last digit 2: 2, 32, 512, 
8192 and 131072