Générer des numéros chanceux


22

Récit:

Lucy a demandé à George quel était son numéro porte-bonheur. Après une certaine réflexion, George a répondu qu'il avait plusieurs numéros porte-bonheur. Après une brève confusion, Lucy a demandé à George quels nétaient ses premiers numéros porte-bonheur. George vous a alors demandé, son copain, de lui écrire un programme pour faire le travail pour lui.

Le défi:

Vous écrirez un programme / fonction qui recevra de l'argument d'entrée / fonction standard une chaîne ou un entier n. Le programme / la fonction renverra / émettra ensuite les premiers n numéros porte-bonheur . Les nombres chanceux sont définis via un tamis comme suit.

Commencez avec les entiers positifs:

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, ...

Maintenant, supprimez chaque deuxième numéro:

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

Le deuxième nombre restant est 3 , donc supprimez chaque troisième nombre:

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

Maintenant, le nombre restant suivant est 7 , alors supprimez tous les septièmes:

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

Ensuite, supprimez chaque neuvième nombre, etc. La séquence résultante sont les numéros porte-bonheur.

Gagnant:

Comme d'habitude pour codegolf, le moins d'octets gagne.

Comme d'habitude, les soumissions utilisant des failles standard sont disqualifiées.


8
Je suggère d'inclure la définition dans le message ainsi que les dix premiers chiffres.
xnor

Une extension intéressante serait que pour chaque élément examiné (3, 7, etc.), cette opération soit effectuée autant de fois. Par exemple pour 3, supprimez le troisième élément de la liste 3 fois, le 7e élément 7 fois, etc. (notez que ce n'est pas la séquence mais l'idée est la même)
Ryan

@Ryan Je pense que cette séquence serait remarquablement similaire aux nombres naturels :)
TheNumberOne

@TheBestOne Vous le pensez? J'ai posté plus tôt sur math.stackexchange: math.stackexchange.com/questions/1153889/…
Ryan

@Ryan En fait, j'ai mal interprété votre suggestion. Comme vous l'avez dit dans votre question sur math.se, je pense que ce serait intéressant.
TheNumberOne

Réponses:


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 magie d'itérer sur une liste lorsque la boucle la modifie!

La liste Lcommence par tous les entiers 1jusqu'à une valeur suffisamment élevée. Le code parcourt chaque élément rde L, en prenant la sous-liste de chaque rélément et en supprimant chacune de ces valeurs. Par conséquent, les valeurs supprimées ne sont pas répétées. À la fin, imprimez le premiern éléments.

L'expression map(A.remove,B)est une astuce que j'attends depuis longtemps. Il appelle A.removechaque élément de B, ce qui entraîne la Bsuppression de tous les éléments de A. En effet, il prend la différence de liste, bien qu'il nécessite Bd'être une sous-liste de A. Cela nécessite Python 2, car Python 3 n'évaluerait pas réellement la carte.

La première boucle doit être placée dans un boîtier spécial pour être convertie rde 1à 2, as r+=r<2.

La limite supérieure suffisamment élevée de 2**nrend le programme très lent pour les grandes valeurs de n. Utiliser n*n+1suffit, mais coûte un personnage. Notez que n*ncela ne fonctionne pas n=1.


Vous avez juste besoin de n**2chiffres, pas2**n
Optimizer

3
C'est une utilisation incroyable que mapvous avez là-bas. Je me demandais s'il y avait une meilleure façon ...
Sp3000

@Optimizer Malheureusement, n**2+1sauf si le cas n=1peut être pardonné.
xnor

Cette utilisation de la carte est brillante. Comme utiliser un ensemble ordonné. Peut-être peut-être aussi être utilisé comme map(A.index,B)pour trouver les index des éléments de B dans A, map(A.count,B)pour trouver le nombre des éléments de B dans A, map(A.extend,B)pour ajouter une liste B aplatie à A.
Logic Knight

13

Haskell, 71 69 octets

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

Définit une fonction f. L'expression est 1:s[3,5..]3évaluée à la liste infinie de nombres porte-bonheur et fprend simplement le premier nd'entre eux take n.

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

Je pourrais raser 5 octets du tamis en utilisant une compréhension de liste parallèle

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

mais cela nécessiterait de passer le gigantesque drapeau du compilateur -XParallelListCompà GHC pour activer l'extension.

Explication du tamis

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'idée de base est de s(n:k)pproduire le (p-1)numéro porte-bonheur n, de supprimer chaque nnuméro de la queue infinie k(compensé par ppour tenir compte des chiffres produits précédemment) et de revenir à cette liste avec l'accumulateur (p+1). Dans f, nous initialisons le processus avec les nombres impairs à partir de 3, et plaquons 1vers l'avant, obtenant exactement les nombres chanceux.


12

Python 2, 71 69 67

Au début, je pensais que ce serait un grand défi pour le découpage de tableaux de Python. Cependant, j'ai rencontré une pierre d'achoppement lorsque j'ai découvert que les tranches avec une étape autre que 1 ne peuvent avoir qu'une autre tranche de longueur identique qui leur est affectée. Mais après avoir googlé "python remove slice", ma foi a été restaurée: j'ai trouvé une deldéclaration funky qui fait parfaitement l'affaire.

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

Ancienne version

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

-2 octets grâce à Sp3000.


10

> <> , 121 114 111 octets

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

Je n'ai que quelques mots à dire ...

... "Argh mon cerveau me fait mal."


Explication

> <> est un langage de programmation ésotérique 2D et n'est certainement pas adapté à cette tâche, en raison de son manque de tableaux. En fait, le seul type de données dans> <> est un étrange mélange d'int / float / char, et tout se passe sur une pile de piles.

Voici le récapitulatif:

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

Voici un exemple simulé qui montre à peu près comment fonctionne le tamisage (voici kle numéro porte-bonheur avec lequel nous tamisons):

[[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
Encore mieux que Java;)
Optimizer

5
J'aime le fait que cela naopuisse apparemment être interprété comme "imprimer cette chose maintenant".
Zgarb

10

CJam - 25

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

Essayez-le en ligne

Explication:

Cette implémentation ne supprime pas les numéros successivement d'un tableau, mais calcule chaque numéro en fonction du nombre qui aurait été supprimé avant lui.
Pour chaque indice i (de 0 à n-1) et chaque numéro porte-bonheur précédent l, dans l'ordre inverse, nous incrémentons i de i / (l-1), sauf pour l = 1 nous utilisons 1 au lieu de 0, et ajoutons également 1 à la fin.
Par exemple, pour i = 4, nous avons les 4 premiers nombres, [1 3 7 9], et calculons:
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

Technique intéressante :)
TheNumberOne

6

Pyth: 23 22 octets

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

Essayez-le en ligne: Pyth Compiler / Executor

Explication:

<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 réduction calcule en fait plus que les Qnombres porte-bonheur (la commande remove est appelée Q + 1 fois, Q-1 devrait suffire).


5

R, 58 octets

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

Avec des sauts de ligne:

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

Version précédente, 62 octets

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
}

Version précédente, 78 octets

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 octets: remplacer n=as.numeric(readline())par function(n){...}. Cela crée un objet fonction qui peut être affecté et appelé. Déposez les accolades bouclés dans la forboucle.
Alex A.

Merci @Alex! Bien que ce soit 66, car il a besoin d'un nom?
freekvd

Il n'a pas besoin d'un nom pour la soumission. Voir les solutions Matlab / Octave. Les objets de fonction R s'apparentent à des fonctions sans nom / lambda dans d'autres langues, qui sont des soumissions valides.
Alex A.

Et alors n=scan(n=1)?
koekenbakker

2
Ça marche! Et c'est 1 caractère de moins. C'est encore plus court si je laisse tomber le n = 1, la fonction ignore tous les éléments de n après le premier.
freekvd

4

CJam, 32 30 octets

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

Prend l'entrée de STDIN.

Explication du code :

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";

Essayez-le en ligne ici


4

Python 2, 105 101 octets

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]

Juste une implémentation simple.

Pyth, 39 36 35 32 octets

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

Similaire à l'approche ci-dessus, mais les choses sont indexées 0 plutôt que indexées 1. Essayez-le en ligne .

Merci à @Jakube d'avoir signalé une économie d'octets.


3

Mathematica, 80 octets

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

Mise en œuvre simple de la définition. Comme certaines autres réponses, commence par une plage de 1à puis continue de filtrer.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 "}

MISE À JOUR: évidemment, grep{...}vaut mieux que map{...?$_:()} 81:

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

MISE À JOUR: OK, en fait, une ligne maintenant. Je peux arrêter. (?) 78:

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

3

Octave, 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

Non golfé:

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 octets

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

Explication (de droite à gauche):

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.@*:@>:semble beaucoup trop long, mais je ne peux que le raccourcir d'un échange d'octets *:avec une !croissance exponentielle de la liste.


2

JavaScript (ES6) 96 99

Modifier le compte à rebours dans la première boucle - merci @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)

Non golfé

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)
}

Tester dans la console Firefox / FireBug

F(57)

Sortie

[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
Vous pouvez enregistrer 1 en décomptant avec la première boucle et en remontant avec la seconde: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

Votre non-golfé n'aide pas vraiment ici: P;)
Optimizer

@Optimizer ungolfed mis à jour - peut-être toujours pas d'une grande aide, mais au moins fonctionne maintenant
edc65

Je voulais dire plus sur les lignes sur "simplement un changement de format n'aidera pas, veuillez fournir des commentaires :)"
Optimizer

2

Matlab, 104 octets

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

Merci à @flawr pour ses commentaires et suggestions très appropriés.

Exemple à partir de l'invite de commande 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

Merci! J'ai utilisé cela dans le passé, mais j'ai tendance à oublier
Luis Mendo

@flawr Bon point. Cette réponse devient plus la vôtre que la mienne! :-)
Luis Mendo

Sûr! Je traîne plus souvent dans StackOverflow, mais c'est le même esprit là-bas. Je vous en suis reconnaissant!
Luis Mendo

Bon point! Je ne suis pas sûr que tout ce que j'apprends sera utile ou réellement nocif pour mon utilisation standard de Matlab, cependant :-P
Luis Mendo

2
Eh bien, codegolf ne concerne pas l'utilisation, mais plutôt l' abus d'une langue ^^
flawr

1

Bash + coreutils, 136

J'avais espéré jouer au golf plus bas, mais bon. Pas tous les jours que vous dirigez vers une fonction récursive dans un script 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

Sortie:

$ ./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

Plus court en utilisant une implémentation plus simple:

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

1

Allez, 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)
    }
}

Mise en œuvre simple à l'aide de goroutine et de tuyaux pour fabriquer des tamis.


7
Ce code Golf, veuillez ajouter un nombre d'octets.
edc65

1

MATLAB, 62 caractères

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

J'ai mal interprété le défi au début - ma version révisée est maintenant en fait plus courte.


0

Raquette 196 octets

Produit des nombres porte-bonheur jusqu'à 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)))))

Version non golfée:

(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)))))
  )

Essai:

(f 100)

Sortie:

'(1 3 7 9 13 15 21 25 31 33 37 43 49 51 63 67 69 73 75 79 87 93 99)
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.