Обчисліть функцію Carmichael


36

Опис завдання

У теорії чисел, то функція Кармайкл  λ приймає позитивне ціле число  п і повертає найменше ціле позитивне число K , так що до -й потужності кожного цілого числа взаємно простих з п дорівнює 1 по модулю п .

З огляду на додатне ціле число n , ваше рішення має обчислити λ (n) . Виграє найкоротший код у байтах.

Ваша програма теоретично повинна працювати для довільно великих входів, але вона не повинна бути ефективною.

Поради

Послідовність усіх λ (n) - OEIS A002322 .

Необов’язана реалізація Python виглядала б так

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

(У Python pow(A, B, C)ефективно обчислює pow(A, B) % C.)

Тестові справи

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

Що тут теоретично означає? Чи можу я припустити, що вхід n вписується в 16-бітове ціле число? Чи можу я припустити, що n ^ λ (n) вписується в подвійне?
Денніс

2
Так і так, я б сказав. Як і в, теоретично включає вигляд, що ваші рідні типи довільно точні та великі (я вважав, що це консенсус, але я не впевнений).
Лінн

Відповіді:



29

Пітон, 76 73 67 байт

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

Спробуйте в Інтернеті!

Подальший байт можна зберегти, повернувши True замість 1 .

Альтернативна реалізація

Використовуючи той самий підхід, є також наступна реалізація від @feersum, яка не використовує розуміння списку.

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)

Зауважте, що для цієї реалізації потрібен час O (n λ (n) ) . Ефективність може бути значно покращена, фактично зменшивши бал до 66 байт , але функція поверне значення True для введення 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)

Фон

Визначення та позначення

Всі використані змінні будуть позначати цілі числа; n , k і α позначатимуть додатні цілі числа; і p позначатиме позитивний простим розрядом .

а | b, якщо b ділиться на a , тобто якщо є q такий, що b = qa .

a ≡ b ( mod m), якщо a і b мають однаковий модуль залишку m , тобто, якщо m | а - б .

λ (n) - найменший k такий, що a k ≡ 1 ( mod n) - тобто такий, що n | a k - 1 - для всіх a, що є спільними з n .

е (п) є найменшим до таким чином, що 2k + 1до + 1 ( по модулю п) - тобто такі , що п | a k + 1 (a k - 1) - для всіх a .

λ (n) ≤ f (n)

Виправте n і нехай a coprime to n .

За визначенням f , n | a f (n) +1 (a f (n) - 1) . Оскільки і п не мають загального прем'єр - фактор, не займайтеся в п (п) +1 і п , звідки слід , що п | a f (n) - 1 .

Оскільки λ (n) - найменше ціле число k таке, що n | a k - 1 для всіх цілих чисел a, які є спільними з n , випливає, що λ (n) ≤ f (n) .

λ (n) = f (n)

Оскільки ми вже встановили нерівність λ (n) ≤ f (n) , достатньо перевірити, чи відповідає k = λ (n) умові, що визначає f , тобто, що n | a λ (n) +1 (a λ (n) - 1) для всіх a . Для цього встановимо, що p α | a λ (n) +1 (a λ (n) - 1), коли p α | н .

λ (k) | λ (n) всякий раз, коли k | n ( джерело ), так (a λ (k) - 1) (a λ (n) -λ (k) + a λ (n) -2λ (k) + ⋯ + a λ (k) + 1) = a λ (n) - 1 і, отже, a λ (k) - 1 | a λ (n) - 1 | a λ (n) +1 (a λ (n) - 1) .

Якщо a і p α є спірними, за визначенням λ і вищевикладеним, p α | a λ (p α ) - 1 | a λ (n) +1 (a λ (n) - 1) слідує за бажанням.

Якщо a = 0 , то a λ (n) +1 (a λ (n) - 1) = 0 , що ділиться на всі цілі числа.

Нарешті, ми повинні розглянути випадок, коли a і p α мають спільний простий фактор. Оскільки p є простим, це означає, що p | а . Теорема Карміхеля встановлює, що λ (p α ) = (p - 1) p α - 1, якщо p> 2 або α <3, а λ (p α ) = p α - 2 в іншому випадку. У всіх випадках λ (p α ) ≥ p α - 2 ≥ 2 α - 2 > α - 2 .

Тому λ (n) + 1 ≥ λ (p α ) + 1> α - 1 , тому λ (n) + 1 ≥ α і p α | p λ (n) +1 | a λ (n) +1 | a λ (n) +1 (a λ (n) - 1) . Це завершує доказ.

Як це працює

Хоча визначення f (n) та λ (n) враховують усі можливі значення a , достатньо перевірити ті, що лежать у [0, ..., n - 1] .

Коли f (n, k) викликається, він обчислює a k + 1 (a k - 1)% n для всіх значень a в цьому діапазоні, що дорівнює 0, якщо і лише тоді, коли n | a k + 1 (a k - 1) .

Якщо всі обчислені залишки дорівнюють нулю, k = λ (n) і anyповертає False , значить f (n, k) повертає 1 .

З іншого боку, в той час як до <λ (п) , 1-any(...)буде повертати 0 , тому е викликається рекурсивно з порядковим значенням до . Провідні -~прирости повертають значення f (n, k + 1) , тому ми додаємо 1 до f (n, λ (n)) = 1 раз на кожне ціле число в [1, ..., λ (n) - 1 ] . Кінцевий результат, таким чином, λ (n) .


Ви можете зберегти принаймні 4 за допомогою рекурсії замість розуміння списку: 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)(Додайте назад один байт, якщо вам це не подобається, щоб він займав n ** λ (n) час).
feersum

1
Спасибі! Тим часом я виявив вдосконалення свого алгоритму, який, здається, зводить нанівець користь від повторної повторної роботи, замість того, щоб використовувати розуміння списку.
Денніс

14

Математика без вбудованого, 58 57 байт

Дякую Мартіну Ендеру за те, що знайшов помилку, а потім врятував мені байти, які знадобилися, щоб виправити!

Дякуємо за милі за економію 1 байта! (що мені здавалося 2)

Вбудовані вкрай непогані ... але для тих, хто хоче реалізувати це без використання грубої сили, ось формула функції Carmichael:

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

Якщо p є простим, функція Кармікеля λ (p ^ r) дорівнює φ (p ^ r) = (p-1) * p ^ (r-1) - за винятком випадків, коли p = 2 і r≥3, в цьому випадку це наполовину, а саме 2 ^ (r-2).

І якщо факторизація потужності n дорівнює p1 ^ r1 * p2 ^ r2 * ..., тоді λ (n) дорівнює найменшому спільному кратному {λ (p1 ^ r1), λ (p2 ^ r2), .. .}.

Виконання - це на один момент більше, ніж розбиття на ціле число.


Ви можете використовувати EulerPhiдля отримання LCM@@(EulerPhi[#^#2]/If[#==2<#2,2,1]&@@@FactorInteger@#)&57 байт.
миль

@miles добре помічений! Я рахую 56 байт, ви можете перевірити?
Грег Мартін

Так, це 57 байт .
миль

Очевидно, я навіть намагаюся взяти підрахунок у гольф ....: /
Грег Мартін

12

Шаблони вважаються шкідливими , 246 байт

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

Безіменна функція (не те, що є іменовані функції).

Це забутий мій esolang, який інтерпретується компілятором C ++ з шаблонами екземплярів. З максимальною глибиною шаблону за замовчуванням g++, це може зробити λ (35), але не може зробити λ (101) (лінива оцінка робить гірше).



8

Желе, 2 байти

Æc

Дякую за вбудований, @Lynn


31
............. ._.
Мальтісен

10
Я ніколи не розумію сенсу впроваджувати такі смішно конкретні вбудовані модулі.
Фаталізувати

31
Це майже доповнення до мови, спеціально створеної для цього виклику. Здійснити Лінн 2 дні тому, виклик @Lynn сьогодні
edc65

5
@ edc65 Не кажучи вже про те, що цей вбудований вкрай марний поза цим викликом та його похідними.
Фаталізувати

3
Що ж, функція Carmichael важлива в теорії чисел (як це відображається в даний час в головному відповіді), тому я б не назвав це марним.
Грег Мартін



5

J, 28 27 байт

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

Функція Кармайгеля дорівнює λ ( n ), а функція підкреслення - φ ( n ).

Використовується визначення, де λ ( p k ) = φ ( p k ) / 2, якщо p = 2 і k > 2 else φ ( p k ). Тоді для загального 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 )] .

Використання

Додаткові команди, які використовуються для форматування декількох входів / виходів.

   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

Пояснення

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

Це дає неправильну відповідь на 10000 (1000 замість правильних 500), і справді для кожного кратного 8. 2 є своєрідним простим, а λ (2 ^ a) = 2 ^ {a-2} (не 2 ^ { a-1}) при a≥3.
Грег Мартін

Дякую, що зрозумів, що, здається, я навіть не можу прочитати власний результат
миль

Ви не самотні іноді .... :)
Грег Мартін,

5

Власне, 30 28 25 19 26 байт

Функція Кармікеля, λ(n)де n = p_0**k_0 * p_1**k_1 * ... * p_a**k_a, визначається як найменш спільне множина (LCM) λ(p_i**k_i)для максимальних простих сил, p_i**k_iякі діляться на n. Зважаючи на те, що для кожної першої потужності, за винятком випадків, коли є простим 2, функція Кармікеля еквівалентна функції Ейлера, яка використовує тутемент λ(n) == φ(n), ми використовуємо φ(n)натомість Для особливого випадку, 2**kде k ≥ 3ми просто перевіряємо, чи 2**3 = 8ділиться на nна початку програми, і ділимо на 2, якщо воно є.

На жаль, фактично наразі немає вбудованого LCM, тому я зробив грубу силу LCM. Пропозиції з гольфу вітаються. Спробуйте в Інтернеті!

;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
Власне, я не маю уявлення, як ти це зробив лише в 19 байтах.
Буфер за прочитане

@TheBitByte З використанням totientта gcdвбудованих. Це було б коротше, якби насправді це було lcmбезпосередньо, але я не заперечую це настільки багато, і це все одно збило б лише 4 байти.
Шерлок9

1
Твердження, що lcm (* a) = продукт (* a) / gcd (* a) є істинним, коли * a - це перелік рівно двох чисел; однак вона загалом хибна для довших списків (приклад: якщо * a - {6,10,15}, це дає 900 замість правильної відповіді 60). [Що стосується цього, це неправильно, це * a - це також список одного номера!] І ви можете перевірити, чи отримаєте ви неправильну відповідь для більш ніж половини тестових випадків, перелічених в ОП.
Грег Мартін

@GregMartin Дякую за голову вгору Виправлено.
Шерлок9,

4

JavaScript (ES6), 143 135 байт

Редагувати: збережено 8 байт завдяки Нілу

Реалізація з використанням функціонального програмування.

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

Негольфірованний і прокоментував

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)

Демо

Хоча це і працює, 6511і 10000я не включатиму їх сюди, оскільки це, як правило, трохи повільно.

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 може зробити 0..n-1діапазони досить легко: [...Array(n).keys()]. Для цього потрібні не один, а два особливі випадки, але я все ще попереду: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
Ніл

2

Рубі, 101 86 91 90 байт

Порт Ruby моєї фактично відповіді . Пропозиції з гольфу вітаються.

Змінити: -4 байти від видалення, aале +9 байт від виправлення помилки, де вона 1повернулася nil. -1 байт завдяки 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

Вам не потрібно a=. На жаль, ви повертаєтесь nilза n = 1 :(. Це (n.prime_division<<[2,1])виправляє. Не впевнений, чи є спосіб гольфіста.
m-chrzan

(n%8<1?n/2:n).prime_division...зберігає ще 2 байти.
m-chrzan

@ m-chrzan a- це залишок попередньої спроби гольфу. Дякуємо за нагадування про aта за голову 1.
Шерлок9,

Ви можете зберегти байт, використовуючи .reduce :lcmзамість .reduce(:lcm).
Cyoce

1

JavaScript (ES 2016) 149

Реалізація посилання Python перенесена на JS. Дещо фантазійного вбудованого Pyhton відсутнє в js, як gcdі pow, і розуміння масиву не є стандартним в ES 6. Це працює в 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')

Менше гольфу

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
} 

рекурсивний модпоу коротший:p=(a,b,c)=>b?a*p(a,b-1,c)%c:1;
Олів'є Грегоар

1

Java, 209 207 202 194 192 байти

Код (96 байт):

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

додаткові функції (96 байт):

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

Тестування & unololfed

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

Примітки

  • використання aбуття intє коротшим, ніж якби мені довелося використовувати а booleanдля виконання своїх тестів.
  • Так, це коротше valueOfвсього нового, BigIntegerніж створити окрему функцію (є 5, плюс ONEконстанта - халява).
  • Алгоритм відрізняється від алгоритму @Master_ex, тому це не просто репост для гольфу. Крім того, цей алгоритм набагато менш ефективний, оскільки gcdобчислюється знову і знову для одних і тих же значень.

Гоління

  1. 209 -> 207 байт:
    • if(...)a=...; -> a=...?...:1;
    • a==1 -> a<2
  2. 207 -> 202 байти
    • Позбувся BigIntegerгольфу gcdі modPowза int.
  3. 202 -> 194 байт
    • циклічний modPow-> рекурсивний
  4. 194 -> 192 байти
    • ==1-> <2(здається, працює для всіх тестових випадків, для інших номерів не знаю.)

Гей! Я помітив, що вихід не є очікуваним. Дивіться питання щодо очікуваних результатів. Особисто я часто пишу одиничні тести, перш ніж починати займатися гольфом, це допомагає! Я здогадуюсь, що проблемою може бути modPow на цілі числа, у мене також була ця проблема, і саме тому я використав BigInteger наприкінці.
Master_ex

Гммм ... я здивований, я дозволяю моїм тестам працювати при кожній зміні. Я перевірю, що не так.
Олів'є Грегоар

1
@Master_ex Я це виправив. Повернутися до попередньої версії - це нормально.
Олів'є Грегоар

Я вважаю ваш рекурсивний метод modpow pдосить розумним. Спочатку я намагався використовувати лише цілі числа, але, як я вже згадував у своїй відповіді, у мене були проблеми з точністю, і тому я перейшов до BigInteger(тобто Math.pow(3, 100)%101повернувся 60.0замість 1). Ваша реалізація не захищена від цього, оскільки виконує мод у кожній ітерації. Однак він все одно страждає від помилки. Для великих m pможуть все-таки повернути неправильні результати. Крім того, через рекурсію StackOverflowErrorможе виникнути велике введення з розміром стека за замовчуванням.
Master_ex

@Master_ex Так, це наслідок обмеження intтипів. Я міг би використовувати longs замість ints, це було б 8 зайвих байт. Але, на мій погляд, всі тестові справи справедливі, тому я залишаю це так. StackOverflowErrorможе статися, але так працює рекурсивна. Існують методи обмеження на 32 стеки, але вони використовують набагато більше байтів. Ця реалізація неміцна, так, ви абсолютно праві. Але він досить сильний для тестових випадків.
Олів'є Грегоар

1

Java8 38 19 + 287 295 253 248 241 = 325 333 272 267 260 байт

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

Імпорт, 19 байт

import java.math.*;

Пояснення

Це пряма реалізація. Ко-праймес обчислюється в Set pk-й потужності кожного з них, щоб перевірити, чи дорівнює 1 модуль n.

Мені довелося користуватися BigIntegerчерез проблеми з точністю.

Використання

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

Безумовно

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

Будь-які пропозиції про те, щоб пограти в гольф більше, вітаються :-)

Оновлення

  • Немає елементів поза функціями, які зберігають державу
  • Дотримуйтесь порад Олів'є Грегоара і врятував 1 байт від B()
  • Видалено k()метод і p(спів-прайме) Набір.
  • Для видалення int видалено не потрібно.
  • Додані вараги та використання замість часу.

Чи можете у вас неперевершені версії (з рядками, коментарями тут і там і т. Д.)
OldBunny2800

@ OldBunny2800: Так, звичайно. Однак я зроблю це пізніше сьогодні, бо зараз я зайнята!
Master_ex

@ OldBunny2800: Я додав версію, яка не перебуває у вовку :-)
Master_ex

Хммм ... я не впевнений, чи вважається це ні функцією, ні програмою. Якщо це функція, існують елементи поза нею, які зберігають стан, що робить його фактичним методом (функція є чистим входом -> вихід без зовнішнього стану), якщо це програма, то основний метод відсутній. Якщо мої трактування невірні, будь ласка, скажіть мені про це! Я думаю, що краще включити k(int)в цикл, оскільки це однолінійка і це можна зробити. Плюс до цього в cметод можна також ввести константу O. Я думаю, ви виграєте байти, зробивши це!
Олів’є Грегоар

Конкретно, while(n>1&&!p.stream().allMatch(x->B((int)x).modPow(B(k), B(n)).equals(O)))голіть байти та виправляє проблеми, про які я згадував, якщо ви додаєте набір та константу назад у метод. Крім того, ви використовуєте Oдвічі, замінюючи B(1)на гоління байтів.
Олів'є Грегоар



0

Ракетка 218 байт

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

Безгольова версія:

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

Тестування:

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

Вихід:

1
2
4
12
100
52
84
3056
500

0

C, 278 276 272 265 256 243 140 134 125 байт

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

Для цього використовується повільний алгоритм модульної експоненції, занадто часто обчислюється GCD і більше не протікає пам'ять!

Безголівки:

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

Спробуйте це на Ideone


0

Аксіома 129 байт

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)

менше гольфу

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

результати

(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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.