0〜2 ^ n-1はPOPCORN順


18

...申し訳ありませんが、ポップコーンはありません。POPCNTだけです。

数値を取り込み、0から2 n -1 までのすべての整数を、数値のバイナリ表現(popcount)の1ビット数値の昇順で出力する最短のプログラムまたは関数を記述します。重複は許可されません。n

同じポップカウントを持つ数字の順序は実装定義です。

たとえば、の場合n = 3、これらの出力はすべて有効です。

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

入力および出力形式は、言語機能を使用してコードをさらに学習できるように実装定義されています。出力にはいくつかの制限があります。

  • 数値は10進形式で出力する必要があります。
  • 出力には、数字の間に適切な区切り文字が含まれている必要があります(末尾の区切り文字は使用できますが、先頭には使用できません)。

    ラインフィード(\n)、タブ(\t)、スペース、,.;|-_/非常に合理的セパレーターです。きれいに印刷するために追加のスペースを気にしませんが、区切り文字として文字や数字を使用しません。

  • 数字と区切り記号は[ ]{ }または任意の配列表記またはリスト表記で囲むことができます。
  • 上記以外の内容は印刷しないでください。

ボーナス

ソリューションがその場で数を生成できる場合は、スコアに0.5を掛けます。このボーナスの精神は、印刷ソリューションをジェネレーターに直接変換する場合、ジェネレーターは最大でO(n)メモリのみを使用することです(nは上記で定義されたビット数です)。(実際にソリューションをジェネレーターに変換する必要はありません)。n <= 28を課している間、すべての数値を格納するために必要なメモリは指数関数的に増加し、単純なソートソリューションはn = 28で少なくとも4 GBのメモリを占有することに注意してください。

このボーナスを請求する前に、ソリューションの仕組みに関する簡単な説明を追加してください。


4
それは非常に退屈で、答えを並べ替える束になるという課題があるようです。チャレンジをより面白くするために、ボーナスを追加したいと思います。「その場で数字を生成する」というラインに沿った何か。よろしければ、このコメントに賛成票を投じてください。それから質問に追加します。
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

同意しない場合は、このコメントに賛成してください。
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

質問をライブで投稿する前に、サンドボックスを使用して、質問に関するさらなる提案を求めてください。
ジョン・ドヴォルザーク

21
@JanDvorak:1か月間サンドボックスにありました。
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

1
この質問には遅すぎると思います。一般的に、自明ではないアルゴリズムを理解する必要がある質問は、私の意見ではコードゴルフにはあまり適していません。代わりにそれらをコードチャレンジにし、必要なすべての制約を課します。
-FUZxxl

回答:



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

このビット調整アルゴリズムvにより、同じPOPCOUNTで次に高いものを繰り返し生成します

実際、ポップカウントを減らして生成し、補数を印刷して増加させる方が簡単であることがわかりました。そのようにして、vオーバーフローし2**n、where でnビットを除くすべてを単純に削除します。そうすれば、1つのループを実行できます。同じPOPCOUNTで次に低い番号を直接検索するより良いソリューションがおそらくあります。&NN=2**n-1

フェンスポストの問題のv=2**(n+1)-1ためv=N-1、最初のループで操作が生成されるようにすることから始める必要があります。

の出力4

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

同じポップカウントの数を増やす必要はありません。順序は実装定義です。
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

1
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳私は承知していますが、キャラクターを別の方法で保存する方法がわかりません。
xnor

単純な3ループの方法では、JSでほぼ同じスコアを持ちます(console.log()vsとprint)。ちょっとしたトリックが重すぎるかもしれません。
edc65

1バイトの節約:v=N-~N
Sp3000

5

J、19文字、ボーナスなし。

[:(/:+/"1@#:)@i.2^]
  • 2 ^ y– 2の累乗y
  • i. 2 ^ y-から整数0(2 ^ y) - 1
  • #: i. 2 ^ y –これらの各整数は、基数2で表されます。
  • +/"1 #: i. 2 ^ y –各表現の合計
  • (i. 2 ^ y) /: +/"1 #: i. 2 ^ yi. 2 ^ y前のベクトルの項目の順序でソートされたベクトル、私たちの答え。


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

編集: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);}}}

編集: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);}}}

またはもう少しフォーマット:

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

それは何ですか?

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

表示する最後の数を計算します(pow(2、n)-1)

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

外側のループはビットカウント(つまり0〜n-1)を反復処理しますが、内側のループは0〜mをカウントします。

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

x86には、設定ビットのカウントに使用できるPOPCNT命令があります。GCCおよび互換コンパイラーは、基本的にその命令にコンパイルされる__builtin_popcount関数をサポートする場合があります。



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、修正!ありがとう!!!
Savenkovアレクセイ

1

JavaScript(ES6)41(82 * 0.5)

最も簡単な方法、ゴルフ

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

非ゴルフ

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

Firefox / FireBugコンソールでテストする

F(4)

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


1

Bash + coreutils、66

始めるための1つ:

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

ここで本当にエキサイティングなことは何もありません。与えられたあなたのコメント私は喜んであなたが質問を変更したい場合は、この答えを修正/削除されますが。
デジタル外傷

0から28までのnのすべての値に対してプログラムが機能する必要があることを強調する必要があるかどうかはわかりませんここでどれだけの答えがその要件を満たしているかわかりません。
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

人々はとにかくそれに気付かないようだから、私はこの条項を削除した。
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳さて、理論上は少なくとも28までは動作するはずです。これまでに22までテストしましたが、もちろんこれにはsort時間がかかります。n = 28では、sort2 ^ 28行/〜13GBのデータをソートする必要があります。
デジタル外傷

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

使用例:f 4、出力[0,1,2,4,8,3,5,9,6,10,12,7,11,13,14,15]

仕組み:[0..2 ^ n-1]の並べ替えも繰り返しの繰り返しも、i 1を含む数値の検索も行いません。

#ヘルパー機能は、2つのパラメータを取りますabとで構成されたすべての番号のリストを構築しa、1とb0を。メイン関数f呼び出し#の組み合わせごとab場所a+bイコールn、1Sなしで始まるn順番に数字を持っている0。Haskellの怠なおかげで、これらのすべてのリストをメモリ内に完全に構​​築する必要はありません。


しない++a#b平均値は(大きいかもしれない)左側が完全に生成され、その結果の最初の項目は、こうしてボーナスの要件に違反し、生成される前にコピーする必要があること?
ジュール

ああ、いや、それがそれらが生成されている間にまだそれらを遅延生成することができると考えると、それぞれのアイテムのコピーを作成するだけです。私を無視。
ジュール


1

Mathematica、26

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

例:

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}

範囲[0..2^n-1] n + 1時間にわたって繰り返します。各反復で、反復変数($i)に等しい1ビットの数を持つ数値のみを出力します。ビットは、でバイナリ文字列に変換された数値1のをカウントすることでカウントy/1//されますsprintf

私をテストしてください

Perl、63

ソート方法:

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

1
@ Optimizer、O(1)メモリを使用します。他にどのような定義がありますか?おっと、それをライブで印刷するのは事実ではありません:)
nutki

@Optimizer、修正済み。
-nutki

条件を設定するとき、私はこれを知っていますが、とにかくそれを許可します。人々が思いつくことができる複雑な答えを見てみたいからです。
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

2
perlが読めないので、「どのように」と尋ねました。
オプティマイザー

@Optimizer、さらに説明が追加されました。
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文字:

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

ゴルフをしていない:

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

説明:

int、intのペアのセットを作成します。最初のintはビットカウント、2番目のintは数値です。ペアは最初のパラメーターに基づいて比較されるため、セットはビットカウントでソートされます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.