14
\$\begingroup\$

Your task is to create a good multiplication table for others to use. Given an integer \$n\$, generate a multiplication table that displays products up to \$n×n\$. You should start with \$2×2\$ as 1 times any number is itself and that is reflected in the row/column indices. Scientific notation and floating-points are NOT allowed. You must print every digit with no decimals (.00 or .00000034).

Formatting is a crucial component (after all, mutiplication tables are notorious for their formatting). The formatting criteria are listed below:

  • At the top left corner or \$ \text{table}[0][0] \$, there will be a single number 1.
  • Each row and column index will be \$n\$ digits + one whitespace.
  • There is one row of hypens/dashes that span from the beginning of the table and ends at the last digit of the number who has the largest amount of digits in the rightmost column.
  • There is 1 column of pipes | that start from the top of the multiplication table and ends at the \$n\$th row. This column of pipes should not get in the way of the row indices' formatting.
  • The values of the table should have its leftmost digit aligned with the leftmost digit of the column index.
  • Between each value in each column, there should be one whitespace seperating the value. There will be NO newlines seperating each row.

Below is an example the covers all of the above points. Note: for brevity, the example table skips from 2 directly to 54, your actual program should include ALL digits from 2 to 54 and onwards to 654546.

1      | 2       54       3443       654546
-------------------------------------------------
2      | 4       108      6886       1309092   
54     | 108     2916     185992     35345484  
3443   | 6886    185992   11854249   2260487878 
654546 | 1309092 35345484 2260487878 431052650116
  1. Observe how in the above table, the hypens take priority over the pipes.
  2. Notice how, no matter the size of the numbers, each column has at least 1 whitespace seperating it.
  3. The hypen row ends at the last digit of \$431052650116\$ NOT \$654546\$.
  4. Each column has its leftmost digit aligned with the leftmost digit of the column index (ex. the "6" in 6886 is aligned with the "2" in the column index).
  5. Refer to the above table when in doubt. Comment for any clarifications.

SAMPLE INPUT

5

SAMPLE OUTPUT

1 | 2  3  4  5
---------------
2 | 4  6  8  10
3 | 6  9  12 15
4 | 8  12 16 20
5 | 10 15 20 25

Constraints

You will possibly need unsigned 64-bit integers. $$ 2 \leq n \leq 10^9 $$

\$\endgroup\$
2
  • 2
    \$\begingroup\$ In the first example, the spaces at the ends of the lines are inconsistent; I assume that means they don't matter? \$\endgroup\$
    – m90
    Oct 3, 2021 at 5:15
  • \$\begingroup\$ @m90 If you mean the spaces at the end of each row, then yes, they don't matter. \$\endgroup\$
    – VJZ
    Oct 3, 2021 at 19:34

15 Answers 15

6
\$\begingroup\$

APL (Dyalog Unicode), 52 bytes (SBCS)

Full program. Requires fully printing high-precision floats.

r←' (\d)'⋄'-'@2↑r⎕R' |&'⍠'ML'1⊢r⎕R'\1'↓⍕⍕¨1(,∘.×⊢)⍳⎕

Try it online!

r←' (\d)' create the PCRE regex r as a space followed by a digit

 prompt for \$n\$

indices 1 through \$n\$

1() apply the following tacit function with that as right argument and 1 as left argument:

, the concatenated arguments

∘.× as vertical axis for the multiplication table with horizontal axis being…

 the right argument

(now we have the number we need, including an extra row which will be replaced by dashes)

⍕¨ format each number as text (since strings are left-justified)

 format the entire matrix (leaves double-spaces between columns)

 split matrix into list of strings

r⎕R'\1' replaces matches for r with their digit (reduces column spacing to 1)

 on that…

r⎕R' |&'⍠'ML'1 insert a space and a pipe before the first r match on each line

 mix list of strings into matrix

'-'@2 replace with dashes at the second row

\$\endgroup\$
5
\$\begingroup\$

Gaia, 27 26 bytes

ṇ'|,¤+ṡ
ׇ€[¦t↑¦ṇ:l'-×,¤+ṣ

Try it online!

ׇ€[¦tụ generates the table without the lines.

Commented:

ṇ'|,¤+ṡ      -- helper function to insert '|' at the second position
ṇ            -- extract first element from list
 '|,         -- pair with "|"
    ¤+       -- prepend to the remaining list
      ṡ      -- join by spaces

ׇ           -- multiplication table for 1..input
  €[¦        -- left-align each row to its maximum length
     t       -- transpose to swap rows/columns
      ↑¦     -- map helper function over each row

ṇ            -- extract first row from table
 :l          -- duplicate and take the length of the copy
   '-×       -- push a string of that many dashes
      ,      -- pair with first row
       ¤+    -- and prepend to table
         ṣ   -- join the table by newlines

My attempt of adding a helper function to insert both - and | is two bytes longer:

¤ṇ:l4ṁ×,¤+
ׇ€[¦t⟨'|⇈ṡ⟩¦'-⇈ṣ

Try it online!

\$\endgroup\$
5
\$\begingroup\$

C (gcc), 174 172 166 164 163 bytes

#define X u-=printf("\n\0-\0%-*i"
s(n){return!n?:s(n/10)+1;}i,j,u;t(n){for(i=0,u=2;j=i<n;X)){for(X"| "+4,s(n),++i);j<n;)X+4,s(n*n),i*++j);if(i<2)for(X);X+2)-2;);}}

Try it online!

-2 thanks to ceilingcat, by initialising j off the loop condition. -6 by introducing the macro X with a few changes to fit it in; -2 by extending it with some more changes. -1 thanks to ceilingcat, shortening s with ?:.

Fairly straightforward:

  • s produces the number of digits in a number plus 1, used to determine the column widths. ?: is a GCC extension, producing the same value as the left expression if it's nonzero (and the value of the right expression otherwise).
  • The macro X contains multiple (null-terminated) strings run together, allowing it to be used for any of those strings – X alone prints a line feed, while X+2 (adding 2 to the pointer) prints a hyphen, and X+4 uses the format string %-*i; in one place, | is added to it, using concatenation of adjacent string literals.
  • The return value of printf is the number of characters printed; u starts at 2 and has those values subtracted from it, making u 1 greater than the negative of the length of the first row excluding the extra space at the end. Using X to print a line feed subtracts the extra 1 from u, and then the row of hyphens is produced using u, subtracting -1 each iteration.
\$\endgroup\$
1
3
\$\begingroup\$

Jelly,  29 28 27  25 bytes

Probably not the right tool for the job.

Zż€Ẏ€
×þ`Dz€⁶Z€ç”|K€ç”-ZY

A full program that accepts a positive integer and prints the formatted multiplication table.

Try it online!

How?

Zż€Ẏ€ - Link 1: transpose & insert chars: list of lists, M; character, C
Z     - transpose M
 ż€   - zip each with C
   Ẏ€ - tighten each

×þ`Dz€⁶Z€ç”|K€ç”-ZY - Main Link: integer N
  `                 - use N as both arguments of:
 þ                  -   table using:
×                   -     multiplication
   D                - covert to decimal digits (vectorises)
     €              - for each (list of digit lists):
    z ⁶             -   transpose with filler of a space character
       Z€           - transpose each
         ç”|        - call last Link (1) as a dyad, f(that, pipe charater)
            K€      - join each with space characters
              ç”-   - call last Link (1) as a dyad, f(that, dash charater)
                 Z  - transpose
                  Y - join with newline characters
                    - implicit, smashing print
\$\endgroup\$
3
\$\begingroup\$

Ruby, 105 97 96 bytes

->n{(r=1..n).map{|x|A=r.map{|y|"%-*s"%["#{y*n}".size,y*x]}.insert(1,?|)*" "}.insert 1,?-*A.size}

Try it online!

  • Saved 8 +1 thanks to @Dingus !
->n{...}    # lambda retuning an array of strings.
(a=r=1..n)  # a: used to take a line length to add '----...
              r: range used 2 times to build a table
"#{y*x}".ljust  # every value of table is converted to string and left-jusified by:
  
"#{y*n}.size "  #> length of max value of column
we insert a | at index 1
and finally we insert a row line--- of length a
\$\endgroup\$
0
2
\$\begingroup\$

05AB1E, 30 28 22 bytes

Lć'|‚ìDδ*€.Bø¬»g'-×1ǝ»

-6 bytes thanks to @Grimmy.

Try it online.

Explanation:

L         # Push a list in the range [1, (implicit) input-integer]
 ć        # Extract head; pop and push [2,input]-list and 1 separated
  '|‚    '# Pair this 1 with "|"
     ì    # And prepend it back: [1,"|",2,3,4,...,input]
Dδ*       # Make a multiplication table:
D         #  Duplicate the list
 δ        #  Apply over the two lists double-vectorized:
  *       #   Multiply
          #   (we'll have a second row of single "|"s now)
€.B       # Box each inner list, appending leading spaces to make all values the same
          # length
   ø      # Zip/transpose; swapping rows/columns
¬         # Get the first row (without popping)
 »        # Pop and join it with newline delimiter
  g       # Pop and push its length (including those newlines)
   '-×   '# Pop and push a string with that many "-"
      1è  # Insert it at the second position in the list of lists
        » # Join each inner list by spaces; and then every string by newlines
          # (after which the result is output implicitly)
             
\$\endgroup\$
3
  • 1
    \$\begingroup\$ εí¤gjí} => €.B for a 26 on modern 05AB1E (TIO) \$\endgroup\$
    – Grimmy
    Oct 14, 2021 at 1:15
  • 1
    \$\begingroup\$ Down to 22 \$\endgroup\$
    – Grimmy
    Oct 14, 2021 at 1:40
  • 1
    \$\begingroup\$ @Grimmy Long time no see! And thanks for the -6. :) \$\endgroup\$ Oct 14, 2021 at 7:39
2
\$\begingroup\$

Factor, 153 bytes

[ [1,b] dup outer [ "|"1 rot insert-nth ] map [ simple-table. ] with-string-writer "\n"split harvest dup last [ drop 45 ] map 1 rot insert-nth "\n"join ]

Try it online!

Explanation

It's a quotation (anonymous function) that takes a number from the data stack and leaves a string on the data stack as output. Assuming 5 is on top of the data stack when this quotation is called...

Snippet Data stack
[1,b]
{ 1 2 3 4 5 }
dup
{ 1 2 3 4 5 }
{ 1 2 3 4 5 }
outer
{
{ 1 2 3 4 5 }
{ 2 4 6 8 10 }
{ 3 6 9 12 15 }
{ 4 8 12 16 20 }
{ 5 10 15 20 25 }
}
[ "|"1 rot insert-nth ] map
{
{ 1 "|" 2 3 4 5 }
{ 2 "|" 4 6 8 10 }
{ 3 "|" 6 9 12 15 }
{ 4 "|" 8 12 16 20 }
{ 5 "|" 10 15 20 25 }
}
[ simple-table. ] with-string-writer
"1 | 2  3  4  5\n2 | 4  6  8  10\n3 | 6  9  12 15\n4 | 8  12 16 20\n5 | 10 15 20 25\n"
"\n"split
{
"1 | 2 3 4 5"
"2 | 4 6 8 10"
"3 | 6 9 12 15"
"4 | 8 12 16 20"
"5 | 10 15 20 25"
""
}
harvest
{
"1 | 2 3 4 5"
"2 | 4 6 8 10"
"3 | 6 9 12 15"
"4 | 8 12 16 20"
"5 | 10 15 20 25"
}
dup last
{
"1 | 2 3 4 5"
"2 | 4 6 8 10"
"3 | 6 9 12 15"
"4 | 8 12 16 20"
"5 | 10 15 20 25"
}
"5 | 10 15 20 25"
[ drop 45 ] map
{
"1 | 2 3 4 5"
"2 | 4 6 8 10"
"3 | 6 9 12 15"
"4 | 8 12 16 20"
"5 | 10 15 20 25"
}
"---------------"
1 rot insert-nth
{
"1 | 2 3 4 5"
"---------------"
"2 | 4 6 8 10"
"3 | 6 9 12 15"
"4 | 8 12 16 20"
"5 | 10 15 20 25"
}
"\n"join
"1 | 2  3  4  5\n---------------\n2 | 4  6  8  10\n3 | 6  9  12 15\n4 | 8  12 16 20\n5 | 10 15 20 25"
\$\endgroup\$
2
\$\begingroup\$

jq, 217 bytes

. as$m|[1+range(.)]|map(["\(.*range($m)+.)"|split("")])|(.[$m-1]|map(keys))as$l|map([to_entries[]|[.value[$l[.key][]]|values//" "]|join("")]|[.[0],"|",.[1:][]]|join(" "))|[.[0],"-"*(.[$m-1]|length),.[1:][]]|join("\n")

Try it online!

What

  . as $m
| [ 1 + range(.) ] # Convert to rows
| map(["\(.*range($m)+.)" | split("")]) # Multiply, then convert numbers to lists of digits
| (.[$m-1] | map(keys)) as $l # Store indices into last (longest) row, for padding
| map(  [
            to_entries[]
          | [.value[$l[.key][]] | values // " "] # Pad with nulls, then replace those with spaces
          | join("")
        ]
      | [.[0], "|", .[1:][]] # Insert vertical rule
      | join(" ") # Join lines into single strings
     )
| [.[0], "-"*(.[$m-1] | length), .[1:][]] # Insert horizontal rule
| join("\n")
\$\endgroup\$
2
\$\begingroup\$

jq -r, 142 bytes

def f:transpose[];[range(.)+1]|. as$r|[.[]|[.*$r[]|@sh/""]|[f|map(.//" ")]|[f|add]]|[f|[.[0],"|"]+.[1:]|join(" ")]|(.[0]|.,"-"*length),.[1:][]

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Charcoal, 36 bytes

Nθ≔E⊕θ↔⁻ι‹ι²ηFη«M→⪫⎇ι×ηιEη|¦¶Mθ↑»↙←ⅈ

Try it online! Link is to verbose version of code. Explanation:

Nθ

Input n.

≔E⊕θ↔⁻ι‹ι²η

Create a range from 0 to n, but swap the first two elements.

Fη«

Iterate over the range.

M→

Leave an empty column.

⪫⎇ι×ηιEη|¦¶

If this is the 0 column, print a column of |s, otherwise multiply the range by the column and print it joined with newlines. This leaves the cursor to the right of the bottom number.

Mθ↑

Move back to the top row.

»↙←ⅈ

Overwrite the row of 0s with a line of -s.

\$\endgroup\$
1
\$\begingroup\$

R, 157 bytes

Or R>4.1, 150 bytes by replacing the word function with \.

function(n,x=outer(1:n,1:n),y=apply(apply(cbind(x[,1],"|",x[,2:n]),2,format),1,paste,collapse=" "))paste(c(y[1],strrep("-",nchar(y[1])),y[2:n]),collapse="
")

Try it online!

Explanation outline:

  1. Compute the (unformatted) multiplication table using outer.
  2. Add a column of |s, conveniently converting the array to type character.
  3. Apply format to columns, which for character vectors does exactly what we need.
  4. Collapse rows using spaces.
  5. Add a row of -s.
  6. Collapse everything using newlines.
\$\endgroup\$
1
\$\begingroup\$

JavaScript (ES8), 138 bytes

n=>(g=i=>i++<n?(h=k=>s=++k<n?(k*i+'').padEnd((k*n+c).length)+[[,'| '][k]]+h(k):k*i)(c=`
`)+c+g(i):'')``.replace(c,c+s.replace(/./g,'-')+c)

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Julia 1.0, 137 bytes

!n=[(A=split(replace(repr("text/plain",[1:n fill(text"|",n) (1:n)*(2:n)']),r"( +)(\S+) ?"=>s"\2\1"),'
'))[2];"-"^~-length(A[2]);A[3:end]]

Try it online!

Explanation:

  • [1:n fill(text"|",n) (1:n)*(2:n)'] creates a matrix: (here for n=5)
 5×6 Matrix{Any}:
 1  |   2   3   4   5
 2  |   4   6   8  10
 3  |   6   9  12  15
 4  |   8  12  16  20
 5  |  10  15  20  25
  • the @text_str macro allows to hide the " around the |
  • repr("text/plain", ... ) formats it like seen above in a string
  • since there is too many spaces and numbers are adjusted right instead of left, we apply the following regex: replace( ... , r"( +)(\S+) ?" => s"\2\1")
"""5×6Matrix{Any}:
1 | 2  3  4  5  
2 | 4  6  8  10 
3 | 6  9  12 15 
4 | 8  12 16 20 
5 | 10 15 20 25 """
  • then we split( ... , '\n'), remove the first line and insert a line of -
  • output is a list of strings:
6-element Vector{AbstractString}:
 "1 | 2  3  4  5  "
 "---------------"
 "2 | 4  6  8  10 "
 "3 | 6  9  12 15 "
 "4 | 8  12 16 20 "
 "5 | 10 15 20 25 "
\$\endgroup\$
0
\$\begingroup\$

Perl 5, 128 bytes

$_='';for$i(@n=1.."@F"){$_.=pack(join('',map A.length$n[-1]*$_.0,@n),map$i*$_,@n).$/}s/.*/"$&
-".$&=~s|.|-|gr/e;s/^\d+ +/$&| /mg

Try it online!

$_='';                         # empty $_, to be used for building output
for$i(@n=1.."@F"){             # loop $i as 1 → n, "@F" is the input N, init array @n=1→N
  $_.=pack(                    # add a new line to output in $_ with a pack template
    join(                      # ...by joining
      '',                      # ...without delimiter
      map A.length$n[-1]*$_.0, # ...the template AxAyAz where x,y,z,... is the col widths
                               # ...of current $_ which is the widest cells which is
                               # ...always on last line
          @n                   # map 1 → N to create a widths template string
    ),
    map$i*$_,@n                # fill template with the multiplications of this line
  ).$/                         # add newline at end of each line
}
s/.*/"$&\n-".$&=~s|.|-|gr/e;   # add ------... second line, same width as first plus one -
s/^\d+ +/$&| /mg               # add | between col 1 and col 2 where col 1 is a number
                               # $_ now has the table string printed due to perl option -p
\$\endgroup\$
0
\$\begingroup\$

Java (JDK), 166 bytes

n->{var s="";for(int i=0,j;i++<n;s+=i<2?"\n"+"-".repeat(s.length()-1)+"\n":"\n")for(j=0;j++<n;)s+=s.format("%-"+((j*n+"").length())+"d ",i*j)+(j<2?"| ":"");return s;}

Try it online!

Credits

\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.