Code Golf: Least Common Multiple

9

3

"CodeGolf" challenge: write the shortest practical Least Common Multiple function that:

  1. Does not use built in GCD, LCM or any related fuctions
  2. Accepts multiple arguments in any order, e.g. LCM[3, 20, 6]
  3. In the spirit of the original, obfuscated is better

Mr.Wizard

Posted 2012-01-25T19:37:22.763

Reputation: 259 163

There were some discussions in the chat room that felt against code golf questions. Hmm... – J. M.'s ennui – 2012-01-25T22:09:05.847

@J.M. I missed them. If you've got a link I'll read them. – Mr.Wizard – 2012-01-25T22:28:15.160

Apparently, it's in meta already. Never mind, then...

– J. M.'s ennui – 2012-01-25T22:35:10.860

Answers

10

I am not sure how this compares in terms of length but it does not throw errors and isn't even obfuscated:

lcm[ls__] := 
 Fold[Denominator[Together[Unique[x]/#1 + Unique[x]/#2]] &, 
  First[{ls}], Rest[{ls}]

Just to check it works:

f = RandomInteger[{1, 100}, 200];

lcm @@ f == LCM @@ f
True

Andrzej Kozlowski

Posted 2012-01-25T19:37:22.763

Reputation: 2 684

Thanks for answering. To format your code, select it and click the curly-brackets button above the text box. – Mr.Wizard – 2012-01-25T21:57:19.200

Yes, I did just that but as you beat me to it it wouldn't let me save my edits ;-) Come to think of it, I am not even sure if using addition of fractions violates the condition about not using "related functions"... – Andrzej Kozlowski – 2012-01-25T22:02:06.443

Good enough for me. :-) – Mr.Wizard – 2012-01-25T22:07:21.997

9

New code, Golfing Simon's method (now v10-syntax compatible):

lcm = Fold[#/#2/._~_~x_|_:># x&,1,{##}]&

This was my original code from a tongue-in-cheek answer on StackOverflow:

gcd = If[#2==0,#,#2~#0~Mod@##]&
lcm = Fold[##/gcd@##&,#,{##2}]&

As a one-liner:

lcm = Fold[If[#2==0,#,#2~#0~Mod@##]&@##^-1##&,#,{##}]&

Intentionally obfuscated:

lcm = If[{}!={##2},#0[If[#2==0,#,#2~#0~Mod@##]&[#,#2]^-1#*#2,##3],#]&

The fact that it throws errors yet works just fine is part of the game.

Mr.Wizard

Posted 2012-01-25T19:37:22.763

Reputation: 259 163

Outstanding! It never occurred to me that you could deal with Rationals and Integers in a single rule. Brilliant stuff. I had a look to see if I could replace Fold with some #0 trickery, but the code to terminate the recursion is just too big. If only Fold was a longer word :-) I think this might just be unbeatable. – Simon Woods – 2012-07-14T12:20:43.023

@Simon Thanks. :-) Using | on the LHS of a pattern is one of my favorite "tricks." I too experimented with using #0 in place of Fold: that is my "Intentionally obfuscated" line at the end of my answer. By the way, if you use my Fold modification you can knock a couple of characters off of this code.

– Mr.Wizard – 2012-07-14T18:12:20.637

1@Mr.Wizard While musing these fine examples, I figured I couldn't run the first line of your beautiful solution, as now we have associations and #x results in errors. The problem is solved by inserting a space between them. – Stitch – 2017-01-23T18:43:02.867

@Stitch Thanks; fixed now. – Mr.Wizard – 2017-06-14T23:55:20.770

6

I couldn't resist having a go. This is pretty small:

lcm = Fold[#(#/#2/.{_~_~x_:>x,_->1})&,1,{##}]&

Simon Woods

Posted 2012-01-25T19:37:22.763

Reputation: 81 905

Marvelous! Just what I was hoping for. Thanks for playing, Simon. I do like your style. :-) – Mr.Wizard – 2012-07-13T22:48:20.073

Simon, I Accepted this answer for a short while, but seeing as I was able to shorten it significantly lifted the Accept. See if you can again beat me. – Mr.Wizard – 2012-07-14T00:31:37.407