打假素!


9

简介/背景

最近一次关于加密聊天的讨论我被挑战去讨论/帮助Fermat素数测试和Carmichael数字。该测试基于a^(p-1) mod p==1始终适用于素数p而不适用于复合材料的前提。现在,carmichael号码本质上是Fermat考验的最大敌人:您必须选择一个号码,a以使其不与素数p相抵a^(p-1) mod p!=1。现在,如果a不是互质,则基本上可以发现一个非平凡的因子p众所周知,保理可能相当困难。特别是在所有因素都足够大的情况下。您现在可能已经意识到,为什么在实践中不经常使用Fermat测试(还有更好的算法),这是因为作为防御者(在安全性方面)您需要为某些数字做与攻击者(即数量)。

因此,既然我们知道为什么这些数字有些引人入胜,我们将以最短的方式生成它们,因此只要需要,我们就可以记住生成的代码!

Carmichael编号在OEIS上也称为A002997。已经
存在一个相关的挑战,但是这里的条目没有竞争力,因为它们是针对速度而非大小进行了优化的。同样的论点也适用于反方向,此处的输入可能会在速度上做出取舍,而有利于大小。

规格

输入项

这是一个标准 挑战,因此您将正整数或非负整数n作为输入。n可以根据需要选择0或1的索引(请指出)。

输出量

根据需要,您的输出将是n-th carmichael数或第一个ncarmichael数(请指出)。

规格

一个整数x是卡迈克尔数当且仅当x是复合材料和所有的整数ygcd(x,y)=1,它认为y^(x-1) mod x==1

谁赢?

这是 ,因此以字节为单位的最短代码获胜!
适用标准IO和漏洞规则。

测试用例

前几个carmichael号码是:

 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

Answers:



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分索引,糖蜜缓慢。

在列表理解中,我使用Dennis方法生成所有整数互n素素(n的totatives),然后为所有整数进行计算x**~-n%n。让我们将此列表称为L

为了检测Carmichael编号,我按字典顺序比较此列表与包含1的列表n-1。为什么这样做?

的每个元素L都是一个正整数:(k/n)是的互质素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专有名词是等同于素数的条件。)然后,成为Carmichael数的条件恰恰是Lequals的每个元素1。因此,此字典顺序比较准确地检测到L我们感兴趣的s。

Xcoder先生通过转换为递归lambda格式节省了一个字节:j每次我们击中Carmichael编号时都会递减计数,而每次递归时都会递减n计数。因此,一旦j达到零,就n-1等于original_value_of_j第卡米尔号。


5

果冻 12  11 字节

-1字节由于英里Xcoder先生(使用卡迈克尔功能原子&它们的高尔夫球的)

%Æc’=ÆP
⁹Ç#

单子链接,获取n并返回第一个nCarmichael编号列表。

在线尝试!

怎么样?

与前一个(以下)相似,除了有一个内置的Carmichael函数-该函数产生最小的幂,因此提高到该幂的输入与所有以整数互质为该整数的幂的模数相等。因此,我们可以在更少的字节中排除假阳性(素数),并获得更快的代码!

%Æ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,则升为Carmichael数,并且升为的任何整数c都与x模完全相同c

我们只需要检查它是否xx=c自己有利。

还要注意,在x=c检查的时候,是否x提高到的幂xxmodulo 是否一致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个字节,但是使用Carmichael原子在一分钟之内就能计算出前33 个字节
英里

使用内置的Carmichael函数可以获取11个字节
Xcoder先生17年

@ Mr.Xcoder我想建议单独发布的里程,然后看到您的里程,然后看到您的评论并删除。DVD可能是因为有人认为它与Miles的评论过于相似,而不是这一点,但我认为这是一个奇怪的原因,因为没有理由认为您没有独立找到同一件事(我知道做了很多次这样的事情)。如果您愿意,我会张贴您的11,但我认为您或Miles应该功劳。
乔纳森·艾伦

@miles太... ^
Jonathan Allan

@JonathanAllan自己张贴。提到英里和我的贡献,我也不认为英里会介意:-)(顺便说一句,在发布答案之前,我

2

ECMAScript正则表达式,86 89字节

警告:如果您不想破坏一元正则表达式魔术,请不要阅读此内容。如果您确实想自己弄清楚该魔术,我强烈建议您从解决ECMAScript regex中的一些问题开始:请参阅此较早的帖子,其中列出了一些连续被扰流器标记的建议问题,以逐一解决。

^(?!(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字符串使用的技巧相同,该字符串的长度为四次方找到“最平滑的数字”正则表达式:用最小的素数重复进行隐式除法。

也有可能直接测试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,

@尼尔,你去。我根据您的想法实施了该算法。这也许就是为什么我不打算自己追求它的原因。它实际上导致更长的正则表达式,因为需要进行is-composite测试。
Deadcode

(根据站点规则,应该删除答案,是的。)我的想法是,使用诸如Retina正则表达式的额外功能,您可以将其压缩到^(?!(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正则表达式编写时,平方检测更短。

^+`

重复直到当前值是一个Carmichael编号。

$
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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.