POPCORN düzeninde 0'dan 2 ^ n - 1'e


18

... Üzgünüm, patlamış mısır yok, sadece POPCNT.

Kısa Yazın programı veya fonksiyonu bir dizi alır nve çıkış 0 ila 2 arasında tüm tamsayıları n 1, bir artan düzende - sayıların ikili gösterimi 1 bit sayısı (popcount). Kopyaya izin verilmiyor.

Aynı popcount değerine sahip sayıların sırası uygulama tanımlıdır.

Örneğin n = 3, tüm bu çıktılar geçerlidir:

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

Giriş ve çıkış formatı, kodu daha da golf oynamak için dil özelliklerinin kullanılmasına izin vermek için uygulama tanımlıdır. Çıktıda birkaç kısıtlama vardır:

  • Sayılar ondalık biçimde yazılmalıdır.
  • Çıktı, sayılar arasında makul bir ayırıcı içermelidir (sondaki ayırıcıya izin verilir, ancak öndeki değil).

    Hat besleme ( \n), sekme ( \t), uzay, ,, ., ;, |, -, _, /oldukça makul ayırıcı vardır. Güzel baskı için ek alanlara aldırmam, ancak ayırıcı olarak harf veya rakam kullanmayın.

  • Sayılar ve ayırıcılar ile çevrili olabilir [ ], { }ya da herhangi bir dizi veya liste gösterimde.
  • Yukarıda belirtilmeyen başka bir şey yazdırmayın.

Bonus

Çözümünüz anında sayı üretebiliyorsa puanınızı 0,5 ile çarpın . Bu bonusun ruhu, eğer baskı çözümünüzü doğrudan bir jeneratöre dönüştürecek olursanız, jeneratör yalnızca en fazla O (n) bellek kullanır; burada n, yukarıda tanımlandığı gibi bit sayısıdır. (Çözümünüzü jeneratöre dönüştürmeniz gerekmez). Ben n <= 28 empoze ederken, tüm sayıları saklamak için gerekli bellek hala üssel olarak büyür ve saf bir sıralama çözümü n = 28 en az 4 GB bellek hog olacaktır unutmayın.

Lütfen bu bonusu talep etmeden önce çözümünüzün nasıl çalıştığına dair basit bir açıklama ekleyin.


4
Görünüşe göre meydan okuma oldukça sıkıcı ve bir grup sıralama cevabı ile sonuçlanacak. Meydan okumayı daha ilginç hale getirmek için biraz bonus eklemek istiyorum. "Numaraları anında oluşturma" çizgisi boyunca bir şey. Eğer onunla iyi iseniz, lütfen bu yorumu oy verin, sonra soruya ekleyeceğim.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

Kabul etmiyorsanız, lütfen bu yorumu onaylayın.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

Bir soruyu canlı yayınlamadan önce daha fazla öneri istemek için lütfen korumalı alanı kullanın.
John Dvorak

21
@ JanDvorak: Bir ay boyunca kum havuzundaydı.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

1
Bence bu soru için çok geç. Genel olarak, önemsiz olmayan bir algoritma bulmak zorunda olduğunuz sorular bence kod golf için uygun değildir. Bunun yerine onlara bir kod meydan okuması yapın ve ihtiyacınız olan tüm kısıtlamaları ortaya koyun.
FUZxxl

Yanıtlar:


10

Pyth, 9 bayt

osjN2U^2Q

otarafından Sarf sum tabanı 2 gösterimi (arasında jN2aralığında) ( Uarasında) 2 ^ Q.

( Q= eval(input())).

Burada deneyin.


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

Bu bit döndürme algoritmasıv ile aynı POPCOUNT ile bir sonraki en yüksek değeri tekrar tekrar üretir .

Aslında, azalan pop-sayımında bunları oluşturmak daha kolay çıktı, daha sonra arttırmak için tamamlayıcıyı yazdırın. Bu şekilde, o zamanv taşar 2**n, nerede nile bit dışında hepsini kaldırırız ve bu, en küçük bir popcount'u daha düşük verir. Bu şekilde, sadece bir döngü yapabiliriz. Muhtemelen aynı POPCOUNT ile bir sonraki düşük sayıyı doğrudan bulan daha iyi bir çözüm vardır .&NN=2**n-1

Bir çit direği sorunu nedeniyle v=2**(n+1)-1, işlemin v=N-1ilk döngüde üretilmesi için başlamamız gerekiyor .

Çıktı 4:

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

Aynı popcount'a sahip sayının artmasına gerek yoktur. Sipariş, uygulama tanımlıdır.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

1
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ Farkındayım, ancak karakterlerin farklı şekilde nasıl kaydedileceğini göremiyorum.
xnor

Bir saf 3 döngüler yöntemi ile JS ( console.log()vs sahip print) neredeyse aynı puan . Belki biraz hile çok ağırdır.
edc65

Bir bayt tasarrufu:v=N-~N
Sp3000

5

J, 19 karakter, bonus yok.

[:(/:+/"1@#:)@i.2^]
  • 2 ^ y- ikisinin gücü y.
  • i. 2 ^ y- dan tamsayılar 0için (2 ^ y) - 1.
  • #: i. 2 ^ y - bu tamsayıların her biri taban 2'de temsil edilir.
  • +/"1 #: i. 2 ^ y - her bir temsilin toplamı
  • (i. 2 ^ y) /: +/"1 #: i. 2 ^ y- önceki vektörün i. 2 ^ yöğelerinin sırasına göre sıralanan vektör, cevabımız.

3

Python, 63 karakter

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: Kısıtlamalar listesi, bir dize sonucu istediğini ima etti.
Keith Randall

Üzgünüm, kaçırdım.
Alex

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

DÜZENLEME: 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);}}}

DÜZENLEME: 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);}}}

veya biraz daha güzel biçimlendirilmiş:

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

Bu ne yapar?

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

gösterilecek son sayıyı hesaplar (pow (2, n) - 1)

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

dış döngü bit sayımı üzerinde yinelenir (yani 0 ila n-1), iç döngü ise 0 ila m arasında sayılır

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

X86'da ayarlanmış bitleri saymak için kullanılabilen POPCNT komutu vardır. GCC ve uyumlu derleyiciler temel olarak bu talimata derleyen __builtin_popcount işlevini destekleyebilir.


2

CJam, 13 bayt

2ri#,{2b1b}$p

Oldukça basit bir uygulama.

Nasıl çalışır :

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

Buradan çevrimiçi deneyin


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, Sabit! Teşekkürler!!!
Savenkov Alexey

1

JavaScript (ES6) 41 (82 * 0.5)

En basit yol, 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;
}

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

Firefox / FireBug konsolunda test et

F(4)

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


1

Bash + coreutils, 66

Başlamanız için bir tane:

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

Burada gerçekten heyecan verici bir şey yok. Verilen Yorumunuzu mutlulukla soruyu değiştirmek istiyorsanız bu cevabı revize / silecektir.
Dijital Travma

Programınızın 0 ile 28 (dahil) arasındaki tüm n değerleri için çalışması gerektiğini vurgulamam gerekir. Burada kaç tane cevabın bu gereksinimi geçtiğini bilmiyorum.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

Maddeyi kaldırdım, çünkü insanlar yine de fark etmiyor gibi görünüyor.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ Şimdi, teoride en azından 28'e kadar çalışmalı. Şimdiye kadar 22'ye kadar test ettim, ama elbette bu sortuzun zaman alıyor. N = 28 ile, sort2 ^ 28 satır / ~ 13GB veri sıralaması gerekecektir.
Dijital Travma

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

Kullanım örneği: f 4çıktıları[0,1,2,4,8,3,5,9,6,10,12,7,11,13,14,15]

Nasıl çalışır: [0..2 ^ n-1] üzerinde sıralama veya tekrar tekrar yineleme ve i 1'ler içeren sayıları arama.

#Yardımcı işlevler iki parametre alır ave bve oluşan her sayısının bir listesini oluşturur a1'ler ve b0'lar. Ana işlevi fçağırır #her kombinasyonu için ave bnerede a+beşittir n, hiçbir 1'ler ve ile başlayan n0s sırayla numaraları için. Haskell'in tembelliği sayesinde, tüm bu listelerin tamamen bellekte oluşturulması gerekmez.


Yok mu ++içinde a#bortalama sol taraf (büyük olabilir) tamamen üretilmesi gerekiyor ve sonuç ilk öğe böylece ikramiye için şartları ihlal üretilmeden önce, sonra kopyaladığınız?
Jules

Ah, hayır, bunu düşünürken üretilirken onları tembel olarak üretebilir, sadece her bir öğenin bir kopyasını alması gerekir, bu da her ikisi de işleme sırasında toplanan çöp olabileceği için alan kullanımının sabit olduğu anlamına gelir. Beni görmezden gel.
Jules

1

Yakut 47 karakter

@KeithRandall Python biri gibi:

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

1

Mathematica, 26

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

Misal:

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}

Sadece menzil [0..2^n-1] n + 1sürelerini tekrarlayın . Her yinelemede yalnızca yineleme değişkenine ( $i) eşit 1 bit sayısına sahip sayılar yazdırılır . Bitler sayılarak sayılır1y/1// ikili dizeye dönüştürülen sayıdaki 's ( )sprintf .

Ölçek Beni et .

Perl, 63

Sıralama yaklaşımı:

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

1
@Optimizer, O (1) bellek kullanır. Başka ne tanımımız var? Hata! Canlı yazdırdığımda bu doğru değil :)
nutki

@Optimizer, sabit.
nutki

Durumu ayarladığımda bunun farkındayım, ama yine de izin veriyorum, çünkü insanların hangi kıvrımlı cevapları ortaya çıkarabileceğini görmek istiyorum.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

2
Ben sadece perl okuyamıyorum gibi "nasıl" sordum :) Daha fazla açıklama eklemek ister misiniz?
Doktor

@Optimizer, biraz daha açıklama eklendi.
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 karakter:

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

Açıklama:

İnt, int çiftleri kümesi oluşturun. İlk int bit sayımı, ikincisi sayıdır. Çiftler kendilerini ilk parametrelerine göre karşılaştırırlar, böylece küme bit sayısına göre sıralanır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.