Compute the Carmichael function

36

4

Task description

In number theory, the Carmichael function λ takes a positive integer n and returns the least positive integer k so that the k-th power of each integer coprime to n equals 1 modulo n.

Given a positive integer n, your solution must compute λ(n). The shortest code in bytes wins.

Your program should theoretically work for arbitrarily large inputs, but doesn’t need to be efficient.

Tips

The sequence of all λ(n) is OEIS A002322.

An ungolfed Python implementation would look like

from fractions import gcd

def carmichael(n):
    coprimes = [x for x in range(1, n) if gcd(x, n) == 1]
    k = 1
    while not all(pow(x, k, n) == 1 for x in coprimes):
        k += 1
    return k

(In Python, pow(A, B, C) efficiently computes pow(A, B) % C.)

Test cases

Input    Output
1        1
2        1
3        2
10       4
35       12
101      100
530      52
3010     84
6511     3056
10000    500

Lynn

Posted 2016-09-18T18:07:49.620

Reputation: 55 648

What does theoretically mean here? Can I assume that the input n fits in a 16-bit integer? Can I assume that n^λ(n) fits in a double? – Dennis – 2016-09-20T22:00:56.267

2Yes and yes, I’d say. As in, the theoretically includes pretend your native types are arbitrarily precise and large (I thought that was consensus, but I’m not sure). – Lynn – 2016-09-20T23:23:23.207

Answers

48

Mathematica, 16 bytes

CarmichaelLambda

Well...

Martin Ender

Posted 2016-09-18T18:07:49.620

Reputation: 184 808

38..... really. ._. – acrolith – 2016-09-18T18:38:16.660

12I don't like u mathematica – downrep_nation – 2016-09-19T09:00:02.077

29

Python, 76 73 67 bytes

f=lambda n,k=1:1-any(a**-~k*~-a**k%n for a in range(n))or-~f(n,k+1)

Try it online!

A further byte could be saved by returning True instead of 1.

Alternative implementation

Using the same approach, there is also the following implementation by @feersum which doesn't use list comprehensions.

f=lambda n,k=1,a=1:a/n or(a**-~k*~-a**k%n<1)*f(n,k,a+1)or-~f(n,k+1)

Note that this implementation requires O(nλ(n)) time. Efficiency could be improved dramatically while actually decreasing score to 66 bytes, but the function would return True for input 2.

f=lambda n,k=1,a=1:a/n or~-a**k*a**-~k%n<1==f(n,k,a+1)or-~f(n,k+1)

Background

Definitions and notation

All employed variables will denote integers; n, k, and α will denote positive integers; and p will denote a positive prime.

a | b if b is divisible by a, i.e., if there is q such that b = qa.

a ≡ b (mod m) if a and b have the same residue modulo m, i.e., if m | a - b.

λ(n) is the smallest k such that ak ≡ 1 (mod n) – i.e., such that n | ak - 1 – for all a that are coprime to n.

f(n) is the smallest k such that a2k+1 ≡ ak+1 (mod n) – i.e., such that n | ak+1(ak - 1) – for all a.

λ(n) ≤ f(n)

Fix n and let a be coprime to n.

By the definition of f, n | af(n)+1(af(n) - 1). Since a and n do not have a common prime factor, neither do af(n)+1 and n, which implies that n | af(n) - 1.

Since λ(n) is the smallest integer k such that n | ak - 1 for all integers a that are coprime to n, it follows that λ(n) ≤ f(n).

λ(n) = f(n)

Since we've already established the inequality λ(n) ≤ f(n), it is sufficient to verify that k = λ(n) satisfies the condition that defines f, i.e., that n | aλ(n)+1(aλ(n) - 1) for all a. For this purpose, we'll establish that pα | aλ(n)+1(aλ(n) - 1) whenever pα | n.

λ(k) | λ(n) whenever k | n (source), so (aλ(k) - 1)(aλ(n)-λ(k) + aλ(n)-2λ(k) + ⋯ + aλ(k) + 1) = aλ(n) - 1 and, therefore, aλ(k) - 1 | aλ(n) - 1 | aλ(n)+1(aλ(n) - 1).

If a and pα are coprime, by the definition of λ and the above, pα | aλ(pα) - 1 | aλ(n)+1(aλ(n) - 1) follows, as desired.

If a = 0, then aλ(n)+1(aλ(n) - 1) = 0, which is divisible by all integers.

Finally, we must consider the case where a and pα have a common prime factor. Since p is prime, this implies that p | a. Carmichael's theorem establishes that λ(pα) = (p - 1)pα - 1 if p > 2 or α < 3 and that λ(pα) = pα - 2 otherwise. In all cases, λ(pα) ≥ pα - 2 ≥ 2α - 2 > α - 2.

Therefore, λ(n) + 1 ≥ λ(pα) + 1 > α - 1, so λ(n) + 1 ≥ α and pα | pλ(n)+1 | aλ(n)+1 | aλ(n)+1(aλ(n) - 1). This completes the proof.

How it works

While the definitions of f(n) and λ(n) consider all possible values of a, it is sufficient to test those that lie in [0, ..., n - 1].

When f(n, k) is called, it computes ak+1(ak - 1) % n for all values of a in that range, which is 0 if and only if n | ak+1(ak - 1).

If all computed residues are zero, k = λ(n) and any returns False, so f(n, k) returns 1.

On the other hand, while k < λ(n), 1-any(...) will return 0, so f is called recursively with an incremented value of k. The leading -~ increments the return value of f(n, k + 1), so we add 1 to f(n, λ(n)) = 1 once for every integer in [1, ..., λ(n) - 1]. The final result is thus λ(n).

Dennis

Posted 2016-09-18T18:07:49.620

Reputation: 196 637

You can save at least 4 with recursion instead of a list comprehension: f=lambda n,k=1,a=1:a/n or(a**k*~-a**k%n<1)*f(n,k,a+2-n%2)or-~f(n,k+1) (Add back one byte if you don't like it to take n**λ(n) time). – feersum – 2016-09-19T19:01:57.523

1Thanks! In the meantime, I found an improvement to my algorithm that seems to nullify the benefit of recursing instead of using a list comprehension. – Dennis – 2016-09-19T22:00:34.060

14

Mathematica without built-in, 58 57 bytes

Thanks to Martin Ender for finding an error, then saving me the bytes it took to fix it!

Thanks to miles for saving 1 byte! (which seemed like 2 to me)

Built-ins are totally fine ... but for those who want to implement it without using brute force, here's a formula for the Carmichael function:

LCM@@(EulerPhi[#^#2]/If[#==2<#2,2,1]&@@@FactorInteger@#)&

If p is a prime, the Carmichael function λ(p^r) equals φ(p^r) = (p-1)*p^(r-1)—except when p=2 and r≥3, in which case it's half that, namely 2^(r-2).

And if the prime-power factorization of n equals p1^r1 * p2^r2 * ..., then λ(n) equals the least common multiple of { λ(p1^r1), λ(p2^r2), ...}.

Runtime is one instant more than factoring the integer in the first place.

Greg Martin

Posted 2016-09-18T18:07:49.620

Reputation: 13 940

You can use EulerPhi to get LCM@@(EulerPhi[#^#2]/If[#==2<#2,2,1]&@@@FactorInteger@#)& for 57 bytes. – miles – 2016-09-19T13:11:21.070

@miles nicely spotted! I count 56 bytes, can you check? – Greg Martin – 2016-09-19T18:11:40.943

Yeah, it's 57 bytes.

– miles – 2016-09-19T19:13:40.603

clearly I even try to golf my counting.... :/ – Greg Martin – 2016-09-19T19:23:40.663

12

Templates Considered Harmful, 246 bytes

Fun<Ap<Fun<If<Eq<A<2>,T>,A<1>,And<Eq<Ap<Fun<If<A<1>,Ap<A<0>,Rem<A<2>,A<1>>,A<1>>,A<2>>>,A<1,1>,A<2>>,T>,Sub<Ap<Fun<Rem<If<A<1>,Mul<A<2,1>,Ap<A<0>,Sub<A<1>,T>>>,T>,A<1,2>>>,A<1>>,T>>,Ap<A<0>,Add<A<1>,T>,A<1,1>>,Ap<A<0>,A<1>,Sub<A<2>,T>>>>,T,A<1>>>

An unnamed function (not that there are named functions).

This is a forgotten esolang of mine which is interpreted by a C++ compiler instantiating templates. With the default max template depth of g++, it can do λ(35), but it can't do λ(101) (the lazy evaluation makes things worse).

feersum

Posted 2016-09-18T18:07:49.620

Reputation: 29 566

10

Haskell, 57 56 bytes

f n=[k|k<-[1..],and[mod(m^k)n<2|m<-[1..n],gcd m n<2]]!!0

dianne

Posted 2016-09-18T18:07:49.620

Reputation: 1 049

8

dianne

Posted 2016-09-18T18:07:49.620

Reputation: 1 049

31............. ._. – Maltysen – 2016-09-18T18:20:43.170

10I never understand the point of implementing such ridiculously specific built-ins. – Fatalize – 2016-09-18T19:24:30.420

31This is almost an addition to the language specifically made for this challenge. Commit by Lynn 2 days ago, challenge by @Lynn today – edc65 – 2016-09-18T19:59:39.817

5@edc65 Not to mention that this built-in is pretty much useless outside this challenge and derivatives of it. – Fatalize – 2016-09-19T06:36:22.373

3Well, the Carmichael function is important in number theory (as the currently top answer reflects), so I wouldn't call it useless. – Greg Martin – 2016-09-19T19:25:00.757

2@Fatalize: Do you have 65536 other functions you'd be inclined to implement before this one? – None – 2016-09-20T08:40:11.217

6

Pyth - 19 18 17 bytes

One byte saved thanks to @TheBikingViking.

Straight up brute force.

f!sm*t.^dTQq1iQdQ

Try it online here.

Maltysen

Posted 2016-09-18T18:07:49.620

Reputation: 25 023

f!smt is one byte shorter. – TheBikingViking – 2016-09-18T19:18:51.917

@TheBikingViking oh, yeah thanks – Maltysen – 2016-09-18T19:23:13.243

Hurts my eyes, how the heck is this python..? Loved it nonetheless haha :) – Yohan Obadia – 2018-04-24T14:22:03.403

6

Ruby, 59 56 bytes

->x{a=1..x
a.detect{|k|a.all?{|y|x.gcd(y)>1||y**k%x<2}}}

m-chrzan

Posted 2016-09-18T18:07:49.620

Reputation: 1 390

5

J, 28 27 bytes

[:*./@(5&p:%2^0=8&|)2^/@p:]

The Carmichael function is λ(n) and the totient function is φ(n).

Uses the definition where λ(pk) = φ(pk)/2 if p = 2 and k > 2 else φ(pk). Then, for general n = p1k1 p2k2piki, λ(n) = LCM[ λ(p1k1) λ(p2k2) ⋯ λ(piki) ].

Usage

Extra commands used to format multiple input/output.

   f =: [:*./@(5&p:%2^0=8&|)2^/@p:]
   f 530
52
   (,.f"0) 1 2 3 10 35 101 530 3010 6511 10000
    1    1
    2    1
    3    2
   10    4
   35   12
  101  100
  530   52
 3010   84
 6511 3056
10000  500

Explanation

[:*./@(5&p:%2^0=8&|)2^/@p:]  Input: integer n
                          ]  Identity function, get n
                    2   p:   Get a table of prime/exponent values for n
                     ^/@     Raise each prime to its exponent to get the prime powers of n
[:    (            )         Operate on the prime powers
                8&|            Take each modulo 8
              0=               Test if its equal to 0, 1 if true else 0
            2^                 Raise 2 to the power of each
       5&p:                    Apply the totient function to each prime power
           %                   Divide it by the powers of 2
  *./@                       Reduce using LCM and return

miles

Posted 2016-09-18T18:07:49.620

Reputation: 15 654

This gives the wrong answer for 10000 (1000 instead of the correct 500), and indeed for every multiple of 8. 2 is a peculiar prime, and λ(2^a) = 2^{a-2} (not 2^{a-1}) when a≥3. – Greg Martin – 2016-09-19T05:52:09.630

Thanks for catching that, seems I can't even read my own output – miles – 2016-09-19T12:30:49.703

you're not alone sometimes.... :) – Greg Martin – 2016-09-19T18:09:29.257

5

Actually, 30 28 25 19 26 bytes

The Carmichael function, λ(n) where n = p_0**k_0 * p_1**k_1 * ... * p_a**k_a, is defined as the least common multiple (LCM) of λ(p_i**k_i) for the maximal prime powers p_i**k_i that divide into n. Given that for every prime power except where the prime is 2, the Carmichael function is equivalent to the Euler totient function, λ(n) == φ(n), we use φ(n) instead. For the special case of 2**k where k ≥ 3, we just check if 2**3 = 8 divides into n at the beginning of the program, and divide by 2 if it does.

Unfortunately, Actually doesn't currently have an LCM builtin, so I made a brute-force LCM. Golfing suggestions welcome. Try it online!

;7&Yu@\w`iⁿ▒`M╗2`╜@♀%ΣY`╓N

Ungolfing

         Implicit input n.
;        Duplicate n.
7&       n&7 == n%8.
Yu       Logical NOT and increment. If n%8 == 0, return 2. Else, return 1.
@\       Integer divide n by 2 if n%8==0, by 1 otherwise.
          Thus, we have dealt with the special case where p_i == 2 and e_i >= 3.
w        Full prime factorization of n as a list of [prime, exponent] lists.
`...`M   Map the following function over the prime factorization.
  i        Flatten the array, pushing exponent, then prime to the stack.
  ⁿ▒       totient(pow(prime, exponent)).
╗        Save that list of totients in register 0.
2`...`╓  Get the first two values of n where the following function f(n) is truthy.
         Those two numbers will be 0 and our LCM.
  ╜@       Push the list in register 0 and swap with our n.
  ♀%       Get n mod (every number in the list)
  Σ        Sum the modulos. This sum will be 0, if and only if this number is 0 or LCM.
  Y        Logical NOT, so that we only get a truthy if the sum of modulos is 0.
N        Grab the second number, our LCM. Implicit return.

Sherlock9

Posted 2016-09-18T18:07:49.620

Reputation: 11 664

2Actually, I have no idea how you did this in only 19 bytes. – Buffer Over Read – 2016-09-20T02:07:06.390

@TheBitByte With use of the totient and gcd builtins. This would be shorter if Actually had lcm directly, but I don't mind it that much and that would only knock off 4 bytes at most, anyway. – Sherlock9 – 2016-09-20T02:10:55.233

1The assertion that lcm(a) = product(a)/gcd(*a) is true when *a is a list of exactly two numbers; however, it is false in general for longer lists (example: if *a is {6,10,15}, it gives 900 instead of the correct answer of 60). [For that matter, it's wrong is *a is a list of one number as well!] And you can check that you get the wrong answer for over half the test cases listed in the OP. – Greg Martin – 2016-09-20T23:20:39.787

@GregMartin Thanks for the heads up. Fixed. – Sherlock9 – 2016-09-21T03:40:28.420

4

JavaScript (ES6), 143 135 bytes

Edit: saved 8 bytes thanks to Neil

An implementation using functional programming.

n=>(A=[...Array(n).keys()]).find(k=>k&&!c.some(c=>A.slice(0,k).reduce(y=>y*c%n,1)-1),c=A.filter(x=>(g=(x,y)=>x?g(y%x,x):y)(x,n)==1))||1

Ungolfed and commented

n =>                                          // Given a positive integer n:
  (A = [...Array(n).keys()])                  // Build A = [0 ... n-1].
  .find(k =>                                  // Try to find k in [1 ... n-1] such as
    k && !c.some(c =>                         // for each coprime c: c^k ≡ 1 (mod n).
      A.slice(0, k).reduce(y =>               // We use reduce() to compute
        y * c % n, 1                          // c^k mod n.
      ) - 1                                   // Compare it with 1.
    ),                                        // The list of coprimes is precomputed
    c = A.filter(x =>                         // before the find() loop is executed:
      (                                       // for each x in [0 ... n-1], keep
        g = (x, y) => x ? g(y % x, x) : y     // only integers that verify:
      )(x, n) == 1                            // gcd(x, n) = 1
    )                                         // (computed recursively)
  ) || 1                                      // Default result is 1 (for n = 1)

Demo

Although it does work for 6511 and 10000, I won't include them here as it tends to be a bit slow.

let f =
n=>(A=[...Array(n).keys()]).find(k=>k&&!c.some(c=>A.slice(0,k).reduce(y=>y*c%n,1)-1),c=A.filter(x=>(g=(x,y)=>x?g(y%x,x):y)(x,n)==1))||1

console.log(f(1));     // 1
console.log(f(2));     // 1
console.log(f(3));     // 2
console.log(f(10));    // 4
console.log(f(35));    // 12
console.log(f(101));   // 100
console.log(f(530));   // 52
console.log(f(3010));  // 84

Arnauld

Posted 2016-09-18T18:07:49.620

Reputation: 111 334

1JS can do 0..n-1 ranges quite easily: [...Array(n).keys()]. This requires not one but two special cases but I'm still ahead: n=>(a=[...Array(n).keys()]).find(k=>k&&!c.some(c=>a.slice(0,k).reduce(y=>y*c%n,1)-1),c=a.filter(x=>(g=(x,y)=>x?g(y%x,x):y)(x,n)==1))||1 – Neil – 2016-09-24T18:52:26.043

2

Ruby, 101 86 91 90 bytes

A Ruby port of my Actually answer. Golfing suggestions welcome.

Edit: -4 bytes from removing a but +9 bytes from fixing a bug where 1 returned nil. -1 byte thanks to Cyoce.

require'prime'
->n{((n%8<1?n/2:n).prime_division<<[2,1]).map{|x,y|x**~-y*~-x}.reduce :lcm}

Ungolfing

require 'prime'
def carmichael(n)
  if n%8 < 1
    n /= 2
  end
  a = []
  n.prime_division.do each |x,y|
    a << x**(y-1)*(x-1)
  end
  return a.reduce :lcm
end

Sherlock9

Posted 2016-09-18T18:07:49.620

Reputation: 11 664

You don't need a=. Unfortunately, you return nil for n = 1 :(. (n.prime_division<<[2,1]) fixes that. Not sure if there's a golfier way. – m-chrzan – 2016-09-20T22:26:18.513

(n%8<1?n/2:n).prime_division... saves another 2 bytes. – m-chrzan – 2016-09-20T22:32:09.943

@m-chrzan a is a remnant of an earlier golfing attempt. Thanks for the reminder about a and for heads up on 1. – Sherlock9 – 2016-09-21T03:40:04.567

You can save a byte by using .reduce :lcm instead of .reduce(:lcm). – Cyoce – 2016-09-24T19:08:26.447

1

JavaScript (ES 2016) 149

Python reference implementation ported to JS. Some fancy Pyhton builtin is missing in js, like gcd and pow, and the array comprehension is not standard in ES 6. This works in Firefox.

n=>eval('for(g=(a,b)=>b?g(b,a%b):a,p=(a,b,c)=>eval("for(r=1;b--;)r=r*a%c"),c=[for(_ of Array(i=n))if(g(i--,n)<2)i+1],k=1;c.some(x=>p(x,k,n)-1);)++k')

Less golfed

n=>{
  g=(a,b)=>b?g(b,a%b):a
  p=(a,b,c)=>{ 
    for(r=1;b--;)
      r=r*a%c
    return r
  }
  c=[for(_ of Array(i=n)) if(g(i--,n)<2) i+1]
  for(k=1;c.some(x=>p(x,k,n)-1);)
    ++k
  return k
} 

edc65

Posted 2016-09-18T18:07:49.620

Reputation: 31 086

recursive modpow is shorter: p=(a,b,c)=>b?a*p(a,b-1,c)%c:1; – Olivier Grégoire – 2016-09-21T11:05:11.357

1

Java8 38 19 + 287 295 253 248 241 = 325 333 272 267 260 bytes

BigInteger B(int i){return new BigInteger(""+i);}int c(int...k){int n=k[0];for(k[0]=1;n>1&!java.util.stream.IntStream.range(0,n).filter(i->B(n).gcd(B(i)).equals(B(1))).allMatch(x->B(x).modPow(B(k[0]),B(n)).equals(B(1)));k[0]++);return k[0];}

Imports, 19 bytes

import java.math.*;

Explanation

It is a straight forward implementation. The co-primes are calculated in the Set p and every one's kth power is used to check if it equals 1 modulo n.

I had to use BigInteger because of precision issues.

Usage

public static void main(String[] args) {
    Carmichael c = new Carmichael();
    System.out.println(c.c(3)); // prints 2
}

Ungolfed

// returns the BigInteger representation of the given interger
BigInteger B(int i) {
    return new BigInteger(""+i);
}
// for a given integer it returns the result of the carmichael function again as interger
// so the return value cannot be larger
int c(int... k) {
    int n = k[0];
    // iterate k[0] until for all co-primes this is true: (x^n) mod n == 1, if n==1 skip the loop
    for (k[0]=1;n > 1 && !java.util.stream.IntStream.range(0, n)
                .filter(i -> B(n).gcd(B(i)).equals(B(1)))
                .allMatch(x -> B((int) x).modPow(B(k[0]), B(n)).equals(B(1)));k[0]++);
    return k[0];
}

Any suggestions to golf it more are welcome :-)

Update

  • No elements outside the functions that keep the state
  • Followed Olivier Grégoire's advice and saved 1 byte from B()
  • Removed the k() method and p (co-primes) Set.
  • Removed not required casting to int.
  • Added varags and use for instead of while.

Master_ex

Posted 2016-09-18T18:07:49.620

Reputation: 526

Can you have an ungolfed version (with linebreaks, comments here & there, etc.) – OldBunny2800 – 2016-09-20T01:52:24.050

@OldBunny2800: Yeah, sure. However, I'll do it later today because now I am busy! – Master_ex – 2016-09-20T05:29:29.750

@OldBunny2800: I added an ungolfed version :-) – Master_ex – 2016-09-20T18:39:48.263

Hmmm... I'm not sure if this counts as it's neither a function nor a program. If it's a function, there are elements outside of it that keep the state, making it a de facto method (function is pure input->output without external state), if it's a program, the whole main method is missing. If my interpretations are incorrect, please tell me so! I think it's better to include k(int) in the loop as it's a one-liner and can be done. Plus, the constant O can be put in the c method as well. I guess you'll win bytes by doing so! – Olivier Grégoire – 2016-09-20T20:00:12.977

Concretely, while(n>1&&!p.stream().allMatch(x->B((int)x).modPow(B(k), B(n)).equals(O))) shaves bytes and fixes the issues I mentioned if you put the set and the constant back into the method. Also, you use O twice, replace by B(1) to shave bytes. – Olivier Grégoire – 2016-09-20T20:04:08.280

return new BigInteger(""+i); is shorter by one byte. – Olivier Grégoire – 2016-09-20T20:13:53.087

@OlivierGrégoire: Hey, thanks for the comments. I moved the "state" inside the methods. I don't think that while(n>1&&!p.stream().allMatch(x->B((int)x).modPow(B(k), B(n)).equals(O))) works as k variable has to be final. I am not sure that this can't be done in less code. I'll look into it with the first opportunity! – Master_ex – 2016-09-20T21:42:20.527

You are right. I'm sorry for that. k should be final, which is hard to do without putting it out (best case would be to write final int K = k; somewhere, hard given it's a parameter of a function, in the condition of a loop). Despite that, I totally disliked your answer because it was basically the initial algorithm, written in Java, and I was sure that we could do better in Java. So I answered it myself with another algorithm, much more "golfable", but much less efficient in terms of computer speed. I disliked, but +1'd still because you've made some pretty good work! – Olivier Grégoire – 2016-09-20T22:37:13.527

1

Java, 209 207 202 194 192 bytes

Code (96 bytes):

n->{for(int x,k=1,a;;k++){for(a=1,x=0;++x<=n&&a<2;)a=g(x,n)<2?p(x,k,n):1;if(a<2||n<2)return k;}}

extra functions (96 bytes):

int g(int a,int b){return b<1?a:g(b,a%b);}int p(int n,int p,int m){return p<2?n:n*p(n,p-1,m)%m;}

Testing & ungolfed

import java.util.Arrays;
import java.util.function.IntUnaryOperator;

public class Main2 {

  static int g(int a,int b) { // recursive gcd
    return b < 1
        ? a
        : g(b,a%b);
  }

  static int p(int n, int p, int m) { // recursive modpow
    return p < 2
      ? n
      : n * p(n, p - 1, m) % m;
  }

  public static void main(String[] args) {

    IntUnaryOperator f = n -> {
      for(int x,k=1,a;;k++) { // for each k
        for(a=1,x=0;++x<=n&&a<2;) // for each x
          a=g(x,n)<2?p(x,k,n):1; // compute modpow(x,k,n) if g(x,n)
        if(a<2||n<2) // if all modpow(x,k,n)=1. Also check for weird result for n=1.
          return k;
      }
    };

    Arrays.stream(new int[]{1, 2, 3, 10, 35, 101, 530, 3010, 6511, 10000})
        .map(f)
        .forEach(System.out::println);
  }
}

Notes

  • the use of a being an int is shorter than if I had to use a boolean to perform my tests.
  • Yes, it's shorter to valueOf all new BigInteger than create a separate function (there are 5, plus the ONE constant is a freebie).
  • Algorithm is different than @Master_ex' algorithm, so it's not just a golfed repost. Also, this algorithm is much less efficient as gcd is computed again and again for the same values.

Shaves

  1. 209 -> 207 bytes:
    • if(...)a=...; -> a=...?...:1;
    • a==1 -> a<2
  2. 207 -> 202 bytes
    • Got rid of BigInteger by golfing gcd and modPow for int.
  3. 202 -> 194 bytes
    • looping modPow -> recursive
  4. 194 -> 192 bytes
    • ==1 -> <2 (seems to work for all the test cases, don't know for other numbers.)

Olivier Grégoire

Posted 2016-09-18T18:07:49.620

Reputation: 10 647

Hey! I've noticed that the output is not the expected. See the question for the expected results. Personally, I often write unit tests before starting golfing my code, it helps! I guess that the problem could be the modPow on integers, I had also this problem and that's why I used BigInteger at the end. – Master_ex – 2016-09-21T07:14:12.017

Hmmm... I'm surprised, I let my tests run at every change. I'll check what's wrong. – Olivier Grégoire – 2016-09-21T07:45:07.173

1@Master_ex I fixed it. Going back to the previous version is ok. – Olivier Grégoire – 2016-09-21T09:00:20.820

I find your recursive modpow method p pretty clever. I tried to use only integers at first too, but as I've mentioned in my answer, I had precision issues and that's why I've moved to BigInteger (i.e. Math.pow(3, 100)%101 returned 60.0 instead of 1). Your implementation is immune to this because it performs the mod in each iteration. However, it still suffers from a bug. For large m p may still return wrong results. Also, because of the recursion, StackOverflowError may easily occur for large input with the default stack size. – Master_ex – 2016-09-22T00:17:41.040

@Master_ex Yes, that's a consequence of the restriction to int types. I could use longs instead of ints, that'd be 8 extra bytes. But in my view, all the test cases are valid so I leave it like that. StackOverflowError can happen, but that's how recursive works. Methods exist to limit to 32 stacks, but these use many many more bytes. This implementation is fragile, yes, you are totally right. But it's strong enough for the test cases. – Olivier Grégoire – 2016-09-22T07:50:22.167

1

C++, 208 200 149 144 140 134 bytes

[](int n){int k=1,x,a,b,t,d=1;for(;d;)for(d=x=0;++x<n;d=a<2&t>1?k++:d){for(a=x,b=n;t=b;a=t)b=a%b;for(t=1,b=k;b--;t=t*x%n);}return k;};

A port of my C implementation.

Try it on Ideone

ceilingcat

Posted 2016-09-18T18:07:49.620

Reputation: 5 503

1

Java, 165 163 158 152 143 bytes

int l(int n){int k=1,x,a,b,t,d=1;for(;d>0;)for(d=x=0;++x<n;d=a<2&t>1?k++:d){for(a=x,b=n;b>0;b=a%b,a=t)t=b;for(t=b=1;b++<=k;t=t*x%n);}return k;}

Another port of my C implementation.

Try it on Ideone

ceilingcat

Posted 2016-09-18T18:07:49.620

Reputation: 5 503

0

Axiom 129 bytes

c(n)==(r:=[x for x in 1..n|gcd(x,n)=1];(v,k):=(1,1);repeat(for a in r repeat(v:=powmod(a,k,n);v~=1=>break);v<=1=>break;k:=k+1);k)

less golfed

cml(n)==
 r:=[x for x in 1..n|gcd(x,n)=1];(v,k):=(1,1)
 repeat 
   for a in r repeat(v:=powmod(a,k,n);v~=1=>break)
   v<=1=>break
   k:=k+1
 k

results

(3) -> [i,c(i)] for i in [1,2,3,10,35,101,530,3010,6511,10000]
   Compiling function c with type PositiveInteger -> PositiveInteger

   (3)
   [[1,1], [2,1], [3,2], [10,4], [35,12], [101,100], [530,52], [3010,84],
    [6511,3056], [10000,500]]
                                             Type: Tuple List PositiveInteger

RosLuP

Posted 2016-09-18T18:07:49.620

Reputation: 3 036

0

C, 278 276 272 265 256 243 140 134 125 bytes

k,x,a,b,t,d;l(n){for(k=d=1;d;)for(d=x=0;++x<n;d=a<2&t>1?k++:d){for(a=x,b=n;t=b;a=t)b=a%b;for(t=1,b=k;b--;t=t*x%n);}return k;}

This uses a slow modular exponentiation algorithm, computes the GCD too often and no longer leaks memory!

Ungolfed:

int gcd( int a, int b ) {
  int t;
  while( b ) {
    t = b;
    b = a%b;
    a = t;
  }
  return a;
}
int pw(int a,int b,int c){
  int t=1;
  for( int e=0; e<b; e++ ) {
    t=(t*a)%c;
  }
  return t;
}
int carmichael(int n) {
  int k = 1;
  for( ;; ) {
    int done = 1;
    for( int x=1; x<n; x++ ) {
      if( gcd(x,n)==1 && pw(x,k,n) != 1 ) {
        done = 0;
        k++;
      }
    }
    if( done ) break;
  }
  return k;
}

Try it on Ideone

ceilingcat

Posted 2016-09-18T18:07:49.620

Reputation: 5 503

0

Racket 218 bytes

(λ(n)(let((fl #f)(cl(for/list((i n) #:when(coprime? n i))i)))(for/sum((k(range 1 n))#:break fl)(set! fl #t)
(for((i(length cl))#:break(not fl))(when(not(= 1(modulo(expt(list-ref cl i)k)n)))(set! fl #f)))(if fl k 0))))

Ungolfed version:

(require math)
(define f
  (λ(n)
    (let ((fl #f)
          (cl (for/list ((i n) #:when (coprime? n i))
                i)))
             (for/sum ((k (range 1 n)) #:break fl)
               (set! fl #t)
               (for ((i (length cl)) #:break (not fl))
                 (when (not (= 1 (modulo (expt (list-ref cl i) k) n)))
                   (set! fl #f)))
               (if fl k 0)))))

Testing:

(f 2) 
(f 3)
(f 10)
(f 35)
(f 101)
(f 530)
(f 3010)
(f 6511)
(f 10000)

Output:

1
2
4
12
100
52
84
3056
500

rnso

Posted 2016-09-18T18:07:49.620

Reputation: 1 635