Regex (ECMAScript), 276 205 201 193 189 byte
Il confronto delle molteplicità (esponenti) di diversi fattori primi è un problema interessante per la risoluzione con la regex di ECMAScript: la mancanza di riferimenti secondari che persistono attraverso iterazioni di un ciclo rende una sfida contare qualsiasi cosa. Anche se è possibile contare il carattere numerico in questione, spesso un approccio più indiretto rende migliore il golf.
Come con gli altri miei post regex ECMA, darò un avviso spoiler: consiglio vivamente di imparare a risolvere i problemi matematici unari in regex ECMAScript. È stato un viaggio affascinante per me e non voglio rovinarlo per nessuno che potrebbe potenzialmente provarlo da solo, in particolare quelli con un interesse per la teoria dei numeri. Vedi questo post precedente per un elenco di problemi raccomandati consecutivamente con tag spoiler da risolvere uno per uno.
Quindi non leggere oltre se non vuoi che qualche magia regex unaria avanzata venga viziata per te . Se vuoi fare un tentativo per capire da solo questa magia, ti consiglio vivamente di iniziare risolvendo alcuni problemi nella regex di ECMAScript come indicato in quel post collegato sopra.
Il payload principale di una regex che ho sviluppato in precedenza si è rivelato molto applicabile a questa sfida. Questa è la regex che trova i primi della massima molteplicità . La mia prima soluzione è stata molto lunga, e in seguito l'ho portata a tappe gradualmente , prima riscrivendola per usare il lookahead molecolare , e poi riportandola sul semplice ECMAScript usando una tecnica avanzata per aggirare la mancanza di un look molecolare , e successivamente giocare a golf per essere molto più piccolo della semplice soluzione ECMAScript originale.
La parte di quella regex che si applica a questo problema è il primo passo, che trova Q, il più piccolo fattore di N che condivide tutti i suoi fattori primi. Una volta che abbiamo questo numero, tutto ciò che dobbiamo fare per dimostrare che N è un "numero esponente costante" è dividere N per Q fino a quando non possiamo più; se il risultato è 1, tutti i numeri primi sono di uguale molteplicità.
Dopo aver inviato una risposta usando il mio algoritmo precedentemente sviluppato per trovare Q, mi sono reso conto che poteva essere calcolato in un modo completamente diverso: Trova il più grande fattore quadrato libero di N (usando lo stesso algoritmo del mio numero di Carmichael regex ). A quanto pare, ciò non pone alcuna difficoltà * in termini di aggirare la mancanza di lookahead molecolare e lookbehind di lunghezza variabile (non è necessario attingere alla tecnica avanzata precedentemente utilizzata), ed è più breve di 64 byte! Inoltre, elimina la complessità del trattamento di N e primi N quadrati liberi da quadrati come diversi casi speciali, eliminando altri 7 byte da questa soluzione.
(Rimangono ancora altri problemi che richiedono la tecnica avanzata precedentemente utilizzata qui per eseguire il golf down del calcolo di Q, ma attualmente nessuno di questi è rappresentato dai miei post PPCG.)
Ho messo il test di molteplicità prima del test dei numeri primi consecutivi perché quest'ultimo è molto più lento; mettere test che possono fallire più rapidamente prima rende il regex più veloce per un input distribuito uniformemente. È anche meglio il golf per dirla prima, perché utilizza più backreferenze (che costerebbero di più se fossero a due cifre).
Sono stato in grado di eliminare 4 byte da questa regex (193 → 189) usando un trucco trovato da Grimy che può ridurre ulteriormente la divisione nel caso in cui il quoziente sia garantito maggiore o uguale al divisore.
^(?=(|(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?)$))
Provalo online!
# 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?)$
)
)
* È ancora più pulito con un lookahead molecolare, senza nessun caso speciale per N che è privo di quadrati. Questo scende di 6 byte, producendo una soluzione 195 187 183 byte :
^(?=(?*(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?)$
)
)
Qui è portato su lookbehind di lunghezza variabile:
Regex (ECMAScript 2018), 198 195 194 186 182 byte
^(?=(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+))))
Provalo online!
# 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
)