Prodotto 7-Distinct-Prime più vicino


14

(via chat )

La voce OEIS A123321 elenca la sequenza di numeri che sono il prodotto di sette numeri primi distinti. Per brevità, chiameremo questo un numero 7DP . I primi numeri e i loro corrispondenti divisori sono di seguito:

510510 = 2 * 3 * 5 * 7 * 11 * 13 * 17
570570 = 2 * 3 * 5 * 7 * 11 * 13 * 19
690690 = 2 * 3 * 5 * 7 * 11 * 13 * 23
746130 = 2 * 3 * 5 * 7 * 11 * 17 * 19

La sfida qui sarà quella di trovare il numero 7DP più vicino, in termini di distanza assoluta, da un dato input.

Ingresso

Un singolo numero intero positivo n in qualsiasi formato conveniente .

Produzione

Il numero 7DP più vicino a n , sempre in qualsiasi formato conveniente. Se due numeri 7DP sono collegati per il più vicino, è possibile produrre uno o entrambi.

Regole

  • Si può presumere che i numeri si adattino al [int]tipo di dati predefinito della tua lingua (o equivalente).
  • È accettabile un programma completo o una funzione.
  • Sono vietate le scappatoie standard .
  • Questo è , quindi si applicano tutte le normali regole del golf e vince il codice più corto.

Esempi

5 -> 510510
860782 -> 870870
1425060 -> 1438710 (or 1411410, or both)

Risposte:


11

Pitone, 89 86 85 byte

f=lambda n,k=0:126^sum(1>>n%i<<7*(n/i%i<1)for i in range(2,n))and f(n+k,k%2*2+~k)or n

L'algoritmo è O (spaventoso) per cominciare e la ricorsione non aiuta davvero, ma funziona bene fino a quando n è sufficientemente vicino a un numero 7DP.

Grazie a @xnor per giocare a golf con 3 byte!

Testarlo su repl.it .

Come funziona

Python non ha incorporato la primalità o la fattorizzazione, ma possiamo identificare i numeri 7DP in base alla quantità e alla natura dei loro divisori.

In base al principio della moltiplicazione, il numero di divisori di un numero intero può essere calcolato come il prodotto degli esponenti incrementati della sua scomposizione in fattori primi. Pertanto, σ 0 (n) ( funzione divisore ) è 2 m ogni volta n è un numero mDP.

σ 0 (n) = 128 è quindi una condizione necessaria, ma non è sufficiente; per esempio, σ 0 (2 127 ) = 128 , ma 2 127 non è chiaramente un numero 7DP. Tuttavia, se entrambi σ 0 (n) = 128 e nessun quadrato perfetto divide n in modo uniforme, allora n è un numero 7DP.

Per l'ingresso n , l'algoritmo consiste nell'ispezionare gli interi n , n - 1 , n + 1 , n - 2 , n + 2 , ecc. E restituire il primo che è un numero 7DP.

Quando f viene chiamato con l'argomento n , si verifica quanto segue:

  • Il codice

    126^sum(1>>n%i<<7*(n/i%i<1)for i in range(2,n))

    verifica se n non lo è un numero 7DP come segue.

    Per tutti i numeri i tali che 1 <i <n , 1>>n%i<<7*(n/i%i<1)viene valutato.

    • Se n è divisibile per i ma non per i 2 , 1>>n%iproduce 1 e (n/i%i<1)produce 0 , risultando in
      1 · 2 7 · 0 = 1 .

    • Se n è divisibile per i 2 , 1>>n%ied (n/i%i<1)entrambi producono 1 , ottenendo 1 · 2 7 · 1 = 128 .

    • Se n non è divisibile per i , 1>>n%iproduce 0 , risultante in 0 · 2 7 · x = 0 .


    La somma dei numeri interi risultanti saranno 2 m - 2 se n è un numero mDP (sue 2 m divisori, escluso 1 e n ) e un numero maggiore di 127 se n ha un fattore quadrato perfetto. Pertanto, la somma sarà 126 se e solo se n è un numero 7DP.

  • Per i numeri 7DP, la somma è 126 , quindi XORing con 126 restituisce 0 , che è falso. Pertanto, la parte o della lambda viene eseguita e f restituisce il valore corrente di n .

  • Se n non è un numero 7DP, XOR restituirà un valore di verità diverso da zero. Pertanto, viene eseguita la parte e della lambda.

    f(n+k,k%2*2+~k)

    chiama ricorsivamente f con i valori aggiornati di n (il prossimo potenziale numero 7DP) e k (la differenza tra il nuovo candidato e quello successivo).

    Se k è un numero intero pari, non negativo, k%2*2produce 0 e ~kproduce - (k + 1) . La somma di entrambi i risultati è - (k + 1) , che è un numero intero dispari negativo che è 1 maggiore in valore assoluto di k .

    Se k è un numero intero dispari, negativo, k%2*2produce 2 e ~kproduce - (k + 1) . La somma di entrambi i risultati è 2 - (k + 1) = - (k - 1) , che è un numero intero uniforme, non negativo, che è 1 unità maggiore in valore assoluto di k .

    Ciò significa che k assume i valori 0, -1, 2, -3, 4, ⋯ .

    Se aggiunti cumulativamente a n 0 (il valore iniziale di n ), gli interi risultanti sono

    • n 0 + 0
    • ( n 0 + 0) - 1 = n 0 - 1
    • ( n 0 - 1) + 2 = n 0 + 1
    • ( n 0 + 1) - 3 = n 0 - 2
    • ( n 0 - 2) + 4 = n 0 + 2
    • eccetera.


    assicurandosi che il primo numero 7DP si incontra è il più vicino al n 0 possibile.


Ottima idea con il divisore che conta! Penso che puoi giocare a golf alternando la camminata aggiornando kdirettamente come f(n+k,k%2*2+~k), a partire da k=0.
xnor

Grande miglioramento. Grazie!
Dennis,

9

Brachylog , 44 40 16 byte

Cancellato 44 è ancora regolare 44; (

:I=+.>0,.$pPdPl7

Esempio:

?- run_from_atom(':I=+.>0,.$pPdPl7',1425060,Z).
Z = 1438710 .

Potrebbe essere che questa lingua non faccia sempre schifo? Ho battuto Jelly e MATL!

Il caso di prova con 5 è il più lungo e impiega circa 10 secondi sulla mia macchina.

Questo sarebbe di 12 byte se $pnon fosse stato corretto (non avremmo bisogno di>0,. parte)

Spiegazione

Brachylog utilizza la programmazione logica dei vincoli per impostazione predefinita per tutta l'aritmetica dei numeri interi. Inoltre, l'etichettatura integrata= funziona su domini forse infiniti.

Unifica successivamente una variabile senza vincoli (cioè in (-inf, inf)) come tale:0, 1, -1, 2, -2, 3, … .

Pertanto, possiamo ottenere il numero 7DP più vicino cercando il primo numero Iunificato in (-inf, inf)(utilizzando il backtracking automatico), per il quale Input + Iè un numero 7DP.

:I=                Label variables in [Input, I]. I has no constraints and Input is known
   +.              Unify Output with Input + I
     >0,           Output > 0 (wouldn't be needed if $p failed for numbers less than 1)
        .$pP       Unify P with the list of prime factors of Output
            dP     Check that P with duplicates removed is still P
              l7   Check that the length of P is 7

1
Ho battuto Jelly e MATL! Ma solo per 0 byte :-P
Luis Mendo,

1
@LuisMendo Sarebbe 13 byte se correggessi un bug con $p. In teoria non ne ho bisogno >0,, ma la mia implementazione è
errata

1
@DavidC Sì, perché inizia all'ingresso e quindi prova tutti i numeri in quanto tali: Input+1, Input-1, Input+2, Input-2, Input+3, ...pertanto il primo 7DP trovato con quel metodo sarà il più vicino.
Fatalizza il

1
@mat La correzione di bug dopo che la sfida è stata pubblicata rende la risposta non competitiva, quindi la lascerò a 16, anche se ora potrebbe essere di 12 byte ( >0,.non necessario)
Fatalizza l'

1
codegolf.stackexchange.com/a/111998/59995 Il 444 barrato è ancora 444. Sarò impressionato quando vedremo il
4444 barrato.

7

Gelatina, 17 byte

Pµạ³,
×⁹ÆRœc7Ç€ṂṪ

Funziona in teoria, ma richiede molti anni per essere completato.


Ecco una versione che funziona effettivamente per gli input dati, ma teoricamente fallisce per input di grandi dimensioni:

Pµạ³,
50ÆRœc7Ç€ṂṪ

Provalo qui. Questo genera tutti i numeri primi fino a 50, quindi trova tutte le 7 combinazioni di numeri primi in quell'elenco e quindi tutti i loro prodotti. Infine, trova semplicemente l'elemento più vicino da quella lista all'argomento dato.

Naturalmente, una volta che i nostri 7DP contengono numeri primi superiori a 50, questo fallirà. La versione teorica genera tutti i numeri primi fino a 256n per un input n , ma altrimenti funziona allo stesso modo.

Prova

Lasciamo p(x)denotare il prossimo primo dopo x. Un limite superiore (estremamente lento) per il prodotto 7DP più vicino a x è:

p(x) * p(p(x)) * p(p(p(x))) * ... * p(p(p(p(p(p(p(x)))))))

Quindi dobbiamo solo controllare i numeri primi in [2… p (p (p (p (p (p (p (x))))))]] . Il postulato di Bertrand afferma che p (x) ≤ 2x , quindi è sufficiente controllare tutti i numeri primi fino a 128x .


×⁹ÆRœc7P€µạ³ỤḢịoppure ×⁹ÆRœc7P€µạ³NMị(stampando l'array di tutte le soluzioni) salva un paio di byte. Inoltre, ×⁹può essere modificato +⁴per migliorare l'efficienza.
Dennis,

5

MATL , 21 17 16 14 13 byte

Grazie a Dennis per un suggerimento che ha rimosso 4 byte e un altro che ha salvato un altro byte!

t17*Zq7XN!pYk

Funziona in teoria, ma esaurisce la memoria per gli input sopra 6(compilatore online).

Una versione più efficiente utilizza 21 byte e calcola tutti i casi di test in circa un secondo:

t3e4/k16+_YqZq7XN!pYk

Provalo online!

Spiegazione

Versione efficiente in termini di memoria

Prendi l'input N = 860782come esempio. Basta considerare i numeri primi fino a M = 29, che è il primo ottimale che moltiplicato per 2*3*5*7*11*13supera N . In questo esempio 2*3*5*7*11*13*29 = 870870,. Il prossimo primo è 31. Qualsiasi prodotto che coinvolgono primo o maggiore saranno almeno 2*3*5*7*11*13*31 = 930930, e così è garantito non essere la soluzione, in quanto supera 870870che supera N .

M viene calcolato come primo primo maggiore di max(N/(2*3*5*7*11*13), 16). La maxfunzione viene utilizzata per garantire che almeno 17venga selezionato. Per salvare alcuni byte, il codice sostituisce 2*3*5*7*11*13 = 30030con 30000e funziona maxper aggiunta. Queste modifiche sono valide perché danno un valore maggiore.

t      % Take input implicitly. Duplicate
3e4/k  % Divide input by 30000 and round down (rounding here is only needed
       % due to a bug in the "next prime" function)
16+    % Add 16
_Yq    % Next prime
Zq     % Prime numbers up to that value
7XN    % Combinations of those primes taken 7 at a time. Gives a 2D array
       % with each combination on a different row
!p     % Product of each row
Yk     % Output product that is closest to the input. Implicitly display

Versione inefficiente di memoria

Per ridurre ulteriormente il numero di byte è possibile rimuovere la divisione; infatti, è sufficiente moltiplicarsi per 17(grazie, @Dennis). Questo assicura che il prossimo primo sia incluso (dal postulato di Bertrand ) e che il risultato sia almeno 17. Funziona in teoria, ma esaurisce la memoria per input più grandi di circa 6.

Nel codice, la sezione

3e4/k  % Divide input by 30000 and round down (rounding here is only needed
       % due to a bug in the "next prime" function)
16+    % Add 16
_Yq    % Next prime

è sostituito da

17*    % Multiply by 17

3

Pyke, 32 byte

#PDl 7q.ID}lRlqi*(#)DF-X,)R],She

Provalo qui!

Nota che questo non funziona online - è scaduto. Questa versione controlla solo 2 numeri primi distinti e dovrebbe funzionare più velocemente. Quando ci sono 2 numeri della stessa distanza dal bersaglio, sceglie quello inferiore.

Questo passa attraverso tutti i numeri fino a quando non ne trova uno più grande dell'input ed è un 7DP. Per ogni numero, se ne sbarazza se non è un 7DP. Ha quindi un elenco di 7DP fino all'input con uno più grande. Quindi seleziona quello più vicino all'ingresso.


3

Julia, 59 byte

!n=sort(map(prod,combinations(17n|>primes,7))-n,by=abs)[]+n

Questo è molto inefficiente, ma funziona per il primo caso di prova in pratica e per gli altri in teoria.

Al costo di 5 byte in più - per un totale di 64 byte - l'efficienza può essere migliorata notevolmente.

!n=sort(map(prod,combinations(n>>14+17|>primes,7))-n,by=abs)[]+n

Provalo online!

sfondo

Come menzionato nella risposta di @ LuisMendo , l'insieme di numeri primi che dobbiamo considerare per il numero 7DP più vicino è piuttosto piccolo. È sufficiente che il set contenga un numero 7DP che è più grande dell'ingresso n , che sarà vero se e solo se contiene un numero primo p ≥ 17 tale che 30300p = 2 · 3 · 5 · 7 · 11 · 13 · p ≥ n .

In L'intervallo contenente almeno un numero primo dimostra che l'intervallo [x, 1,5x) contiene almeno un numero primo ogni volta che x ≥ 8 . Dal momento che 30030/16384 83 1,83 , ciò significa che ci deve essere un numero primo p in (n / 30030, n / 16384) ogni volta che n> 8 · 30300 = 242400 .

Infine, quando n <510510 , p = 17 è chiaramente sufficiente, quindi dobbiamo considerare solo numeri primi fino a n / 16384 + 17 .

A scapito dell'efficienza, possiamo invece considerare numeri primi fino a 17n . Funziona quando n = 1 ed è notevolmente più grande di n / 16384 + 17 per valori maggiori di n .

Come funziona

17n|>primese n>>14+17|>primes(il bitshift equivale a dividere per 2 14 = 16384 ) calcola gli intervalli primi menzionati nel paragrafo precedente. Quindi, combinations(...,7)calcola tutte le matrici di sette diversi numeri primi in quell'intervallo e mappando prodsu quelli calcola i loro prodotti, cioè i numeri 7DP da cui scegliere la risposta.

Successivamente, -nsottrae n prom ogni numero 7DP, quindi sort(...,by=abs)ordina tali differenze in base ai loro valori assoluti. Infine, selezioniamo la prima differenza con []e calcoliamo il numero 7DP corrispondente aggiungendo n con +n.


2

Pyth, 30 byte

L&{IPbq7lPby#.W!syMH,hhZa0teZ,

Provalo online!

Suite di test.

(5 richiede troppo tempo per essere eseguito)

Spiegazione

L&{IPbq7lPby#.W!syMH,hhZa0teZ,

L&{IPbq7lPb     Defines a function y, whose argument is b:
 &                  Return if both the following are true:
  {IPb                  the prime factorization contains no duplicate; and:
      q7lPb             the number of prime factors is 7

           y#.W!syMH,hhZa0teZ,   The main programme. Input as Q.
                             ,QQ Implicit arguments, yield [Q,Q].
             .W                  While
               !syMH                   both numbers do not satisfy y:
                    ,hhZ             increment the first number
                          teZ        and decrement the second number
                        a0           while making it non-negative.

1

Mathematica 136 80 75 byte

Questo è un approccio semplice, che lavora da fuori n.

nè un prodotto a 7 distinti primi se il numero di fattori primi è 7 ( PrimeNu@#==7) e nessuno di questi fattori appare più di una volta ( SquareFreeQ@#&).

g@n_:=(k=1;While[!(PrimeNu@#==7&&SquareFreeQ@#&)⌊z=n-⌊k/2](-1)^k⌋,k++];z)

La mia precedente presentazione (136 byte) ha trovato sia il primo prodotto con 7 distinti primi di cui sopra n, sia, se esiste, il primo prodotto con 7 distinti di primi n. Quindi ha semplicemente stabilito quale fosse il più vicinon . Se i prodotti erano equidistanti, avrebbero restituito entrambi.

La versione corrente controlla n-1, n + 1, n-2, n + 2 ... fino a quando non raggiunge il primo prodotto 7-prime-prime. Questa versione più efficiente adotta l'approccio adottato da Dennis.

L'avanzamento chiave è stato nell'uso ⌊k/2](-1)^k⌋di restituire la serie, 0, 1, -1, 2, -2 ... Lo zero viene utilizzato per verificare se nè esso stesso un prodotto a 7 distinti. Per questo motivo, viene utilizzato Floor(ovvero, ⌊...⌋) anziché Ceiling.


g[5]
g[860782]
g[1425060]

510510

870.870

1438710


1

05AB1E , 10 byte

°Åp7.ÆPs.x

Provalo online!

Prova tutte le combinazioni di 7 dei primi 10 ** input primi. Esaurisce la memoria per gli ingressi maggiori di 1.

Versione 14 byte notevolmente più efficiente:

5°/7+Åp7.ÆPs.x

Provalo online!

Utilizza i primi (input / 100000 + 7) primi.

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.