Descrição da tarefa
Na teoria dos números, a função Carmichael λ pega um número inteiro positivo n e retorna o número inteiro menos positivo k, de modo que a k -ésima potência de cada número inteiro coprime para n seja igual a 1 módulo n .
Dado um número inteiro positivo n , sua solução deve calcular λ (n) . O código mais curto em bytes vence.
Teoricamente, seu programa deve funcionar com entradas arbitrariamente grandes, mas não precisa ser eficiente.
Dicas
A sequência de todos os λ (n) é OEIS A002322 .
Uma implementação Python não-gasta pareceria
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
(Em Python, pow(A, B, C)
calcula com eficiência pow(A, B) % C
.)
Casos de teste
Input Output
1 1
2 1
3 2
10 4
35 12
101 100
530 52
3010 84
6511 3056
10000 500
Respostas:
Mathematica, 16 bytes
Bem...
fonte
Python,
767367 bytesExperimente online!
Um outro byte pode ser salvo retornando True em vez de 1 .
Implementação alternativa
Usando a mesma abordagem, também existe a seguinte implementação por @feersum, que não usa compreensão de lista.
Observe que essa implementação requer tempo O (n λ (n) ) . A eficiência pode ser melhorada drasticamente enquanto diminui a pontuação para 66 bytes , mas a função retornará True para a entrada 2 .
fundo
Definições e notação
Todas as variáveis empregadas indicarão números inteiros; n , k , e α denotará positivos inteiros; e p denotará um primo positivo .
a | b se b é divisível por a , ie, se houver q tal que b = qa .
a ≡ b ( mod m) se a e b tiverem o mesmo resíduo módulo m , ou seja, se m | a - b .
λ (n) é o menor k tal que um k ≡ 1 ( mod n) - ou seja, tal que n | um k - 1 - para todo um que são primos entre si para n .
f (n) representa a menor k tal que um 2k + 1 ≡ um k + 1 ( mod n) - ou seja, de tal modo que n | a k + 1 (a k - 1) - para todos a .
λ (n) ≤ f (n)
Corrija n e deixe a ser coprime para n .
Pela definição de f , n | a f (n) +1 (a f (n) - 1) . Desde um e n não tem um fator primo comum, nem um f (n) 1 e n , o que implica que n | a f (n) - 1 .
Como λ (n) é o menor número inteiro k tal que n | a k - 1 para todos os inteiros a que são coprime para n , segue-se que λ (n) ≤ f (n) .
λ (n) = f (n)
Como já estabelecemos a desigualdade λ (n) ≤ f (n) , é suficiente verificar que k = λ (n) satisfaz a condição que define f , ou seja, que n | a λ (n) +1 (a λ (n) - 1) para todos a . Para esse fim, estabeleceremos que p α | a λ (n) +1 (a λ (n) - 1) sempre que p α | n .
λ (k) λ (n) sempre que k | n ( fonte ), então (a λ (k) - 1) (a λ (n) -λ (k) + a λ (n) -2λ (k) + ⋯ + a λ (k) + 1) = a λ (n) - 1 e, portanto, a λ (k) - 1 | a λ (n) - 1 | a λ (n) +1 (a λ (n) - 1) .
Se a e p α são coprime, pela definição de λ e acima, p α | a λ (p α ) - 1 | a λ (n) +1 (a λ (n) - 1) segue, conforme desejado.
Se a = 0 , em seguida, um λ (n) 1 (um λ (n) - 1) = 0 , que é divisível por todos os inteiros.
Finalmente, devemos considerar o caso em que um e p α tem um fator primordial comum. Como p é primo, isso implica que p | a . O teorema de Carmichael estabelece que λ (p α ) = (p - 1) p α - 1 se p> 2 ou α <3 e que λ (p α ) = p α - 2 caso contrário. Em todos os casos, λ (p α ) ≥ p α - 2 ≥ 2 α - 2 > α - 2 .
Portanto, λ (n) + 1 ≥ λ (p α ) + 1> α - 1 , de modo λ (n) + 1 ≥ α e p α | p λ (n) +1 | a λ (n) +1 | a λ (n) +1 (a λ (n) - 1) . Isso completa a prova.
Como funciona
Enquanto as definições de f (n) e λ (n) consideram todos os valores possíveis de a , é suficiente testar aqueles que estão em [0, ..., n - 1] .
Quando f (n, k) é chamada, ele calcula um k + 1 (um k - 1)% n para todos os valores de um nessa gama, o que é 0 , se e somente se n | a k + 1 (a k - 1) .
Se todos os resíduos calculados forem zero, k = λ (n) e
any
retorna False , então f (n, k) retorna 1 .Por outro lado, enquanto k <λ (n) ,
1-any(...)
retornará 0 , então f é chamado recursivamente com um valor incrementado de k . O início-~
incrementa o valor de retorno de f (n, k + 1) , então adicionamos 1 a f (n, λ (n)) = 1 uma vez para cada número inteiro em [1, ..., λ (n) - 1 ] . O resultado final é, portanto, λ (n) .fonte
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)
(Adicione um byte novamente se não gostar de demorar n ** λ (n) tempo).Mathematica sem built-in,
5857 bytesAgradeço a Martin Ender por encontrar um erro e depois me salvou os bytes necessários para corrigi-lo!
Graças a milhas por economizar 1 byte! (que me pareceu 2)
Os embutidos são totalmente bons ... mas para aqueles que querem implementá-lo sem usar força bruta, aqui está uma fórmula para a função Carmichael:
Se p é um primo, a função Carmichael λ (p ^ r) é igual a φ (p ^ r) = (p-1) * p ^ (r-1) - exceto quando p = 2 e r≥3, nesse caso é metade disso, ou seja 2 ^ (r-2).
E se a fatoração de potência principal de n for igual a p1 ^ r1 * p2 ^ r2 * ..., então λ (n) será igual ao múltiplo menos comum de {λ (p1 ^ r1), λ (p2 ^ r2), .. .}.
O tempo de execução é um instante a mais do que fatorar o número inteiro em primeiro lugar.
fonte
EulerPhi
para obterLCM@@(EulerPhi[#^#2]/If[#==2<#2,2,1]&@@@FactorInteger@#)&
57 bytes.Modelos considerados nocivos , 246 bytes
Uma função sem nome (não que haja funções nomeadas).
Este é um esquecimento esquecido meu que é interpretado por um compilador C ++ instanciando modelos. Com a profundidade máxima padrão do modelo de
g++
, ele pode executar λ (35), mas não pode executar λ (101) (a avaliação lenta torna as coisas piores).fonte
Haskell,
5756 bytesfonte
Geléia, 2 bytes
Obrigado pelo builtin, @Lynn
fonte
Pitão -
191817 bytesUm byte economizado graças a @TheBikingViking.
Força bruta reta.
Experimente online aqui .
fonte
f!smt
é um byte mais curto.Rubi,
59.56 bytesfonte
J,
2827 bytesA função Carmichael é λ ( n ) e a função totiente é φ ( n ).
Usa a definição em que λ ( p k ) = φ ( p k ) / 2 se p = 2 e k > 2 mais φ ( p k ). Então, para geral n = p 1 k 1 p 2 k 2 ⋯ p i k i , λ ( n ) = LCM [λ ( p 1 k 1 ) λ ( p 2 k 2 ) ⋯ λ ( p i k i )] .
Uso
Comandos extras usados para formatar várias entradas / saídas.
Explicação
fonte
Na verdade,
3028251926 bytesA função Carmichael,
λ(n)
onden = p_0**k_0 * p_1**k_1 * ... * p_a**k_a
, é definida como o mínimo múltiplo comum (LCM)λ(p_i**k_i)
para as potências primárias máximasp_i**k_i
que se dividemn
. Dado que, para todo poder primordial, exceto onde está o primo2
, a função Carmichael é equivalente à função totiente de Eulerλ(n) == φ(n)
, usamos em seuφ(n)
lugar. Para o caso especial de2**k
ondek ≥ 3
, apenas verificamos se2**3 = 8
divide emn
no início do programa e, se o fizer, dividimos por 2.Infelizmente, atualmente, na verdade, não há um LCM embutido, então criei um LCM de força bruta. Sugestões de golfe são bem-vindas. Experimente online!
Ungolfing
fonte
totient
egcd
builtins. Isso seria mais curto se realmente tivesselcm
diretamente, mas eu não me importo muito com isso e isso apenas derrubaria 4 bytes, no máximo.JavaScript (ES6),
143135 bytesEdit: salvou 8 bytes graças a Neil
Uma implementação usando programação funcional.
Ungolfed e comentou
Demo
Embora funcione para
6511
e10000
não os incluirei aqui, pois tende a ser um pouco lento.fonte
0..n-1
varia bastante facilidade:[...Array(n).keys()]
. Isso não requer um, mas dois casos especiais, mas eu ainda estou à frente: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
Ruby,
101869190 bytesUma porta Ruby da minha resposta Real . Sugestões de golfe são bem-vindas.
Edit: -4 bytes de remoção,
a
mas +9 bytes de correção de um bug onde1
retornadosnil
. -1 byte graças a Cyoce.Ungolfing
fonte
a=
. Infelizmente, você retornarnil
para n = 1 :(.(n.prime_division<<[2,1])
Correções Não tenho certeza se há uma maneira Golfier..(n%8<1?n/2:n).prime_division...
salva outros 2 bytes.a
é um remanescente de uma tentativa anterior de golfe. Obrigado pelo lembrete sobrea
e pelo aviso1
..reduce :lcm
vez de.reduce(:lcm)
.JavaScript (ES 2016) 149
Implementação de referência Python portada para JS. Faltam alguns recursos sofisticados do Pyhton nos js, like
gcd
epow
, e a compreensão da matriz não é padrão no ES 6. Isso funciona no Firefox.Menos golfe
fonte
p=(a,b,c)=>b?a*p(a,b-1,c)%c:1;
Java,
209207202194192 bytesCódigo (96 bytes):
funções extras (96 bytes):
Testes e não destruídos
Notas
a
ser umint
é mais curto do que se eu tivesse que usar aboolean
para realizar meus testes.valueOf
todos os novosBigInteger
que criar uma função separada (existem 5, mais aONE
constante é um brinde).gcd
é calculado repetidamente para os mesmos valores.Barbear
if(...)a=...;
->a=...?...:1;
a==1
->a<2
BigInteger
golfegcd
emodPow
paraint
.modPow
-> recursivo==1
-><2
(parece funcionar para todos os casos de teste, não sabe para outros números.)fonte
p
bastante inteligente. Também tentei usar apenas números inteiros no início, mas como mencionei na resposta, tive problemas de precisão e foi por isso que mudei paraBigInteger
(ou seja,Math.pow(3, 100)%101
retornei em60.0
vez de1
). Sua implementação é imune a isso porque executa o mod em cada iteração. No entanto, ele ainda sofre de um bug. Para grandesm
p
ainda pode retornar resultados errados. Além disso, devido à recursão,StackOverflowError
pode ocorrer facilmente para entradas grandes com o tamanho da pilha padrão.int
tipos. Eu poderia usar longos em vez de ints, isso seria 8 bytes extras. Mas, na minha opinião, todos os casos de teste são válidos, então deixo assim.StackOverflowError
pode acontecer, mas é assim que a recursividade funciona. Existem métodos para limitar a 32 pilhas, mas usam muitos mais bytes. Esta implementação é frágil, sim, você está totalmente certo. Mas é forte o suficiente para os casos de teste.Java8
3819 +287295253248241 =325333272267260 bytesImportações, 19 bytes
Explicação
É uma implementação direta. Os co-primos são calculados na
Set p
potência de cada indivíduo e é usado para verificar se é igual a 1 módulo n.Eu tive que usar
BigInteger
por causa de problemas de precisão.Uso
Ungolfed
Quaisquer sugestões para jogar mais são bem-vindas :-)
Atualizar
B()
k()
método ep
(co-primos) Set.fonte
k(int)
no loop, pois é uma linha e pode ser feito. Além disso, a constante O também pode ser inserida noc
método. Eu acho que você ganhará bytes fazendo isso!while(n>1&&!p.stream().allMatch(x->B((int)x).modPow(B(k), B(n)).equals(O)))
raspa bytes e corrige os problemas que eu mencionei se você colocar o conjunto e a constante novamente no método. Além disso, você usaO
duas vezes, substitua porB(1)
para barbear bytes.Java,
165 163 158 152143 bytesOutra porta da minha implementação C .
Experimente no Ideone
fonte
C ++,
208 200 149 144 140134 bytesUma porta de minha implementação C .
Experimente no Ideone
fonte
Raquete 218 bytes
Versão não destruída:
Teste:
Saída:
fonte
C,
278 276 272 265 256 243 140 134125 bytesIsso usa um algoritmo de exponenciação modular lento, calcula o GCD com muita freqüência e não mais vaza memória!
Ungolfed:
Experimente no Ideone
fonte
Axiom 129 bytes
menos golfe
resultados
fonte