Genera numeri fortunati


22

Storia:

Lucy chiese a George quale fosse il suo numero fortunato. Dopo qualche riflessione, George rispose che aveva diversi numeri fortunati. Dopo una breve confusione, Lucy chiese a George quali fossero i suoi primi nnumeri fortunati. George quindi chiese a te, suo amico, di scrivergli un programma per fare il lavoro per lui.

La sfida:

Scriverai un programma / funzione che riceverà dall'argomento input / funzione standard una stringa o un numero intero n. Il programma / funzione restituirà quindi / emetterà i primi n numeri fortunati . I numeri fortunati vengono definiti tramite un setaccio come segue.

Inizia con gli interi positivi:

1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, ...

Ora rimuovi ogni secondo numero:

1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, ...

Il secondo numero rimanente è 3 , quindi rimuovi ogni terzo numero:

1, 3, 7, 9, 13, 15, 19, 21, 25, ...

Ora il prossimo numero rimanente è 7 , quindi rimuovi ogni settimo numero:

1, 3, 7, 9, 13, 15, 21, 25, ...

Quindi, rimuovere ogni nono numero e così via. La sequenza risultante sono i numeri fortunati.

Vincente:

Come al solito per codegolf, vince il minor numero di byte.

Come al solito, le richieste che utilizzano scappatoie standard vengono squalificate.


8
Suggerirei di includere la definizione nel post, nonché i primi dieci numeri circa.
xnor

Un'estensione interessante sarebbe quella per ogni oggetto esaminato (3, 7, ecc.) Farà quell'operazione quel numero di volte. Ad esempio per 3, rimuovi il terzo elemento nell'elenco 3 volte, il 7 ° elemento 7 volte, ecc. (Nota che questa non è la sequenza ma l'idea è la stessa)
Ryan,

@Ryan Penso che la sequenza sarebbe notevolmente simile ai numeri naturali :)
TheNumberOne,

@TheBestOne La pensi così? Ho postato prima su math.stackexchange: math.stackexchange.com/questions/1153889/…
Ryan,

@Ryan In realtà, ho frainteso il tuo suggerimento. Come hai affermato nella tua domanda su math.se, penso che sarebbe interessante.
TheNumberOne

Risposte:


16

Python 2, 79

n=input()
L=range(1,2**n)
for r in L:r+=r<2;map(L.remove,L[r-1::r])
print L[:n]

La magia di scorrere una lista mentre il ciclo la modifica!

L'elenco Linizia con tutti i numeri interi 1con un valore sufficientemente alto. Il codice scorre su ogni elemento rdi L, prendendo la lista secondaria di ogni relemento e rimuovendo ciascuno di quei valori. Di conseguenza, i valori rimossi non vengono ripetuti. Alla fine, stampa i primi nelementi.

L'espressione map(A.remove,B)è un trucco che stavo aspettando da tempo da usare. Richiede A.removeogni elemento di B, che causa la Brimozione di tutti gli elementi di A. In effetti, prende la differenza della lista, anche se richiede Bdi essere una lista secondaria di A. Richiede Python 2, dal momento che Python 3 non valuterebbe effettivamente la mappa.

Il primo loop deve essere in maiuscolo per convertire rda 1a 2, come r+=r<2.

Il limite superiore sufficientemente alto di 2**nrende il programma molto lento per grandi valori di n. L'uso è n*n+1sufficiente, ma costa un personaggio. Si noti che n*nnon funziona per n=1.


Hai solo bisogno di n**2numeri, non2**n
Ottimizzatore

3
Questo è un uso straordinario di mapte che hai lì. Mi chiedevo se ci fosse un modo migliore ...
Sp3000,

@Optimizer Sfortunatamente, a n**2+1meno che il caso non n=1possa essere perdonato.
xnor

L'uso della mappa è geniale. Come usare un set ordinato. Forse può anche essere usato come map(A.index,B)trovare gli indici degli elementi di B in A, map(A.count,B)per trovare il numero degli elementi di B in A, map(A.extend,B)per aggiungere un elenco B appiattito ad A. La mente vacilla.
Logic Knight,

13

Haskell, 71 69 byte

s(n:k)p=n:s[m|(i,m)<-zip[p..]k,i`mod`n>0](p+1)
f n=take n$1:s[3,5..]3

Definisce una funzione f. L'espressione 1:s[3,5..]3restituisce la lista infinita di numeri fortunati, e fsemplicemente prende il primo ndi loro da take n.

f 20
[1,3,7,9,13,15,21,25,31,33,37,43,49,51,63,67,69,73,75,79]

Potrei radere 5 byte dal setaccio usando una comprensione di lista parallela

s(n:k)p=n:s[m|m<-k|i<-[p..],i`mod`n>0](p+1)

ma ciò richiederebbe il passaggio dell'enorme flag del compilatore -XParallelListCompa GHC per consentire l'estensione.

Spiegazione del setaccio

s(n:k)p=               -- Sieving a list with head n and tail k with accumulator p is
 n:                    -- the head n, followed by
  s[m|                 -- the result of sieving the list of numbers m
    (i,m)<-zip[p..]k,  -- where (i,m) is drawn from [(p,k_0),(p+1,k_1),(p+2,k_2),..] and
    i`mod`n>0]         -- i does not divide n,
   (p+1)               -- using p+1 as the accumulator

L'idea di base è che s(n:k)pproduce il (p-1)numero fortunato n, fa cadere ogni nnumero dalla coda infinita k(compensa per ptenere conto dei numeri prodotti in precedenza) e ricicla in quella lista con l'accumulatore (p+1). In f, inizializziamo il processo con i numeri dispari a partire da 3, e viriamo 1in avanti, ottenendo esattamente i numeri fortunati.


12

Python 2, 71 69 67

All'inizio, ho pensato che questa sarebbe stata una grande sfida per l'affilatura di array di Python. Tuttavia, ho riscontrato un ostacolo quando ho scoperto che le sezioni con un passaggio diverso da 1 possono avere solo un'altra sezione di identica lunghezza assegnata a loro. Ma dopo aver cercato su Google "Python Remove Slice", la mia fede è stata ripristinata: ho trovato delun'affermazione funky che fa perfettamente il trucco.

n=input()
l=range(n*n+9)
for v in l:del l[v&~1::v or 2]
print l[:n]

Vecchia versione

n=input()
l=range(1,n*n+9)
for v in l:del l[v-1%v::v+1/v]
print l[:n]

-2 byte grazie a Sp3000.


10

> <> , 121 114 111 byte

i2+:&:*1\
:})?v:2+>l{
nao2\r~1
)?vv>1+:&:&=?;:[{::nao}]$}l1-[01+}:l3-$%$l1-@@-{$[{~l1
3.\ ff+
!?:<]-1v
~]{43. >

Ho solo poche parole da dire ...

... "Argh mi fa male il cervello."


Spiegazione

> <> è un linguaggio di programmazione esoterico 2D e non è sicuramente adatto a questo compito, a causa della sua mancanza di array. In effetti, l'unico tipo di dati in> <> è strano mix di int / float / char, e tutto accade su una pila di pile.

Ecco il riassunto:

Line 1:            i2+:&:*1\

i2+:&              Read a char as input (n) and add 2, copying n+2 into the register
:*                 Duplicate and multiply, giving (n+2)^2 on the stack
1\                 Push 1 and go to the next line

Line 2:            >l{:})?v:2+

l{:})?v            Go to the next line if the stack's length is greater than (n+2)^2
:2+                Otherwise duplicate the top of the stack and add 2 to it

Line 3:            \r~1nao2

r~                 Reverse the stack and pop; stack contains the first (n+2)^2 odd integers
1nao               Print 1 (special case)
2\                 Push 2 (let's call this "i" for "iterations") and go to the next line

Line 4:            >1+:&:&=?;:[{::nao}]$}l1-[01+}:l3-$%$l1-@@-{$[{~l1)?vv

1+                 Increment i
:&:&=?;            If i is equal to n+2 (+2 because we started at 2), halt
:[{::nao}]$}       Print the i-th element down (the next lucky number) and also
                   copy it to the top of the stack, while moving i to the bottom
l1-[               Move everything but i to a new stack
0                  Push 0 (let's call this "r" for recursion depth)

Sieve loop:

1+                 Increment r
}:l3-$%$l1-@@-{$[  Move everything up to the last element to be sieved out to a new stack
{~                 Remove said last element
1)?vv              If the length is 1, go to line 6 (sieving complete)
                   Otherwise go to line 5, which repeats this sieve loop by teleporting

Line 6:            :?!v1-]

:?!v1-]            Keep unrolling and decrementing r until r is 0

Line 7:            >~]{43.             

~]                 Pop r and unroll once more (to the stack where i waits)
43.                Loop, performing everything from line 4 all over again

Ecco un esempio falso che dimostra approssimativamente come funziona il setaccio (ecco kil numero fortunato con cui setacciamo):

[[15 13 11 9 7 5 3 1 k=3 r=0]]     -- move -->
[[15 13] [11 9 7 5 3 1 k=3 r=1]]   -- pop  -->
[[15 13] [9 7 5 3 1 k=3 r=1]]      -- move -->
[[15 13] [9 7] [5 3 1 k=3 r=2]]    -- pop  -->
[[15 13] [9 7] [3 1 k=3 r=2]]      -- move -->
[[15 13] [9 7] [3 1] [k=3 r=3]]    -- pop  -->
[[15 13] [9 7] [3 1] [r=3]]        (now we unroll)

7
Ancora meglio di Java;)
Ottimizzatore

5
Mi piace il fatto che naoapparentemente possa essere interpretato come "stampa questa cosa adesso".
Zgarb,

10

CJam - 25

Lri{1$W%{1$\(1e>/+}/)+}/p

Provalo online

Spiegazione:

Questa implementazione non rimuove i numeri in successione da un array, ma calcola ciascun numero in base a quanti sarebbero stati rimossi prima di esso.
Per ogni indice i (da 0 a n-1) e ogni numero fortunato precedente l, in ordine inverso, incrementiamo i di i / (l-1), ad eccezione di l = 1 usiamo 1 invece di 0 e aggiungiamo anche 1 alla fine.
Ad esempio per i = 4 abbiamo i primi 4 numeri, [1 3 7 9] e calcoliamo:
4 + 4 / (9-1) = 4
4 + 4 / (7-1) = 4
4 + 4 / (3 -1) = 6
6 + 6/1 = 12
12 + 1 = 13

L              empty array - the first 0 lucky numbers :)
ri             read and convert to integer (n)
{…}/           for each number (i) from 0 to n-1
    1$         copy the previous array
    W%         reverse the order
    {…}/       for each array element (l)
        1$     copy i
        \(     swap with l and decrement l
        1e>    use 1 if l=1
        /+     divide and add to i
    )+         increment and add the new lucky number to the array
p              pretty print

Tecnica interessante :)
TheNumberOne

6

Pyth: 23 22 byte

<u-G%@GhH+0GQ%2r1^hQ2Q

Provalo online: Pyth Compiler / Executor

Spiegazione:

<u-G%@GhH+0GQ%2r1^hQ2Q    Q = input()
             %2r1^hQ2     create the list [1, 2, ..., (Q+1)^2-1][::2]
 u          Q%2r1^hQ2     G = [1, 2, ..., (Q+1)^2-1][::2]
                           modify G for each H in [0, 1, 2, ..., Q]:
  -G%:GhH+0G                  G = G - ([0] + G)[::G[H+1]]
                               (minus is remove in Pyth)
<                    Q    print the first Q elements of the resulting list

La riduzione in realtà calcola più di Qnumeri fortunati (il comando di rimozione si chiama Q + 1 volte, Q-1 dovrebbe essere sufficiente).


5

R, 58 byte

n=scan();s=r=1:n^2;for(j in 1:n)r=r[-max(2,r[j])*s];r[1:n]

Con interruzioni di riga:

n=scan()              #user input
s=r=1:n^2             #declare r and s simultaneously, both large enough to sieve
for(j in 1:n)
  r=r[-max(2,r[j])*s] #iteratively remove elements by position in vector
r[1:n]                #print

Versione precedente, 62 byte

function(n){
  s=r=1:n^2             #declare r and s simultaneously, both large enough to sieve
  for(j in 1:n)
    r=r[-max(2,r[j])*s] #iteratively remove elements by position in vector
  r[1:n]                #print
}

Versione precedente, 78 byte

n=as.numeric(readline())   #ask for user input and convert it to numeric
r=1:n^2                    #create a large enough vector to sieve
for(j in 1:n){             #loop
  r=r[-max(2,r[j])*1:n^2]  #iteratively remove elements by position in vector
}
r[1:n]                     #print

64 byte: passare n=as.numeric(readline())a function(n){...}. Questo crea un oggetto funzione che può essere assegnato e chiamato. Rilascia le parentesi graffe nel forcircuito.
Alex A.

Grazie @Alex! Anche se è 66, dal momento che ha bisogno di un nome?
freekvd,

Non ha bisogno di un nome per l'invio. Vedi le soluzioni Matlab / Octave. Gli oggetti funzione R sono simili alle funzioni senza nome / lambda in altre lingue, che sono invii validi.
Alex A.

Che dire n=scan(n=1)?
koekenbakker,

2
Che funzioni! Ed è 1 carattere in meno. È ancora più breve se lascerei cadere n = 1, la funzione ignora tutti gli elementi di n dopo il primo.
freekvd,

4

CJam, 32 30 byte

3ri:N#,N{0\__I1e>)=%-+}fI(;N<p

Riceve input da STDIN.

Spiegazione del codice :

3ri:N#,                          "Read the input in N and get first 3^N whole numbers";
       N{0\__I1e>)=%-+}fI        "Run the code block N times, storing index in I";
         0\__                    "Put 0 before the array and take 2 copies";
             I1e>)=              "Take min(2, I + 1) th index from the copy";
                   %             "Take every array[ min (2, I + 1)] element from the array";
                    -+           "Remove it from the list and prepend 0 to the list";
                         (;N<p   "Print number index 1 to N";

Provalo online qui


4

Python 2, 105 101 byte

n=input()
L=range(-1,n*n+9,2)
i=2
while L[i:]:L=sorted(set(L)-set(L[L[i]::L[i]]));i+=1
print L[1:n+1]

Solo un'implementazione semplice.

Pyth, 39 36 35 32 byte

J%2r1h^Q2VJI>JhN=J-J%@JhN+2J;<JQ

Simile all'approccio sopra, ma le cose sono indicizzate 0 anziché 1 indicizzate. Provalo online .

Grazie a @Jakube per aver segnalato un risparmio di byte.


3

Mathematica, 80 byte

(For[l=Range[#^2];i=1,(m=l[[i++]]~Max~2)<=Length@l,l=l~Drop~{m,-1,m}];l[[;;#]])&

Implementazione diretta della definizione. Come alcune altre risposte, inizia con un intervallo da 1a e quindi continua a filtrare.n2


3

Perl, 86 81 78

86:

@a=(1..($k=<>)**2);for$n(@a){$i=1;@a=map{$i++%($n+($n<2))?$_:()}@a;$k-=$k&&print"$n "}

AGGIORNAMENTO: ovviamente, grep{...}è meglio di map{...?$_:()} 81:

@a=(1..($k=<>)**2);for$n(@a){$i=1;@a=grep{$i++%($n+($n<2))}@a;$k-=$k&&print"$n "}

AGGIORNAMENTO: OK, in realtà un one-liner ora. Posso smettere. (?) 78:

@a=(1..($k=<>)**2);for$n(@a){$k-=$i=$k&&print"$n ";@a=grep{$i++%($n+=$n<2)}@a}

3

Ottava, 139 83 72

function r=l(n)r=1:2:n^2;for(i=2:n)h=r(i);r(h:h:end)=[];end;r=r(1:n);end

Ungolfed:

function r=l(n)
  r=1:2:n^2;
  for(i=2:n)
    h=r(i);
    r(h:h:end)=[];
  end
r=r(1:n);  # reduce it to only N lucky numbers
end

2

J, 60 52 byte

   ({.}.@((>:@{.,]#~0<({~{.)|i.@#)@]^:[2,1+2*i.@*:@>:)) 8
1 3 7 9 13 15 21 25

Spiegazione (da destra a sinistra):

2,1+2*i.@*:@>:  generates the list 2 1 3 5 7 9... with (n+1)^2 odd numbers
^:[             repeats n times the following
@]                using the list
0<({~{.)|i.@#     is the remainder of the indexes of the lists elements with the first element positive (i.e. index divisible by first element)
]#~               keep those elements from the list
>:@{.,            concatenate a first element with the value of the current one +1
}.@             drop first element
{.              take the first n element

2,1+2*i.@*:@>:sembra troppo lungo ma posso accorciarlo solo di 1 byte scambiando *:con !la crescita esponenziale dell'elenco.


2

JavaScript (ES6) 96 99

Modifica Conto alla rovescia nel primo ciclo - grazie a @DocMax

F=n=>(i=>{
  for(o=[1];--i;)o[i]=i-~i;
  for(;++i<n;)o=o.filter((x,j)=>++j%o[i]);
})(n*n)||o.slice(0,n)

Ungolfed

F=n=>{
  for (i = n*n, o = [1]; --i;)
    o[i] = i+i+1;
  for (; ++i < n; )
    o = o.filter((x, j) => (j+1) % o[i])
  return o.slice(0,n)
}

Test nella console di Firefox / FireBug

F(57)

Produzione

[1, 3, 7, 9, 13, 15, 21, 25, 31, 33, 37, 43, 49, 51, 63, 67, 69, 73, 75, 79, 87, 93, 99, 105, 111, 115, 127, 129, 133, 135, 141, 151, 159, 163, 169, 171, 189, 193, 195, 201, 205, 211, 219, 223, 231, 235, 237, 241, 259, 261, 267, 273, 283, 285, 289, 297, 303]

1
Puoi salvare 1 facendo il conto alla rovescia con il primo ciclo e verso l'alto con il secondo:F=n=>{for(o=[1],i=n*n;--i;)o[i]=2*i+1;for(;++i<n;o=o.filter((x,j)=>++j%o[i]));return o.slice(0,n)}
DocMax

Il tuo non golfato non aiuta davvero qui: P;)
Ottimizzatore

@Optimizer ungolfed aggiornato - forse non è ancora di grande aiuto, ma almeno funziona ora
edc65

Intendevo di più sulle righe "semplicemente un cambiamento di formattazione non aiuta, per favore fornisci commenti :)"
Ottimizzatore

2

Matlab, 104 byte

function x=f(n)
k=1;N=n;x=0;while nnz(x)<n
x=1:N;m=1;while m-nnz(x)
m=x(x>m);x(m:m:end)=[];end
N=N+2;end

Grazie a @flawr per commenti e suggerimenti molto appropriati.

Esempio dal prompt dei comandi di Matlab:

>> f(40)
ans =
  Columns 1 through 22
     1     3     7     9    13    15    21    25    31    33    37    43    49    51    63    67    69    73    75    79    87    93
  Columns 23 through 40
    99   105   111   115   127   129   133   135   141   151   159   163   169   171   189   193   195   201

Grazie! L'ho usato in passato, ma tendo a dimenticare
Luis Mendo,

@flawr Ottimo punto. Questa risposta sta diventando più tua della mia! :-)
Luis Mendo,

Sicuro! Frequento più spesso in StackOverflow, ma è lo stesso spirito lì. Lo apprezzo!
Luis Mendo,

Buon punto! Non sono sicuro che tutto ciò che sto imparando sarà utile o effettivamente dannoso per il mio utilizzo standard di Matlab, tuttavia :-P
Luis Mendo,

2
Bene codegolf non riguarda l'uso, ma piuttosto l' abuso di una lingua ^^
flawr

1

Bash + coreutils, 136

Speravo di giocare a golf più in basso, ma vabbè. Non tutti i giorni in cui si inserisce una funzione ricorsiva in uno script di shell:

f(){
mapfile -tn$2 a
(($1>$2))&&{
tr \  \\n<<<${a[@]}
sed $[${a[-1]}-$2]~${a[-1]}d
}|f $1 $[$2+1]||echo ${a[@]}
}
yes|sed -n 1~2=|f $1 2

Produzione:

$ ./lucky.sh 23
1 3 7 9 13 15 21 25 31 33 37 43 49 51 63 67 69 73 75 79 87 93 99
$ 

Bash + coreutils, 104

Più breve usando un'implementazione più semplice:

a=(`seq 1 2 $[3+$1**2]`)
for((;i++<$1;));{
a=($(tr \  \\n<<<${a[@]}|sed 0~${a[i]}d))
}
echo ${a[@]:0:$1}

1

Vai, 326

package main
import"fmt"
func s(k, p int,in chan int)chan int{
    o := make(chan int)
    go func(){
        for p>0{
            o<-<-in;p--
        }
        for{
            <-in
            for i:=1;i<k;i++{o<-<-in}
        }
    }()
    return o
}
func main(){
    n := 20
    fmt.Print(1)
    c := make(chan int)
    go func(c chan int){
        for i:=3;;i+=2{c<-i}
    }(c)
    for i:=1;i<n;i++{
        v := <-c
        fmt.Print(" ", v)
        c = s(v, v-i-2, c)
    }
}

Implementazione diretta usando goroutine e tubi per creare setacci.


7
Questo codice Golf, aggiungi un numero di byte.
edc65,

1

MATLAB, 62 caratteri

n=input('');o=1:2:n^2;for i=2:n;o(o(i):o(i):end)=[];end;o(1:n)

Inizialmente ho interpretato male la sfida: la mia versione rivista è ora più corta.


0

Racchetta 196 byte

Produce numeri fortunati fino a n:

(λ(n)(let loop((l(filter odd?(range 1 n)))(i 1))(define x(list-ref l i))(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)
    (let loop ((l (filter odd? (range 1 n))) (i 1))
      (define x (list-ref l i))
      (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)

Produzione:

'(1 3 7 9 13 15 21 25 31 33 37 43 49 51 63 67 69 73 75 79 87 93 99)
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.