# Construct a Modulo Multiplication Table

Consider a n x n multiplication table and replace each item with its remainder of division by n. For example, here is a 6x6 table and its "modulo 6" structure: (The last column and row are ignored since both are null)

1  2  3  4  5  6   |   1 2 3 4 5
2  4  6  8 10 12   |   2 4 0 2 4
3  6  9 12 15 18   |   3 0 3 0 3
4  8 12 16 20 24   |   4 2 0 4 2
5 10 15 20 25 30   |   5 4 3 2 1
6 12 18 24 30 36   |


Now it is evident that the multiplication table modulo n is symmetric and can be reconstructed by one of its triangular quadrants:

1 2 3 4 5
4 0 2
3


## Challenge

Given a positive integer N, print the upper quadrant of multiplication table modulo N. Assume that there is no restriction on the width of string in your output environment. The alignment of numbers shall be preserved. This means, the output should look like a part of a uniform product table, where the cells have equal widths. So for example, if we have a two-digit number in the table, all single-digit entries are separated by two spaces.

## Rules

Standard rules apply.

## Test cases

N = 1:
// no output is printed

N = 3:
1 2

N = 13:
1  2  3  4  5  6  7  8  9 10 11 12
4  6  8 10 12  1  3  5  7  9
9 12  2  5  8 11  1  4
3  7 11  2  6 10
12  4  9  1
10  3


Sandbox

• thanks, I should have read it more closely. While it may be too late to change, I personally think it is already a reasonable challenge to extract the triangle and the formatting just makes it more cumbersome.
– Wezl
Commented Jun 2, 2021 at 20:06
• In the N=13 case, can we have single-space between the first 3 columns?
Commented Jun 2, 2021 at 20:19
• +1 for a somewhat interesting challenge,-1 for the unnecessarily cumbersome output format. Commented Jun 2, 2021 at 21:23
• @Shaggy I thought the challenge without this specific output format would be a pretty trivial and boring one. As in multiply and then modulo? meh... Commented Jun 2, 2021 at 21:47
• The alignment of numbers shall be preserved Is it OK to use more spaces than necessary as long as the alignment is preserved? If not, it should be specified more clearly. Commented Jun 2, 2021 at 21:48

# Jelly, 14 bytes

’×þ%ɓoU¥⁺GµḶ⁶ẋ


Try it online!

Outputs a bunch of trailing whitespace. Used the ’×þ% trick from hyper-neutrino's answer, so be sure to give them an upvote

## How it works

’×þ%ɓoU¥⁺GµḶ⁶ẋ - Main link. Takes N on the left
’              - Decrement
×þ            - Create a multiplication table for all integers from 1 to N-1 and 1 to N
%           - Mod each by N. This leaves a trailing row of zeros.
Call this table T

Ḷ   - Yield [0, 1, 2, ..., N-1]
⁶ẋ - Yield that many spaces for each
Call this list of spaces S

ɓ     µ    - New dyadic chain f(S, T):
¥       -   Group the previous 2 links into a dyad g(S, T):
o         -     For each row in S and T, replace the first N elements of the row in T with spaces,
where N is the number of spaces in the row in S
U        -     Reverse each row
⁺      -   Do it again
G     -  Format it as a grid and output


# Jelly, 14 bytes

’×þ%µJ’⁶ẋoUµ⁺G


Try it online!

I stole the idea to use logical OR to avoid needing to trim and re-pad the lists from caird. Go upvote their solution too, please.

’×þ%µJ’⁶ẋoUµ⁺G   Main Link; accepts x
’                x - 1
×               using multiplication
þ              create a product table (this does x - 1 by x)
%             modulo x
----µ---------   start a new chain on this table
J           range over length (1, 2, ..., N)
’          decrement (0, 1, 2, ..., N - 1)
⁶ẋ        repeat " " by ^
o       vectorized logical OR; basically fills the lower left triangle with spaces
U      reverse each row
------µ⁺    duplicate the last chain, so this fills the lower left and flips horizontally twice, thus cutting the list to just the upper triangle
G   format as grid


# J, 60 55 bytes

1}."1,/"2@((' ',.' ',":@,.){~(<|.)@(>/~)*1+#|>:*/>:)@i.


Try it online!

-5 thanks to xash

I thought this would be a good challenge for J, and the essence of the problem is, but the formatting details destroyed me here.

• Tried my luck at it, got it down to 55b, but sadly nothing groundbreaking.
– xash
Commented Jun 3, 2021 at 10:00
• Much appreciated! Commented Jun 3, 2021 at 14:02

# R >= 4.1.0, 165 152 bytes

\(n,/=sprintf){z=outer(1:n,1:n,\(x,y)(x*y)%%n[2-(pmin(y,n-y)>=x)]);z[is.na(z)]="";z[]="%%%ds"/nchar(n-1)/z;cat(apply(z,1,paste,collapse=" "),sep="
")}


Try it online!

An anonymous function that takes an integer and prints the triangle to STDOUT. The TIO link replaces \ with function since TIO is on an earlier version of R.

Thanks to @RobinRyder for saving 5 bytes, and @KirillL for saving a further 8!

• Nice idea using NAs! This builds the NAs in the same way at -2 bytes. Commented Jun 3, 2021 at 16:17
• And you can gain 3 more bytes by removing extra spaces and changing "\n" into an actual new line. Commented Jun 3, 2021 at 16:31
• A couple of extra savings: 1) You can use nchar(n-1) as padding size because it is the max number in the table 2) Assigning sprintf to operator allows cheaply reusing it to form %?s string too, for 166 in R 3.x. However, I also found an entirely different approach Commented Jun 6, 2021 at 20:14
• @KirillL. Thanks! Like your answer too +1 Commented Jun 6, 2021 at 20:25

# MATLAB/Octave, 117 bytes

function f(n)
r=1:n;m=num2str(mod(r'*r,n));s=(nnz(m(1,:))+2)/n;for k=1:n
m(k,1:k*s-s)=32;disp(m(k,1:(n-k)*s))
end
end


Try it online! This prints out quite a lot of trailing whitespaces. If we sacrifice 2 bytes to replace k=1:n with k=1:n/2 the empty lines won't be printed though.

Despite my efforts to find more elegant solution using triu function (takes upper triangle of square matrix) this stayed the shortest solution I came up with.

Ungolfed/explained:

function f(n)
r=1:n;
m=num2str(mod(r'*r,n)); % modulo table transformed to char array
s=(length(m(1,:))+2)/n; % how many characters takes up one number
for k=1:n
m(k,1:k*s-s)=' ';     % replace first k-1 numbers with spaces
disp(m(k,1:(n-k)*s))  % print first n-k numbers
end
end


# JavaScript (ES8), 92 bytes

Expects the input as a string.

n=>(g=k=>++k>n/2?'':(h=i=>++i>n-k?
:(i<k?'':i*k%n+'').padStart(n.length+1)+h(i))+g(k))


Try it online!

# Python 3, 113 96 bytes

def f(n):d=range(1,n);[print(*[f"{['',v*x%n][v>=x<=n-v]:{len(str(n-1))}}"for v in d])for x in d]


Try it online!

# APL (Dyalog Unicode), 4341 35 bytes (SBCS)

Anonymous prefix lambda.

{1↓⍕d⍪' '@{∨∘⌽⍨∘.>⍨⍳d}⍵|∘.×⍨⍳d←⍵-1}


Try it online!

{} "dfn"; N is ⍵:

d←⍵-1 let d be N minus one

⍳ indices one through N

∘.×⍨ multiplication table

⍵| that modulus N

' '@{} replace with spaces at locations indicated by:

⍳d indices one through d

∘.>⍨ greater-than table

∨∘⌽⍨ logical OR with its own mirror image

d⍪ prepend a row of ds (to size columns widths right)

⍕ format to character matrix

1↓ drop the first row

• If you don't mind some trailing whitespace, (⌈d÷2)↑ can be replaced with ¯1↓.
– ovs
Commented Jun 3, 2021 at 9:12
Commented Jun 3, 2021 at 9:26

# Charcoal, 32 bytes

Ｅ⊘θ⪫Ｅ⊖θ◧⎇‹›ιλ‹⁺ιλ⊖θＩ﹪×⊕ι⊕λＩθωＬθ


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

  θ                                 Input n
⊘                                  Halved
Ｅ                                   Map over implicit range
θ                             Input n
⊖                              Decremented
Ｅ                               Map over implicit range
⎇‹›ιλ‹⁺ιλ⊖θ                 If this entry is wanted
⊕ι            Row value
×              Multiplied by
⊕λ          Column value
﹪               Modulo
Ｉθ        n as an intger
Ｉ                Cast to string
ω       Otherwise the empty string
◧                     Ｌθ     Pad to length of n
⪫                                Join with spaces
Implicitly print

• Accepted your answer since it is the shortest one without trailing spaces Commented Jun 7, 2021 at 18:15

# Jelly, 16 15 bytes

’<þa⁶oUo’×þ%ƊG  Try it online! Also outputs a ton of trailing whitespace # R, 109 bytes n=scan();m=(1:n%o%1:n%%n)[,-n];m[l<-lower.tri(m)]="";m[l[,n-1:n]]="";write.table(format(m,j="r"),,,F,r=F,c=F)  Try it online! A full program with some hacking around the built-in formatting/printing functionality to achieve the desired result. Here is the printing statement with all the formatting options ungolfed: write.table(format(m,justify="right"),quote=FALSE,row.names=FALSE,col.names=FALSE)  If printing the numbers left-aligned is allowed after all, then we can save a few extra bytes by removing right-justification. # Stax, 16 bytes ù▼åU☻┐≈◘E╝ÖBñGRR  Run and debug it about as short as I could get it. centering the stuff took more bytes than i expected. ## Explanation vc{*x%K{itiT|>Jm|Cm vc decrement and duplicate input n { K cross-product map ranges (1..n-1) and (1..n-1) * multiply the numbers x% mod n { m map each row to itiT iteration number trimmed from both sides |> right align each number J join with spaces |C center m print joined with newlines  # VyxalCM, 35 30 bytes ƛ⁰ɽƛ⁰ɽ*⁰%;in(ṪḢ);ƛƛ:L⁰Lεð*p;Ṅ


Try it Online!

ƛ⁰ɽƛ⁰ɽ*⁰%;$in(ṪḢ);ƛƛ:L⁰Lεð*p;Ṅ ƛ ; For each n in range(0,input): ⁰ɽƛ ; Generate the table: For each in range(1,input): ⁰ɽ* Multiply by range(1,input) to make a table. ⁰% Mod(input) everything$i                       Make a triangle: Get the nth row of the table
n(  )                  Repeat n times:
ṪḢ                    Remove the head and tail

Align the numbers:
ƛ                                 For each row of the triangular table:
ƛ        ;                        For each number in that row:
:L⁰Lε                             Take difference of length(input) and length(number)
ð*p                          Prepend that many spaces
Ṅ                       Join each row on spaces


C centers the output, and M makes implicit ranges start from 0.

Improvements welcome.

# 05AB1E (legacy), 26 bytes

L¨Dδ*s%εNF¦¨]DZg>jðδÛ˜õK.c?


With leading spaces and trailing spaces/newlines (20 bytes):

L¨Dδ*s%εNF¦¨]DZg>j.c


Explanation (of the longer version):

L               # Push a list in the range [1, (implicit) input]
¨              # Remove the final value to make the range [1, input)
# Create a multiplication table matrix:
D             #  Duplicate this list
δ            #  Apply double-vectorized:
*           #   Multiply
s          # Swap so the (implicit) input is at the top of the stack
%         # Modulo each value in the matrix by this
ε               # Map over each row:
NF             #  Loop the (0-based) map-index amount of times:
¦¨           #   And remove the leading/trailing items
]D              # After both the inner loop and map: duplicate it
Z             # Get the flattened maximum of this matrix (without popping)
g            # Pop and get its length
>           # Increase this length by 1
j          # Prepend spaces in front of each integer up to that length+1,
# and then join every row together to a single string
δ        # Map over each inner string:
ð Û       #  Strip leading spaces
˜      # Flatten this list (δ unfortunately wraps the strings in lists in the
# legacy version..)
õK    # Remove all trailing empty strings
.c  # Centralize this list of strings
? # And output it without trailing newline


# C (gcc)-lm, 96 bytes

-7 thanks to @ceilingcat

w,i,j;f(a){w=log10(a)+2;for(i=0;i++<a;puts(""))for(j=i;j+i<=a;)printf("%*d",j++-i?w:w*i,i*j%a);}


Try it online!

# C (gcc), 106 103 bytes

-3 thanks to @ceilingcat

w,i,j;f(a){for(w=2,i=a;i/=10;w++);for(;i++<a;puts(""))for(j=i;j+i<=a;)printf("%*d",j++-i?w:w*i,i*j%a);}


Try it online!