จาก 0 ถึง 2 ^ n - 1 ตามลำดับ POPCORN


18

... อ่าขอโทษที่ไม่มีข้าวโพดคั่วที่นี่แค่ POPCNT

เขียนโปรแกรมหรือฟังก์ชั่นที่สั้นที่สุดซึ่งรับจำนวนnแล้วเอาท์พุทจำนวนเต็มทั้งหมดจาก 0 ถึง 2 n - 1 ตามลำดับจากน้อยไปหามากของ 1 บิตในการแทนเลขฐานสองของตัวเลข (popcount) ไม่อนุญาตให้ทำซ้ำ

ลำดับของตัวเลขที่มี popcount เดียวกันนั้นถูกกำหนดตามการนำไปใช้งาน

ตัวอย่างเช่นสำหรับ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 

รูปแบบอินพุตและเอาต์พุตถูกกำหนดโดยการนำไปปฏิบัติเพื่ออนุญาตให้ใช้คุณลักษณะภาษาเพื่อเขียนโค้ดเพิ่มเติม มีข้อ จำกัด บางประการเกี่ยวกับผลลัพธ์:

  • ตัวเลขจะต้องส่งออกในรูปแบบทศนิยม
  • เอาต์พุตต้องมีตัวคั่นที่เหมาะสมระหว่างตัวเลข (ตัวคั่นต่อท้ายอนุญาต แต่ไม่นำหน้า)

    อาหารเส้น ( \n) แท็บ ( \t), พื้นที่, ,, ., ;, |, -, _, /มีคั่นค่อนข้างเหมาะสม ฉันไม่สนใจช่องว่างเพิ่มเติมสำหรับการพิมพ์ที่สวย แต่ไม่ได้ใช้ตัวอักษรหรือตัวเลขเป็นตัวคั่น

  • ตัวเลขและตัวคั่นสามารถถูกล้อมรอบด้วย[ ], { }หรืออาร์เรย์หรือรายการสัญกรณ์ใด ๆ
  • อย่าพิมพ์สิ่งอื่นที่ไม่ได้ระบุไว้ข้างต้น

โบนัส

ทวีคูณคะแนนของคุณ0.5หากวิธีการแก้ปัญหาของคุณสามารถสร้างตัวเลขได้ทันที จิตวิญญาณของโบนัสนี้คือถ้าคุณต้องแปลงโซลูชันการพิมพ์ของคุณไปยังเครื่องกำเนิดโดยตรงตัวสร้างจะใช้หน่วยความจำ O (n) เกือบทุกตัวโดยที่ n คือจำนวนบิตตามที่กำหนดไว้ด้านบน (คุณไม่จำเป็นต้องแปลงโซลูชันเป็นตัวสร้าง) โปรดทราบว่าในขณะที่ฉันกำหนดให้ n <= 28 หน่วยความจำที่จำเป็นในการจัดเก็บตัวเลขทั้งหมดยังคงเพิ่มขึ้นแบบทวีคูณและโซลูชันการเรียงลำดับแบบไร้เดียงสาจะทำให้หน่วยความจำอย่างน้อย 4 GB ที่ n = 28

โปรดเพิ่มคำอธิบายง่ายๆว่าโซลูชันของคุณทำงานอย่างไรก่อนรับโบนัสนี้


4
ดูเหมือนว่าความท้าทายในขณะที่มันน่าเบื่อมากและจะส่งผลให้คำตอบเรียงลำดับ ฉันต้องการเพิ่มโบนัสบางอย่างเพื่อให้ความท้าทายน่าสนใจยิ่งขึ้น บางสิ่งบางอย่างตามสายของ "การสร้างตัวเลขได้ทันที" หากคุณตกลงกับมันได้โปรดโหวตความคิดเห็นนี้จากนั้นฉันจะเพิ่มในคำถาม
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

หากคุณไม่เห็นด้วยโปรดโหวตความคิดเห็นนี้
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

โปรดใช้แซนด์บ็อกซ์เพื่อขอคำแนะนำเพิ่มเติมเกี่ยวกับคำถามก่อนโพสต์สด
John Dvorak

21
@JanDvorak: มันอยู่บน sandbox เป็นเวลาหนึ่งเดือน
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เราก็เอา แต่ทั้งหมดnบิตกับ&Nที่N=2**n-1และที่ให้มีขนาดเล็กที่สุดจำนวนหนึ่ง popcount ต่ำ ด้วยวิธีนี้เราทำได้แค่วงเดียว อาจเป็นทางออกที่ดีกว่าที่จะค้นหาจำนวนที่ต่ำกว่าถัดไปด้วย POPCOUNT โดยตรง

เนื่องจากปัญหาเสารั้วเราต้องเริ่มต้นด้วย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

ไม่จำเป็นสำหรับหมายเลขที่มี popcount เดียวกันจะเพิ่มขึ้น คำสั่งนั้นถูกกำหนดให้นำไปปฏิบัติ
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

1
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ ฉันรู้แล้ว แต่ฉันไม่เห็นวิธีบันทึกตัวละครที่ทำมันแตกต่างกัน
xnor

ด้วยวิธีการที่ไร้เดียงสา 3 ลูปฉันได้คะแนนเกือบเท่ากันใน JS (มีconsole.log()vs print) บางทีเคล็ดลับเล็กน้อยนั้นหนักเกินไป
edc65

ประหยัดหนึ่งไบต์:v=N-~N
Sp3000

5

J, 19 ตัวอักษรไม่มีโบนัส

[:(/:+/"1@#:)@i.2^]
  • 2 ^ y- yสองถึงอำนาจของ
  • i. 2 ^ y- จำนวนเต็มจากไป0(2 ^ y) - 1
  • #: i. 2 ^ y - จำนวนเต็มเหล่านี้แต่ละตัวแสดงอยู่ในฐานสอง
  • +/"1 #: i. 2 ^ y - ผลรวมของการเป็นตัวแทนแต่ละครั้ง
  • (i. 2 ^ y) /: +/"1 #: i. 2 ^ y- เวกเตอร์i. 2 ^ yเรียงลำดับตามรายการของเวกเตอร์ก่อนหน้าคำตอบของเรา

3

Python 63 ตัวอักษร

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: รายการข้อ จำกัด ที่บอกเป็นนัยว่าเขาต้องการผลลัพธ์สตริง
Keith Randall

ขออภัยที่พลาด
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;}

แก้ไข: 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 Alexey

1

JavaScript (ES6) 41 (82 * 0.5)

วิธีที่ง่ายที่สุด golfed

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

F(4)

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


1

Bash + coreutils, 66

หนึ่งเพื่อให้คุณเริ่มต้น:

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

ไม่มีอะไรน่าตื่นเต้นจริงๆที่นี่ ให้ความคิดเห็นของคุณฉันจะลบ / แก้ไขคำตอบนี้อย่างมีความสุขหากคุณต้องการเปลี่ยนคำถาม
Digital Trauma

ไม่แน่ใจว่าฉันควรเน้นโปรแกรมของคุณจะต้องทำงานสำหรับค่าทั้งหมดของ n จาก 0 ถึง 28 รวม ฉันไม่ทราบว่าคำตอบจำนวนมากผ่านที่นี่ผ่านข้อกำหนดที่
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

ฉันลบประโยคเนื่องจากคนดูเหมือนจะไม่สังเกตเห็น
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ ทีนี้ในทางทฤษฎีแล้วอย่างน้อยมันควรทำงานได้ถึง 28. ฉันได้ทดสอบจนถึง 22 แต่แน่นอนว่ามันsortใช้เวลานาน ด้วย n = 28 sortจะต้องเรียงลำดับข้อมูล 2 ^ 28 เส้น / ~ 13GB
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)]

ตัวอย่างการใช้งาน: f 4ซึ่งเป็นเอาต์พุต[0,1,2,4,8,3,5,9,6,10,12,7,11,13,14,15]

มันทำงานอย่างไร: ไม่ต้องเรียงหรือซ้ำซ้ำ [0..2 ^ n-1] และค้นหาตัวเลขที่มี i 1s

#ฟังก์ชั่นผู้ช่วยที่จะใช้เวลาสองพารามิเตอร์aและbและสร้างรายชื่อของทุกจำนวนที่สร้างขึ้นจากa1s และb0s ฟังก์ชั่นหลักfเรียกร้อง#ให้ทุกการรวมกันของaและbที่a+bเท่ากับnเริ่มต้นด้วย no 1s และn0s ที่จะมีตัวเลขตามลำดับ ด้วยความเกียจคร้านของ Haskell รายการทั้งหมดเหล่านี้ไม่จำเป็นต้องถูกสร้างขึ้นอย่างสมบูรณ์ในความทรงจำ


จึงไม่++อยู่ในa#bค่าเฉลี่ยที่ด้านซ้ายมือ (ซึ่งอาจจะเป็นขนาดใหญ่) จะต้องมีการผลิตทั้งหมดและจากนั้นคัดลอกก่อนที่รายการแรกในผลที่ได้คือการผลิตจึงละเมิดข้อกำหนดสำหรับโบนัสหรือไม่
Jules

อาไม่คิดว่ามันยังสามารถสร้างพวกเขาอย่างเกียจคร้านในขณะที่พวกเขากำลังผลิตมันก็ต้องทำสำเนาของแต่ละรายการซึ่งทั้งสองสามารถเก็บขยะในระหว่างการประมวลผลหมายความว่าการใช้พื้นที่คงที่ ไม่สนใจฉัน
Jules



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เวลา ในแต่ละการวนซ้ำพิมพ์เฉพาะตัวเลขที่มีจำนวน 1 บิตเท่ากับตัวแปรการทำซ้ำ ( $i) บิตถูกนับโดยการนับ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;}

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

คำอธิบาย:

สร้างชุดของคู่ int, int int แรกคือการนับบิตหนึ่งที่สองคือจำนวน คู่เปรียบเทียบตัวเองตามพารามิเตอร์แรกของพวกเขาดังนั้นชุดจะเรียงลำดับตามจำนวนบิต

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.