Regex (ECMAScript), 131 byte
Ít nhất -12 byte nhờ Deadcode (trong trò chuyện)
(?=((xx+)(?=\2+$)|x+)+)(?=((x*?)(?=\1*$)(?=(\4xx+?)(\5*(?!(xx+)\7+$)\5)?$)(?=((x*)(?=\5\9*$)x)(\8*)$)x*(?=(?=\5$)\1|\5\10)x)+)\10|x
Hãy thử trực tuyến!
Đầu ra là độ dài của trận đấu.
Các biểu thức ECMAScript làm cho nó cực kỳ khó để đếm bất cứ điều gì. Bất kỳ backref nào được xác định bên ngoài một vòng lặp sẽ không đổi trong vòng lặp, mọi backref được xác định bên trong một vòng lặp sẽ được đặt lại khi lặp. Vì vậy, cách duy nhất để mang trạng thái qua các vòng lặp là sử dụng vị trí khớp hiện tại. Đó là một số nguyên duy nhất và nó chỉ có thể giảm (tốt, vị trí tăng, nhưng độ dài của đuôi giảm và đó là những gì chúng ta có thể làm toán học).
Với những hạn chế đó, chỉ đơn giản là đếm số lượng đồng thanh toán dường như là không thể. Thay vào đó, chúng tôi sử dụng công thức của Euler. để tính tổng.
Đây là cách nó trông giống như trong mã giả:
N = input
Z = largest prime factor of N
P = 0
do:
P = smallest number > P that’s a prime factor of N
N = N - (N / P)
while P != Z
return N
Có hai điều đáng ngờ về điều này.
Đầu tiên, chúng tôi không lưu dữ liệu đầu vào, chỉ sản phẩm hiện tại, vậy làm thế nào chúng tôi có thể nhận được các yếu tố chính của đầu vào? Thủ thuật là (N - (N / P)) có cùng các thừa số nguyên tố> P như N. Nó có thể đạt được các thừa số nguyên tố mới <P, nhưng dù sao chúng ta cũng bỏ qua các yếu tố đó. Lưu ý rằng điều này chỉ hoạt động bởi vì chúng tôi lặp đi lặp lại các yếu tố chính từ nhỏ nhất đến lớn nhất, đi theo cách khác sẽ thất bại.
Thứ hai, chúng ta phải nhớ hai số trên các lần lặp lặp (P và N, Z không được tính vì nó không đổi) và tôi chỉ nói rằng điều đó là không thể! Rất may, chúng ta có thể làm mờ hai số đó trong một số duy nhất. Lưu ý rằng, khi bắt đầu vòng lặp, N sẽ luôn là bội số của Z, trong khi P sẽ luôn nhỏ hơn Z. Vì vậy, chúng ta chỉ cần nhớ N + P và trích xuất P bằng một modulo.
Đây là mã giả chi tiết hơn một chút:
N = input
Z = largest prime factor of N
do:
P = N % Z
N = N - P
P = smallest number > P that’s a prime factor of N
N = N - (N / P) + P
while P != Z
return N - Z
Và đây là regex bình luận:
# \1 = largest prime factor of N
# Computed by repeatedly dividing N by its smallest factor
(?= ( (xx+) (?=\2+$) | x+ )+ )
(?=
# Main loop!
(
# \4 = N % \1, N -= \4
(x*?) (?=\1*$)
# \5 = next prime factor of N
(?= (\4xx+?) (\5* (?!(xx+)\7+$) \5)? $ )
# \8 = N / \5, \9 = \8 - 1, \10 = N - \8
(?= ((x*) (?=\5\9*$) x) (\8*) $ )
x*
(?=
# if \5 = \1, break.
(?=\5$) \1
|
# else, N = (\5 - 1) + (N - B)
\5\10
)
x
)+
) \10
Và như một phần thưởng
Regex (ECMAScript 2018, số lượng trận đấu), 23 byte
x(?<!^\1*(?=\1*$)(x+x))
Hãy thử trực tuyến!
Đầu ra là số lượng trận đấu. ECMAScript 2018 giới thiệu nhìn phía sau có độ dài thay đổi (được đánh giá từ phải sang trái), giúp bạn có thể chỉ cần đếm tất cả các số nguyên tố cùng với đầu vào.
Hóa ra đây là phương pháp độc lập tương tự được sử dụng bởi giải pháp Retina của Leaky Nun và regex thậm chí có cùng độ dài ( và có thể thay thế cho nhau ). Tôi để nó ở đây vì có thể quan tâm rằng phương pháp này hoạt động trong ECMAScript 2018 (và không chỉ .NET).
# Implicitly iterate from the input to 0
x # Don’t match 0
(?<! ) # Match iff there is no...
(x+x) # integer >= 2...
(?=\1*$) # that divides the current number...
^\1* # and also divides the input