Peter’s blog ✴ Week 134 ✴ 11 October 2021

THE WEEKLY CHALLENGE
Pandigitals and term counts

The Perl Camel

Task 2

Distinct terms count

You are given 2 positive numbers, $m and $n. Write a script to generate multiplcation table and display count of distinct terms.

Examples


Example 1
Input: $m = 3, $n = 3
Output:
      x | 1 2 3
      --+------
      1 | 1 2 3
      2 | 2 4 6
      3 | 3 6 9
Distinct Terms: 1, 2, 3, 4, 6, 9
Count: 6

Example 2
Input: $m = 3, $n = 5
Output:
      x | 1  2  3  4  5
      --+--------------
      1 | 1  2  3  4  5
      2 | 2  4  6  8 10
      3 | 3  6  9 12 15
Distinct Terms: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15
Count: 11

Analysis

The hardest part of this challenge is formatting the output.

With that conquered, 2 nested loops generate the multiplication table, and each entry is saved as $terms[$j * $k], thus ensuring that duplicated entries are merged.

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: 5



example: 6

Script


#!/usr/bin/perl

# Peter Campbell Smith - 2021-10-13
# PWC 134 task 2

use v5.20;
use warnings;
use strict;

my ($m, $n, $col_width, $j, $k, $term, @terms, $line, $count, @tests, $test);

# get params
@tests = ([2, 3], [5, 6], [15, 12]);

# loop over tests
for $test (@tests) {
    ($m, $n) = @$test;
    @terms = ();
    $line = '';
    print qq[\nInput: \$m = $m, \$n = $n\nOutput:\n\n];

    # calculate column width = width of largest term + 1
    $col_width = int(log($m * $n)/log(10)) + 1;

    # print top row and underline
    print sprintf(" %${col_width}s", 'x') . ' |';
    for $j (1 .. $n) {
        print sprintf(" %${col_width}d", $j);
    }
    print qq[\n];
    print '-' x ($col_width + 2) . '+' . '-' x (($col_width + 1) * $n) . "\n";

    # print other rows
    for $j (1 .. $m) {
        print sprintf(" %${col_width}d", $j) . ' |';
        for $k (1 .. $n) {
            $term = $j * $k;
            print sprintf(" %${col_width}d", $term);
            $terms[$term] = 1;
        }
        print qq[\n];
    }

    # print unique terms nicely
    for $j (0 .. @terms - 1) {
        $line .= ($j + 0) . ', ' if $terms[$j];
    }
    say '';
    multiline(qq[Distinct terms: ], substr($line, 0, -2), 57, ',', 3);
}

sub multiline {
    
    my ($prefix, $text, $width, $separator, $margin, $this_line, $intro);
    
    ($prefix, $text, $width, $separator, $margin) = @_;
    
    # split long string over lines max width $width
    $intro = $prefix;
    while (length($intro) + length($text) > $width) {
        $this_line = substr($text, 0, $width - length($intro));
        $this_line =~ m|(.*$separator)|;
        say $intro . $1;        
        $text = substr($text, length($1), 99999);
        $intro = ' ' x $margin;
        $text =~ s|^\s*||;
    }
    say $intro . $text if $text !~ m|^\s*$|;
    return;
}

13 lines of code

Output from script


Input: $m = 2, $n = 3
Output:

 x | 1 2 3
---+------
 1 | 1 2 3
 2 | 2 4 6

Distinct terms: 1, 2, 3, 4, 6

Input: $m = 5, $n = 6
Output:

  x |  1  2  3  4  5  6
----+------------------
  1 |  1  2  3  4  5  6
  2 |  2  4  6  8 10 12
  3 |  3  6  9 12 15 18
  4 |  4  8 12 16 20 24
  5 |  5 10 15 20 25 30

Distinct terms: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16,
   18, 20, 24, 25, 30

Input: $m = 15, $n = 12
Output:

   x |   1   2   3   4   5   6   7   8   9  10  11  12
-----+------------------------------------------------
   1 |   1   2   3   4   5   6   7   8   9  10  11  12
   2 |   2   4   6   8  10  12  14  16  18  20  22  24
   3 |   3   6   9  12  15  18  21  24  27  30  33  36
   4 |   4   8  12  16  20  24  28  32  36  40  44  48
   5 |   5  10  15  20  25  30  35  40  45  50  55  60
   6 |   6  12  18  24  30  36  42  48  54  60  66  72
   7 |   7  14  21  28  35  42  49  56  63  70  77  84
   8 |   8  16  24  32  40  48  56  64  72  80  88  96
   9 |   9  18  27  36  45  54  63  72  81  90  99 108
  10 |  10  20  30  40  50  60  70  80  90 100 110 120
  11 |  11  22  33  44  55  66  77  88  99 110 121 132
  12 |  12  24  36  48  60  72  84  96 108 120 132 144
  13 |  13  26  39  52  65  78  91 104 117 130 143 156
  14 |  14  28  42  56  70  84  98 112 126 140 154 168
  15 |  15  30  45  60  75  90 105 120 135 150 165 180

Distinct terms: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
   13, 14, 15, 16, 18, 20, 21, 22, 24, 25, 26, 27, 28,
   30, 32, 33, 35, 36, 39, 40, 42, 44, 45, 48, 49, 50,
   52, 54, 55, 56, 60, 63, 64, 65, 66, 70, 72, 75, 77,
   78, 80, 81, 84, 88, 90, 91, 96, 98, 99, 100, 104, 105,
   108, 110, 112, 117, 120, 121, 126, 130, 132, 135, 140,
   143, 144, 150, 154, 156, 165, 168, 180

 

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