Calculate Landau's function

19

1

Landau's function \$g(n)\$ (OEIS A000793) gives the maximum order of an element of the symmetric group \$S_n\$. Here, the order of a permutation \$\pi\$ is the smallest positive integer \$k\$ such that \$\pi^k\$ is the identity - which is equal to the least common multiple of the lengths of the cycles in the permutation's cycle decomposition. For example, \$g(14) = 84\$ which is achieved for example by (1,2,3)(4,5,6,7)(8,9,10,11,12,13,14).

Therefore, \$g(n)\$ is also equal to the maximum value of \$\operatorname{lcm}(a_1, \ldots, a_k)\$ where \$a_1 + \cdots + a_k = n\$ with \$a_1, \ldots, a_k\$ positive integers.

Problem

Write a function or program that calculates Landau's function.

Input

A positive integer \$n\$.

Output

\$g(n)\$, the maximum order of an element of the symmetric group \$S_n\$.

Examples

n    g(n)
1    1
2    2
3    3
4    4
5    6
6    6
7    12
8    15
9    20
10   30
11   30
12   60
13   60
14   84
15   105
16   140
17   210
18   210
19   420
20   420

Score

This is : Shortest program in bytes wins. (Nevertheless, shortest implementations in multiple languages are welcome.)

Note that there are no requirements imposed on run-time; therefore, your implementation does not necessarily need to be able to generate all the above example results in any reasonable time.

Standard loopholes are forbidden.

Daniel Schepler

Posted 2019-08-30T16:12:31.470

Reputation: 1 001

Answers

9

05AB1E, 6 bytes

Åœ€.¿Z

Try it online!

    Ŝ       # integer partitions of the input
      €.¿    # lcm of each
         Z   # maximum

Grimmy

Posted 2019-08-30T16:12:31.470

Reputation: 12 521

10

Wolfram Language (Mathematica), 44 bytes

Max[PermutationOrder/@Permutations@Range@#]&

Try it online!

Wolfram Language (Mathematica), 31 bytes

@DanielSchepler has a better solution:

Max[LCM@@@IntegerPartitions@#]&

Try it online!

Roman

Posted 2019-08-30T16:12:31.470

Reputation: 1 190

Not that familiar with the language - but Max[Apply@LCM/@IntegerPartitions@#]& seems to work for me and would give 36 bytes if it's correct. – Daniel Schepler – 2019-08-30T17:22:37.407

2

@DanielSchepler yes, super! Why don't you propose it as a separate solution? You can even do Max[LCM@@@IntegerPartitions@#]& for 31 bytes, because @@@ does Apply at level 1.

– Roman – 2019-08-30T17:39:39.870

4

Haskell, 44 bytes

(%1)
n%t=maximum$t:[(n-d)%lcm t d|d<-[1..n]]

Try it online!

xnor

Posted 2019-08-30T16:12:31.470

Reputation: 115 687

4

Python, 87 bytes

f=lambda n,d=1:max([f(m,min(range(d,d<<n,d),key=(n-m).__rmod__))for m in range(n)]+[d])

Try it online!

A recursive function that tracks the remaining n to partition and the running LCM d. Note that this means we don't need to track the actual numbers in the partition or how many of them we've used. We try each possible next part, n-m, replacing n with what's left m, and d with lcm(d,n-m). We take the maximum of those recursive results and d itself. When nothing remains n=0, the result ist just d.

The tricky thing is that Python doesn't have any built-ins for LCM, GCD, or prime factorization. To do lcm(d,m-n), we generate a list of multiples of d, and take the value attaining the minimum modulo n-m, that is with key=(n-m).__rmod__. Since min will give the earlier value in case of a tie, this is always the first nonzero multiple of d that's divisible by n-m, so their LCM. We only multiples of d up to d*(n-m) to be guaranteed to hit the LCM, but it's shorter to write d<<n (which is d*2**n) which suffices with Python's upper bounds being exclusive.

Python 3's math library has gcd (but not lcm) after 3.5, which is a few bytes shorter. Thanks to @Joel for shortening the import.

Python 3.5+, 84 bytes

import math
f=lambda n,d=1:max([f(m,d*(n-m)//math.gcd(n-m,d))for m in range(n)]+[d])

Try it online!

Using numpy's lcm is yet shorter.

Python with numpy, 77 bytes

from numpy import*
f=lambda n,d=1:max([f(m,lcm(d,n-m))for m in range(n)]+[d])

Try it online!

xnor

Posted 2019-08-30T16:12:31.470

Reputation: 115 687

Using from math import* is 85 bytes and using import math + math.gcd(...) is 84 bytes. The same applies to numpy. – Joel – 2019-08-31T03:21:41.660

@Joel Thanks, I forgot about that. – xnor – 2019-08-31T03:25:33.137

@Joel Thanks, I had forgotten to update the byte count, they're both 77. numpy's length of 5 is the break-even point for import*.

– xnor – 2019-08-31T03:30:15.997

Right. In that case I prefer to use import numpy because numpy.max would override Python's built-in max (same for min) if from numpy import* is used. It does not cause problems here but we all know that import* is not a good programming practice in general. – Joel – 2019-08-31T03:34:08.913

@Joel While import* is no doubt bad practice, I don't think it actually overwrites Python's min and max, so the confusion would be someone expecting numpy's function and getting the base one. – xnor – 2019-08-31T03:39:37.973

Oh, you are right. I saw a warning about that in an earlier version of numpy. Maybe in the newer versions the behavior has changed. – Joel – 2019-08-31T03:43:17.513

3

Jelly, 7 bytes

Œṗæl/€Ṁ

Try it online!

A monadic link taking an integer as its argument and returning an integer.

Explanation

Œṗ      | Integer partitions
  æl/€  | Reduce each using LCM
      Ṁ | Maximum

Nick Kennedy

Posted 2019-08-30T16:12:31.470

Reputation: 11 829

3

JavaScript (ES6), 92 bytes

Computes the maximum value of \$\operatorname{lcm}(a_1,\ldots,a_k)\$ where \$a_1+\ldots+a_k\$ is a partition of \$n\$.

f=(n,i=1,l=m=0)=>n?i>n?m:f(n-i,i,l*i/(G=(a,b)=>b?G(b,a%b):a)(l,i)||i)&f(n,i+1,l)|m:m=l>m?l:m

Try it online!


JavaScript (ES6), 95 bytes

f=(n,i=1,m)=>i>>n?m:f(n,i+1,i<m|(g=(n,k=2,p=0)=>k>n?p:n%k?p+g(n,k+1):g(n/k,k,p*k||k))(i)>n?m:i)

Try it online!

How?

We define:

$$\cases{ g(1)=0\\ g(n)=\sum_{j=1}^{N}{p_j}^{k_j}\quad\text{for}\enspace n>1\enspace\text{and}\enspace n=\prod_{j=1}^{N}{p_j}^{k_j} }$$

(this is A008475)

Then we use the formula (from A000793):

$$f(n)=\max_{g(k)\le n}k$$

Arnauld

Posted 2019-08-30T16:12:31.470

Reputation: 111 334

3

Perl 6, 50 bytes

{max .map:{+(.[$_],{.[@^a]}...$_,)}}o&permutations

Try it online!

Checks all permutations directly, like @histocrat's Ruby solution.

Explanation

                                     &permutations  # Permutations of [0;n)
{                                  }o  # Feed into block
     .map:{                       }  # Map permutations
                           ...  # Construct sequence
             .[$_]  # Start with permutation applied to itself [1]
                  ,{.[@^a]}  # Generate next item by applying permutation again
                              $_,  # Until it matches original permutation [2]
           +(                    )  # Length of sequence
 max  # Find maximum

1 We can use any sequence of n distinct items for the check, so we simply take the permutation itself.

2 If the endpoint is a container, the ... sequence operator smartmatches against the first item. So we have to pass a single-element list.

nwellnhof

Posted 2019-08-30T16:12:31.470

Reputation: 10 037

2

Gaia, 25 23 22 bytes

,:Π¤d¦&⊢⌉/
1w&ḍΣ¦¦⇈⊢¦⌉

Try it online!

Not having LCM or integer partitions makes this approach rather long.

,:Π¤d¦&⊢⌉/		;* helper function: LCM of 2 inputs


1w&ḍΣ¦¦			;* push integer partitions
         ¦		;* for each
       ⇈⊢		;* Reduce by helper function
	  ⌉		;* and take the max

Giuseppe

Posted 2019-08-30T16:12:31.470

Reputation: 21 077

2

Ruby, 77 bytes

f=->n{a=*0...n;a.permutation.map{|p|(1..).find{a.map!{|i|p[i]}==a.sort}}.max}

Try it online!

(1..) infinite range syntax is too new for TIO, so the link sets an arbitrary upper bound.

This uses the direct definition--enumerate all possible permutations, then test each one by mutating a until it gets back to its original position (which also conveniently means I can just mutate the original array in each loop).

histocrat

Posted 2019-08-30T16:12:31.470

Reputation: 20 600

2

Haskell, 70 67 bytes

f n=maximum[foldl1 lcm a|k<-[1..n],a<-mapM id$[1..n]<$[1..k],sum a==n]

Try it online!

Edit: -3 bytes thanks to @xnor.

nimi

Posted 2019-08-30T16:12:31.470

Reputation: 34 639

I think it should work to do mapM(:[1..n]), since the extra element is harmless. – xnor – 2019-08-31T02:18:01.387

1

Python 3 + numpy, 115 102 99 bytes

-13 bytes thanks to @Daniel Shepler

-3 more bytes from @Daniel Shepler

import numpy
c=lambda n:[n]+[numpy.lcm(i,j)for i in range(1,n)for j in c(n-i)]
l=lambda n:max(c(n))

Try it online!

Brute force method: find all possible sequences a,b,c,... where a+b+c+...=n, then pick the one with the highest lcm.

Hiatsu

Posted 2019-08-30T16:12:31.470

Reputation: 679

Incidentally, I have a Python 3 + numpy solution running 87 bytes. – Daniel Schepler – 2019-08-30T17:01:48.457

I don't know enough about numpy to figure out how to do that, so I suggest you just post your solution separately. – Hiatsu – 2019-08-30T17:03:51.967

Well, I was planning to wait for a while to post it. – Daniel Schepler – 2019-08-30T17:08:41.357

I just realized you posted this challenge. Sorry, I'll do my best. – Hiatsu – 2019-08-30T17:11:08.977

Since it came up, you should not try to run this solution for any input higher than 26, even with caching. After nearly freezing my computer for about two and a half hours, the process was killed without giving out an answer. This is not surprising, since it had to calculate the maximum of summing each of about 2^26 lists, which are not memory efficient. – Hiatsu – 2019-08-30T22:30:14.387

1

If you change c to return a set and memoize it doesn't do badly at all (though admittedly it does ungolf a bit): https://tio.run/##RY1BCsIwEEX3PUWWM1CLoiuhV/AKEsfUTkkmIU3AWnr2Ggvq7vM@//0wpd7LcV3ZBR@TkuzCVFFrtbvdtZLzLEuThb3AvHWNJQdcD9j5qFixqKjlYeBQy4aGDyKQHeOClf2LnH5C4Yjfqy4LJe/tWO5@ubExX0lTb6AMRn6Z9uLFIBBWIbIksHDaF8kb

– Daniel Schepler – 2019-08-30T22:55:45.587

0

Pyth, 24 15 bytes

eSm.U/*bZibZd./

Try it online!

             ./Q  # List of partitions of the input
  m               # map that over lambda d:
   .U       d     # reduce d (with starting value first element of the list) on lambda b,Z:
     /*bZgbZ      # (b * Z) / GCD(b, Z)
 S                # this gives the list of lcms of all partitions. Sort this
e                 # and take the last element (maximum)

-9 bytes: paid attention and noticed that Pyth actually has a GCD builtin (i).

ar4093

Posted 2019-08-30T16:12:31.470

Reputation: 531