Calcola la funzione di Carmichael


36

Descrizione del compito

Nella teoria dei numeri, la funzione di Carmichael  λ prende un intero positivo  n e restituisce il numero intero meno positivo k in modo che la potenza k -esima di ogni intero coprime a n sia uguale a 1 modulo n .

Dato un numero intero positivo n , la soluzione deve calcolare λ (n) . Vince il codice più breve in byte.

Il tuo programma dovrebbe teoricamente funzionare con input arbitrariamente grandi, ma non deve essere efficiente.

Suggerimenti

La sequenza di tutti λ (n) è OEIS A002322 .

Un'implementazione di Python non modificata sarebbe simile

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)calcola in modo efficiente pow(A, B) % C.)

Casi test

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

Cosa significa teoricamente qui? Posso presumere che l'ingresso n si adatti a un numero intero a 16 bit? Posso presumere che n ^ λ (n) si adatti a un doppio?
Dennis,

2
Sì e sì, direi. Come in, teoricamente include fingere che i tuoi tipi nativi siano arbitrariamente precisi e di grandi dimensioni (pensavo fosse un consenso, ma non ne sono sicuro).
Lynn,

Risposte:



29

Python, 76 73 67 byte

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

Provalo online!

È possibile salvare un ulteriore byte restituendo True anziché 1 .

Implementazione alternativa

Utilizzando lo stesso approccio, vi è anche la seguente implementazione di @feersum che non utilizza la comprensione dell'elenco.

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)

Questa implementazione richiede tempo O (n λ (n) ) . L'efficienza potrebbe essere notevolmente migliorata, riducendo in realtà il punteggio a 66 byte , ma la funzione restituirà True per l'ingresso 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)

sfondo

Definizioni e notazione

Tutte le variabili impiegate indicheranno numeri interi; n , k e α denoteranno numeri interi positivi ; e p indicherà un numero primo positivo .

a | b se b è divisibile per a , cioè se esiste q tale che b = qa .

a ≡ b ( mod m) se un e b hanno lo stesso residuo modulo m , cioè, se m | a - b .

λ (n) è il più piccolo k tale che a k ≡ 1 ( mod n) - cioè, tale che n | a k - 1 - per tutti a che sono coprime a n .

f (n) è il più piccolo k tale che un 2k + 1 ≡ a k + 1 ( mod n) - cioè, tale che n | a k + 1 (a k - 1) - per tutti a .

λ (n) ≤ f (n)

Fix n e lasciare un coprimi be a n .

Dalla definizione di f , n | a f (n) +1 (a f (n) - 1) . Poiché a e n non hanno un fattore primo comune, né a f (n) +1 e n , il che implica che n | a f (n) - 1 .

Poiché λ (n) è il numero intero più piccolo k tale che n | un k - 1 per tutti gli interi a che sono primi con n , segue che λ (n) ≤ f (n) .

λ (n) = f (n)

Poiché abbiamo già stabilito la disuguaglianza λ (n) ≤ f (n) , è sufficiente verificare che k = λ (n) soddisfi la condizione che definisce f , cioè che n | a λ (n) +1 (a λ (n) - 1) per tutti a . A tal fine, stabiliremo che p α | a λ (n) +1 (a λ (n) - 1) ogni volta che p α | n .

λ (k) | λ (n) ogni volta che k | n ( sorgente ), quindi (a λ (k) - 1) (a λ (n) -λ (k) + a λ (n) -2λ (k) + ⋯ + a λ (k) + 1) = a λ (n) - 1 e, quindi, a λ (k) - 1 | a λ (n) - 1 | a λ (n) +1 (a λ (n) - 1) .

Se a e p α sono coprimi, con la definizione di λ e sopra, p α | a λ (p α ) - 1 | a λ (n) +1 (a λ (n) - 1) segue, come desiderato.

Se a = 0 , allora a λ (n) +1 (a λ (n) - 1) = 0 , che è divisibile per tutti i numeri interi.

Infine, dobbiamo considerare il caso in cui a e p α hanno un fattore primo comune. Poiché p è primo, questo implica che p | a . Il teorema di Carmichael stabilisce che λ (p α ) = (p - 1) p α - 1 se p> 2 o α <3 e che λ (p α ) = p α - 2 altrimenti. In tutti i casi, λ (p α ) ≥ p α - 2 ≥ 2 α - 2 > α - 2 .

Pertanto, λ (n) + 1 ≥ λ (p α ) + 1> α - 1 , quindi λ (n) + 1 ≥ α e p α | p λ (n) +1 | a λ (n) +1 | a λ (n) +1 (a λ (n) - 1) . Questo completa la prova.

Come funziona

Mentre le definizioni di f (n) e λ (n) considerano tutti i possibili valori di a , è sufficiente testare quelli che si trovano in [0, ..., n - 1] .

Quando viene chiamato f (n, k) , calcola un k + 1 (a k - 1)% n per tutti i valori di a in quell'intervallo, che è 0 se e solo se n | a k + 1 (a k - 1) .

Se tutti i residui calcolati sono zero, k = λ (n) e anyrestituisce False , quindi f (n, k) restituisce 1 .

D'altra parte, mentre k <λ (n) , 1-any(...)restituirà 0 , quindi f viene chiamato ricorsivamente con un valore incrementato di k . Il principale -~incrementa il valore di ritorno di f (n, k + 1) , quindi aggiungiamo 1 a f (n, λ (n)) = 1 una volta per ogni numero intero in [1, ..., λ (n) - 1 ] . Il risultato finale è quindi λ (n) .


Puoi salvare almeno 4 con ricorsione invece di una comprensione di lista: 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)(Aggiungi un byte se non ti piace prendere n ** λ (n) tempo).
feersum,

1
Grazie! Nel frattempo, ho trovato un miglioramento nel mio algoritmo che sembra annullare il vantaggio di ricorrere invece di utilizzare una comprensione dell'elenco.
Dennis,

14

Mathematica senza built-in, 58 57 byte

Grazie a Martin Ender per aver trovato un errore, quindi salvarmi i byte necessari per risolverlo!

Grazie a miglia per aver salvato 1 byte! (che mi è sembrato 2)

Gli incorporati vanno benissimo ... ma per coloro che vogliono implementarlo senza usare la forza bruta, ecco una formula per la funzione di Carmichael:

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

Se p è un numero primo, la funzione di Carmichael λ (p ^ r) è uguale a φ (p ^ r) = (p-1) * p ^ (r-1) - tranne quando p = 2 e r≥3, nel qual caso è la metà, vale a dire 2 ^ (r-2).

E se la fattorizzazione in potenza primaria di n è uguale a p1 ^ r1 * p2 ^ r2 * ..., allora λ (n) è uguale al multiplo minimo comune di {λ (p1 ^ r1), λ (p2 ^ r2), .. .}.

Il runtime è un istante in più rispetto al factoring intero in primo luogo.


È possibile utilizzare EulerPhiper ottenere LCM@@(EulerPhi[#^#2]/If[#==2<#2,2,1]&@@@FactorInteger@#)&per 57 byte.
miglia,

@miles ben individuato! Conto 56 byte, puoi controllare?
Greg Martin,

Sì, sono 57 byte .
miglia,

chiaramente provo persino a giocare a golf il mio conteggio ....: /
Greg Martin,

12

Modelli considerati dannosi , 246 byte

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>>>

Una funzione senza nome (non che ci siano funzioni con nome).

Questo è un mio esolang dimenticato che viene interpretato da un compilatore C ++ che crea modelli. Con la profondità massima predefinita del modello di g++, può fare λ (35), ma non può fare λ (101) (la valutazione pigra peggiora le cose).


10

Haskell, 57 56 byte

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

8

Gelatina, 2 byte

Æc

Grazie per l'integrato, @Lynn


31
............. ._.
Maltysen,

10
Non capisco mai il punto di implementare incorporazioni così ridicolmente specifiche.
Fatalizza il

31
Questa è quasi un'aggiunta al linguaggio appositamente creato per questa sfida. Commit by Lynn 2 giorni fa, sfida di @Lynn oggi
edc65

5
@ edc65 Per non parlare del fatto che questo built-in è praticamente inutile al di fuori di questa sfida e dei suoi derivati.
Fatalizza il

3
Bene, la funzione di Carmichael è importante nella teoria dei numeri (come riflette la risposta principale attualmente), quindi non la definirei inutile.
Greg Martin,


6

Rubino, 59 56 byte

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

5

J, 28 27 byte

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

La funzione Carmichael è λ ( n ) e la funzione totient è φ ( n ).

Usa la definizione in cui λ ( p k ) = φ ( p k ) / 2 se p = 2 e k > 2 altrimenti φ ( p k ). Quindi, per il generale n = p 1 k 1 p 2 k 2p i k i , λ ( n ) = LCM [λ ( p 1 k 1 ) λ ( p 2 k 2 ) ⋯ λ ( p i k i )] .

uso

Comandi extra usati per formattare più 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

Spiegazione

[:*./@(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

Questo dà la risposta sbagliata per 10000 (1000 anziché 500 corretti), e in effetti per ogni multiplo di 8. 2 è un numero primo peculiare e λ (2 ^ a) = 2 ^ {a-2} (non 2 ^ { a-1}) quando a≥3.
Greg Martin,

Grazie per averlo scoperto, sembra che non riesca nemmeno a leggere la mia produzione
miglia

a volte non sei solo .... :)
Greg Martin,

5

In realtà, 30 28 25 19 26 byte

La funzione di Carmichael, λ(n)dove n = p_0**k_0 * p_1**k_1 * ... * p_a**k_a, è definita come il minimo comune multiplo (LCM) di λ(p_i**k_i)per i massimi poteri primi p_i**k_iche si dividono in n. Dato che per ogni potere primo, tranne dove si trova il primo 2, la funzione di Carmichael è equivalente alla funzione totulante di Eulero λ(n) == φ(n), φ(n)invece usiamo . Per il caso speciale di 2**kdove k ≥ 3, controlliamo solo se si 2**3 = 8divide nall'inizio del programma e dividere per 2 se lo fa.

Sfortunatamente, attualmente non ha un LCM incorporato, quindi ho creato un LCM a forza bruta. Suggerimenti di golf benvenuti. Provalo 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.

2
In realtà, non ho idea di come hai fatto in soli 19 byte.
Buffer Over Read

@TheBitByte Con l'uso di totiente gcdbuiltins. Questo sarebbe più breve se in realtà fosse stato lcmdirettamente, ma non mi dispiace così tanto e ciò eliminerebbe comunque solo 4 byte al massimo.
Sherlock9,

1
L'affermazione che mcm (* a) = product (* a) / gcd (* a) è vera quando * a è un elenco di esattamente due numeri; tuttavia, è falso in generale per elenchi più lunghi (esempio: se * a è {6,10,15}, fornisce 900 anziché la risposta corretta di 60). [Del resto, è sbagliato che * a sia anche un elenco di un numero!] E puoi verificare di avere la risposta sbagliata per oltre la metà dei casi di test elencati nel PO.
Greg Martin,

@GregMartin Grazie per il testa a testa. Fisso.
Sherlock9,

4

JavaScript (ES6), 143 135 byte

Modifica: salvato 8 byte grazie a Neil

Un'implementazione che utilizza la programmazione funzionale.

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

Ungolf e commentato

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)

dimostrazione

Anche se funziona per 6511e 10000, non li includerò qui perché tende ad essere un po 'lento.

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


1
JS può fare 0..n-1range abbastanza facilmente: [...Array(n).keys()]. Ciò richiede non uno ma due casi speciali, ma sono ancora avanti: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,

2

Rubino, 101 86 91 90 byte

Una porta di Ruby della mia risposta effettiva . Suggerimenti di golf benvenuti.

Modifica: -4 byte dalla rimozione ama +9 byte dalla correzione di un bug 1restituito nil. -1 byte grazie a 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

Non hai bisogno a=. Sfortunatamente, ritorni nilper n = 1 :(. (n.prime_division<<[2,1])Risolve quello. Non sono sicuro che ci sia un modo più golfista.
m-chrzan,

(n%8<1?n/2:n).prime_division...salva altri 2 byte.
m-chrzan,

@ m-chrzan aè un residuo di un precedente tentativo di golf. Grazie per il promemoria ae per l'informazione 1.
Sherlock9,

È possibile salvare un byte utilizzando .reduce :lcminvece di .reduce(:lcm).
Cyoce,

1

JavaScript (ES 2016) 149

Implementazione di riferimento Python trasferita su JS. Manca un po 'di fantasia Pyhton integrata in js, like gcde powe la comprensione dell'array non è standard in ES 6. Funziona 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')

Meno golf

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
} 

il modpow ricorsivo è più breve:p=(a,b,c)=>b?a*p(a,b-1,c)%c:1;
Olivier Grégoire,

1

Giava, 209 207 202 194 192 byte

Codice (96 byte):

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;}}

funzioni extra (96 byte):

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;}

Test e non golf

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);
  }
}

Gli appunti

  • l'uso di aessere un intè più breve di se dovessi usare un booleanper eseguire i miei test.
  • Sì, è più breve per valueOftutti i nuovi BigIntegerrispetto a creare una funzione separata (ce ne sono 5, più la ONEcostante è un omaggio).
  • L'algoritmo è diverso dall'algoritmo di @Master_ex, quindi non è solo un repost golf. Inoltre, questo algoritmo è molto meno efficiente poiché gcdviene calcolato ripetutamente per gli stessi valori.

rade

  1. 209 -> 207 byte:
    • if(...)a=...; -> a=...?...:1;
    • a==1 -> a<2
  2. 207 -> 202 byte
    • Mi sono sbarazzato del BigIntegergolf gcde modPowper int.
  3. 202 -> 194 byte
    • loop modPow-> ricorsivo
  4. 194 -> 192 byte
    • ==1-> <2(sembra funzionare per tutti i casi di test, non so per altri numeri.)

Hey! Ho notato che l'output non è previsto. Vedi la domanda per i risultati previsti. Personalmente, scrivo spesso unit test prima di iniziare a giocare a golf il mio codice, mi aiuta! Immagino che il problema potrebbe essere il modPow sugli interi, ho avuto anche questo problema ed è per questo che ho usato BigInteger alla fine.
Master_ex,

Hmmm ... Sono sorpreso, ho lasciato correre i miei test ad ogni cambio. Controllerò cosa c'è che non va.
Olivier Grégoire,

1
@Master_ex L'ho risolto. Tornare alla versione precedente è ok.
Olivier Grégoire,

Trovo il tuo metodo modpow ricorsivo pabbastanza intelligente. All'inizio ho provato a usare solo numeri interi, ma come ho già detto nella mia risposta, ho avuto problemi di precisione ed è per questo che mi sono trasferito BigInteger(ovvero Math.pow(3, 100)%101restituito 60.0invece di 1). L'implementazione è immune a questo perché esegue la mod in ogni iterazione. Tuttavia, soffre ancora di un bug. In caso m pcontrario, potrebbero comunque restituire risultati errati. Inoltre, a causa della ricorsione, StackOverflowErrorpuò verificarsi facilmente per input di grandi dimensioni con dimensioni dello stack predefinite.
Master_ex,

@Master_ex Sì, questa è una conseguenza della restrizione ai inttipi. Potrei usare long invece di ints, che sarebbe 8 byte extra. Ma a mio avviso, tutti i casi di test sono validi, quindi lascio così. StackOverflowErrorpuò succedere, ma è così che funziona ricorsivo. Esistono metodi per limitare a 32 stack, ma questi usano molti più byte. Questa implementazione è fragile, sì, hai perfettamente ragione. Ma è abbastanza forte per i casi di test.
Olivier Grégoire,

1

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

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];}

Importazioni, 19 byte

import java.math.*;

Spiegazione

È un'implementazione diretta. I co-primi sono calcolati in Set pe ogni kth power è usato per verificare se è uguale a 1 modulo n.

Ho dovuto usare a BigIntegercausa di problemi di precisione.

uso

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];
}

Tutti i suggerimenti per giocare a golf sono i benvenuti :-)

Aggiornare

  • Nessun elemento al di fuori delle funzioni che mantengono lo stato
  • Seguito il consiglio di Olivier Grégoire e salvato 1 byte da B()
  • Rimosso il k()metodo e p(co-primes) Set.
  • Rimosso il casting non richiesto su int.
  • Aggiunti varag e uso per invece di while.

Puoi avere una versione non golfata (con interruzioni di riga, commenti qua e là, ecc.)
OldBunny2800

@ OldBunny2800: Sì, certo. Tuttavia, lo farò più tardi oggi perché ora sono occupato!
Master_ex,

@ OldBunny2800: ho aggiunto una versione ungolf :-)
Master_ex

Hmmm ... Non sono sicuro se questo conta perché non è né una funzione né un programma. Se è una funzione, ci sono elementi al di fuori di esso che mantengono lo stato, rendendolo un metodo di fatto (la funzione è puro input-> output senza stato esterno), se è un programma, manca l'intero metodo principale. Se le mie interpretazioni sono errate, per favore dimmelo! Penso che sia meglio includerlo k(int)nel loop in quanto è una linea e può essere fatto. Inoltre, la costante O può essere inserita anche nel cmetodo. Immagino che vincerai byte facendo così!
Olivier Grégoire,

Concretamente, while(n>1&&!p.stream().allMatch(x->B((int)x).modPow(B(k), B(n)).equals(O)))rade i byte e risolve i problemi che ho citato se si inserisce il set e la costante nel metodo. Inoltre, usi Odue volte, sostituisci con B(1)per radere i byte.
Olivier Grégoire,

1

Java, 165 163 158 152 143 byte

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;}

Un altro porto della mia implementazione C .

Provalo su Ideone



0

Racchetta 218 byte

(λ(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))))

Versione non golfata:

(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)))))

test:

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

Produzione:

1
2
4
12
100
52
84
3056
500

0

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

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;}

Questo utilizza un algoritmo di esponenziazione modulare lento, calcola il GCD troppo spesso e non perde più memoria!

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;
}

Provalo su Ideone


0

Axiom 129 byte

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)

meno golf

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

risultati

(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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.