De 0 à 2 ^ n - 1 dans l'ordre POPCORN

18

... Ah désolé, pas de pop-corn ici, juste POPCNT.

Écrivez le programme ou la fonction la plus courte qui prend un nombre net sortez tous les entiers de 0 à 2 n - 1, dans l'ordre croissant du nombre de 1 bits dans la représentation binaire des nombres (popcount). Aucun doublon autorisé.

L'ordre des nombres avec le même nombre est défini par l'implémentation.

Par exemple, pour n = 3, toutes ces sorties sont valides:

0, 1, 2, 4, 3, 5, 6, 7
[0, 4, 1, 2, 5, 3, 6, 7]
0 4 2 1 6 5 3 7 

Le format d'entrée et de sortie est défini par l'implémentation pour permettre l'utilisation de fonctionnalités linguistiques pour approfondir le code. Il y a quelques restrictions sur la sortie:

  • Les nombres doivent être sortis au format décimal.
  • La sortie doit contenir un séparateur raisonnable entre les nombres (séparateur de fin autorisé, mais pas en tête).

    Saut de ligne ( \n), onglet ( \t), l' espace, ,, ., ;, |, -, _, /sont tout à fait raisonnable séparateur. Cela ne me dérange pas d'espaces supplémentaires pour une jolie impression, mais n'utilisez pas de lettres ou de chiffres comme séparateurs.

  • Les nombres et les séparateurs peuvent être entourés par [ ], { }ou n'importe quel tableau ou notation de liste.
  • N'imprimez rien d'autre que ce qui est indiqué ci-dessus.

Prime

Multipliez votre score par 0,5 si votre solution peut générer le nombre à la volée. L'esprit de ce bonus est que si vous deviez convertir directement votre solution d'impression en un générateur, le générateur n'utilise au maximum que de la mémoire O (n) où n est le nombre de bits tel que défini ci-dessus. (Vous n'avez pas besoin de convertir votre solution en générateur). Notez que bien que j'impose n <= 28, la mémoire nécessaire pour stocker tous les nombres augmente toujours de façon exponentielle, et une solution de tri naïf monopoliserait au moins 4 Go de mémoire à n = 28.

Veuillez ajouter quelques explications simples sur le fonctionnement de votre solution avant de réclamer ce bonus.

n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
la source
4
Il semble que le défi car il est assez ennuyeux et entraînerait un tas de réponses de tri. Je voudrais ajouter un bonus pour rendre le défi plus intéressant. Quelque chose dans le sens de "générer des chiffres à la volée". Si cela vous convient, veuillez voter pour ce commentaire, puis je l'ajouterai à la question.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
Si vous n'êtes pas d'accord, veuillez voter pour ce commentaire.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
Veuillez utiliser le bac à sable pour demander d'autres suggestions sur une question avant de la publier en direct.
John Dvorak
21
@JanDvorak: C'était sur le bac à sable pendant un mois.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
1
Je pense qu'il est trop tard pour cette question. Généralement, les questions où vous devez trouver un algorithme non trivial ne sont pas bien adaptées pour le golf de code à mon avis. Faites-en plutôt un défi de code et posez toutes les contraintes dont vous avez besoin.
FUZxxl

Réponses:

10

Pyth, 9 octets

osjN2U^2Q

order par le s um de la représentation de base 2 ( jN2) sur la plage ( U) de 2 ^ Q.

(Q = eval(input())).

Essayez-le ici.

isaacg
la source
7

Python 2, 75 * 0,5 = 37,5

N=2**input()-1
v=N-~N
while v:t=1+(v|~-v);v=N&t|~-(t&-t)/(v&-v)/2;print v^N

vGénère à plusieurs reprises le prochain plus élevé avec le même POPCOUNT par cet algorithme de twiddling de bits .

En fait, il s'est avéré plus facile de les générer en diminuant le nombre de pop, puis d'imprimer le complément pour le faire augmenter. De cette façon, puis vdéborde 2**n, nous supprimons simplement tout sauf les nbits avec &NN=2**n-1 supprimons , et cela donne le plus petit nombre de popcount inférieur. De cette façon, nous pouvons simplement faire une boucle. Il existe probablement une meilleure solution qui trouve directement le numéro inférieur suivant avec le même POPCOUNT.

En raison d'un problème de clôture, nous devons commencer par v=2**(n+1)-1 pour que l'opération se produise v=N-1sur la première boucle.

Sortie pour 4:

0
8
4
2
1
12
10
9
6
5
3
14
13
11
7
15
xnor
la source
Il n'est pas nécessaire que le nombre avec le même nombre augmente. L'ordre est défini par l'implémentation.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
1
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ Je suis au courant, mais je ne vois pas comment enregistrer les personnages en le faisant différemment.
xnor
Avec une méthode naïve de 3 boucles, je marque presque le même en JS (ayant console.log()vs print). Peut-être que le truc est trop lourd.
edc65
Économie d'un octet:v=N-~N
Sp3000
5

J, 19 personnages, pas de bonus.

[:(/:+/"1@#:)@i.2^]
  • 2 ^ y- deux au pouvoir de y.
  • i. 2 ^ y- les entiers de 0à (2 ^ y) - 1.
  • #: i. 2 ^ y - chacun de ces nombres entiers représentés en base deux.
  • +/"1 #: i. 2 ^ y - les sommes de chaque représentation
  • (i. 2 ^ y) /: +/"1 #: i. 2 ^ y- le vecteur i. 2 ^ ytrié par ordre des éléments du vecteur précédent, notre réponse.
FUZxxl
la source
3

Python, 63 caractères

F=lambda n:`sorted(range(1<<n),key=lambda x:bin(x).count('1'))`

>>> F(3)
'[0, 1, 2, 4, 3, 5, 6, 7]'
Keith Randall
la source
@Alex: La liste des restrictions impliquait qu'il voulait un résultat de chaîne.
Keith Randall
Désolé, j'ai raté ça.
Alex A.
3

C 179 * 0,5 = 89,5

main(){int n,i=0,m,o;scanf("%d",&n);m=~((~0)<<n);for(;n--;++i){for(o=0;o<m;++o){int bc=0,cb=28;for(;cb--;)bc+=o&(1<<cb)?1:0;if(bc==i)printf("%d ",o);}}printf("%d\n",m);return 0;}

EDIT: 157 * 0,5 = 78,5

main(){int n,i=0,m,o;scanf("%d",&n);m=~((~0)<<n);for(++n;n--;++i){for(o=0;o<=m;++o){int bc=0,cb=28;for(;cb--;)bc+=o&(1<<cb)?1:0;if(bc==i)printf("%d ",o);}}}

EDIT: 132 * 0,5 = 66

main(){int n,i=0,m,o;scanf("%d",&n);m=~((~0)<<n);for(++n;n--;++i){for(o=0;o<=m;++o){if(__builtin_popcount(o)==i)printf("%d ",o);}}}

ou un format un peu plus agréable:

main()
{
    int n, i = 0, m, o;
    scanf("%d", &n);
    m = ~((~0) << n);
    for(++n; n--; ++i)
    {
        for(o = 0; o <= m; ++o)
        {
            if (__builtin_popcount(o) == i)
                printf("%d ", o);
        }
    }
}

Ce qu'il fait?

m = ~((~0) << n);

calcule le dernier nombre à afficher (pow (2, n) - 1)

    for(++n; n--; ++i)
    {
        for(o = 0; o <= m; ++o)
        {

la boucle externe itère sur le nombre de bits (donc 0 à n-1) tandis que la boucle interne ne compte que de 0 à m

            if (__builtin_popcount(o) == i)
                printf("%d ", o);

Sur x86, il y a l'instruction POPCNT qui peut être utilisée pour compter les bits définis. GCC et les compilateurs compatibles peuvent prendre en charge la fonction __builtin_popcount qui compile essentiellement cette instruction.

Felix Bytow
la source
2

CJam, 13 octets

2ri#,{2b1b}$p

Implémentation assez simple.

Comment ça marche :

2ri#,             "Get an array of 0 to 2^n - 1 integers, where n is the input";
     {    }$      "Sort by";
      2b1b        "Convert the number to binary, sum the digits";
            p     "Print the array";

Essayez-le en ligne ici

Optimiseur
la source
2

Mathematica, 50 46

SortBy[Range[0,2^#-1],Tr@IntegerDigits[#,2]&]&

.

SortBy[Range[0,2^#-1],Tr@IntegerDigits[#,2]&]&

{0, 1, 2, 4, 8, 16, 3, 5, 6, 9, 10, 12, 17, 18, 20, 
24, 7, 11, 13, 14, 19, 21, 22, 25, 26, 28, 15, 
23, 27, 29, 30, 31}
Savenkov Alexey
la source
@ MartinBüttner, fixe! Merci!!!
Savenkov Alexey
1

JavaScript (ES6) 41 (82 * 0,5)

Le plus simple, le golf

F=b=>{
  for(l=0;l<=b;l++)
    for(i=1<<b;i;t||console.log(i))
      for(t=l,u=--i;u;--t)
        u&=u-1;
}

Non golfé

F=b=>
{
  for (l = 0; l <= b; l++)
  {
    for (i = 1 << b; i > 0; )
    {
      --i;
      for (t = 0, u = i; u; ++t) // Counting bits set, Brian Kernighan's way
        u &= u - 1;
      if (t == l) console.log(i);
    }
  }
}

Tester dans la console Firefox / FireBug

F(4)

0
8
4
2
1
12
10
9
6
5
3
14
13
11
7
15

edc65
la source
1

Bash + coreutils, 66

Un pour vous aider à démarrer:

jot -w2o%dpc $[2**$1] 0|dc|tr -d 0|nl -ba -v0 -w9|sort -k2|cut -f1
Traumatisme numérique
la source
Rien de vraiment excitant ici. Compte tenu de votre commentaire, je me ferai un plaisir de supprimer / réviser cette réponse si vous souhaitez modifier la question.
Digital Trauma
Je ne sais pas si je dois souligner que votre programme doit fonctionner pour toutes les valeurs de n de 0 à 28 inclus. Je ne sais pas combien de réponses répondent à cette exigence.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
J'ai supprimé la clause, car les gens ne semblent pas le remarquer de toute façon.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ Maintenant, en théorie au moins cela devrait fonctionner jusqu'à 28. J'ai testé jusqu'à 22 jusqu'à présent, mais bien sûr, cela sortprend beaucoup de temps. Avec n = 28, sortil faudra trier 2 ^ 28 lignes / ~ 13 Go de données.
Digital Trauma
1

Haskell, (87 * 0,5) = 43,5

f n=[0..n]>>=(\x->x#(n-x))
a#0=[2^a-1]
0#_=[0]
a#b=[1+2*x|x<-(a-1)#b]++[2*x|x<-a#(b-1)]

Exemple d'utilisation:, f 4qui génère[0,1,2,4,8,3,5,9,6,10,12,7,11,13,14,15]

Fonctionnement: ni tri ni itération répétée sur [0..2 ^ n-1] et recherche de nombres contenant i 1s.

Les #fonctions d'assistance prennent deux paramètres aet bconstruisent une liste de chaque nombre composé de a1 et de b0. La fonction principale fappelle #chaque combinaison de aet ba+best égal n, en commençant par aucun 1 et n0 pour avoir les nombres dans l'ordre. Grâce à la paresse de Haskell, toutes ces listes n'ont pas à être entièrement construites en mémoire.

nimi
la source
Est -ce que pas ++en a#bmoyenne que le côté gauche ( ce qui pourrait être grande) doit être entièrement puis copiés avant le premier élément du résultat est produit, violant ainsi les exigences de la prime?
Jules
Ah, non, y penser peut toujours les générer paresseusement pendant leur production, il suffit de faire une copie de chaque élément, car les deux peuvent être récupérés pendant le traitement, ce qui signifie que l'utilisation de l'espace est constante. Ignore moi.
Jules
1

Ruby 47 caractères

Tout comme celui en Python de @KeithRandall:

f=->n{(0..1<<n).sort_by{|x|x.to_s(2).count ?1}}
steenslag
la source
1

Mathematica, 26

Tr/@(2^Subsets@Range@#/2)&

Exemple:

Tr/@(2^Subsets@Range@#/2)&[4]

{0, 1, 2, 4, 8, 3, 5, 9, 6, 10, 12, 7, 11, 13, 14, 15}

alephalpha
la source
0

Perl, 64/2 = 32

#!perl -ln
for$i(0..$_){$i-(sprintf"%b",$_)=~y/1//||print for 0..2**$_-1}

Parcourez simplement les plages de [0..2^n-1] n + 1temps. Dans chaque itération, imprimez uniquement les nombres dont le nombre de 1 bits est égal à la variable d'itération ( $i). Les bits sont comptés en comptant 1's ( y/1//) dans le nombre converti en chaîne binaire avec sprintf.

Testez- moi .

Perl, 63

Approche de tri:

#!perl -l
print for sort{eval+(sprintf"%b-%b",$a,$b)=~y/0//dr}0..2**<>-1
nutki
la source
1
@Optimizer, il utilise la mémoire O (1). Quelle autre définition avons-nous? Oups, ce n'est pas vrai car je l'imprime en direct :)
nutki
@Optimizer, fixe.
nutki
Eh bien, j'en suis conscient lorsque je fixe la condition, mais je l'autorise quand même, car je veux voir quelles réponses compliquées les gens peuvent trouver.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
2
Je viens de demander "comment" car je ne peux pas lire perl :) Vous voulez ajouter plus d'explications?
Optimizer
@Optimizer, quelques explications supplémentaires ajoutées.
nutki
0

Java 8, 205

public class S{public static void main(String[] n){java.util.stream.IntStream.range(0,1<<Integer.parseInt(n[0])).boxed().sorted((a,b)->Integer.bitCount(a)-Integer.bitCount(b)).forEach(System.out::print);}}
cPu1
la source
0

C ++ 11, 117 caractères:

using namespace std;int main(){ set<pair<int,int> > s;int b;cin>>b;int i=0;while(++i<pow(2,b))s.insert({bitset<32>(i).count(),i});for (auto it:s) cout <<it.second<<endl;}

Non golfé:

using namespace std;
int main()
{
    set<pair<int,int> > s;
    int b;
    cin>>b;
    int i=0;
    while (++i<pow(2,b))  {
        s.insert({bitset<32>(i).count(),i});
    }
    for (auto it:s) {
        cout <<it.second<<endl;
    }
}

Explication:

Créez un ensemble de paires int, int. Le premier entier est le nombre de bits, le second est le nombre. Les paires se comparent en fonction de leur premier paramètre, donc l'ensemble est trié par nombre de bits.

Nucléaire
la source