Multiplication tables

From Rosetta Code
Revision as of 06:31, 6 December 2009 by rosettacode>Paddy3118 (→‎{{header|Python}}: Comment on Python version and limits to size variable.)
Task
Multiplication tables
You are encouraged to solve this task according to the task description, using any language you may know.

Produce a formatted 12×12 multiplication table of the kind memorised by rote when in primary school.

Only print the top half triangle of products.

ALGOL 68

Works with: ALGOL 68 version Standard - no extensions to language used
Works with: ALGOL 68G version Any - tested with release 1.18.0-9h.tiny

<lang Algol68>main:(

 INT max = 12;
 INT width = ENTIER(log(max)*2)+1;
 STRING empty = " "*width, sep="|", hr = "+" + (max+1)*(width*"-"+"+");
 FORMAT ifmt = $g(-width)"|"$; # remove leading zeros #
 printf(($gl$, hr));
 print(sep + IF width<2 THEN "x" ELSE " "*(width-2)+"x " FI + sep);
 FOR col TO max DO printf((ifmt, col)) OD;
 printf(($lgl$, hr));
 FOR row TO max DO
   [row:max]INT product;
   FOR col FROM row TO max DO product[col]:=row*col OD;
   STRING prefix=(empty+sep)*(row-1);
   printf(($g$, sep, ifmt, row, $g$, prefix, ifmt, product, $l$))
 OD;
 printf(($gl$, hr))

)</lang> 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|   |  4|  6|  8| 10| 12| 14| 16| 18| 20| 22| 24|
|  3|   |   |  9| 12| 15| 18| 21| 24| 27| 30| 33| 36|
|  4|   |   |   | 16| 20| 24| 28| 32| 36| 40| 44| 48|
|  5|   |   |   |   | 25| 30| 35| 40| 45| 50| 55| 60|
|  6|   |   |   |   |   | 36| 42| 48| 54| 60| 66| 72|
|  7|   |   |   |   |   |   | 49| 56| 63| 70| 77| 84|
|  8|   |   |   |   |   |   |   | 64| 72| 80| 88| 96|
|  9|   |   |   |   |   |   |   |   | 81| 90| 99|108|
| 10|   |   |   |   |   |   |   |   |   |100|110|120|
| 11|   |   |   |   |   |   |   |   |   |   |121|132|
| 12|   |   |   |   |   |   |   |   |   |   |   |144|
+---+---+---+---+---+---+---+---+---+---+---+---+---+

C

<lang c>#include <math.h>

  1. include <stdio.h>

int main(int argc, char *argv[]) {

   int max = 12;
   char format[8];
   char format2[8];
   int	dgts;
   int i,j;
   dgts = (int)(.99+ log(1.0*max*max)/log(10.0));
   sprintf(format," %%%dd", dgts);
   sprintf(format2,"%%%ds%%c", dgts);
   printf(format2,"",'x');
   for (i=1; i<=max; i++) printf(format,i);
   printf("\n\n");
   for (j=1; j<=max; j++) {
       printf(format,j);
       for(i=1; i<j; i++) printf(format2,"",' ');
       for(i=j; i<=max; i++) printf(format, i*j);
       printf("\n");
   }
   printf("\n");
   return 0;

}</lang> 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       4   6   8  10  12  14  16  18  20  22  24
   3           9  12  15  18  21  24  27  30  33  36
   4              16  20  24  28  32  36  40  44  48
   5                  25  30  35  40  45  50  55  60
   6                      36  42  48  54  60  66  72
   7                          49  56  63  70  77  84
   8                              64  72  80  88  96
   9                                  81  90  99 108
  10                                     100 110 120
  11                                         121 132
  12                                             144

C++

This is a slightly more-generalized version that takes any minimum and maximum table value, and formats the table columns.

<lang cpp>#include <iostream>

  1. include <iomanip>
  2. include <cmath>
  1. define MAX(a, b) (a > b ? a : b)
  2. define ABS(x) (x > 0 ? x : (0 - x) )

size_t get_table_column_width(const int min, const int max) {

   unsigned int abs_max = 0;
   abs_max = MAX(abs_max, ABS(max*max));
   abs_max = MAX(abs_max, ABS(max*min));
   abs_max = MAX(abs_max, ABS(min*min));
   // abs_max is the largest absolute value we might see.
   // If we take the log10 and add one, we get the string width
   // of the largest possible absolute value.
   // Add one for a little whitespace guarantee.
   size_t colwidth = (1 + log10(abs_max)) + 1;
   bool has_negative_result = false;
   // If both are less than 0, then all results will be positive
   if(!(min < 0) && (max < 0))
   {
       // If only one of them is less than 0, then some will
       // be negative.
       if((min < 0) || (max < 0 ))
           has_negative_result = true;
   }
   // If some values may be negative, then we need to add some space
   // for a sign indicator (-)
   if(has_negative_result)
       colwidth += 1;
   return colwidth;

}

void print_table_header(const int min, const int max) {

   size_t colwidth = get_table_column_width(min, max);
   // table corner
   std::cout << std::setw(colwidth) << " ";
   
   for(int col = min; col <= max; ++col)
   {
       std::cout << std::setw(colwidth) << col;
   }
   // End header with a newline and blank line.
   std::cout << std::endl << std::endl;

}

void print_table_row(const int num, const int min, const int max) {

   size_t colwidth = get_table_column_width(min, max);
   // Header column
   std::cout << std::setw(colwidth) << num;
   // Spacing to ensure only the top half is printed
   for(int multiplicand = min; multiplicand < num; ++multiplicand)
   {
       std::cout << std::setw(colwidth) << " ";
   }
   // Remaining multiplicands for the row.
   for(int multiplicand = num; multiplicand <= max; ++multiplicand)
   {
       std::cout << std::setw(colwidth) << num * multiplicand;
   }
   // End row with a newline and blank line.
   std::cout << std::endl << std::endl;

}

void print_table(const int min, const int max) {

   // Header row
   print_table_header(min, max);
   // Table body
   for(int row = min; row <= max; ++row)
   {
       print_table_row(row, min, max);
   }

}

int main() {

   print_table(1, 12);
   return 0;

} </lang>

Output:

       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       4   6   8  10  12  14  16  18  20  22  24

   3           9  12  15  18  21  24  27  30  33  36

   4              16  20  24  28  32  36  40  44  48

   5                  25  30  35  40  45  50  55  60

   6                      36  42  48  54  60  66  72

   7                          49  56  63  70  77  84

   8                              64  72  80  88  96

   9                                  81  90  99 108

  10                                     100 110 120

  11                                         121 132

  12                                             144

Haskell

<lang haskell>import Control.Monad import Text.Printf

main = do

   putStrLn $ "   x" ++ concatMap fmt [1..12]
   zipWithM_ f [1..12] $ iterate ("    " ++) ""
 where f n s = putStrLn $ fmt n ++ s ++ concatMap (fmt . (*n)) [n..12]
       fmt n = printf "%4d" (n :: Int)</lang>

Python

<lang python>>>> size = 12 >>> for row in range(-1,size+1): if row==0: print("─"*3 + "┼"+"─"*(4*size-1)) else: print("".join("%3s%1s" % (("x","│") if row==-1 and col==0 else (row,"│") if row>0 and col==0 else (col,"") if row==-1 else ("","") if row>col else (row*col,"")) for col in range(size+1)))


 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│      4   6   8  10  12  14  16  18  20  22  24 
 3│          9  12  15  18  21  24  27  30  33  36 
 4│             16  20  24  28  32  36  40  44  48 
 5│                 25  30  35  40  45  50  55  60 
 6│                     36  42  48  54  60  66  72 
 7│                         49  56  63  70  77  84 
 8│                             64  72  80  88  96 
 9│                                 81  90  99 108 
10│                                    100 110 120 
11│                                        121 132 
12│                                            144 

>>> </lang>

The above works with Python 3.X, which uses Unicode strings by default.
Declaring a file type of UTF-8 and adding a u to all string literals to transform them into Unicode literals would make the above work in Python 2.X.

The code works fine for all values of integer 0 <= size <= 31 as above that, table numbers can get greater than the three digits allotted to them in the output formatting. This is a reasonable limitation for this format of multiplication table as other considerations, such as the width of the printed line are also excessive for large values of size.

Ruby

<lang ruby>def multiplication_table(n)

 puts "    " + ((" %3d" * n) % (1..n).to_a)
 1.upto(n) do |x|
   print "%3d " % x
   1.upto(x-1) {|y| print "    "}
   x.upto(n)   {|y| print " %3d" % (x*y)}
   puts ""
 end

end

multiplication_table 12</lang>

Tcl

<lang tcl>puts " x\u2502 1 2 3 4 5 6 7 8 9 10 11 12" puts \u0020\u2500\u2500\u253c[string repeat \u2500 48] for {set i 1} {$i <= 12} {incr i} {

   puts -nonewline [format "%3d" $i]\u2502[string repeat " " [expr {$i*4-4}]]
   for {set j 1} {$j <= 12} {incr j} {

if {$j >= $i} { puts -nonewline [format "%4d" [expr {$i*$j}]] }

   }
   puts ""

}</lang> 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│       4   6   8  10  12  14  16  18  20  22  24
  3│           9  12  15  18  21  24  27  30  33  36
  4│              16  20  24  28  32  36  40  44  48
  5│                  25  30  35  40  45  50  55  60
  6│                      36  42  48  54  60  66  72
  7│                          49  56  63  70  77  84
  8│                              64  72  80  88  96
  9│                                  81  90  99 108
 10│                                     100 110 120
 11│                                         121 132
 12│                                             144