Determina se un numero è friabile nel 2017 senza numeri primi nel codice sorgente


41

Di tutti gli anni in cui ho affrontato questa sfida, il 2017 è il primo anno ad essere un numero primo. Quindi la domanda riguarderà i numeri primi e le loro proprietà.

Il vostro compito è quello di produrre un programma o una funzione che avrà un numero arbitrariamente grande intero positivo come input e output o di ritorno se il numero è 2.017-friabile - cioè, se il più grande fattore primo in quel numero è 2017 o meno.


Alcuni esempi di input e loro output:

1 (has no prime factors)
true

2 (= 2)
true

80 (= 2 x 2 x 2 x 2 x 5)
true

2017 (= 2017)
true

2019 (= 3 x 673)
true

2027 (= 2027)
false

11111 (= 41 x 271)
true

45183 (= 3 x 15061)
false

102349 (= 13 x 7873)
false

999999 (= 3 x 3 x 3 x 7 x 11 x 13 x 37)
true

1234567 (= 127 x 9721)
false

4068289 (= 2017 x 2017)
true

Il tuo programma non deve produrre letteralmente truee false- qualsiasi valore di verità o falsità, e in effetti due diversi output che sono coerenti tra casi veri e falsi vanno bene.


Tuttavia, non è possibile utilizzare numeri primi nel codice sorgente. I primes sono di due tipi:

  • Personaggi, o sequenze di personaggi, che rappresentano letterali in numero primo.

    • I personaggi 2, 3, 5, e 7sono illegali in lingue dove i numeri sono gettoni validi.

    • Il numero 141è illegale perché contiene 41, anche se 1e 4sono altrimenti validi.

    • I caratteri Be D(o be d) sono illegali nelle lingue in cui vengono generalmente utilizzati come 11 e 13, come CJam o Befunge.

  • Caratteri che hanno valori Unicode con valori primi o che contengono byte con valori primi nella loro codifica.

    • I caratteri %)+/5;=CGIOSYaegkmqsono illegali in ASCII, così come il carattere di ritorno a capo.

    • Il personaggio óè illegale in UTF-8 perché ha la sua codifica 0xb3. Tuttavia, in ISO-8859-1, la sua codifica è semplicemente 0xf3, che è composita e quindi va bene.

Vince il codice più breve per fare quanto sopra in qualsiasi lingua.


Nota a margine: "friabile" è un miglioramento adottato rispetto al "liscio" vecchio e non descrittivo in questo contesto.
Greg Martin,

1
I valori di verità e falsità devono essere coerenti? O possono variare purché siano sincere o false?
Luis Mendo

10
La mancanza di =regole esclude la maggior parte delle lingue standard ...
Neil

4
-1 per una sfida do X senza Y. È davvero piuttosto banale nascosto dietro un insieme piuttosto inutile di restrizioni sui personaggi
Downgoat,

1
Non mi piace che la loro parte sia arbitrariamente grande. Sarebbe meglio se salissero a 2 ^ 31-1.
Bijan,

Risposte:


37

Gelatina , 8 byte

44‘²!*ḍ@

Provalo online! Si noti che i casi di test 11111 e successivi sono un po 'troppo per TIO.

Verifica

$ source="34,34,fc,82,21,2a,d5,40"
$ xxd -ps -r > 2017.jelly <<< $source
$ xxd -g 1 2017.jelly
0000000: 34 34 fc 82 21 2a d5 40                          44..!*.@
$ eval printf '"%d "' 0x{$source}; echo # Code points in decimal
52 52 252 130 33 42 213 64
$ test_cases="1 2 80 2017 2019 2027 11111 45183 102349 999999 1234567 4068289"
$ for n in $test_cases; do printf "%11d: %d\n" $n $(jelly f 2017.jelly $n); done
      1: 1
      2: 1
     80: 1
   2017: 1
   2019: 1
   2027: 0
  11111: 1
  45183: 0
 102349: 0

Il test case 999999 è attivo da 13 ore. Sono pessimista riguardo al calcolo del 2025! 4068289 ...

Come funziona

44‘²!*ḍ@  Main link. Argument: n

44        Yield 44.
  ‘       Increment to yield 45.
   ²      Square to yield 2025.
          Note that no integers in [2018, ..., 2025] are prime numbers.
    !     Take the factorial of 2025.
     *    Raise it to the n-th power.
          This repeats all prime factors in 2025! at least n times, so the result
          will be divisible by n if (and only if) all of its prime factors fall
          in the range [1, ..., 2025].
      ḍ@  Test the result for divisibility by n.

22
Sei crudele con i numeri. :)
Greg Martin

3
@GregMartin bah. Ho visto una risposta (in una lingua diversa) in cui un input di dimensione 6 avrebbe inghiottito la memoria per diverse ore, quindi si sarebbe bloccato. Mi limiterò a dire: (2^n)!. Questo richiede anche input di sei dimensioni, ma almeno gli input sono in un alfabeto decimale piuttosto che in un binario.
John Dvorak,

Non sono 13 byte? Dennis, hai così tanta reputazione che sono sicuro che sto facendo uno sbaglio qui ahah 😬
Albert Renshaw,

7
@AlbertRenshaw Sarebbe davvero 13 byte in UTF-8, ma Jelly usa una tabella codici personalizzata che codifica tutti i caratteri che comprende come un singolo byte ciascuno.
Dennis,

3
@Dennis sapeva che ci sarebbe stata una spiegazione; molto bello da imparare, grazie!
Albert Renshaw,

11

Jelly , 8 caratteri, 14 byte di UTF-8

Æf½ṀḤ<90

Provalo online!

Jelly normalmente usa la propria codepage per i programmi. Tuttavia, la maggior parte dei suoi builtin relativi a prime iniziano con Æ, che è il punto di codice 13; non molto utile. Fortunatamente, l'interprete supporta anche UTF-8, che ha una codifica più semplice.

Verifica

Questo programma, in UTF-8, hexdump come questo:

00000000: c386 66c2 bde1 b980 e1b8 a43c 3930  ..f........<90

Verifica che tutti i byte siano compositi:

$ for x in c3 86 66 c2 bd e1 b9 80 e1 b8 a4 3c 39 30; do factor $((0x$x)); done
195: 3 5 13
134: 2 67
102: 2 3 17
194: 2 97
189: 3 3 3 7
225: 3 3 5 5
185: 5 37
128: 2 2 2 2 2 2 2
225: 3 3 5 5
184: 2 2 2 23
164: 2 2 41
60: 2 2 3 5
57: 3 19
48: 2 2 2 2 3

Verifica che tutti i punti di codice Unicode siano compositi:

$ perl -Mutf8 -E '$a = ord, print `factor $a` for split //, "Æf½ṀḤ<90"'
198: 2 3 3 11
102: 2 3 17
189: 3 3 3 7
7744: 2 2 2 2 2 2 11 11
7716: 2 2 3 643
60: 2 2 3 5
57: 3 19
48: 2 2 2 2 3

L'unico token analizzato come numero è 90. Nessuno di 9, 0e 90sono primi.

Spiegazione

L'intuizione matematica principale qui è che 45² è il 2025, che cade ordinatamente tra il 2017 (l'anno in corso) e il 2027 (il prossimo primo). Quindi, possiamo prendere la radice quadrata di ogni fattore primo del numero e vedere se uno supera 45. Sfortunatamente, non possiamo scrivere a 45causa del valore letterale 5, quindi dobbiamo raddoppiarlo e confrontarlo con 90.

Æf½ṀḤ<90
Æf        In the list of prime factors,
  ½       taking the square root of each element
   Ṁ      then taking the largest element
    Ḥ     and doubling it
     <90  produces a result less than 90.

2
Jelly non richiede un flag (1 byte) per usare UTF-8?
Luis Mendo,

@LuisMendo: Interprete della riga di comando, ma l'interprete su Try It Online! è configurato in modo diverso e non lo richiede. Quindi questo è solo un caso di scegliere l'interprete che interpreta il tuo programma nel modo desiderato. (In ogni caso, la bandiera in questione, uè composita, quindi sarebbe solo una questione di cambiare il punteggio piuttosto che qualcosa che lo invalida.)

10

Mathematica, 62 58 55 byte

Gli ultimi tre byte salvati sono totalmente dovuti a Martin Ender!

#4<4||#<44*46&&#6[#^-1#4]&[Divisors[#][[6-4]],,,#,,#0]&

Funzione senza nome che accetta un argomento intero positivo e restituisce Trueo False.

Algoritmo ricorsivo, #4<4essendo il caso base veritiero (abbiamo solo bisogno che ritorni Truesull'imput 1, ma i casi base extra vanno bene). Altrimenti, calcoliamo il secondo divisore più piccolo (che è necessariamente primo) dell'input con Divisors[#][[6-4]]; se è maggiore di 2024 ( 44*46) allora usciamo con False, altrimenti chiamiamo la funzione in modo ricorsivo (usando #6set a #0) sull'input diviso per questo piccolo fattore primo #(che dobbiamo esprimere come #^-1volte l'input #4, poiché /non è consentito).

Strutturalmente, il primo tempo #4<4||#<44*46&&#6[#^-1#4]&è una funzione anonima di sei argomenti, chiamato con argomenti Divisors[#][[6-4]], Null, Null, #, Null, e #0; questo è quello di aggirare il divieto di personaggi 2, 3e 5.

Versione precedente, che ha salvato quattro byte sostituendola 8018-6000con 44*46, ispirata alla risposta Jelly di ais523 (Martin Ender sembrava anche ispirato da un commento ais523):

#<4||Divisors[#][[6-4]]<44*46&&#0[Divisors[#][[6-4]]^-1#]&

Questo è stato piuttosto brutto: non conosco ancora un modo per impostare una variabile in Mathematica con queste restrizioni! Entrambi =e gli ein Setsono vietati. Evitare +ed )era anche un problema, ma non troppo difficile da aggirare a spese di più byte.


Potresti forse impostare un parametro lambda anziché una variabile. (Detto questo, #2sarebbe anche vietato, quindi dovresti stare attento a come i tuoi lambdas hanno annidato e la mancanza di parentesi potrebbe renderlo difficile.)

L'implementazione del suggerimento di @ ais523 consente di salvare tre byte: #4<4||#<44*46&&#6[#^-1#4]&[Divisors[#][[6-4]],,,#,,#0]&genera una serie di avvisi perché ora tenta Divisors[#][[2]]prima di assicurarsi che l'input sia maggiore di 1 (o 3), ma il risultato è ancora corretto.
Martin Ender,

Oh amico, è un'astuzia da brividi.
Greg Martin,

7

Haskell, 48 47 byte

\n->[snd$[product[1..44*46]^n]!!0`divMod`n]<[1]

Fondamentalmente una traduzione della risposta Jelly di Dennis . xnor ha salvato un byte.

Utilizza […]!!0come parentesi perché )è vietato e snd+ divModperché min mode remè vietato.


Bel trucco con il divMod! Penso che puoi sostituire il !!0<1con <[1]. Ma sembra che sia in corto da usare divcome [\p n->p^n`div`n*n>p^n-1]!!0$product[1..44*46].
xnor

C'è anche \n->[0|p<-[product[1..44*46]^n],0<-[p,p-n..0]], che utilizza che gli output devono solo essere coerenti.
xnor

@xnor Sentiti libero di pubblicare quelle come risposte separate, penso che siano sufficientemente diverse dalle mie ^^
Lynn

6

Pyke, 10 8 7 9 byte

P_Z|hwMX<

Provalo qui!

Salvato 1 byte usando il modo di generare 2025 di Dennis

P         -     factors(input)
 _        -    reversed(^)
  Z|      -   ^ or 0
    h     -  ^[0] or 1
        < - ^ < V
     wM   -  ⁴45 (ord("M")-32)
       X  -  ^**2

5

Brachylog , 9 10 byte

*$ph$r*<90

Provalo online!

Fondamentalmente usando lo stesso algoritmo della mia altra risposta. $phtrova il primo ( h) fattore primo ( $p); questo è il fattore primo più grande, poiché le liste dei fattori primi di Brachylog vanno dal più grande al più piccolo. Quindi prendo la radice quadrata ( $r), double ( *) e test per vedere se è inferiore a 90 ( <90).

Ho dovuto prima raddoppiare l'input perché 1 non ha fattori primi (e quindi non ha un primo fattore primo). Ciò aggiunge un ulteriore fattore primo di 2, che non può influire sul fatto che un numero sia o meno vulnerabile al 2017, ma impedisce un errore durante la gestione 1.


5

In realtà , 9 byte

τyM:44u²≥

Grazie a Dennis per molti byte!

Provalo online!

Spiegazione:

τyM:44u²≥
τyM        largest prime factor of 2*input (doubled to deal with edge case of n = 1)
   :44u²   2025 (2027 is the next prime after 2017, so any number in [2017, 2026] can be used here - 2025 is very convenient)
        ≥  is 2025 greater than or equal to largest prime factor?

5

Mathematica, 66 74 byte

Grazie a Dennis per averci fatto notare che U+F4A1è proibito.

Fold[Function[{x,d},And[x,Tr[Divisors@d^0]>6-4||d<44*46]],0<1,Divisors@#]&

Spiegazione:

Divisors@#: Elenco di divisori interi del primo argomento #.

0<1: Golf per True(evita anche l'uso della lettera e).

Divisors@d^0: Elenco del modulo {1, 1, ..., 1}con lunghezza pari al numero di divisori di d.

Tr: Per un elenco semplice, Trrestituisce la somma di tale elenco. Tr[Divisors@d^0]Restituisce quindi il numero di divisori di d.

Function[{x,d},And[x,Tr[Divisors@d^0]>6-4||d<44*46]]: Funzione anonima con due argomenti xe d. L'idea è che dè un divisore di #e testiamo per vedere se è composito o inferiore o uguale a 2017(inclusivo). 2017- la responsabilità equivale a tutti i divisori che soddisfano questa condizione. Come scoperto ais523 , essere un numero primo inferiore o uguale a 2017equivale a essere un numero primo minore di 2025. Come ha sottolineato Greg Martin , è sufficiente verificare se è inferiore a 2024=44*46. L'argomento xfunge da accumulatore per verificare se tutti i divisori incontrati finora soddisfano questa proprietà. Abbiamo quindi lasciato Foldquesta funzione attraverso tutti i divisori di #con valore inizialeTrue, Dal momento che abbiamo accesso a nessuno dei due Map, né /@.


1
Modo di combattere attraverso le restrizioni!
Greg Martin,

2

05AB1E , 10 byte

fθ46n99-›È

Restituisce 1 se vero, 0 altrimenti.

Provalo online!

Spiegazione

f          # Push the list of prime factors (ordered)
 θ         # Get the last element
  46n99-   # Push 2017 (46² - 99)
        >  # Push 1 if the last prime factor is greater than 2017, 0 otherwise
         È # Is the resulting number even ? Transforms 1 to 0 and 0 to 1.
           # Implicit display

Benvenuti in PPCG!
Martin Ender,

1

MATL , 15 byte

t:\~ftZp*44QU<A

Uscite 0per non friabile 12017 o friabile 2017.

Provalo online! Oppure verifica tutti i casi di test .

Questo programma verifica che tutti i byte siano compositi.

Spiegazione

t       % Implicit input n. Duplicate
:       % Range [1 2 ... n]
\       % Modulo. Gives 0 for divisors of n
~f      % Indices of zero values
t       % Duplicate
Zp      % Is-prime. Gives 1 for primes, 0 for composites
*       % Multiply
44QU    % 44, add 1, square: 2025
<       % Less than, element-wise
A       % True (1) if all entries are nonzero

1

Bash, 144 byte

Codifica ASCII:

{
printf '[ '
`tr D-Z _-z <<<KFH`tor $1|tr -d :|`tr B-Z _-z <<<JUH`p -o '[0-9]*$'
printf ' -lt $[24*86-46] ]'
}|tr \\n \ |`tr B-Z _-z <<<EDVK`

Come al solito per la shell, il codice di uscita indica successo (0) o fallimento (diverso da 0).

Questa è effettivamente una diversa ortografia di

[ factor $1|tr -d :|grep -o '[0-9]*$' -lt 2018 ]

Otteniamo il fattore più grande con factor $1|grep -o '[0-9]*$'; la tr -d :è di speciale caso = ingresso 1.

L'espressione $[6*6*69-466]restituisce 2018.

Era difficile da usare trper i nomi dei comandi e usare ancora la sostituzione dei comandi: non potevo usare il modulo di annidamento $( ), quindi ho finito per eseguire il piping in un altro Bash per valutare il risultato.

Risultati del test:

$ for i in 1 2 80 2017 2019 2027 11111 45183 102349 999999 1234567 4068289; do printf '%d %s\n' $i `./105241.sh $i  && echo true || echo false`; done
1 true
2 true
80 true
2017 true
2019 true
2027 false
11111 true
45183 false
102349 false
999999 true
1234567 false
4068289 true

Conferma dei codici carattere:

$ grep -v '^#' ./105241.sh | perl -n -Mutf8 -E '$a = ord, print `factor $a` for split //, $_' | grep -v ': .* ' | wc -l
0




0

Braingolf , 11 byte [molto non competitivo]

VRp#ߢ-?0:1

Provalo online!

Illeggibile a causa del ߢquale avvita con i numeri, tuttavia funziona ancora in un interprete.

Non ho nemmeno notato le restrizioni sui personaggi quando ho scritto questo, ma tutto quello che dovevo fare era cambiare lo strano personaggio unicode dal 2017 al 2018.

Dato che il 2018 non è un numero primo, anche un numero primo lo <= 2018è<= 2017

Spiegazione

VRp#ߢ-?0:1  Implicit input from command-line args
VR            Create stack2, return to stack1
  p           Split last item into prime factors, push each one to stack in asc order
   #ߢ         Push 2018
     -      Subtract last 2 items (highest prime factor - 2017)
      ?     If last item > 0..
       0    ..push 1
        :   Else..
         1  ..Push 1
            Implicit output of last item on stack
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.