Numeri sfortunati!


22

Cose da sapere:

Innanzitutto numeri fortunati.

I numeri fortunati vengono generati in questo modo:

Prendi tutti i numeri naturali:

1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20...

Quindi, rimuovere ogni secondo numero.

1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39...

Adesso 3è al sicuro.

Rimuovi ogni 3o numero:

1, 3, 7, 9, 13, 15, 19, 21, 25, 27, 31, 33, 37, 39, 43, 45, 49, 51, 55, 59...

Adesso 7è al sicuro.

Rimuovi ogni 7o numero.

Continua e rimuovi tutti ni numeri, dove si ntrova il primo numero sicuro dopo un'eliminazione.

L'elenco finale dei numeri sicuri sono i numeri fortunati.


I numeri sfortunati sono composti da liste separate di numeri, che sono [U1, U2, U3... Un].

U1 è la prima serie di numeri rimossi dai fortunati "candidati", quindi sono:

2, 4, 6, 8, 10, 12, 14, 16, 18, 20...

U2 viene rimosso il secondo set di numeri:

5, 11, 17, 23, 29, 35, 41, 47, 53, 59...

E così via e così via ( U3è la terza lista, U4è la quarta, ecc.)


Sfida:

Il tuo compito è, quando vengono dati due input me n, generare il mnumero th nell'elenco Un.

Ingressi e uscite di esempio:

(5, 2) -> 29
(10, 1) -> 20

Specifiche:

  • Il programma deve funzionare mfino a 1e6e nfino a 100.
    • Sei garantito che entrambi me nsono numeri interi positivi.
    • Se sei curioso, U(1e6, 100)= 5,333,213,163. (Grazie @pacholik!)
  • Il programma deve calcolarlo entro 1 giorno su un computer moderno e ragionevole.

Questo è , quindi vince il codice più breve in byte!

PS: Sarebbe bello se qualcuno inventasse una formula generale per generarli. Se hai una formula, inseriscila nella tua risposta!


Su OEIS: A219178 e A255543
Arnauld,


2
Hai implementato codice che può effettivamente eseguire (1e6,1e6)?
Jonathan Allan,

2
Se hai un requisito di tempo, devi specificare l'ambiente di temporizzazione (come la tua macchina, una macchina virtuale online liberamente disponibile o "un computer moderno ragionevole").
Mego,

1
È accettabile che la funzione non funzioni per il n=1caso? Poiché questo è speciale, per tutti gli altri casi, l'indice in base 0 del prossimo numero fortunato è n-1.
Myridium,

Risposte:


1

CJam , 74 byte

ri0Lri:U{1$W%{1$\(1e>/+}/)+}/2t:A0@{@:B:(_0#):D{D(_A=tD<BD>+}&@)@DU=-}h]1=

Provalo online! Timeout per casi più grandi, più sui vincoli di tempo di seguito.


Spiegazione:

Il nostro programma prende spudoratamente in prestito il codice di Aditsu per generare un elenco di N numeri fortunati, sostituendo 1 con 2 si ottiene l'incremento in ciascuna fase del setaccio. Il codice rimanente decrementa su ogni elemento fino a quando non viene trovato uno zero (tagliando e aggiungendo una coda non decrementata) e conta efficacemente i passi in ciascuna delle N fasi del setaccio contemporaneamente.

ri                               e# read M
0Lri:U{1$W%{1$\(1e>/+}/)+}/2t:A  e# list steps (also becomes B)
0@                               e# arrange stack [B I M]
{                                e# while M
   @:B                           e#   get current B
   :(                            e#   decrement every element in B
   _0#):D                        e#   find first 0
   {                             e#   if there is a 0
      D(_A=t                     e#     reset that element in B
      D<BD>+                     e#     replace tail after 0
   }&                            e#   end if
   @)                            e#   increment I
   @DU=-                         e#   decrement M if N-th phase of sieve
}h                               e# end loop
]1=                              e# return I

Timing:

Se è assolutamente necessario eseguire il programma nel browser per numeri più grandi, è possibile utilizzare questo interprete e consentire allo script di continuare se richiesto, ma questo potrebbe essere troppo lento per qualificarsi. L'uso di ( M , N ) = (100.100) richiede ~ 247s. L'iterazione dei programmi è relativamente lineare in termini di M , quindi l'elaborazione (1e6,100) potrebbe richiedere ~ 29 giorni.

Usando l'interprete della shell su un PC il programma calcola (100.100) in ~ 6s e calcola (1e4.100) in ~ 463s. Il programma dovrebbe essere in grado di calcolare (1e6,100) in circa 13-17 ore. In questo caso, suppongo che il programma sia idoneo.

Si noti che tutti i tempi sono stati arrotondati per eccesso sia nelle misurazioni che nei calcoli.


7

Perl, 87 85 82 81 byte

Include +4 per -pX

Fornisci input su STDIN come prima riga con n (nota che questo è il contrario dell'ordine suggerito nella sfida). Quindi per calcolare U(1000000, 100):

unlucky.pl <<< "100 1000000"

Algoritmo basato su aditsu 's numeri fortunati rispondere la complessità temporale è O(n^2)quindi è piuttosto rapido per il campo richiesto. Il 100, 1000000caso dà 5333213163in 0,7 secondi. A causa dei problemi che il perl ha con la do$0ricorsione basata usa molta memoria. Riscriverlo come funzione farebbe usare la memoria O(n)ma è più lungo di un numero di byte

unlucky.pl:

#!/usr/bin/perl -pX
$_=$a{$_}||=/\d+$/>--$_?2*$&+$^S:($_=$_.A.(do$0,$^S?0|$&+$&/~-$_:$&*$_-1),do$0)

Funziona come mostrato, ma usa letterale ^Sper ottenere il punteggio richiesto.

Non sono a conoscenza di alcun uso precedente di $^Sin perlgolf.


Ma quanto ci vuole (1e6,100)?
Myridium,

@Myridium A causa dell'esplosione della memoria causata da do$0esso è praticamente irraggiungibile su qualsiasi computer realistico. Ma se quella memoria esistesse per circa 2 anni. Non ho davvero scritto e testato una normale versione basata su subroutine, ma mi aspetto che finisca tra qualche mese e funzionerà anche su computer con pochissima memoria. Quindi è una buona cosa che questi valori non siano nell'intervallo richiesto per questa sfida.
Ton Hospel,

Non è la sfida per calcolare (1e6,100)entro un giorno? Cosa intendi dire che questi valori non sono richiesti?
Myridium,

@Myridium Notare che nel mio programma ne msono riportati in ordine inverso. L' 100 1000000ingresso calcola U(1000000, 100)e fornisce 5,333,213,163in 0,7 secondi. È di gran lunga il programma più veloce di questi attualmente pubblicati
Ton Hospel,

Ah ok, mi aspettavo (100,1e6)di essere molto più veloce di (1e6,100), e ho pensato che questa fosse la spiegazione per il fulmineo 0,7 secondi!
Myridium,

7

Python 3, 170

from itertools import*
def L(n,k=1):
 if n<2:yield from count(2+k,2)
 t=L(n-1);l=next(t)
 for i in t:
  n+=1
  if(n%l>0)==k:yield i
U=lambda m,n:sum(islice(L(n,0),m-1,m))

La funzione L genera la riga di possibili numeri fortunati (se k è True) o Un (se False). Valutato pigramente (quindi non devo generare liste infinite n-1 se voglio Un ).

Esegui funzione U .

Velocità

U (1.000.000; 100) impiega circa 1h 45min per funzionare sulla mia macchina con PyPy. Ho il sospetto di circa quattro ore con CPython. (Sì, 4h 20min per essere precisi.)

Se avessi usato un elenco al posto dei generatori, avrei potuto guadagnare un po 'di velocità, ma avrei bisogno di un elenco di dimensioni maggiori di quelle consentite da Python. E se lo facesse, avrebbe bisogno di dozzine di gigabyte di RAM.


Sì e U (1.000.000; 100) = 5.333.213.163 .


Dovrebbe essere valido ora.
clismique,

3

Haskell

Impossibile calcolare per n = 1: 175 160 byte

Una volta compilato, il mio computer ha impiegato 2h 35m per calcolare l'input (1000000,100)dell'utilizzo di questo:

n#s=y:(n#p)where y:p=drop(n-1)s
n%s=f n s$[]where f n s=(take(n-1)s++).f n(drop n s) 
l 2=[1,3..]
l m=((l$m-1)!!(m-2))%(l$m-1)
m?n=(((l n)!!(n-1))#(l$n))!!(m-1)

Ho provato a liberare i wheremoduli, ma sembrano influenzare la velocità e non sono sicuro del perché ... Ma penso che ci sia più potatura da fare qui.

Il metodo da usare è m?nper interrogare la risposta data un me n.

Ungolfed

everynth n xs = y:(everynth n ys) -- Takes every nth element from a list 'xs'
  where y:ys = drop (n-1) xs

skipeverynth n xs = f' n xs $ []  -- Removes every nth element from a list 'xs'
  where f' n xs = (take (n-1) xs ++) . f' n (drop n xs) 

l 2 = [1,3..] -- The base case of the list of lucky numbers for 'n=2'
l m = skipeverynth ((l$m-1)!!(m-2)) (l$m-1) -- Recursively defining next case as being the last one with every 'ath' element skipped. Here, 'a' is the (m-1)th elemnent of the (l (m-1)) list.
ul m = everynth ((l m)!!(m-1)) (l$m) -- This is not used other than to compute the final, required unlucky number list. It picks out every 'ath' element.

ans m n = (ul n)!!(m-1) -- The function giving the answer.

Penso che potrebbe essere possibile combinare le funzioni 'skipeverynth' e 'everynth' in un'unica funzione che restituisce una coppia.

Ho usato il codice di questa persona gentile per saltare ogni ennesimo elemento. L'ho fatto da solo alcune volte, ma era sempre molto più inefficiente e non riuscivo a capire perché.

In grado di calcolare per tutti n: 170 byte

Questo è fondamentalmente lo stesso, ma un paio di maxfunzioni hanno dovuto essere lanciate per gestire il caso speciale di n=1.

n#s=y:(n#p)where y:p=drop(n-1)s
n%s=f n s$[]where f n s=(take(n-1)s++).f n(drop n s) 
l 1=[1..]
l m=((l$m-1)!!(max 1$m-2))%(l$m-1)
m?n=(((l n)!!(max 1$n-1))#(l$n))!!(m-1)

2

R 82 byte

f<-function(m,n){a=1:2e8
i=1
while(i<n){a=c(0,a)[c(F,rep(T,i))]
i=i+1}
a[(n+1)*m]}

uso

f(5,2)
Returns 29

Questo deve avere un vettore abbastanza grande per iniziare, quindi ci sono abbastanza numeri rimanenti per restituire il valore. Il vettore creato è già di circa 800 Mb e la funzione può gestire fino a m = 1e4 e n = 100, quindi ancora ben al di sotto dell'obiettivo.

Per creare un vettore abbastanza grande da calcolare f (1e6,100) richiederebbe un vettore iniziale di 1: 2e10. A causa delle procedure di allocazione dei dati Rs, questo crea un vettore> 70Gb che non può essere eseguito su nessun computer che conosco, anche se il codice verrebbe eseguito.

Error: cannot allocate vector of size 74.5 Gb

Per riferimento f (1e4,100) viene eseguito in circa 30 secondi circa. Sulla base di questo e un paio di test più piccoli f (1e6,100) richiederebbero circa un'ora.


Contrassegnare la tua risposta come non competitiva non la scusa dal mancato rispetto dei requisiti della sfida.
Mego

@Mego Ho visto molte risposte che non soddisfano i requisiti (ce ne sono almeno 1 in questa sfida). L'ho codificato e ritengo che soddisfi lo spirito della richiesta di codifica, ho anche dichiarato chiaramente dove non era all'altezza. Inoltre, come menzionate nei vostri commenti alla domanda, non indica quale tipo di computer deve testare. Sono sicuro che ci sono computer là fuori che potrebbero scrivere 7 Gb in memoria ed elaborarlo. Quello su cui mi trovavo non poteva farlo ma volevo ancora pubblicare e ho pensato che la chiara dichiarazione fosse un valido compromesso.
gtwebb,

Abbiamo una chiara politica sulle risposte che non soddisfano le specifiche della sfida . Detto questo, non sono sicuro del motivo per cui hai etichettato la tua risposta come non competitiva. Se ho capito bene, questo dovrebbe funzionare con memoria sufficiente, ma non è possibile testarlo perché non si dispone di RAM sufficiente. È corretto?
Dennis,

1
1. Questa politica viene applicata, ma quattro moderatori non possono testare tutte le risposte sul sito. Se trovi un invio che non rispetta le regole, segnalalo per l'attenzione del moderatore in modo che possiamo dare un'occhiata. 2. Non è necessario imparare una lingua per giocare a golf. I linguaggi di produzione come R sono i benvenuti. Pubblica risposte Python su base regolare.
Dennis,

1
3. Le specifiche non menzionano alcun limite di memoria, ma esiste un limite di tempo di 24 ore. In assenza di un computer con 70 GiB (o intendevi bit giga ) per testarlo, è difficile determinare se questa risposta è valida o meno. Suggerisco di provare a estrapolare il runtime nel miglior modo possibile. Se è meno di un giorno, rimuovi l'intestazione non competitiva e includi la tua estrapolazione nel post. Se impiega più tempo, l'invio deve essere ottimizzato o rimosso.
Dennis,

1

Racchetta 332 byte

(λ(N m n)(let loop((l(filter odd?(range 1 N)))(i 1))(define x (list-ref l i))(if(= i (sub1 n))
(begin(set! l(for/list((j(length l))#:when(= 0(modulo(add1 j)x)))(list-ref l j)))(list-ref l(sub1 m)))
(begin(set! l(for/list((j(length l))#:unless(= 0(modulo(add1 j) x)))(list-ref l j)))(if(>= i(sub1 (length l)))l
(loop l(add1 i)))))))

Versione non golfata:

(define f
  (λ(N m n)
    (let loop ((l (filter odd? (range 1 N))) (i 1))
      (define x (list-ref l i))
      (if (= i (sub1 n))
          (begin (set! l (for/list ((j (length l)) 
                                   #:when (= 0 (modulo (add1 j) x)))
                           (list-ref l j)))
                 (list-ref l (sub1 m)))
          (begin (set! l (for/list ((j (length l)) 
                                   #:unless (= 0 (modulo (add1 j) x)))
                           (list-ref l j)))
                 (if (>= i (sub1 (length l)))
                     l
                     (loop l (add1 i))))))))

test:

(f 100 5 2)

Produzione:

29

1

Clojure, 221 byte

Possibilmente lungo ma gestisce il caso (f 1). Senza quel caso speciale era di 183 byte. Questo è stato uno sforzo eccessivo per non pubblicarlo.

(defn f([n](if(< n 2)(take-nth 2(drop 2(range)))(f n 1(take-nth 2(rest(range))))))([n i c](if (< n 2)c(let[N(first(drop i c))F #((if(= 2 n)= >)(mod(inc %)N)0)](f(dec n)(inc i)(filter some?(map-indexed #(if(F %)%2)c)))))))

Output di esempio:

(pprint (map #(take 10 (f %)) (range 1 10)))
((2 4 6 8 10 12 14 16 18 20)
 (5 11 17 23 29 35 41 47 53 59)
 (19 39 61 81 103 123 145 165 187 207)
 (27 57 91 121 153 183 217 247 279 309)
 (45 97 147 199 253 301 351 403 453 507)
 (55 117 181 243 315 379 441 505 571 633)
 (85 177 277 369 471 567 663 757 853 949)
 (109 225 345 465 589 705 829 945 1063 1185)
 (139 295 447 603 765 913 1075 1227 1377 1537))

Il caso 1000000 100 è stato calcolato in circa 4,7 ore, almeno non si è bloccato.

java -jar target\stackoverflow-0.0.1-SNAPSHOT-standalone.jar 1000000 100
5333213163
"Elapsed time: 1.7227805535565E7 msecs"
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.