# Illustrate the Least Common Multiple

Given two positive integers, A and B, illustrate their least common multiple by outputting two lines of dashes (-) with length LCM(A, B) after replacing every Ath dash in the first line and every Bth dash in the second line with vertical bars (|).

In this way, the end of each line will be the only place two |'s line up.

For example, if A = 6 and B = 4, LCM(6, 4) = 12, so:

two lines of 12 dashes:
------------
------------

replace every 6th dash in the first line with a vertical bar:
-----|-----|
------------

replace every 4th dash in the second line with a vertical bar:
-----|-----|
---|---|---|


Thus the final output would be

-----|-----|
---|---|---|


The order of the input numbers should correspond to the order of the lines.

The shortest code in bytes wins.

# Testcases

A B
line for A
line for B

1 1
|
|

1 2
||
-|

2 1
-|
||

2 2
-|
-|

6 4
-----|-----|
---|---|---|

4 6
---|---|---|
-----|-----|

2 3
-|-|-|
--|--|

3 2
--|--|
-|-|-|

3 6
--|--|
-----|

2 5
-|-|-|-|-|
----|----|

4 3
---|---|---|
--|--|--|--|

10 10
---------|
---------|

10 5
---------|
----|----|

10 6
---------|---------|---------|
-----|-----|-----|-----|-----|

24 8
-----------------------|
-------|-------|-------|

7 8
------|------|------|------|------|------|------|------|
-------|-------|-------|-------|-------|-------|-------|

6 8
-----|-----|-----|-----|
-------|-------|-------|

13 11
------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|------------|
----------|----------|----------|----------|----------|----------|----------|----------|----------|----------|----------|----------|----------|

• @LeakyNun Extending an answer from codegolf.stackexchange.com/q/94999 seems easier than from that one. Either way, people will have fun doing this one which is a decent reason imo. – Calvin's Hobbies Sep 25 '17 at 19:02
• Can I output an array with two strings, one for each line? – BlackCap Sep 25 '17 at 19:05
• @BlackCap No. Print the strings to stdout or a file or return the whole multiline string. – Calvin's Hobbies Sep 25 '17 at 19:06
• Bonus for handling arbitrary number of inputs? – Adám Sep 25 '17 at 23:49
• @HelkaHomba Ok thanks; saved 1 more byte. :) (As if there is any other reason to ask such questions on codegolf challenges. ;p) – Kevin Cruijssen Sep 28 '17 at 6:58

# Python 3, 80 bytes

Saved 1 byte thanks to Halvard Hummel and 1 byte thanks to Jonathan Allan.

import math
def f(*l):
for k in 0,1:print(l[~k]//math.gcd(*l)*(~-l[k]*"-"+"|"))


Test it online!

lambda*l:"\n".join(l[0]*l[1]//math.gcd(*l)//k*(~-k*"-"+"|")for k in l)
import math


Test it online! (82 bytes - initial answer)

This is the best I could do in Python 2 (81 bytes). It seems like I cannot comment on that answer, I'll just post this here instead:

from fractions import*
l=a,b=input()
for k in l:print a*b/gcd(*l)/k*(~-k*"-"+"|")


Test it online!

First attempt here, probably sub-optimal!

• Welcome to PPCG! – Laikoni Sep 25 '17 at 19:46
• @Laikoni Thank you! This seems like a fun community :-) – user74686 Sep 25 '17 at 19:47
• 81 bytes – Halvard Hummel Sep 25 '17 at 20:02
• @HalvardHummel Thanks, will post as an alternative! – user74686 Sep 25 '17 at 20:03
• While trying a diferent approach entirely I realised your version could be done in 80. – Jonathan Allan Sep 25 '17 at 21:20

x%y=unlines[["-|"!!(0^mod a b)|a<-[1..lcm x y]]|b<-[x,y]]


Try it online!

• I've never seen that 0^0=1 trick before - clever – BlackCap Sep 25 '17 at 19:36
• @BlackCap I can't claim it myself because I have seen it a few times before, though I don't remember where I saw the trick first. – Laikoni Sep 25 '17 at 19:42

# Jelly, 12 bytes

Ṭ€ị⁾|-ṁ€æl/Y


Try it online!

# MATL, 16 15 bytes

'-|'!i&Zm:G\go)


Input is a column vector with the two numbers. Try it online!

As a bonus, the input can contain more than two numbers. Try it online!

### Explanation

'-|'   % Push this string
!      % Transpose. This is needed because of input [1; 1]
i      % Input column vector of 2 (or N) numbers
&Zm    % LCM of the 2 (or N) numbers, say L
:      % Range
G      % Push input again
\      % Modulus, element-wise with broadcast. Gives a 2×L (or N×L) matrix
g      % Convert to logical: gives false for zeros, true for nonzeros
o      % Convert to double: gives 0 for false, 1 for true
)      % Index into string (modular, 1-based). Implicitly display

• I think you left in a stray He? – Sanchises Sep 28 '17 at 8:27
• @Sanchises Thanks! Yes, it was in the previous version, but it's not necessary – Luis Mendo Sep 28 '17 at 8:50
• Also, this seems to work just fine without the transpose? You've been overthinking things... ;) – Sanchises Sep 28 '17 at 9:37
• @Sanchises Without the transpose it doesn't work for input [1; 1], due to how MATL(AB) handles array shape with indexing. (Alternatively, the transpose could be replaced by He at the end, which is why it was initially there) – Luis Mendo Sep 28 '17 at 10:21
• Ah yes I figured that it was there because of row behaviour but I didn't think of this edge case. – Sanchises Sep 28 '17 at 10:49

# R, 109 105 bytes

function(a,b){q=1:a*b
l=min(q[!q%%a])
x=rep("-",l*2)
x[c(seq(0,l,a),l+seq(0,l,b))]="|"
write(x,"",l,,"")}


Try it online!

Anonymous function. Computes l=lcm(a,b), then generates a range from 0 to l by a, then from l to 2*l by b, setting the indices to | and printing as a matrix with l columns.

# Python 2, 66 bytes

l=a,b=input()
while a%b:a+=l[0]
for x in l:print a/x*('-'*~-x+'|')


Try it online!

# C, 72 bytes

i;f(x,y){for(i=1;i%y|i%x;)putchar(i++%x?45:124);puts("|");y>0&&f(y,-x);}


# Husk, 12 bytes

†?'-'|TUṪ%N


Try it online!

Yeah, there is a lcm builtin in Husk. No, I don't need it.

Bonus: works with any number of input values

### Explanation

†?'-'|TUṪ%N    input:[2,3]
Ṫ%N    table of all remainders of positive naturals divided by
input numbers:
[[1,1],[0,2],[1,0],[0,1],[1,2],[0,0],[1,1],[0,2],...
U        get all elements before the first repeated one:
[[1,1],[0,2],[1,0],[0,1],[1,2],[0,0]]
T         transpose:
[[1,0,1,0,1,0],[1,2,0,1,2,0]]
†?'-'|          replace all truthy elements with '-' and all falsy elements
with '|':
["-|-|-|","--|--|"]
implicit: since this is a full program, join the resulting array
of strings with newlines, and print to stdout


# Mathematica, 63 bytes

(s=LCM@##;Print[""<>If[i~Mod~#<1,"|","-"]~Table~{i,s}]&/@{##})&


and another version which user202729 really, really, really wants to see posted

# Mathematica, 59 bytes

(s=LCM@##;Print[""<>If[#∣i,"|","-"]~Table~{i,s}]&/@{##})&


this one uses special character \[Divides] ∣

• If this is Mathematica you can probably use \[Divides] instead of Mod operator to represent divisibility, which saves 4 bytes. Also Mathics TIO should not print the {Null, Null}. – user202729 Sep 27 '17 at 10:04
• @user202729 I fixed the Mathics print. – J42161217 Sep 27 '17 at 10:14
• I think that your first comment was clear enough. Please stop pressing me in order to make the changes that you want, the exact time you want. Give the users some hours to respond. Some of us have a life out of this place – J42161217 Sep 27 '17 at 12:51

# 05AB1E, 13 bytes

ʒ<'-×'|«¹.¿∍,


Uses the 05AB1E encoding. Try it online!

• Filter was a good idea, I got 17 doing it entirely different .¿Lε²¹‚%_„-|è}øJ». – Magic Octopus Urn Oct 4 '17 at 16:22

# APL (Dyalog), 22 bytes

Assumes ⎕IO←0. Takes A,B as right argument. Bonus: handles input list of any length!

{'|-'[⌽×⍵∘.|⍳∧/⍵]}


Try it online!

{} anonymous lambda where ⍵ represents the right argument

'|-'[] index the string with:

∧/ LCM across the input

⍳ first that many ɩntegers (0 through N-1)

⍵∘.| division remainder table with the input vertically and that horizontally

× signum

⌽ flip horizontally

• What does that first assumption mean? – Calvin's Hobbies Sep 26 '17 at 1:00
• @HelkaHomba It means that arrays index starting at 0, a default on APL interpreters, I believe. – Conor O'Brien Sep 26 '17 at 1:04
• @HelkaHomba Since APL systems come in both 0-based and 1-based flavours, I just write the assumption. Otherwise one would have to have two APLs. E.g. ngn/apl can run this very same code without specifying ⎕IO←0, as that is the default there. – Adám Sep 26 '17 at 6:19

# Octave, 46 38 bytes

-8 bytes thanks to several suggestions by Luis Mendo

@(a,b)'-|'.'(~mod(1:lcm(a,b),[a;b])+1)


Try it online!

# JavaScript (ES6), 69 bytes

f=(a,b,S,A=1)=>(A%a?'-':'|')+(A%a|A%b?f(a,b,S,A+1):S?'':
+f(b,a,1))


Recursively runs until A is divisible by both a and b – outputting a dash or pipe based on a's divisibility by A.

The function then calls itself, swapping a and b.

The S variable prevents the function from calling itself infinitely.

Test Cases:

f=(a,b,S,A=1)=>(A%a?'-':'|')+(A%a|A%b?f(a,b,S,A+1):S?'':
+f(b,a,1))

console.log(f(1,1));
console.log(f(1,2));
console.log(f(2,1));
console.log(f(2,2));
console.log(f(6,4));
console.log(f(4,6));
console.log(f(2,3));
console.log(f(3,2));
console.log(f(10,10));
console.log(f(3, 6));
console.log(f(2, 5));
console.log(f(4, 3));
console.log(f(10, 10));
console.log(f(10, 5));
console.log(f(10, 6));
console.log(f(24, 8));
console.log(f(7, 8));
console.log(f(6, 8));
console.log(f(13, 11));

# JavaScript (ES8), 91 bytes

f=(a,b,i=2,g=(c,d)=>d?g(d,c%d):c)=>i?'|'.padStart(a,'-').repeat(b/g(a,b))+
+f(b,a,i-1):''


Uses the algorithms:

lcm(a, b) = ab / gcd(a, b)
gcd(c, d) = d ? gcd(d, c%d) : c


Recursively calls itself just once to output the second line.

Test Cases:

f=(a,b,i=2,g=(c,d)=>d?g(d,c%d):c)=>i?'|'.padStart(a,'-').repeat(b/g(a,b))+
+f(b,a,i-1):''

console.log(f(1,1));
console.log(f(1,2));
console.log(f(2,1));
console.log(f(2,2));
console.log(f(6,4));
console.log(f(4,6));
console.log(f(2,3));
console.log(f(3,2));
console.log(f(10,10));
console.log(f(3, 6));
console.log(f(2, 5));
console.log(f(4, 3));
console.log(f(10, 10));
console.log(f(10, 5));
console.log(f(10, 6));
console.log(f(24, 8));
console.log(f(7, 8));
console.log(f(6, 8));
console.log(f(13, 11));

# JavaScript (ES6), 93 bytes

f=(a,b,i=2,g=(c,d)=>!d=>d?c:g(d,c%d):c)=>i?('-'.repeat(a-1)+'|').repeat(a*bb/g(a,b)/a)+
+f(b,a,i-1):''


Same algorithm as before, using repeat instead of padStart.

• I thought padStart was ES8? – Neil Sep 25 '17 at 23:34
• f=(a,b,A=1)=>(A%a?'-':'|')+(A%a|A%b?f(a,b,A+1):a<0?'':\n+f(-b,a)) – l4m2 Oct 22 '18 at 6:05
• @l4m2, I can barely understand code that I wrote a year ago, but it does look like yours does shave off some bytes, thanks! – Rick Hitchcock Oct 22 '18 at 19:24

# Scala, 98 bytes

print((a to a*b).find(l=>l%a+l%b==0).map(l=>("-"*(a-1)+"|")*(l/a)+"\n"+("-"*(b-1)+"|")*(l/b)).get)


Try it online

• Hi, welcome to PPCG! This looks like a great first answer, so +1 from me. I'm not sure, since I've never programmed in Scala, but can *(a-1) be golfed to *~-a and *(b-1) to *~-b? Also, could you perhaps add a TIO link with test code? (Oh, and that avatar doesn't seem very cubic to me. ;p) – Kevin Cruijssen Sep 26 '17 at 14:31
• Thanks! The trick with *~-a is great, but unfortunately Scala requires more brackets: *(~(-a)) to make clear that the concatenations *~-, *~, ~- are not fancy function names. I added a TIO link. – cubic lettuce Sep 27 '17 at 7:12
• Ah yes, ~- can be function names in Scala. I remember someone mentioning that before quite a while ago. That's unfortunate regarding golfing. Again welcome, and nice first answer. – Kevin Cruijssen Sep 27 '17 at 7:37

# Java (OpenJDK 8), 103 bytes

a->b->{String l="",r="|\n";for(int m=0;(++m%a|m%b)>0;r+=m%b<1?'|':'-')l+=m%a<1?'|':'-';return l+r+'|';}


Try it online!

### 110 bytes, n input values

a->{String s="";for(int v:a){for(int i=1,z=1;z>(z=0);s+=i++%v<1?'|':'-')for(int k:a)z|=i%k;s+='\n';}return s;}


Try it online!

# Java 8, 125118 117 bytes

a->b->{String A="\n",B=A,t="|";for(int i=1;!A.endsWith(t)|!B.endsWith(t);B+=i++%b<1?t:"-")A+=i%a<1?t:"-";return A+B;}


-7 bytes thanks to @Nevay.
-1 byte by starting with a trailing new-line (A="",B="\n" replaced with A="\n",B=A).

Explanation:

Try it here.

a->b->{             // Method with two integer parameters and String return-type
String A="\n",    //  String top line (starting with a trailing new-line)
B=A,       //  String bottom-line (starting with a new-line)
t="|";     //  Temp String "|" which is used multiple times
for(int i=1;      //  Index-integer, starting at 1
!A.endsWith(t)|!B.endsWith(t);
//  Loop as long as both Strings aren't ending with "|"
B+=           //    After every iteration: append B with:
i++%b<1?   //     If i is divisible by b:
//     (and increase i by 1 in the process)
t         //      t (holding "|")
:          //     Else:
"-")      //      A literal "-"
A+=             //   Append A with:
i%a<1?       //    If i is divisible by a
t           //     t (holding "|")
:            //    Else:
"-";        //     A literal "-"
//  End of loop (implicit / single-line body)
return A+B;       //  Return both lines, separated by the new-line B started with
}                   // End of method

• 118 bytes: a->b->{String A="",B="\n",k="|";for(int i=0;!A.endsWith(k)|!B.endsWith(k);B+=i%b<1?k:"-")A+=++i%a<1?k:"-";return A+B;} – Nevay Sep 27 '17 at 17:16
• @Nevay Thanks. Can't believe I missed the most obvious thing !A.endsWith(t)|!B.endsWith(t) when I was looking for a short way to check whether both are ending with |.. And starting B with a new-line instead of putting it between them at the return is also smart. – Kevin Cruijssen Sep 27 '17 at 17:24

# Python 2, 96 88 bytes

Edit: Saved 4 bytes thanks to @Leaky Nun

Edit: Saved 4 bytes thanks to @Rod

lambda a,b:b/gcd(a,b)*("-"*~-a+"|")+"\n"+a/gcd(a,b)*("-"*~-b+"|")
from fractions import*


Try it online!

• 88 bytes or 77 bytes for a more flexible output – Rod Sep 25 '17 at 18:56
• 88 bytes – ovs Sep 25 '17 at 18:57
• Apparently outputting a list of strings isn't acceptable. :I Replace [...] with '\n'.join(...) to fix. – totallyhuman Sep 25 '17 at 19:22

# Python 2, 89 bytes

Not the shortest Python 2 entry, but a different approach than gcd which may still be golfable.

a,b=input()
h,p='-|'
x=b*(h*~-a+p),a*(h*~-b+p)
for v in x:print v[~zip(*x).index((p,p)):]


Try it online!

a#b=do x<-[a,b];lcm a btakecycle(([2..x]>>"-")++"|")++"\n"


Try it online!

Same length:

a#b=unlines[take(lcm a b)$cycle$([2..x]>>"-")++"|"|x<-[a,b]]


Old solution:

l!x=[1..div l x]>>([2..x]>>"-")++"|"
a#b|l<-lcm a b=l!a++'\n':l!b

• You can save a byte with '\n':. – Laikoni Sep 25 '17 at 21:05
• @Laikoni Careful, I am closing in on you – BlackCap Sep 26 '17 at 9:54

# C (gcc), 121999392 89 bytes

This should be much shorter, hmmmm....

#define L(x)for(j=-1,i=a;j<i;i+=i%b||i%a)putchar(++j?j%x?45:124:10);
i,j;f(a,b){L(a)L(b)}


Try it online!

# J, 20 bytes

'-|'{~*.$&>;&(<:=i.)  Try it online! • this is pretty J – Jonah Sep 26 '17 at 1:33 # SOGL V0.12, 19 16 bytes 2{H┌*┐+..*..g/mP  Try it Here! Explanation: 2{ two times do H decreate ToS - input - by 1 ┌* get that many dashes ┐+ append a vertical bar ..* push both inputs multiplied \ ..g push gcd(input1, input2) | LCM - 7 bytes :/ / divide the multiblication by the GCD / m mold the string to that length P print that in a new line  • You documented before implementing? o0 – totallyhuman Sep 25 '17 at 19:23 • @icrieverytim SOGL has many, many documentated things that aren't implemented. :p The documentation is basically my TODO list (which I rarely do :p) – dzaima Sep 25 '17 at 19:24 # Stacked, 42 38 bytes [:...lcm@z:[:z\/\#-'-'*\rep'|'+out]"!]  Try it online! Input in the form of a pair of numbers. All the test cases put together look kinda like buildings. ## Explanation This first takes the lcm of the two input numbers into z. Then, for each number k, we generate z / k strings of - of length k - 1, adding | to the end of each, and outputting each. ## Previous counted attempts 42 bytes: [:...lcm@z:[:z\/\#-'-'*\rep'|'+''#out]"!] ## Other attempts 43 bytes: [:...lcm@z:[:z\/\#-'-'*\rep'|'#'|'+out]"!] 45 bytes: ['@lcm'!#~@z,[:z\/\#-'-'*\rep'|'#'|'+out]"!] 45 bytes: [:...lcm@x[x'-'*\#<$betailmap'|'#'|'+out]"!]

53 bytes: [:...lcm'-'*@z#-'.'*'('\+')'+'.'+[z\'$1|'repl out]"!] 54 bytes: [:...lcm@x{!x'-'*('('n#-'.'*').')''#'$1|'repl out}"!]

# JavaScript (ES6), 89

f=(a,b,t=
,l=0,R=n=>'-'.repeat(n-1)+'|')=>l||1/t?f(a,b,l<0?t+R(b,l+=b):R(a,l-=a)+t,l):t


Evaluating the LCM with repeated addictions.

Less golfed

F=(a,b, sa='', sb='', la=0, lb=0)=>
{
var R=n=>'-'.repeat(n-1)+'|'
if (la != lb || la == 0)
{
if (la < lb) {
sa += R(a)
la += a
}
else
{
sb += R(b)
lb += b
}
return F(a, b, sa, sb, la, lb)
}
else
return sa+'\n'+sb
}


Test

f=(a,b,t=
,l=0,R=n=>'-'.repeat(n-1)+'|')=>l||1/t?f(a,b,l<0?t+R(b,l+=b):R(a,l-=a)+t,l):t

function update()
{
var [a,b]=I.value.match(/\d+/g)
R.textContent = f(+a,+b)
}

update()
<input id=I oninput='update()' value='4 6'>
<pre id=R></pre>

VBA (Excel) , 144 142 bytes

Sub q()
a=[a1]
b=[a2]
Do Until c=d And d="|"
e=e+1
c=IIf(e Mod a,"-","|")
d=IIf(e Mod b,"-","|")
f=f& c
g=g& d
Loop
Debug.? f& vbCr& g
End Sub


-2 bytes. thanks Sir Washington Guedes.

• Yes Thank you @WashingtonGuedes. :) – remoel Sep 27 '17 at 2:35

# Ruby, 64 57 bytes

->a,b{[a,b].map{|n|(1..a.lcm(b)).map{|x|x%n>0??-:?|}*''}}


-7 bytes thanks to G B.

Try it online!

• You don't need to include the 'puts', if the function returns 2 strings it's ok. And you can make it shorter by using the array * operator (array*'' is equivalent to array.join) – G B Sep 29 '17 at 6:16
• @GB thanks for your help! – Snack Sep 29 '17 at 17:07

# Charcoal, 3230 29 bytes

ＮθＮη≔θζＷ﹪ζη≦⁺θζＥ⟦θη⟧…⁺×-⁻ι¹|ζ


Try it online! Link is to verbose version of code. Edit: Saved 1 byte thanks to @ASCII-only.

Anonymous worksheet formula that takes input from range A1:B1 and outputs to the calling cell

=REPT(REPT("-",A1-1)&"|",LCM(1:1)/A1)&"
"&REPT(REPT("-",B1-1)&"|",LCM(1:1)/B1


-4 Bytes thanks to @EngineerToast

• Can you presume that the nothing else is input to row 1? If so, you can shorted LCM(A1,B1) to just LCM(1:1) to save 4 bytes. I think it's reasonable to presume a blank starting sheet and specify where both the inputs and formula are. – Engineer Toast Oct 19 '18 at 20:41

# Excel VBA, 79 Bytes

Anonymous VBE immediate window function that takes input from the range [A1:B1] and outputs a visualization of their LCM to the VBE immediate window.

?[Rept(Rept("-",A1-1)&"|",LCM(1:1)/A1)]:?[Rept(Rept("-",B1-1)&"|",LCM(1:1)/B1)]


# Japt, 12 bytes

£×/Ury)î|ù-X


Japt Interpreter

Inputs as an array of numbers. Outputs as an array of strings. The -R flag slightly improves how the output looks, but isn't necessary for the logic.

Explanation:

£              For each of the two inputs as X, print...
|           The string "|"
ù-X        Left-padded with "-" until it is X characters long
î            Repeated until its length is
×/Ury)             The Least Common Multiple

Extra thanks to Shaggy for finding some bytes to save.

• 15 bytes – Shaggy Oct 23 '18 at 19:10
• @Shaggy Interesting, I never thought to use that part of Japt in that exact way. – Kamil Drakari Oct 23 '18 at 19:17
• Knocked another few bytes off – Shaggy Oct 23 '18 at 19:33