Từ 0 đến 2 ^ n - 1 theo thứ tự POPCORN


18

... Ah xin lỗi, không có bỏng ngô ở đây, chỉ có POPCNT.

Viết chương trình hoặc hàm ngắn nhất có một số nxuất tất cả các số nguyên từ 0 đến 2 n - 1, theo thứ tự tăng dần của số 1 ​​bit trong biểu diễn nhị phân của các số (popcount). Không cho phép trùng lặp.

Thứ tự của các số có cùng số đếm được xác định theo thực hiện.

Ví dụ: cho n = 3, tất cả các đầu ra này là hợp lệ:

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

Định dạng đầu vào và đầu ra được xác định theo triển khai để cho phép sử dụng các tính năng ngôn ngữ để tiếp tục đánh mã. Có một vài hạn chế về đầu ra:

  • Các số phải được xuất ở định dạng thập phân.
  • Đầu ra phải chứa một dấu phân cách hợp lý giữa các số (dấu phân cách cho phép, nhưng không dẫn đầu).

    Thức ăn Line ( \n), tab ( \t), không gian, ,, ., ;, |, -, _, /là dấu phân cách khá hợp lý. Tôi không nhớ các không gian bổ sung để in đẹp, nhưng không sử dụng chữ cái hoặc chữ số làm dấu phân cách.

  • Các số và dấu phân cách có thể được bao quanh bởi [ ], { }hoặc bất kỳ ký hiệu mảng hoặc danh sách.
  • Đừng in bất cứ điều gì khác không được nêu ở trên.

Tặng kem

Nhân số điểm của bạn với 0,5 nếu giải pháp của bạn có thể tạo ra số nhanh chóng. Tinh thần của phần thưởng này là nếu bạn trực tiếp chuyển đổi giải pháp in của mình sang máy phát, thì trình tạo chỉ sử dụng tối đa bộ nhớ O (n) trong đó n là số bit như được xác định ở trên. (Bạn không thực sự phải chuyển đổi giải pháp của mình sang máy phát điện). Lưu ý rằng trong khi tôi áp đặt n <= 28, bộ nhớ cần lưu trữ tất cả các số vẫn tăng theo cấp số nhân và một giải pháp sắp xếp ngây thơ sẽ chiếm ít nhất 4 GB bộ nhớ với n = 28.

Vui lòng thêm một số giải thích đơn giản về cách giải pháp của bạn hoạt động trước khi yêu cầu phần thưởng này.


4
Có vẻ như thử thách này khá nhàm chán và sẽ dẫn đến một loạt các câu trả lời sắp xếp. Tôi muốn thêm một số phần thưởng để làm cho thử thách thú vị hơn. Một cái gì đó dọc theo dòng "tạo ra các số trên bay". Nếu bạn đồng ý với nó, xin vui lòng đưa ra nhận xét này, sau đó tôi sẽ thêm nó vào câu hỏi.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

Nếu bạn không đồng ý, xin vui lòng đưa ra nhận xét này.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ 27/2/2015

Vui lòng sử dụng hộp cát để yêu cầu thêm gợi ý về câu hỏi trước khi đăng trực tiếp.
John Dvorak

21
@JanDvorak: Nó đã ở trên hộp cát trong một tháng.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

1
Tôi nghĩ rằng đã quá muộn cho câu hỏi này. Nói chung, theo tôi, các câu hỏi mà bạn phải tìm ra một thuật toán không tầm thường không phù hợp với môn đánh gôn. Thay vào đó hãy biến chúng thành một thách thức mã và đặt ra tất cả các ràng buộc bạn cần.
FUZxxl

Câu trả lời:



7

Con trăn 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

Liên tục tạo ra mức cao nhất tiếp theo vvới cùng POPCOUNT bằng thuật toán xoay vòng bit này .

Trên thực tế, nó trở nên dễ dàng hơn để tạo ra chúng trong việc giảm số lượng pop, sau đó in phần bổ sung để làm cho nó tăng lên. Bằng cách đó, sau đó vtràn ra 2**n, chúng tôi chỉ cần loại bỏ tất cả trừ ncác bit &Nở đâu N=2**n-1và điều đó làm cho số lượng nhỏ nhất số một thấp hơn. Bằng cách đó, chúng ta chỉ có thể thực hiện một vòng lặp. Có lẽ có một giải pháp tốt hơn trực tiếp tìm thấy số thấp hơn tiếp theo với cùng POPCOUNT.

Do một vấn đề về hàng rào, chúng ta cần bắt đầu v=2**(n+1)-1để hoạt động tạo ra v=N-1trên vòng lặp đầu tiên.

Đầu ra cho 4:

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

Không có nhu cầu về số lượng có cùng số lượng tăng lên. Trình tự được xác định thực hiện.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ 27/2/2015

1
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ Tôi biết, nhưng tôi không thấy cách lưu các nhân vật làm việc đó khác đi.
xnor 27/2/2015

Với phương thức 3 vòng lặp ngây thơ, tôi cho điểm gần như giống nhau trong JS (có console.log()vs print). Có lẽ mẹo nhỏ quá nặng.
edc65

Tiết kiệm một byte:v=N-~N
Sp3000

5

J, 19 ký tự, không có tiền thưởng.

[:(/:+/"1@#:)@i.2^]
  • 2 ^ y- hai đến sức mạnh của y.
  • i. 2 ^ y- các số nguyên từ 0đến (2 ^ y) - 1.
  • #: i. 2 ^ y - mỗi số nguyên này được biểu diễn trong cơ sở hai.
  • +/"1 #: i. 2 ^ y - tổng của mỗi đại diện
  • (i. 2 ^ y) /: +/"1 #: i. 2 ^ y- vectơ được i. 2 ^ ysắp xếp theo thứ tự của các mục của vectơ trước, câu trả lời của chúng tôi.

3

Python, 63 ký tự

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: Danh sách các hạn chế ngụ ý anh ta muốn có một kết quả chuỗi.
Keith Randall

Xin lỗi, đã bỏ lỡ điều đó.
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);}}}

hoặc một chút đẹp hơn được định dạng:

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

Những gì nó làm?

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

tính số cuối cùng để hiển thị (pow (2, n) - 1)

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

vòng lặp bên ngoài lặp lại qua số bit (vì vậy 0 đến n-1) trong khi vòng lặp bên trong chỉ đếm từ 0 đến m

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

Trên x86 có lệnh POPCNT có thể được sử dụng để đếm các bit đã đặt. GCC và trình biên dịch tương thích có thể hỗ trợ hàm __builtin_popcount về cơ bản biên dịch theo hướng dẫn đó.


2

CJam, 13 byte

2ri#,{2b1b}$p

Thực hiện khá thẳng về phía trước.

Cách thức hoạt động :

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

Dùng thử trực tuyến tại đây


2

Toán học, 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, Đã sửa! Cảm ơn!!!
Savenkov Alexey

1

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

Cách đơn giản nhất, chơi gôn

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

Ung dung

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

Kiểm tra trong bảng điều khiển Firefox / FireBug

F(4)

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


1

Bash + coreutils, 66

Một để giúp bạn bắt đầu:

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

Không có gì thực sự thú vị ở đây. Đưa ra nhận xét của bạn, tôi sẽ vui vẻ xóa / sửa lại câu trả lời này nếu bạn muốn thay đổi câu hỏi.
Chấn thương kỹ thuật số

Không chắc chắn nếu tôi nên làm nổi bật chương trình của bạn phải hoạt động cho tất cả các giá trị của n từ 0 đến 28. Tôi không biết có bao nhiêu câu trả lời ở đây vượt qua yêu cầu đó.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ 27/2/2015

Tôi đã loại bỏ điều khoản này, vì mọi người dường như không nhận thấy điều đó.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ 27/2/2015

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ Bây giờ, trên lý thuyết ít nhất nó sẽ hoạt động tới 28. Cho đến nay tôi đã thử nghiệm tới 22, nhưng tất nhiên điều này làm sortmất nhiều thời gian. Với n = 28, sortsẽ cần sắp xếp 2 ^ 28 dòng / ~ 13GB dữ liệu.
Chấn thương kỹ thuật số

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

Ví dụ sử dụng : f 4, mà đầu ra[0,1,2,4,8,3,5,9,6,10,12,7,11,13,14,15]

Cách thức hoạt động: không sắp xếp cũng không lặp lại nhiều lần [0..2 ^ n-1] và tìm kiếm các số có chứa i 1s.

Các #hàm trợ giúp có hai tham số abxây dựng một danh sách mọi số được tạo thành từ a1 và b0. Hàm chính fgọi #mọi kết hợp abtrong đó a+bbằng nhau n, bắt đầu bằng số 1 và n0 để có các số theo thứ tự. Nhờ sự lười biếng của Haskell, tất cả những danh sách đó không phải được xây dựng hoàn toàn trong bộ nhớ.


Không những ++trong a#bbình mà phía bên tay trái (mà có thể là lớn) cần phải được sản xuất hoàn toàn và sau đó sao chép trước mục đầu tiên trong kết quả được sản xuất, do đó vi phạm các yêu cầu đối với tiền thưởng?
Jules

À, không, nghĩ về việc nó vẫn có thể tạo ra chúng một cách lười biếng khi chúng được sản xuất, nó chỉ cần tạo một bản sao của từng mặt hàng, vì cả hai đều có thể là rác được thu thập trong quá trình xử lý có nghĩa là không gian sử dụng là không đổi. Phớt lờ tôi.
Jules

1

Ruby 47 ký tự

Rất giống với Python từ @KeithRandall:

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

1

Toán học, 26

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

Thí dụ:

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}

Đơn giản chỉ cần lặp đi lặp lại trong phạm vi [0..2^n-1] n + 1thời gian. Trong mỗi lần lặp chỉ in các số có số lượng 1 bit bằng với biến lặp ( $i). Các bit được tính bằng cách đếm 1's ( y/1//) trong số được chuyển đổi thành chuỗi nhị phân với sprintf.

Kiểm tra tôi .

Perl, 63

Cách tiếp cận sắp xếp:

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

1
@Optimizer, Nó sử dụng bộ nhớ O (1). Chúng ta có định nghĩa nào khác? Rất tiếc, điều đó không đúng khi tôi in trực tiếp :)
nutki 27/2/2015

@Optimizer, đã sửa.
nutki

Chà, tôi nhận thức được điều này khi tôi đặt điều kiện, nhưng dù sao tôi cũng cho phép, vì tôi muốn xem những câu trả lời phức tạp mà mọi người có thể đưa ra.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ 27/2/2015

2
Tôi chỉ hỏi "làm thế nào" vì tôi không thể đọc perl :) Bạn có muốn giải thích thêm không?
Trình tối ưu hóa

@Optimizer, thêm một số giải thích.
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 ký tự:

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

Ung dung:

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

Giải trình:

Tạo một tập hợp các cặp int, int. Số int đầu tiên là số bit, số thứ hai là số. Các cặp so sánh bản thân theo tham số đầu tiên của chúng, vì vậy tập hợp được sắp xếp theo số bit.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.