Chơi golf giả!


9

Giới thiệu / Bối cảnh

Trong một cuộc thảo luận gần đây trong cuộc trò chuyện về tiền điện tử, tôi đã được thử thách thảo luận / trợ giúp với bài kiểm tra tính nguyên thủy của Fermat và các số của Carmichael. Bài kiểm tra này dựa trên tiền đề a^(p-1) mod p==1sẽ luôn giữ các số nguyên tố p, nhưng không phải lúc nào cũng cho các vật liệu tổng hợp. Bây giờ, một số carmichael về cơ bản là kẻ thù tồi tệ nhất trong bài kiểm tra của Fermat: Một số mà bạn phải chọn ađể không phải là đồng tướng pđể có được a^(p-1) mod p!=1. Bây giờ nếu akhông phải là đồng nguyên tố, về cơ bản bạn đã tìm thấy một yếu tố không tầm thường củapvà như chúng ta đều biết bao thanh toán có thể khá khó khăn. Đặc biệt là nếu tất cả các yếu tố là đủ lớn. Bây giờ bạn có thể nhận ra lý do tại sao thử nghiệm Fermat không được sử dụng trong thực tế thường xuyên (cũng có thuật toán tốt hơn), bởi vì có những con số mà bạn với tư cách là một người bảo vệ (về mặt bảo mật) sẽ phải thực hiện một số lượng công việc tương tự như một kẻ tấn công (cụ thể là yếu tố số lượng).

Vì vậy, bây giờ chúng tôi biết tại sao những con số này có phần hấp dẫn, chúng tôi sẽ tạo ra chúng theo cách ngắn nhất có thể, vì vậy chúng tôi chỉ có thể ghi nhớ mã tạo nếu chúng tôi cần!

Số Carmichael còn được gọi là A002997 trên OEIS .
Đã có một thách thức liên quan , nhưng các mục từ đó không cạnh tranh ở đây vì chúng được tối ưu hóa cho tốc độ trái ngược với kích thước. Lập luận tương tự cho hướng ngược lại, các mục ở đây có khả năng tạo ra sự đánh đổi so với tốc độ có lợi cho kích thước.

Sự chỉ rõ

Đầu vào

Đây là một thách thức tiêu chuẩn , vì vậy bạn lấy số nguyên dương hoặc không âm nlàm đầu vào. ncó thể là 0- hoặc 1 - được lập chỉ mục nếu bạn muốn (vui lòng cho biết).

Đầu ra

Đầu ra của bạn sẽ là nsố carmichael thứ hoặc số ncarmichael đầu tiên , nếu bạn muốn (vui lòng cho biết).

Sự chỉ rõ

Một số nguyên xlà một số Carmichael khi và chỉ khi xlà tổng hợp và cho tất cả các số nguyên yvới gcd(x,y)=1, nó giữ số đó y^(x-1) mod x==1.

Ai thắng?

Đây là , vì vậy mã ngắn nhất tính bằng byte sẽ thắng!
Áp dụng quy tắc IO và kẽ hở tiêu chuẩn.

Các trường hợp thử nghiệm

Một số số carmichael đầu tiên là:

 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

Câu trả lời:



6

Python 2 , 92 byte

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

Hãy thử trực tuyến!

1-chỉ số và chậm như mật đường.

Trong danh sách hiểu biết, tôi sử dụng phương pháp của Dennis để tạo ra tất cả các số nguyên tố cùng nhau đển (n của totatives ), và sau đó tôi tính toán x**~-n%ncho tất cả chúng. Hãy gọi danh sách này L.

Để phát hiện ra một số Carmichael, tôi so sánh danh sách này theo từ vựng với một danh sách bao gồm các danh sách n-1. Tại sao điều này làm việc?

Mỗi phần tử của Llà một số nguyên dương: (k/n)là nguyên tố cùng n, vì vậy (k/n)**~-ncũng là như vậy (k/n)**~-n%n > 0. Do đó, các giá trị khả dĩ duy nhất của Lnó là ít hơn về mặt từ vựng so với các giá trị [1]*(n-1)bao gồm ít hơn các giá trị n-1. ( Lkhông thể chứa nhiều hơn n-1các giá trị, vì nkhông thể có nhiều hơn n-1tổng số! Vì vậy, các so sánh giống như đã [1,1,1,1,3] < [1,1,1,1]hết.)

Kiểm tra rằng có ít hơn n-1các mục trong Lđảm bảo nlà tổng hợp. (Có n-1tổng số là một điều kiện tương đương với tính nguyên thủy.) Và sau đó, điều kiện để trở thành một số Carmichael chính xác là mọi yếu tố đều Lbằng nhau 1. Vì vậy, so sánh từ vựng này phát hiện chính xác những gì Lchúng ta quan tâm.

Ông Xcoder đã lưu một byte bằng cách chuyển sang dạng lambda đệ quy: jđếm ngược mỗi khi chúng tôi nhấn số Carmichael và nđếm ngược mỗi khi chúng tôi lặp lại. Vì vậy, một khi jchạm 0, n-1bằng với số original_value_of_jthứ tự của Carmichael.


5

Thạch ,  12  11 byte

-1 byte nhờ dặm & Ông Xcoder (sử dụng Carmichael chức năng nguyên tử và một sân golf của chúng)

%Æc’=ÆP
⁹Ç#

Một liên kết đơn âm lấy nvà trả về một danh sách các nsố Carmichael đầu tiên .

Hãy thử trực tuyến!

Làm sao?

Giống như trước đây (bên dưới) ngoại trừ có tích hợp chức năng Carmichael - mang lại công suất nhỏ nhất sao cho đầu vào được tăng lên với công suất đó phù hợp với một modulo có công suất cho tất cả các số nguyên đồng nguyên với số nguyên đó. Do đó, chúng tôi có thể loại trừ các giá trị dương (số nguyên tố) theo ít byte hơn và có mã nhanh hơn!

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

Trước 12 byte :

Ṗ*%⁼Ṗ_ÆP
⁹Ç#

Hãy thử trực tuyến! (Vâng, nó hết thời gian cho n=3).

Làm sao?

Một số ,, clà một số Carmichael nếu nó là hợp số và đúng là bất kỳ số nguyên nào x, được nâng lên cđều đồng dạng với xmodulo c.

Chúng ta chỉ cần kiểm tra điều này cho tích cực xlên đến x=cchính nó.

Cũng lưu ý rằng x=ctrong kiểm tra là liệu xnâng lên sức mạnh của việc xphù hợp với xmodulo hay không x, điều này đúng - vì vậy chúng ta không cần kiểm tra điều này (điều này làm cho mã ngắn hơn).

Ṗ*%⁼Ṗ_Æ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

Cũng 12 byte nhưng tính toán 33 đầu tiên trong vòng một phút bằng cách sử dụng nguyên tử Carmichael.
dặm

11 byte bằng cách sử dụng chức năng Carmichael tích hợp.
Ông Xcoder

@ Mr.Xcoder tôi sẽ đề nghị dặm posted riêng biệt, sau đó bạn cưa sau đó nhìn thấy bình luận của bạn và xóa. Các dv có thể là do ai đó nghĩ nó quá giống với dặm nhận xét một chứ không phải là thế này, nhưng tôi nghĩ rằng thậm chí đó là một lý do kỳ lạ vì không có lý do gì để nghĩ rằng bạn không tìm thấy điều tương tự một cách độc lập (Tôi biết tôi' đã làm điều đó nhiều lần). Tôi sẽ đăng 11 của bạn nếu bạn muốn, nhưng tôi có ý kiến bạn hoặc dặm nên dùng một số tín dụng.
Jonathan Allan

@miles quá ... ^
Jonathan Allan

@Jonathan ALLan Chỉ cần đăng nó cho mình. Đề cập dặm và đóng góp của tôi, và tôi không nghĩ dặm óc hoặc :-) (BTW Tôi thậm chí không nhìn thấy dặm bình luận: - / trước khi gửi bài trả lời của tôi)
Ông Xcoder

2

Regex ECMAScript, 86 89 byte

Cảnh báo: Đừng đọc điều này nếu bạn không muốn một số ma thuật regex unary hư hỏng cho bạn. Nếu bạn thực sự muốn tự mình tìm ra phép thuật này, tôi khuyên bạn nên bắt đầu bằng cách giải quyết một số vấn đề trong biểu thức ECMAScript: xem bài đăng trước đó để biết danh sách các vấn đề được đề xuất liên quan đến spoiler để giải quyết từng vấn đề.

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

Hãy thử trực tuyến!

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

Phép thuật chính của regex này nằm ở phần khẳng định rằng tất cả các yếu tố chính của N đều là bội số chính xác. Đó là một mẹo tương tự như được sử dụng bởi các chuỗi Match của tôi có độ dài là sức mạnh thứ tưTìm các biểu thức số mượt nhất : phân chia ngầm định lặp lại theo thừa số nguyên tố nhỏ nhất.

Cũng có thể kiểm tra trực tiếp rằng N không có yếu tố bình phương hoàn hảo (nghĩa là N không có hình vuông). Điều này sử dụng một biến thể của thuật toán nhân được mô tả ngắn gọn trong một đoạn của bài regex số phong phú của tôi để kiểm tra xem một số có phải là một hình vuông hoàn hảo hay không. Đây là một spoiler . Vì vậy, đừng đọc thêm nữa nếu bạn không muốn một số phép thuật regex unary tiên tiến được làm hỏng cho bạn . Nếu bạn thực sự muốn tự mình tìm ra phép thuật này, tôi khuyên bạn nên bắt đầu bằng cách giải quyết một số vấn đề trong danh sách các vấn đề được đề xuất liên quan đến spoiler trong bài viết trước đó và cố gắng đưa ra những hiểu biết toán học một cách độc lập.

Tuy nhiên, sử dụng thuật toán đó cho vấn đề này không mang lại bất kỳ lợi ích nào. Nó dẫn đến một regex chậm hơn, với kích thước lớn hơn 97 byte. Nếu không có phép thử bội số nguyên tố (trong một vòng lặp khẳng định cả hai có ít nhất 2 thừa số nguyên tố và chúng là mỗi bội số đơn), chúng ta phải khẳng định riêng rằng N là hợp số.

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

Hãy thử trực tuyến!


 ^
 (?!
     # 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
(Nói đúng ra, đây là một decision-problemcâu trả lời, nhưng thách thức là một sequencethách thức.) Có lẽ trong một biến thể regex mạnh hơn sẽ có một thử nghiệm trực tiếp hơn cho các ước số vuông có sẵn?
Neil

@Neil Bạn nói đúng, tôi có thể đánh gôn bằng cách trực tiếp kiểm tra các ước số vuông. Trong ECMA, không có tính năng bổ sung cần thiết. Nhưng điều đó sẽ làm cho nó chậm hơn nhiều (và tôi cũng muốn ẩn nó dưới thẻ spoiler). Tôi nghĩ tôi sẽ bao gồm cả hai phiên bản.
Deadcode

Vâng, thật khó chịu khi tìm câu hỏi cho các biểu thức mà tôi đã viết, đó không phải là loại thách thức đúng. Tôi có nên xóa câu trả lời của mình?
Deadcode

@Neil Ở đây bạn đi. Tôi thực hiện thuật toán bằng ý tưởng của bạn. Đây có lẽ là lý do tại sao tôi không nghĩ sẽ tự mình theo đuổi nó; nó thực sự dẫn đến một regex dài hơn, bởi vì một bài kiểm tra tổng hợp là cần thiết.
Deadcode

(Theo quy tắc trang web, bạn nên xóa câu trả lời của mình, vâng.) Ý tưởng của tôi là sử dụng các tính năng bổ sung của Retina regexes, bạn có thể đánh golf xuống ^(?!(x(x+))(?!\2*$)\1*(?=\1$)(?!(xx+)\3+$)|((^x|xx\5){2,})\4*$)(xx+)\6+$hoặc thậm chí có thể dưới 72 byte.
Neil


1

Võng mạc , 94 byte

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

Hãy thử trực tuyến! 1 chỉ mục. Không nhanh, vì vậy sẽ hết thời gian cho n>5TIO. Giải trình:

\d*$
x

Tăng giá trị hiện tại. Trong lần đầu tiên, điều này cũng xóa nkhỏi bộ đệm đầu ra (nhưng $+vẫn có thể truy cập nó).

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

Kiểm tra xem giá trị hiện tại có phải là số của Carmichael không. Điều này sử dụng thuật toán thay thế của @ Deadcode, vì phát hiện bình phương ngắn hơn khi được viết bằng regex .NET / Perl / PCRE.

^+`

Lặp lại cho đến khi giá trị hiện tại là một số Carmichael.

$
x

Tăng giá trị hiện tại.

"$+"}

Lặp lại bước tăng ban đầu và nthời gian vòng lặp trên .

x

Chuyển đổi kết quả thành số thập phân.


0

Haskell , 95 byte

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

Hãy thử trực tuyến!

Bị thoái hóa:

-- 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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.