Regex (ECMAScript), 276 205 201 193 189 ไบต์
การเปรียบเทียบหลายหลาก (เลขยกกำลัง) ของปัจจัยสำคัญต่าง ๆ เป็นปัญหาที่น่าสนใจสำหรับการแก้ด้วย ECMAScript regex - การขาดการอ้างอิงย้อนกลับที่ยังคงมีอยู่ผ่านการวนซ้ำของลูปทำให้มันนับเป็นเรื่องท้าทาย แม้ว่าจะมีการนับลักษณะตัวเลขที่เป็นไปได้ แต่บ่อยครั้งที่วิธีทางอ้อมมากขึ้นทำให้กอล์ฟดีขึ้น
เช่นเดียวกับการโพสต์ regex ECMA อื่น ๆ ของฉันฉันจะให้คำเตือนผู้สปอยเลอร์:ฉันขอแนะนำให้เรียนรู้วิธีการแก้ปัญหาทางคณิตศาสตร์ที่ไม่ธรรมดาใน ECMAScript regex มันเป็นการเดินทางที่น่าสนใจสำหรับฉันและฉันไม่ต้องการที่จะทำลายมันสำหรับใครก็ตามที่อาจต้องการลองด้วยตัวเองโดยเฉพาะผู้ที่มีความสนใจในทฤษฎีจำนวน ดูโพสต์ก่อนหน้านี้สำหรับรายการปัญหาที่แนะนำติดแท็กสปอยเลอร์ติดต่อกันเพื่อแก้ไขทีละรายการ
ดังนั้นไม่ได้อ่านเพิ่มเติมใด ๆ ถ้าคุณไม่ต้องการบางขั้นสูงมายากล regex เอกมากมายสำหรับคุณ หากคุณต้องการถ่ายภาพเพื่อหาเวทมนตร์นี้ด้วยตัวเองฉันขอแนะนำให้เริ่มต้นด้วยการแก้ปัญหาบางอย่างใน ECMAScript regex ดังที่อธิบายไว้ในโพสต์ที่ลิงก์ด้านบน
น้ำหนักบรรทุกหลักจาก regex ที่ฉันพัฒนาขึ้นก่อนหน้านี้เปิดใช้งานเพื่อความท้าทายนี้มาก นั่นคือregex ที่พบนายก (s) ของหลายหลากสูงสุด วิธีแก้ปัญหาแรกของฉันนั้นยาวมากและต่อมาฉันก็ตีมันลงเป็นขั้นตอนเขียนใหม่ให้ใช้โมเลกุลลุคเฮดแล้วเปลี่ยนกลับเป็น ECMAScript ธรรมดาโดยใช้เทคนิคขั้นสูงเพื่อแก้ปัญหาการขาดอณูของโมเลกุลและต่อมา ตีกอล์ฟให้เล็กลงกว่า ECMAScript แบบเดิม ๆ
ส่วนจาก regex นั้นที่ใช้กับปัญหานี้คือขั้นตอนแรกซึ่งพบ Q ซึ่งเป็นปัจจัยที่เล็กที่สุดของ N ที่แบ่งใช้ปัจจัยสำคัญทั้งหมดของมัน เมื่อเรามีจำนวนนี้สิ่งที่เราต้องทำเพื่อแสดงว่า N คือ "จำนวนเลขชี้กำลัง - คงที่" จะหาร N ด้วย Q จนกว่าเราจะทำไม่ได้อีกต่อไป ถ้าผลลัพธ์คือ 1 primes ทั้งหมดมีหลายหลากเท่ากัน
หลังจากส่งคำตอบโดยใช้อัลกอริทึมที่พัฒนาขึ้นก่อนหน้านี้ของฉันเพื่อค้นหา Q ฉันรู้ว่ามันสามารถคำนวณได้ในวิธีที่แตกต่างกันโดยสิ้นเชิง: ค้นหาตัวประกอบแบบไม่มีช่องสี่เหลี่ยมที่ใหญ่ที่สุดของ N (ใช้อัลกอริทึมแบบเดียวกับเลขทะเบียน Carmichaelของฉัน) มันกลับกลายเป็นว่าไม่มีความยุ่งยากเลย * ในแง่ของการก้าวไปรอบ ๆ โดยที่ไม่มีโมเลกุล lookahead และ lookbehind ความยาวผันแปร (ไม่จำเป็นต้องดึงเทคนิคขั้นสูงที่ใช้ก่อนหน้านี้) และสั้นกว่า 64 ไบต์! นอกจากนี้ยังช่วยลดความซับซ้อนในการรักษา N แบบไม่มีสี่เหลี่ยมและไพรม์ N เป็นกรณีพิเศษที่แตกต่างกันโดยทิ้งอีก 7 ไบต์จากโซลูชันนี้
(ยังคงมีปัญหาอื่น ๆ ที่ต้องใช้เทคนิคขั้นสูงซึ่งก่อนหน้านี้ใช้เพื่อคำนวณการคำนวณ Q แต่ปัจจุบันไม่มีโพสต์ PPCG ของฉันแสดง)
ฉันใส่การทดสอบหลายหลากก่อนการทดสอบช่วงต่อเนื่องเพราะช่วงหลังช้ากว่ามาก การทดสอบที่สามารถล้มเหลวได้เร็วขึ้นก่อนทำให้ regex เร็วขึ้นสำหรับการป้อนข้อมูลแบบกระจาย นอกจากนี้ยังเป็นสนามกอล์ฟที่ดีกว่าที่จะนำมาไว้ก่อนเพราะจะใช้การอ้างอิงย้อนกลับมากขึ้น (ซึ่งจะมีค่าใช้จ่ายมากกว่า
ฉันสามารถปล่อย 4 ไบต์จาก regex นี้ (193 → 189) โดยใช้กลอุบายที่พบโดยGrimyซึ่งสามารถแบ่งส่วนที่สั้นลงในกรณีที่รับประกันหารหารหารได้มากกว่าหรือเท่ากับตัวหาร
^(?=(|(x+)\2*(?=\2$))((?=(xx+?)\4*$)(?=(x+)(\5+$))\6(?!\4*$))*x$)(?=.*$\2|((?=((x*)(?=\2\9+$)x)(\8*$))\10)*x$)(?!(((x+)(?=\13+$)(x+))(?!\12+$)(x+))\11*(?=\11$)(?!(\15\14?)?((xx+)\18+|x?)$))
ลองออนไลน์!
# For the purposes of these comments, the input number = N.
^
# Assert that all of N's prime factors are of equal multiplicity
# Step 1: Find Q, the largest square-free factor of N (which will also be the smallest
# factor of N that has all the same prime factors as N) and put it in \2.
# If N is square-free, \2 will be unset.
(?=
# Search through all factors of N, from largest to smallest, searching for one that
# satisfies the desired property. The first factor tried will be N itself, for which
# \2 will be unset.
(|(x+)\2*(?=\2$)) # for factors < N: \2 = factor of N; tail = \2
# Assert that tail is square-free (its prime factors all have single multiplicity)
(
(?=(xx+?)\4*$) # \4 = smallest prime factor of tail
(?=(x+)(\5+$)) # \5 = tail / \4 (implicitly); \6 = tool to make tail = \5
\6 # tail = \5
(?!\4*$) # Assert that tail is no longer divisible by \4, i.e. that that
# prime factor was of exactly single multiplicity.
)*x$
)
# Step 2: Require that either \2 is unset, or that the result of repeatedly
# dividing tail by \2 is 1.
(?=
.*$\2
|
(
# In the following division calculation, we can skip the test for divisibility
# by \2-1 because it's guaranteed that \2 <= \8. As a result, we did not need to
# capture \2-1 above, and can use a better-golfed form of the division.
(?=
( # \8 = tail / \2
(x*) # \9 = \8-1
(?=\2\9+$)
x
)
(\8*$) # \10 = tool to make tail = \8
)
\10 # tail = \8
)*
x$ # Require that the end result is 1
)
# Assert that there exists no trio of prime numbers such that N is divisible by the
# smallest and largest prime but not the middle prime.
(?!
( # \11 = a factor of N
( # \12 = a non-factor of N between \11 and \13
(x+)(?=\13+$) # \13 = a factor of N smaller than \11
(x+) # \14 = tool (with \15) to make tail = \13
)
(?!\12+$)
(x+) # \15 = tool to make tail = \12
)
\11*(?=\11$) # tail = \11
# Assert that \11, \12, and \13 are all prime
(?!
(\15\14?)? # tail = either \11, \12, or \13
((xx+)\18+|x?)$
)
)
* มันยังคงสะอาดกว่าด้วย lookahead ในระดับโมเลกุลโดยไม่มีกรณีพิเศษสำหรับ N ที่ไม่มีรูปทรงสี่เหลี่ยม สิ่งนี้จะลดลง 6 ไบต์ซึ่งให้ผลการแก้ปัญหา195 187 183 ไบต์ :
^(?=(?*(x+))\1*(?=\1$)((?=(xx+?)\3*$)(?=(x+)(\4+$))\5(?!\3*$))*x$)(?=((?=((x*)(?=\1\8+$)x)(\7*$))\9)*x$)(?!(((x+)(?=\12+$)(x+))(?!\11+$)(x+))\10*(?=\10$)(?!(\14\13?)?((xx+)\17+|x?)$))
# For the purposes of these comments, the input number = N.
^
# Assert that all of N's prime factors are of equal multiplicity
# Step 1: Find Q, the largest square-free factor of N (which will also be the smallest
# factor of N that has all the same prime factors as N) and put it in \1.
(?=
(?*(x+)) # \1 = proposed factor of N
\1*(?=\1$) # Assert that \1 is a factor of N; tail = \1
# Assert that tail is square-free (its prime factors all have single multiplicity)
(
(?=(xx+?)\3*$) # \3 = smallest prime factor of tail
(?=(x+)(\4+$)) # \4 = tail / \3 (implicitly); \5 = tool to make tail = \4
\5 # tail = \4
(?!\3*$) # Assert that tail is no longer divisible by \3, i.e. that that
# prime factor was of exactly single multiplicity.
)*x$
)
# Step 2: Require that the result of repeatedly dividing tail by \1 is 1.
(?=
(
# In the following division calculation, we can skip the test for divisibility
# by \1-1 because it's guaranteed that \2 <= \8. As a result, we did not need to
# capture \1-1 above, and can use a better-golfed form of the division.
(?=
( # \7 = tail / \1
(x*) # \8 = \7-1
(?=\1\8+$)
x
)
(\7*$) # \9 = tool to make tail = \7
)
\9 # tail = \7
)*
x$ # Require that the end result is 1
)
# Assert that there exists no trio of prime numbers such that N is divisible by the
# smallest and largest prime but not the middle prime.
(?!
( # \10 = a factor of N
( # \11 = a non-factor of N between \10 and \12
(x+)(?=\12+$) # \12 = a factor of N smaller than \10
(x+) # \13 = tool (with \14) to make tail = \12
)
(?!\11+$)
(x+) # \14 = tool to make tail = \11
)
\10*(?=\10$) # tail = \10
# Assert that \10, \11, and \12 are all prime
(?!
(\14\13?)? # tail = either \10, \11, or \12
((xx+)\17+|x?)$
)
)
นี่คือพอร์ตไปยัง lookbehind ความยาวผันแปร:
Regex (ECMAScript 2018) 198 195 194 186 182 ไบต์
^(?=(x+)(?=\1*$)(?<=^x((?<!^\5*)\3(?<=(^\4+)(x+))(?<=^\5*(x+?x)))*))((?=((x*)(?=\1\8+$)x)(\7*$))\9)*x$(?<!(?!(\14\16?)?((xx+)\12+|x?)$)(?<=^\13+)((x+)(?<!^\15+)((x+)(?<=^\17+)(x+))))
ลองออนไลน์!
# For the purposes of these comments, the input number = N.
^
# Assert that all of N's prime factors are of equal multiplicity
# Step 1: Find Q, the largest square-free factor of N (which will also be the smallest
# factor of N that has all the same prime factors as N) and put it in \1.
(?=
(x+)(?=\1*$) # \1 = factor of N; head = \1
(?<= # This is evaluated right-to-left, so please read bottom to top.
^x
(
(?<!^\5*) # Assert that head is no longer divisible by \6, i.e. that
# that prime factor was of exactly single multiplicity.
\3 # head = \4
(?<=(^\4+)(x+)) # \4 = head / \5 (implicitly); \3 = tool to make head = \4
(?<=^\5*(x+?x)) # \5 = smallest prime factor of head
)*
)
)
# Step 2: Require that the result of repeatedly dividing tail by \1 is 1.
(
# In the following division calculation, we can skip the test for divisibility
# by \1-1 because it's guaranteed that \2 <= \8. As a result, we did not need to
# capture \1-1 above, and can use a better-golfed form of the division.
(?=
( # \7 = tail / \1
(x*) # \8 = \7-1
(?=\1\8+$)
x
)
(\7*$) # \9 = tool to make tail = \7
)
\9 # tail = \7
)*
x$ # Require that the end result is 1
# Assert that there exists no trio of prime numbers such that N is divisible by the
# smallest and largest prime but not the middle prime.
# This is evaluated right-to-left, so please read bottom to top, but switch back to
# reading top to bottom at the negative lookahead.
(?<!
# Assert that \13, \15, and \17 are all prime.
(?!
(\14\16?)? # tail = either \13, \15, or \17
((xx+)\12+|x?)$
)
(?<=^\13+)
( # tail = \13
(x+) # \14 = tool to make tail = \15
(?<!^\15+)
(
(x+) # \16 = tool (with \14) to make tail = \17
(?<=^\17+)(x+) # \17 = a factor of N smaller than \13
) # \15 = a non-factor of N between \13 and \17
) # \13 = a factor of N
)