Regex (ECMAScript) 131 ไบต์
อย่างน้อย -12 ไบต์ต้องขอบคุณ Deadcode (ในการแชท)
(?=((xx+)(?=\2+$)|x+)+)(?=((x*?)(?=\1*$)(?=(\4xx+?)(\5*(?!(xx+)\7+$)\5)?$)(?=((x*)(?=\5\9*$)x)(\8*)$)x*(?=(?=\5$)\1|\5\10)x)+)\10|x
ลองออนไลน์!
ผลลัพธ์คือความยาวของการแข่งขัน
ECMAScript regexes ทำให้ยากมากที่จะนับสิ่งใด backref ใด ๆ ที่กำหนดไว้ภายนอก loop จะคงที่ในระหว่าง loop, backref ใด ๆ ที่กำหนดภายใน loop จะถูกรีเซ็ตเมื่อทำการลูป ดังนั้นวิธีเดียวที่จะทำให้สถานะข้ามการวนซ้ำนั้นใช้ตำแหน่งการจับคู่ปัจจุบัน นั่นคือจำนวนเต็มเดียวและมันสามารถลดลงได้ (ตำแหน่งก็จะเพิ่มขึ้น แต่ความยาวของหางจะลดลงและนั่นคือสิ่งที่เราสามารถทำคณิตศาสตร์ได้)
เมื่อพิจารณาจากข้อ จำกัด เหล่านั้นการนับจำนวน coprime ดูเหมือนเป็นไปไม่ได้ แต่เราใช้สูตรของออยเลอร์ในการคำนวณหาผลรวม
นี่คือลักษณะของปลอมใน pseudocode:
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
มีสองสิ่งที่น่าสงสัยเกี่ยวกับเรื่องนี้
อันดับแรกเราไม่บันทึกอินพุตเฉพาะผลิตภัณฑ์ปัจจุบันดังนั้นเราจะไปถึงปัจจัยสำคัญของอินพุตได้อย่างไร เคล็ดลับคือ (N - (N / P)) มีปัจจัยสำคัญเหมือนกัน> P เป็น N มันอาจได้รับปัจจัยใหม่ที่สำคัญ <P แต่เราไม่สนใจสิ่งเหล่านั้น โปรดทราบว่าสิ่งนี้ใช้งานได้เพียงเพราะเราวนซ้ำปัจจัยที่สำคัญที่สุดจากน้อยที่สุดไปหามากที่สุดไปทางอื่นจะล้มเหลว
ข้อที่สองเราต้องจำตัวเลขสองตัวในการวนซ้ำวนซ้ำ (P และ N, Z ไม่นับเพราะมันคงที่) และฉันแค่บอกว่ามันเป็นไปไม่ได้! โชคดีที่เราสามารถ Swizzle ทั้งสองตัวเลขในหนึ่งเดียว โปรดทราบว่าในตอนเริ่มต้นของลูป N จะเป็นผลคูณของ Z เสมอในขณะที่ P จะน้อยกว่า Z เสมอดังนั้นเราสามารถจำ N + P และแยก P ด้วยโมดูโลได้
นี่คือรหัสเทียมที่มีรายละเอียดเล็กน้อยมากขึ้น:
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
และนี่คือ regex ที่แสดงความคิดเห็น:
# \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
และเป็นโบนัส ...
Regex (ECMAScript 2018, จำนวนการแข่งขัน), 23 ไบต์
x(?<!^\1*(?=\1*$)(x+x))
ลองออนไลน์!
ผลลัพธ์คือจำนวนการแข่งขัน ECMAScript 2018 แนะนำการมองความยาวผันแปร (ประเมินจากขวาไปซ้าย) ซึ่งทำให้สามารถนับจำนวน coprime ทั้งหมดด้วยอินพุตได้อย่างง่ายดาย
ปรากฎว่าสิ่งนี้เป็นวิธีเดียวกับที่ใช้โดยโซลูชัน Retina ของ Leaky Nunและ regex นั้นก็มีความยาวเท่ากัน ( และสามารถเปลี่ยนได้ ) ฉันออกจากที่นี่เพราะอาจเป็นที่สนใจว่าวิธีนี้ใช้ได้ใน ECMAScript 2018 (ไม่ใช่แค่. 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