Regex (ECMAScript), 131 byte
Setidaknya -12 byte berkat Deadcode (dalam obrolan)
(?=((xx+)(?=\2+$)|x+)+)(?=((x*?)(?=\1*$)(?=(\4xx+?)(\5*(?!(xx+)\7+$)\5)?$)(?=((x*)(?=\5\9*$)x)(\8*)$)x*(?=(?=\5$)\1|\5\10)x)+)\10|x
Cobalah online!
Output adalah panjang pertandingan.
Regex ECMAScript membuatnya sangat sulit untuk menghitung apa pun. Setiap backref yang didefinisikan di luar loop akan konstan selama loop, setiap backref yang didefinisikan di dalam loop akan direset ketika looping. Dengan demikian, satu-satunya cara untuk membawa status melintasi loop berulang adalah menggunakan posisi kecocokan saat ini. Itu bilangan bulat tunggal, dan itu hanya bisa berkurang (well, posisinya meningkat, tetapi panjang ekornya berkurang, dan itulah yang bisa kita lakukan dengan matematika).
Mengingat pembatasan-pembatasan itu, menghitung angka-angka coprime tampaknya mustahil. Sebagai gantinya, kami menggunakan formula Euler untuk menghitung angka total.
Begini tampilannya di 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
Ada dua hal yang meragukan tentang ini.
Pertama, kita tidak menyimpan input, hanya produk saat ini, jadi bagaimana kita bisa sampai pada faktor utama input? Triknya adalah bahwa (N - (N / P)) memiliki faktor prima yang sama> P dengan N. Ini mungkin mendapatkan faktor prima baru <P, tetapi kita tetap mengabaikannya. Perhatikan bahwa ini hanya berfungsi karena kita beralih pada faktor utama dari yang terkecil hingga yang terbesar, sebaliknya akan gagal.
Kedua, kita harus mengingat dua angka di seluruh iterasi loop (P dan N, Z tidak dihitung karena konstan), dan saya hanya mengatakan itu tidak mungkin! Syukurlah, kita dapat memutar dua angka itu dalam satu. Perhatikan bahwa, pada awal loop, N akan selalu menjadi kelipatan Z, sedangkan P akan selalu kurang dari Z. Dengan demikian, kita bisa mengingat N + P, dan mengekstrak P dengan modulo.
Berikut kode semu yang sedikit lebih detail:
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
Dan inilah regex yang dikomentari:
# \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
Dan sebagai bonus ...
Regex (ECMAScript 2018, jumlah kecocokan), 23 byte
x(?<!^\1*(?=\1*$)(x+x))
Cobalah online!
Output adalah jumlah kecocokan. ECMAScript 2018 memperkenalkan variabel-panjang melihat-belakang (dievaluasi dari kanan ke kiri), yang memungkinkan untuk hanya menghitung semua angka coprime dengan input.
Ternyata ini adalah metode independen yang sama yang digunakan oleh solusi Retina Leaky Nun , dan regex bahkan memiliki panjang yang sama ( dan dapat dipertukarkan ). Saya meninggalkannya di sini karena mungkin menarik bahwa metode ini berfungsi di ECMAScript 2018 (dan bukan hanya .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