De 0 a 2 ^ n - 1 em ordem POPCORN


18

... Desculpe, não há pipoca aqui, apenas POPCNT.

Escreva o programa ou função mais curto que recebe um número ne gera todos os números inteiros de 0 a 2 n - 1, em ordem crescente do número de 1 bits na representação binária dos números (popcount). Não são permitidas duplicatas.

A ordem dos números com o mesmo número de pop-up é definida pela implementação.

Por exemplo, para n = 3, todas essas saídas são válidas:

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

O formato de entrada e saída é definido pela implementação para permitir o uso de recursos de idioma para aprimorar ainda mais o código. Existem algumas restrições na saída:

  • Os números devem ser impressos no formato decimal.
  • A saída deve conter um separador razoável entre os números (o separador à direita é permitido, mas não à esquerda).

    Alimentação de linha ( \n), guia ( \t), espaço, ,, ., ;, |, -, _, /são separador bastante razoável. Não me preocupo com espaços adicionais para uma impressão bonita, mas não use letras ou dígitos como separadores.

  • Os números e separadores podem ser colocados entre [ ], { }ou qualquer notação de matriz ou lista.
  • Não imprima nada além do indicado acima.

Bônus

Multiplique sua pontuação por 0,5 se sua solução puder gerar o número em tempo real. O espírito desse bônus é que, se você converter diretamente sua solução de impressão em um gerador, o gerador usará apenas no máximo O (n) de memória, onde n é o número de bits, conforme definido acima. (Na verdade, você não precisa converter sua solução em gerador). Observe que, embora eu imponha n <= 28, a memória necessária para armazenar todos os números ainda cresce exponencialmente, e uma solução de classificação ingênua consumiria pelo menos 4 GB de memória em n = 28.

Adicione uma explicação simples de como sua solução funciona antes de reivindicar esse bônus.


4
Parece que o desafio é bastante chato e resultaria em várias respostas de classificação. Eu gostaria de adicionar um bônus para tornar o desafio mais interessante. Algo na linha de "gerar os números em tempo real". Se você concorda com isso, faça um voto positivo neste comentário e adicionarei à pergunta.
N

Se você não concordar, faça um voto positivo neste comentário.
ǹ̷̰ĥ̷̳h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ 27/02

Use a caixa de areia para pedir mais sugestões sobre uma pergunta antes de publicá-la ao vivo.
John Dvorak

21
@ JanDvorak: Ficou na caixa de areia por um mês.
ǹ̷̰ĥ̷̳h̷͉̃a̷̭̿h̸̡̅ẗ̵̷̨̰́̀ĥ̷̳

1
Eu acho que é tarde demais para esta pergunta. Geralmente, perguntas em que você precisa descobrir um algoritmo não trivial não são adequadas para o código de golfe na minha opinião. Torne-os um desafio de código e coloque todas as restrições necessárias.
FUZxxl 28/02

Respostas:


10

Pitão, 9 bytes

osjN2U^2Q

order pelo sum da representação da base 2 ( jN2) no intervalo ( U) de 2 ^ Q.

( Q= eval(input())).

Experimente aqui.


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

Gera repetidamente o próximo valor mais alto vcom o mesmo POPCOUNT por esse algoritmo de variação de bits .

Na verdade, ficou mais fácil gerá-los na diminuição da contagem de pop-ups e depois imprimir o complemento para aumentá-lo. Dessa forma, em seguida, vtransborda 2**n, simplesmente removemos todos os nbits, exceto &Nonde N=2**n-1, e isso diminui a quantidade de pop-ups número um. Dessa forma, podemos apenas fazer um loop. Provavelmente existe uma solução melhor que encontra diretamente o próximo número mais baixo com a mesma POPCOUNT.

Devido a um problema no poste, precisamos começar v=2**(n+1)-1para que a operação produza v=N-1no primeiro loop.

Saída para 4:

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

Não há necessidade de aumentar o número com o mesmo número de pop-up. A ordem é definida pela implementação.
N

1
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ Estou ciente, mas não vejo como salvar os personagens de maneira diferente.
xnor 27/02

Com um método ingênuo de 3 loops, eu tenho quase o mesmo resultado em JS (tendo console.log()vs print). Talvez o truque seja muito pesado.
edc65 27/02

Economia de um byte:v=N-~N
Sp3000

5

J, 19 caracteres, sem bônus.

[:(/:+/"1@#:)@i.2^]
  • 2 ^ y- dois ao poder de y.
  • i. 2 ^ y- os números inteiros de 0a (2 ^ y) - 1.
  • #: i. 2 ^ y - cada um desses números inteiros representados na base dois.
  • +/"1 #: i. 2 ^ y - as somas de cada representação
  • (i. 2 ^ y) /: +/"1 #: i. 2 ^ y- o vetor i. 2 ^ yclassificado pela ordem dos itens do vetor anterior, nossa resposta.

3

Python, 63 caracteres

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

>>> F(3)
'[0, 1, 2, 4, 3, 5, 6, 7]'

@ Alex: A lista de restrições implicava que ele queria um resultado de string.
Keith Randall

Desculpe, perdi isso.
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 um pouco mais agradável formatado:

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

O que faz?

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

calcula o último número a ser exibido (pow (2, n) - 1)

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

o loop externo itera sobre a contagem de bits (de 0 a n-1) enquanto o loop interno conta de 0 a m

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

No x86, há a instrução POPCNT que pode ser usada para contar os bits definidos. O GCC e os compiladores compatíveis podem oferecer suporte à função __builtin_popcount que basicamente é compilada para essa instrução.


2

CJam, 13 bytes

2ri#,{2b1b}$p

Implementação bastante direta.

Como funciona :

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

Experimente online aqui


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}

@ MartinBüttner, Fixed! Obrigado!!!
Savenkov Alexey

1

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

A maneira mais simples, jogar golfe

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

Ungolfed

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

Teste no console Firefox / FireBug

F(4)

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


1

Bash + coreutils, 66

Um para você começar:

jot -w2o%dpc $[2**$1] 0|dc|tr -d 0|nl -ba -v0 -w9|sort -k2|cut -f1

Nada realmente emocionante aqui. Dado o seu comentário , terei prazer em excluir / revisar esta resposta se você quiser alterar a pergunta.
Digital Trauma

Não tenho certeza se devo destacar que seu programa deve funcionar para todos os valores de n de 0 a 28, inclusive. Não sei quantas respostas aqui passam nesse requisito.
ǹ̷̰ĥ̷̳h̷͉̃a̷̭̿h̸̡̅ẗ̵̷̨̰́̀ĥ̷̷̳̰̀ĥ̷̳

Eu removi a cláusula, pois as pessoas parecem não perceber de qualquer maneira.
N

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ Agora, em teoria, pelo menos, deve funcionar até 28. Eu testei até 22 até agora, mas é claro que isso sortleva muito tempo. Com n = 28, sortserá necessário classificar 2 ^ 28 linhas / ~ 13GB de dados.
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)]

Exemplo de uso:, f 4que gera[0,1,2,4,8,3,5,9,6,10,12,7,11,13,14,15]

Como funciona: nem classificando nem repetidamente repetindo sobre [0..2 ^ n-1] e procurando números contendo i 1s.

As #funções auxiliares usam dois parâmetros ae bconstroem uma lista de todos os números compostos de a1s e b0s. A função principal fexige #que todas as combinações de ae bonde sejam a+biguais n, começando com 1s e n0s, tenha os números em ordem. Graças à preguiça de Haskell, todas essas listas não precisam ser totalmente construídas na memória.


Não o ++em a#bmédia que o lado esquerdo (que poderia ser grande) precisa ser inteiramente produzido e depois copiado antes de o primeiro item no resultado é produzido, violando, assim, os requisitos para o bônus?
Jules

Ah, não, pensar nisso ainda pode gerá-los preguiçosamente enquanto estão sendo produzidos, basta fazer uma cópia de cada item, que pode ser coletado como lixo durante o processamento, pois o uso do espaço é constante. Me ignore.
Jules

1

Ruby 47 chars

Muito parecido com o Python de @KeithRandall:

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

1

Mathematica, 26

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

Exemplo:

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

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


0

Perl, 64/2 = 32

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

Simplesmente itere sobre os intervalos de [0..2^n-1] n + 1tempo. Em cada iteração, imprima apenas os números com número de 1 bits igual à variável de iteração ( $i). Os bits são contados contando 1's ( y/1//) no número convertido em string binária com sprintf.

Teste- me .

Perl, 63

Abordagem de classificação:

#!perl -l
print for sort{eval+(sprintf"%b-%b",$a,$b)=~y/0//dr}0..2**<>-1

1
@ Otimizador, Ele usa memória O (1). Que outra definição temos? Ops, isso não é verdade, pois eu imprimo ao vivo :) #
nutki 27/02

@Optimizer, fixo.
nutki

Bem, estou ciente disso quando defino a condição, mas aceito de qualquer maneira, pois quero ver quais respostas complicadas as pessoas podem ter.
N

2
Eu apenas perguntei "como", pois não consigo ler perl :) Gostaria de adicionar mais explicações?
Optimizer

@ Optimizer, mais algumas explicações adicionadas.
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);}}

0

C ++ 11, 117 caracteres:

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

Ungolfed:

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

Explicação:

Crie um conjunto de pares int, int. O primeiro int é a contagem de bits, o segundo é o número. Os pares se comparam de acordo com o primeiro parâmetro, para que o conjunto seja classificado pela contagem de bits.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.