9
\$\begingroup\$

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

\$\endgroup\$
19
  • 4
    \$\begingroup\$ 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. \$\endgroup\$
    – Wezl
    Jun 2 at 20:06
  • 2
    \$\begingroup\$ In the N=13 case, can we have single-space between the first 3 columns? \$\endgroup\$
    – Adám
    Jun 2 at 20:19
  • 8
    \$\begingroup\$ +1 for a somewhat interesting challenge,-1 for the unnecessarily cumbersome output format. \$\endgroup\$
    – Shaggy
    Jun 2 at 21:23
  • 4
    \$\begingroup\$ @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... \$\endgroup\$ Jun 2 at 21:47
  • 4
    \$\begingroup\$ 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. \$\endgroup\$
    – Arnauld
    Jun 2 at 21:48

15 Answers 15

2
\$\begingroup\$

Charcoal, 32 bytes

E⊘θ⪫E⊖θ◧⎇‹›ιλ‹⁺ιλ⊖θI﹪×⊕ι⊕λIθωLθ 

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

  θ                                 Input `n`
 ⊘                                  Halved
E                                   Map over implicit range
      θ                             Input `n`
     ⊖                              Decremented
    E                               Map over implicit range
        ⎇‹›ιλ‹⁺ιλ⊖θ                 If this entry is wanted
                      ⊕ι            Row value
                     ×              Multiplied by
                        ⊕λ          Column value
                    ﹪               Modulo
                          Iθ        `n` as an intger
                   I                Cast to string
                            ω       Otherwise the empty string
       ◧                     Lθ     Pad to length of `n`
   ⪫                                Join with spaces
                                    Implicitly print
\$\endgroup\$
1
  • \$\begingroup\$ Accepted your answer since it is the shortest one without trailing spaces \$\endgroup\$ Jun 7 at 18:15
9
\$\begingroup\$

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
\$\endgroup\$
0
5
\$\begingroup\$

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
\$\endgroup\$
5
\$\begingroup\$

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.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Tried my luck at it, got it down to 55b, but sadly nothing groundbreaking. \$\endgroup\$
    – xash
    Jun 3 at 10:00
  • \$\begingroup\$ Much appreciated! \$\endgroup\$
    – Jonah
    Jun 3 at 14:02
5
\$\begingroup\$

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!

\$\endgroup\$
4
  • 1
    \$\begingroup\$ Nice idea using NAs! This builds the NAs in the same way at -2 bytes. \$\endgroup\$ Jun 3 at 16:17
  • 1
    \$\begingroup\$ And you can gain 3 more bytes by removing extra spaces and changing "\n" into an actual new line. \$\endgroup\$ Jun 3 at 16:31
  • 1
    \$\begingroup\$ 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 \$\endgroup\$
    – Kirill L.
    Jun 6 at 20:14
  • \$\begingroup\$ @KirillL. Thanks! Like your answer too +1 \$\endgroup\$ Jun 6 at 20:25
4
\$\begingroup\$

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
\$\endgroup\$
3
\$\begingroup\$

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!

\$\endgroup\$
3
\$\begingroup\$

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!

\$\endgroup\$
3
\$\begingroup\$

APL (Dyalog Unicode), 43 41 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

\$\endgroup\$
2
  • \$\begingroup\$ If you don't mind some trailing whitespace, (⌈d÷2)↑ can be replaced with ¯1↓. \$\endgroup\$
    – ovs
    Jun 3 at 9:12
  • \$\begingroup\$ @ovs Oh, I misread OP's answer to caird and me. \$\endgroup\$
    – Adám
    Jun 3 at 9:26
2
\$\begingroup\$

Jelly, 16 15 bytes

’<þa⁶oU$o’×þ%ƊG

Try it online!

Also outputs a ton of trailing whitespace

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

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  
\$\endgroup\$
1
\$\begingroup\$

Vyxal CM, 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.

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

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.

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

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!

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

05AB1E (legacy), 26 bytes

Without trailing/leading spaces/newlines (26 bytes):

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

Try it online or verify all test cases.

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

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

Try it online or verify all test cases.

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
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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