Гольф псевдокрими!


9

Вступ / Довідка

У нещодавній дискусії в крипто-чаті мені поставили виклик обговорити / допомогти з тестом на первинність Ферма та номерами Кармайкла. Цей тест ґрунтується на передумові, яка a^(p-1) mod p==1завжди буде мати право для прайметів p, але не завжди для композитів. Тепер номер карикатури - це, по суті, найгірший ворог тесту Ферма: Число, для якого вам доведеться вибрати, aщоб не бути спільним pдля проживання a^(p-1) mod p!=1. Тепер, якщо aце не є основним, ви, по суті, знайшли нетривіальний факторpі, як ми всі знаємо, факторинг може бути досить важким. Особливо, якщо всі фактори досить великі. Тепер ви можете зрозуміти, чому тест Ферма не використовується на практиці так часто (ну, є кращі алгоритми), це тому, що є цифри, для яких вам, як захиснику (з точки зору безпеки), доведеться виконати аналогічну кількість роботи зловмисник (а саме коефіцієнт числа).

Отже, тепер, коли ми знаємо, чому ці цифри є дещо захоплюючими, ми збираємо їх якомога коротшим способом, тому ми можемо просто запам'ятати генеруючий код, якщо він нам коли-небудь знадобиться!

Номери Carmichael також відомі як A002997 на OEIS . Вже
є виклик, пов'язаний з цим , але записи тут не є конкурентоспроможними, оскільки вони оптимізовані для швидкості на відміну від розміру. Той самий аргумент справедливий і для зворотного напрямку, записи тут, ймовірно, можуть робити компроміси проти швидкості на користь розміру.

Специфікація

Вхідні дані

Це стандарт виклик, тому ви берете позитивне чи негативне ціле число nяк вхідне. nможе бути 0- або 1-індексованим, як вам зручніше (вкажіть).

Вихідні дані

Вашим результатом буде або номер n-номер карикатури, або перші nномери карміхале, як вам зручніше (вкажіть).

Специфікація

Ціле число xє числом Кармайкл тоді і тільки тоді xє складовим і для всіх цілих чисел yз gcd(x,y)=1, він вважає , що y^(x-1) mod x==1.

Хто виграє?

Це є , тому найкоротший код у байті виграє!
Застосовуються стандартні правила вводу-виводу та лазівки.

Випробування

Перші кілька номерів карміхалей:

 561,1105,1729,2465,2821,6601,8911,10585,15841,
 29341,41041,46657,52633,62745,63973,75361,101101,
 115921,126217,162401,172081,188461,252601,278545,
 294409,314821,334153,340561,399001,410041,449065,
 488881,512461

Відповіді:


8

Математика, 71 байт

(t=s=1;While[t<=#,If[++s~Mod~CarmichaelLambda@s==1&&!PrimeQ@s,t++]];s)&  

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

50->1461241 Спробуйте в Інтернеті!


4
Mathematica зараз на TiO, тому якщо хтось зацікавлений, ви можете спробувати його в Інтернеті!
Містер Xcoder

@ Mr.Xcoder Ей, це чудово! Я додав (моє перше) математика TIO
J42161217

6

Python 2 , 92 байти

f=lambda j,n=1:j and f(j-([(k/n)**~-n%n for k in range(n*n)if k/n*k%n==1]<[1]*~-n),n+1)or~-n

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

1-індексований і повільний, як патока.

У розумінні списку я використовую метод Денніса для генерації всіх цілих чисел coprime доn (n- тотативів ), а потім я обчислюю їх x**~-n%nдля всіх. Давайте назвемо цей список L.

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

Кожен елемент значення Lмає додатне ціле число: (k/n)є coprime до n, так (k/n)**~-nсамо є, так (k/n)**~-n%n > 0. Таким чином, єдино можливі значення Lлексикографічно менше, ніж [1]*(n-1) ті, що складаються повністю з менших n-1 . ( LНе може містити більш ніж n-1значення, так як nне може бути більше , ніж n-1totatives! Так що порівняння подобається [1,1,1,1,3] < [1,1,1,1]поза.)

Перевірка наявності менших n-1записів Lгарантує, що вона nє складовою. (Наявність n-1тотативних засобів є рівнозначною умовою первинності.) І тоді, умова бути номером Кармайкеля - це саме те, що кожен елемент Lдорівнює 1. Тож це лексикографічне порівняння виявляє саме те, Lщо нас цікавить.

Містер Xcoder врятував байт, перейшовши на рекурсивну лямбда-форму: jпідраховує кожен раз, коли ми потрапляємо на номер Carmichael, і nпідраховує кожен раз, коли ми повторюємо. Отже, як тільки jпотрапляє нуль, n-1дорівнює original_value_of_j'-му номеру Кармікеля.


5

Желе ,  12  11 байт

-1 байт завдяки милям і містер Xcoder (використання атома функції Carmichael та його гольфу)

%Æc’=ÆP
⁹Ç#

Монадійне посилання, яке приймає nта повертає список перших nномерів Кармікеля.

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

Як?

Так само, як і в попередньому (нижче), за винятком того, що існує вбудована функція Carmichael - яка дає найменшу потужність, щоб вхід, піднятий на цю потужність, був співзвучним одному модулю, що потужність для всіх цілих чисел є спільним для цього цілого числа. Таким чином, ми можемо виключити помилкові позитиви (primes) у меншій кількості байтів і мати швидший код!

%Æc’⁼ÆP - isCarmichael: number, n (any integer)
 Æc     - Carmicael function of n
%       - n modulo that
   ’    - decremented (0 for Carmichael numbers and primes)
     ÆP - is n prime? (1 for primes 0 otherwise)
    ⁼   - equal?

⁹Ç# - Main link: number, n
  # - count up finding the first n values satisfying:
 Ç  - ...condition: call the last link as a monad
⁹   - ...starting with a value of: literal 256

Попередні 12 байт :

Ṗ*%⁼Ṗ_ÆP
⁹Ç#

Спробуйте в Інтернеті! (Так, це час виходить n=3).

Як?

Число c,, є числом Кармікеля, якщо воно складене, і правда, що будь-яке ціле число x, підняте на, cє збіговим з xмодулем c.

Нам потрібно тільки , щоб перевірити це для позитивного xдо x=cсебе.

Зауважимо також, що під x=cчас перевірки, чи xпіднімається до потужності xвідповідність xмодулю x, це правда - тому нам не потрібно перевіряти це (це робить коротший код).

Ṗ*%⁼Ṗ_ÆP - Link 1, isCarmichaelNumber: integer c (greater than 1)
Ṗ        - pop c (uses the implicit range(c)) = [1, 2, 3, ..., c-1]
 *       - raise to the power of c (vectorises) = [1^c, 2^c, 3^c, ..., (c-1)^c]
  %      - modulo by c (vectorises) = [1^c%c, 2^c%c, 3^c%c, ..., (c-1)^c%c]
    Ṗ    - pop c = [1, 2, 3, ..., c-1]
   ⁼     - equal? (non-vectorising) = 1 if so, 0 if not
      ÆP - isPrime?(c) = 1 if so, 0 if not
     _   - subtract = 1 if Carmichael 0 if not
         -     (Note the caveat that c must be an integer greater than 1, this is because
         -      popping 1 yields [] thus the equality check will hold; same for 0,-1,...)

⁹Ç# - Main link: number, n
  # - count up finding the first n values satisfying:
 Ç  - ...condition: call the last link as a monad
⁹   - ...starting with a value of: literal 256

Також 12 байт, але обчислює перші 33 хвилини за хвилину, використовуючи атом Кармікеля.
милі

11 байт за допомогою вбудованої функції Carmichael.
Містер Xcoder

@ Mr.Xcoder Я збирався запропонувати милі, розміщені окремо, потім побачив ваші, потім побачив ваш коментар і видаліть. Телевізор може бути через те, що хтось вважає, що він занадто схожий на милі, - прокоментував один, а не цей, але я думаю, що це навіть дивна причина, оскільки немає підстав думати, що ви не знайшли те саме, що незалежно (я знаю, що Ви робили таку річ багато разів). Я відправлю ваші 11, якщо ви хочете, але я вважаю, що ви, або милі, повинні взяти певну оцінку.
Джонатан Аллан

@miles too ... ^
Джонатан Аллан

@JonathanAllan Просто опублікуйте це самостійно. Згадайте милі "і мій внесок, і я не думаю, що милі також не
зважають

2

ECMAScript Regex, 86 89 байт

Попередження: Не читайте цього, якщо ви не хочете, щоб певна манія одинарних виразів була зіпсована для вас. Якщо ви хочете самостійно спробувати вирішити цю магію, я настійно рекомендую почати з вирішення деяких проблем у регулярному вираженні ECMAScript: перегляньте це попереднє повідомлення, щоб ознайомитись зі списком рекомендованих послідовно позначених спойлерами проблем, щоб вирішити одну за одною.

^(?!(x(x+))(?!\2*$)\1*(?=\1$)(?!(xx+)\3+$))((?=(xx+?)\5*$)(?=(x+)(\6+$))\7(?!\5*$)){2,}x$

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

# Match Carmichael numbers in the domain ^x*$ using Korselt's criterion
# N = input number (initial value of tail)
^
(?!
    # Iterate through factors \1, with \2 = \1-1, for which \2 does not divide into N-1
    (x(x+))
    (?!\2*$)           # Assert N-1 is not divisible by \2
    \1*(?=\1$)         # Assert N is divisible by \1; tail = \1
    # If the factor \1, which already passed the aboved tests, is prime, then fail the
    # outside negative lookahead, because N is not a Carmichael number.
    (?!(xx+)\3+$)
)
# Assert that N has at least 2 unique prime factors, and that all of its prime factors
# are of exactly single multiplicity (i.e. that N is square-free).
(
    (?=(xx+?)\5*$)     # \5 = smallest prime factor of tail
    (?=(x+)(\6+$))     # \6 = tail / \5 (implicitly); \7 = tool to make tail = \6
    \7                 # tail = \6
    (?!\5*$)           # Assert that tail is no longer divisible by \5, i.e. that that
                       # prime factor was of exactly single multiplicity.
){2,}
x$

Основна магія цього регулярного вираження полягає в тій частині, яка стверджує, що всі основні фактори N мають рівномірну кратність. Це той самий трюк, який використовується у моїх рядках Match, довжина яких є четвертою потужністю та Find the Smoothest Number regexes: повторне неявне ділення на найменший простий коефіцієнт.

Також можна безпосередньо перевірити, що N не має досконалих квадратних факторів (тобто, що N не має квадрата). Для цього використовується варіант алгоритму множення, коротко описаний в абзаці мого рядового регекс-повідомлення, щоб перевірити, чи число є ідеальним квадратом. Це спойлер . Тому не читайте більше, якщо ви не хочете, щоб якась просунута онірна регекс-магія зіпсована для вас . Якщо ви хочете спробувати вирішити цю магію самостійно, я настійно рекомендую почати з вирішення деяких проблем у списку послідовно позначених спойлерами рекомендованих проблем у цій попередній публікації та намагатися самостійно придумати математичну інформацію.

Однак використання цього алгоритму не дає жодної користі. Це призводить до більш повільного регулярного вираження, з більшим розміром 97 байт. Без тесту простої кратності (який в одній петлі стверджує, що є щонайменше два простих коефіцієнта і що кожен з них є однією кратністю), ми повинні окремо стверджувати, що N є складовим.

^(?!(x(x+))(?!\2*$)\1*(?=\1$)(?!(xx+)\3+$)|((xx+)\5*(?=\5$))?(x(x*))(?=(\6*)\7+$)\6*$\8)(xx+)\9+$

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


 ^
 (?!
     # Iterate through factors \1, with \2 = \1-1, for which \2 does not divide into N-1
     (x(x+))
     (?!\2*$)           # Assert N-1 is not divisible by \2
     \1*(?=\1$)         # Assert N is divisible by \1; tail = \1
     # If the factor \1, which already passed the aboved tests, is prime, then fail the
     # outside negative lookahead, because N is not a Carmichael number.
     (?!(xx+)\3+$)
 |
 # Assert that N is square-free, i.e. has no divisor >1 that is a perfect square.
     ((xx+)\5*(?=\5$))?  # cycle tail through all of the divisors of N, including N itself
     # Match iff tail is a perfect square
     (x(x*))             # \6 = potential square root; \7 = \6 - 1
     (?=
         (\6*)\7+$       # iff \6 * \6 == our number, then the first match here must result in \8 == 0
     )
     \6*$\8              # test for divisibility by \6 and for \8 == 0 simultaneously
 )
 (xx+)\9+$               # Assert that N is composite
 


2
(Суворо кажучи, це decision-problemвідповідь, але виклик - це sequenceвиклик.) Імовірно, у більш потужному варіанті регексу може бути більш пряме випробування для квадратних дільників?
Ніл

@Neil Ви маєте рацію, я можу пропустити його, безпосередньо перевіривши на квадратні дільники. У ECMA додаткові функції не потрібні. Але це зробить це набагато повільніше (і я також захочу заховати його під тегом спойлера). Я хочу включити обидві версії, думаю.
Deadcode

Так, це дуже дратує пошук питань для регулярних виразів, про які я вже писав, які не є правильним правильним типом виклику. Чи слід видалити свою відповідь?
Deadcode

@Neil Ось ти. Я реалізував алгоритм, використовуючи вашу ідею. Це, мабуть, тому я не думав займатися цим самостійно; це фактично призводить до більш тривалого регексу, тому що необхідний комплексний тест.
Deadcode

(Відповідно до правил сайту, ви повинні видалити свою відповідь, так.) Моя ідея полягала в тому, що, використовуючи додаткові функції, скажімо, регенетів сітківки, ви можете переграти його до ^(?!(x(x+))(?!\2*$)\1*(?=\1$)(?!(xx+)\3+$)|((^x|xx\5){2,})\4*$)(xx+)\6+$, а може, навіть менше, ніж 72 байти.
Ніл


1

Сітківка , 94 байти

\d*$
x
"$+"}/^(?!(x(x+))(?!\2*$)\1*(?=\1$)(?!(xx+)\3+$)|((^x|xx\5){2,})\4*$)(xx+)\6+$/^+`$
x
x

Спробуйте в Інтернеті! 1-індексований. Не швидко, тому час n>5на TIO вичерпається . Пояснення:

\d*$
x

Збільшення поточного значення. При першому пропуску це також видаляє nз вихідного буфера (але $+все ще може отримати доступ до нього).

/^(?!(x(x+))(?!\2*$)\1*(?=\1$)(?!(xx+)\3+$)|((^x|xx\5){2,})\4*$)(xx+)\6+$/

Перевірте, чи є поточне значення числом Carmichael. Для цього використовується альтернативний алгоритм @ Deadcode, оскільки виявлення квадрата коротше під час запису за допомогою регулярного виразів .NET / Perl / PCRE.

^+`

Повторюйте, поки поточне значення не стане числом Карікмейла.

$
x

Збільшення поточного значення.

"$+"}

Повторіть початковий приріст і вище циклу n.

x

Перетворіть результат у десятковий.


0

Haskell , 95 байт

s=filter
c n=s(\x->let l=s((1==).gcd x)f;f=[1..x-1]in l/=f&&all(\y->y^(x-1)`mod`x==1)l)[1..]!!n

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

Дегольф:

-- function to filter out Carmichael numbers
filterFunction x = 
    let coprimes = filter ((1 ==) . gcd x) lesserNumbers
        lesserNumbers = [1 .. x - 1]
    in
        -- the number x is Carmichael if it is not prime
        lesserNumbers /= coprimes && 
            -- and all of its coprimes satisfy the equation
            all (\y -> y ^ (x - 1) `mod` x == 1) coprimes

-- get n'th Carmichael number (zero-based)
c n = filter filterFunction [1..] !! n
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.