สลับลำดับบิตของจำนวนเต็ม 32 บิต


21

เขียนรหัสที่สั้นที่สุดเพื่อกลับลำดับบิตของจำนวนเต็ม 32 บิต

กฎ:

  1. การป้อนข้อมูลจะถือว่าเป็นจำนวนเต็มหรือสตริงที่ถูกต้องหากภาษาของคุณไม่รองรับค่าตัวเลข (เช่น Windows Batch)
  2. ผลลัพธ์จะต้องเป็นจำนวนเต็มหรือสตริงที่ถูกต้องหากภาษาของคุณไม่รองรับค่าตัวเลข (เช่น Windows Batch)
  3. ไลบรารีมาตรฐานเท่านั้น
  4. มันอาจจะเป็นฟังก์ชั่นหรือโปรแกรมที่สมบูรณ์
  5. อินพุตอาจมาจากstdinหรือเป็นอาร์กิวเมนต์ของฟังก์ชัน
  6. เอาต์พุตต้องเป็นอย่างใดอย่างหนึ่งstdoutหรือเป็นค่าที่ส่งคืน
  7. หากภาษาของคุณมีฟังก์ชันไลบรารีในตัวหรือมาตรฐานที่ทำสิ่งนี้ในขั้นตอนเดียว (เช่นrbitในชุดประกอบ ARM) จะไม่สามารถใช้งานได้

ตัวอย่าง:

สำคัญ:

  1. ทศนิยม
    • เลขฐานสอง
    • (ย้อนกลับ)
    • ย้อนกลับไบนารี
    • เอาต์พุตทศนิยม

ตัวอย่าง:

  1. -90 (ตัวอย่าง 8 บิตสำหรับการสาธิต)

    • 10100110b
    • (ย้อนกลับ)
    • 01100101b
    • 101
  2. 486

    • 00000000000000000000000111100110b
    • (ย้อนกลับ)
    • 01100111100000000000000000000000b
    • 1736441856
  3. -984802906

    • 11000101010011010001100110100110b
    • (ย้อนกลับ)
    • 01100101100110001011001010100011b
    • 1704506019

หมายเหตุ: การละเว้นเป็นเกมฟรี ถ้าฉันไม่ได้บอกว่ามันไม่ใช่ช่องโหว่มาตรฐานมันก็อนุญาตอย่างสมบูรณ์


"การละเว้น" ใน "การละเว้นเป็นเกมฟรี" หมายถึงอะไร
ทอดด์เลห์แมน

1
สิ่งใดก็ตามที่ไม่ได้ระบุไว้อย่างชัดเจนในกฎ
Isiah Meadows

ตารางแบบคงที่ 16gb จะถูกนับเป็นส่วนหนึ่งของความยาวของโปรแกรมหรือไม่
Licks ร้อน

@HotLicks ตามการตีความทั่วไปของโปรแกรมใช่
FUZxxl

ภาษาที่รองรับเฉพาะอินพุต 8 บิตเราสามารถรับอินพุตเป็นตัวเลข 8 บิตสี่ตัวได้หรือไม่
Sparr

คำตอบ:


0

ชุดประกอบ x86 ขนาด 9 ไบต์

    xor eax, eax
    inc eax
myloop:
    shr ecx, 1
    adc eax, eax
    jnc short myloop

ในรูปแบบไบต์: 33 C0 40 D1 E9 13 C0 73 FA, 9 ไบต์


นั่นเป็นอีกครั้งตราบใดที่โซลูชันของฉันหากคุณ (ก) เชื่อฟังแบบแผนการประชุมที่เรียกว่า cdecl และ (ข) กลับมาจากฟังก์ชันจริง
FUZxxl

@FUZxxl อย่างใดฉันไม่เห็นรุ่นของคุณ คุณถูกต้องครบถ้วน ฉันคิดและไม่ได้มี__fastcall ret
Myria

24

แอสเซมบลี MMIX (28 ไบต์)

หมายเลข 64 บิต

rbit:
    SETH $1,#0102 # load matrix in 16-byte steps
    ORMH $1,#0408
    ORML $1,#1020
    ORL  $1,#4080
    MOR  $0,$1,$0 # multiplication 1
    MOR  $0,$0,$1 # multiplication 2
    POP  1,0      # return

แอสเซมบลีนี้เพื่อ:

rbit:
    E0010102 # SETH $1,#0102
    E9010408 # ORMH $1,#0408
    EA011020 # ORML $1,#1020
    EB014080 # ORL  $1,#4080
    DC000100 # MOR  $0,$1,$0
    DC000001 # MOR  $0,$0,$1
    F8010000 # POP  1,0

มันทำงานยังไง?

MORคำแนะนำและดำเนินการคูณเมทริกซ์สองจำนวน 64 บิตใช้เป็นสอง 8x8 เมทริกซ์บูลี หมายเลขบูลีนที่มีดิจิต abcdefghklmnopqr 2ถูกใช้เป็นเมทริกซ์ดังนี้:

/ abcd \
| efgh |
| klmn |
\ opqr /

MORคำแนะนำคูณเมทริกซ์ที่แสดงโดยขัดแย้งของพวกเขาที่คูณและนอกจากเป็นand orมันคือ:

/ 0001 \      / abcd \      / opqr \
| 0010 |  \/  | efgh |  --  | klmn |
| 0100 |  /\  | klmn |  --  | efgh |
\ 1000 /      \ opqr /      \ abcd /

และนอกจากนี้:

/ opqr \      / 0001 \      / rqpo \
| klmn |  \/  | 0010 |  --  | nmlk |
| efgh |  /\  | 0100 |  --  | hgfe |
\ abcd /      \ 1000 /      \ dcba /

ซึ่งเป็นลำดับย้อนกลับของบิตของหมายเลขเดิม

ตัวเลข 32 บิต

หากคุณต้องการย้อนกลับของตัวเลข 32 บิตแทนหมายเลข 64 บิตคุณสามารถใช้วิธีการแก้ไขนี้:

rbit:
    SETL   $1,#0408 # load first matrix in two steps
    ORML   $1,#0102
    MOR    $1,$1,$0 # apply first matrix
    SLU    $2,$1,32 # compile second matrix
    16ADDU $1,$2,$1
    MOR    $1,$0,$1 # apply second matrix
    POP    1,0      # return

ประกอบ:

rbit:
    E3010408 # SETL   $1,#0408
    EA010102 # ORML   $1,#0102
    DC010001 # MOR    $1,$1,$0
    3B020120 # SLU    $2,$1,32
    2E010201 # 16ADDU $1,$2,$1
    DC010001 # MOR    $1,$0,$1
    F8010000 # POP    1,0

การคูณเมทริกซ์แรกนั้นใช้งานได้ดังนี้:

/ 0000 \      / 0000 \      / 0000 \
| 0000 |  \/  | 0000 |  --  | 0000 |
| 0001 |  /\  | abcd |  --  | efgh |
\ 0010 /      \ efgh /      \ abcd /

octabyte ที่สอดคล้องกันคือ#0000000001020408สิ่งที่เราโหลดในสองคำสั่งแรก การคูณครั้งที่สองมีลักษณะดังนี้:

/ 0000 \      / 0001 \      / 0000 \
| 0000 |  \/  | 0010 |  --  | 0000 |
| efgh |  /\  | 0100 |  --  | hgfe |
\ abcd /      \ 1000 /      \ dcba /

octabyte ที่เกี่ยวข้องคือ#0102040810204080สิ่งที่เราสร้างจากเมทริกซ์แรกเช่นนี้

SLU $2,$1,#32   # $2 = #0102040800000000
16ADDU $1,$2,$1 # $2 = $2 + $1 << 4
                     = $2 + #0000000010204080
                #    = #0102040810204080

การคูณที่สองคือธุรกิจตามปกติรหัสผลลัพธ์มีความยาวเท่ากัน (28 ไบต์)


1
นี่เป็นครั้งแรกที่ฉันได้ยินเกี่ยวกับคำสั่งการคูณเมทริกซ์บนซีพียู
phuclv

@ LưuVĩnhPhúc: ไม่คูณเมทริกซ์ แต่ VAX มีคำแนะนำในการประเมินพหุนาม
nneonneo

1
@nneonneo POLYคำสั่งของ VAX นั้นเป็นการหลอมรวมและเพิ่มแบบทวีคูณด้วยลูป builtin สิ่งที่คล้ายกันนั้นมีอยู่ในสถาปัตยกรรมสมัยใหม่ (เช่น x86) แต่โดยปกติแล้วพวกเขาจะไม่มีลูปในตัวเพื่อประเมินพหุนามทั้งหมดในครั้งเดียว
FUZxxl

12

ชุดประกอบ 80386 ( 13 12 ไบต์)

เป็นฟังก์ชั่นในไวยากรณ์ AT&T โดยใช้หลักการเรียก cdecl

    # reverse bits of a 32 bit word
    .text
    .globl rbit
    .type rbit,@function
rbit:
    push $32       # prepare loop counter
    pop %ecx
0:  shrl 4(%esp)   # shift lsb of argument into carry flag
    adc  %eax,%eax # shift carry flag into lsb
    loop 0b        # decrement %ecx and jump until ecx = 0
    ret            # return

ฟังก์ชันนี้ประกอบกับลำดับไบต์ต่อไปนี้:

6a 20 59 d1 6c 24 04 11 c0 e2 f8 c3

แบ่งออกเป็นคำแนะนำ:

6a 20       push $32
59          pop %ecx
d1 6c 24 04 shrl 0x4(%esp)
11 c0       adc  %eax,%eax
e2 f8       loop .-6
c3          ret    

มันใช้งานได้เช่นนี้: ในการวนซ้ำทั้ง 32 ครั้งของการวนรอบอาร์กิวเมนต์ซึ่งตั้งอยู่ที่4(%esp)จะเลื่อนไปทางขวาโดยตำแหน่งหนึ่ง บิตสุดท้ายถูกย้ายไปยังแฟล็กการดำเนินการโดยนัย adcการเรียนการสอนเพิ่มสองค่าและเพิ่มมูลค่าของธงดำเนินการเพื่อผล หากคุณเพิ่มมูลค่าให้กับตัวเองกล่าวคือ%eaxคุณเลื่อนไปทางซ้ายหนึ่งตำแหน่งได้อย่างมีประสิทธิภาพ นี่adc %eax,%eaxเป็นวิธีที่สะดวกในการกะซ้าย%eaxทีละตำแหน่งในขณะที่เลื่อนเนื้อหาของแฟล็กการพกพาไปยังบิตลำดับต่ำ

ฉันทำซ้ำขั้นตอนนี้ 32 ครั้งเพื่อให้เนื้อหาทั้งหมดของถูกโยนลงไปใน4(%esp) %eaxฉันไม่เคยเริ่มต้นอย่างชัดเจน%eaxเนื่องจากเนื้อหาก่อนหน้าถูกเลื่อนออกระหว่างลูป


+1 ขอบคุณสำหรับประโยคสุดท้ายของคุณตอนนี้เห็นได้ชัด แต่ฉันพลาดไป
edc65

1
ฉันยินดีเสมอที่จะเห็นการแก้ปัญหาการชุมนุมที่นี่ :)
1354557

8

C,    63    52   48

รุ่นเดิม:

int r(int n){int r=0,i=32;for(;i--;r=r<<1|n&1,n>>=1);return r;}

อัปเดตเวอร์ชัน (พร้อมการเปลี่ยนแปลงที่ดำเนินการโดยAllbeert , es1024และDennis ):

r(n){int r,i=32;for(;i--;r=r*2|n&1,n>>=1);return r;}

หมายเหตุ: เนื่องจากรุ่นที่สองไม่ได้ตั้งค่าr=0รหัสจะถือว่าintเป็น 32 บิต หากสมมติฐานนี้เป็นเท็จฟังก์ชันส่วนใหญ่จะสร้างผลลัพธ์ที่ไม่ถูกต้องขึ้นอยู่กับสถานะเริ่มต้นของrเมื่อเข้าสู่ฟังก์ชัน


รุ่นสุดท้าย (ด้วยการเปลี่ยนแปลงเพิ่มเติมที่แนะนำโดยDennisและAlchymist ):

r(n,r,i){for(;32-i++;r=r*2|n&1,n>>=1);return r;}

หมายเหตุ: สิ่งนี้ทำให้การประกาศของตัวแปรงานrและiลงในรายการพารามิเตอร์ พารามิเตอร์มีดังนี้: nเป็นตัวเลขที่จะกลับรายการบิต rและiเป็นตัวแปรงานที่ต้องส่งเป็น 0


1
คุณสามารถลบintประเภทฟังก์ชั่นและเปลี่ยนreturn rเป็นสิ่งที่ชอบi=rเนื่องจากคอมไพเลอร์ C ส่วนใหญ่มักจะออกจากผลการดำเนินงานล่าสุดในการลงทะเบียนกลับ มันทำงานบน gcc และ cl สำหรับฉัน
Allbeert

1
คุณสามารถโกนทิ้งได้อีก 4 ไบต์โดยใช้r(n){...}แทนr(int n){...}
es1024

2
@FUZxxl คุณไม่สามารถปล่อยintในint r=0,i=32;เว้นแต่ว่าคุณจะย้ายพวกเขาออกจากร่างกายฟังก์ชั่น
es1024

1
@FUZxxl: ไม่ควรแสดงความคิดเห็นเมื่อฉันเหนื่อย ... การคำนวณและการหารทางคณิตศาสตร์ไม่เท่ากัน รอบหลังไปสู่ศูนย์ในขณะที่รอบแรกไปทางลบอนันต์ -1 >> 1คือ-1สำหรับ AS และ2**31 - 1สำหรับ LS ในขณะที่เป็น-1 / 2 0
Dennis

1
@Todd: เหตุผลใด ๆ ที่คุณไม่ได้กำหนดrและใช้iเป็นข้อโต้แย้ง? จะช่วยประหยัดสามไบต์เพิ่มเติม ...
เดนนิส

5

Julia 0.2, 33 bytes

f(n)=parseint(reverse(bits(n)),2)

ทำในสิ่งที่ดูเหมือน

bitsให้คุณเป็นตัวแทนบิต (เคารพส่วนประกอบสองอย่าง) parseintไม่สนใจส่วนประกอบสองอย่าง แต่ส่งคืนจำนวนเต็ม 32 บิตดังนั้นส่วนประกอบทั้งสองนั้นได้รับการจัดการอย่างล้นหลาม

ตามการเปลี่ยนแปลงการตรวจจับล้นถูกเพิ่มparseintใน Julia 0.3 ดังนั้นสิ่งนี้อาจไม่ทำงานอีกต่อไป


5
นี่คือรหัสการผลิตไม่ใช่รหัส golfed! xD ฉันเดาว่า Julia ยอดเยี่ยมมาก
cjfaure

4

Python 2, 50

print int("{:032b}".format(input()%2**32)[::-1],2)

กว้างเหมือนกับโซลูชัน Pyth ของฉัน ใช้อินพุต mod 2 ** 32, แปลงเป็นไบนารี่แพทช์แบบ 32 บิต, ย้อนกลับ, แปลงไบนารีต่อยกลับเป็นทศนิยมและพิมพ์


4

CJam, 15 ไบต์

li4H#+2bW%32<2b

ลองออนไลน์

โจ๊กเกอร์ "เกมฟรี" ที่ใช้: ผลลัพธ์จะเป็นแบบไม่ได้ลงชื่อเสมอจำนวนเต็มแบบเสมอ

กรณีทดสอบ

$ cjam reverse32.cjam <<< 486; echo
1736441856
$ cjam reverse32.cjam <<< -984802906; echo
1704506019

มันทำงานอย่างไร

li   " Read from STDIN and cast to integer. ";
4H#+ " Add 4 ** 17 to avoid special cases. ";
2b   " Convert into array of digits in base 2. ";
W%   " Reverse the order. ";
32<  " Discard the 33th and all following digits. ";
2b   " Convert the array of digits into an integer. ";

4

JavaScript (E6) 37 39 40 50

ฟังก์ชั่นใส่หมายเลขและส่งกลับจำนวน อัลกอริทึมพื้นฐานส่วนใหญ่อาจจะสามารถเล่นกอล์ฟได้มากขึ้นด้วยเคล็ดลับที่ชาญฉลาด

แก้ไขการเรียกซ้ำแทนการวนซ้ำ

แก้ไข 2 กำลังติดตาม @bebe คำแนะนำk*2แทนk<<1

แก้ไข 3สิ่งที่ฉันพลาดไปทั้งหมด: มันเป็นวงเต็ม 32 บิตไม่จำเป็นต้องเริ่มต้น k ขอบคุณ @FUZxxl

R=(v,b=32,k)=>b?R(v>>1,b-1,k*2|v&1):k

มันเป็น

R=v=>{for(k=b=0;b++<32;)k+=k+(v&1),v>>=1;return k}

ทดสอบในคอนโซล FireFox ทดสอบการใช้ตัวเลขใน OP และตัวเลขสุ่ม 16 และ 32 บิต

Bin=x=>('0'.repeat(32)+(x<0?-x-1:x).toString(2)).slice(-32).replace(/./g,d=>x>0?d:1-d),
Dec=x=>(' '.repeat(11)+x).slice(-11),
R16=_=>Math.random()*65536|0,  
R32=_=>(Math.random()*65536<<16)|R16(),  
[-90,486,-984802906,R16(),R16(),R16(),R32(),R32(),R32(),R32()]
 .forEach(n=> console.log(Dec(n)+' '+Bin(n)+' '+Dec(R(n))+' '+Bin(R(n))))

ตัวอย่างผลการทดสอบ

        -90 11111111111111111111111110100110  1711276031 01100101111111111111111111111111
        486 00000000000000000000000111100110  1736441856 01100111100000000000000000000000
 -984802906 11000101010011010001100110100110  1704506019 01100101100110001011001010100011
      45877 00000000000000001011001100110101 -1395851264 10101100110011010000000000000000
      39710 00000000000000001001101100011110  2027487232 01111000110110010000000000000000
      56875 00000000000000001101111000101011  -730136576 11010100011110110000000000000000
-1617287331 10011111100110100010011101011101 -1159439879 10111010111001000101100111111001
-1046352169 11000001101000011110111011010111  -344488573 11101011011101111000010110000011
 1405005770 01010011101111101010111111001010  1408597450 01010011111101010111110111001010
  -35860252 11111101110111001101000011100100   655047615 00100111000010110011101110111111

b=k=0,R=v=>b++<32?R(v>>1,k+=k+(v&1)):kสำหรับการใช้งานเพียงครั้งเดียวและR=(v,b=0,k=0)=>b<32?R(v>>1,b+1,k+k+(v&1)):kสามารถนำมาใช้ซ้ำได้
bebe

@bebe :( ฉันกำลังแก้ไขคำตอบของฉันโดยใช้การเรียกซ้ำและสูญเสียทั้งหมดเพื่ออ่านความคิดเห็นของคุณ ...
edc65

2
คุณจะอยู่ที่ 38 ไบต์ถ้าk<<1กลายเป็นk*2และจะกลายเป็นv>>1 v/2มันใช้งานได้กับ 486 ฉันไม่รู้เกี่ยวกับกรณีทดสอบอื่น ๆ
bebe

1
@bebe v / 2 จะไม่ทำงานกับจำนวนลบ 486/512 == 0.9 ... และ 486 >> 9 == 0 ตัดให้เหมือนเดิม แต่ -90/128 == -0.7 ... และ -90 >> 7 == - 1
edc65

4

x86 assemply, 10 ไบต์

   f9                      stc    
   d1 d8            1:     rcr    %eax
   74 05                   je     2f
   d1 d2                   rcl    %edx
   f8                      clc    
   eb f7                   jmp    1b
                    2:

นี่ถือว่าอินพุตเป็น eax, เอาต์พุตใน edx (นอกจากนี้บนเอาต์พุต eax เป็นศูนย์และตั้งค่า CF และ ZF หากใครสนใจ)

แทนที่จะเป็นตัวนับจะมีการเพิ่ม 1 เข้าไปในจุดเริ่มต้นในฐานะจุดสิ้นสุดข้อมูล


นี่มีขนาดเท่าจริงกับโซลูชันของฉันซึ่งใหญ่กว่าสามไบต์ หากคุณเพิ่มretคำสั่งให้กลับมาจากฟังก์ชั่นและใช้ cdecl (เช่นเปลี่ยนrcr %eaxเป็นrcr 4(%esp)และrcl %edxเป็นrcl %eax) คุณจะต้องจบลงด้วยหนึ่งไบต์พิเศษสำหรับretหนึ่งและอีกสองไบต์สำหรับการอ้างอิงหน่วยความจำ ยังเป็นทางออกที่ดี
FUZxxl

3

J ( 17 15 13 ไบต์)

_32#.@|.@{.#:

นี่คือคำจำกัดความที่ชัดเจนเพื่ออธิบายสิ่งที่ทำ:

3 : '#. |. _32 {. #: y'
  1. #: yแสดงให้เห็นyว่าเป็นหมายเลขฐาน 2 โดยใช้หลายสถานที่เท่าที่จำเป็น
  2. x {. yใช้เวลา|x(ขนาดx) จากรายการจากyด้านหน้าถ้าxเป็นบวกจากด้านหลังหากxเป็นลบ หากเรานำสิ่งของมากกว่าที่เป็นปัจจุบันผลลัพธ์จะถูกเติมด้วยศูนย์ _32 {. #: yแผ่นได้อย่างมีประสิทธิภาพ#: yถึง 32 บิต
  3. |. yพลิกyฉัน yฝืนคำสั่งของรายการใน
  4. #. y ตีความ yว่าเป็นเลขฐาน 2


2

Python - 89

def r(n):
 if n<0:n=~n^0xFFFFFFFF
 print int(['','-'][n%2]+'{:032b}'.format(n)[::-1],2)

Python แสดงเลขฐานสองเชิงลบอย่างง่ายดาย -0b{positive_number}งูหลามหมายถึงเลขฐานสองเชิงลบเป็นเพียงแค่ดังนั้นในการจัดการกับสิ่งนี้เติมเต็มจำนวนลบแล้ว XOR กับ 1 ทั้งหมด

หลังจากนั้นสร้างการแสดงสตริงของจำนวนเต็มตามรูปแบบ {:032b}ที่ให้การแสดงตัวเลข 32 บิต ในที่สุดย้อนกลับสตริงและเปลี่ยนกลับเป็นจำนวนเต็ม

แก้ไข

ขอบคุณ@Martin Büttnerชี้ให้เห็นถึงปัญหาที่สมบูรณ์ของทั้งสอง ถ้าnสิ้นสุดใน 1 จากนั้นเติมสองโดยรุ่นที่ตรงกันข้ามจะเป็นเชิงลบ

โชคดีดังที่อธิบายไว้ข้างต้น Python ชอบเลขฐานสองเชิงลบในวิธีที่ค่อนข้างง่าย intฟังก์ชั่นPythonอนุญาตให้ใช้อักขระเครื่องหมายก็ได้ในอาร์กิวเมนต์แรก

ดังนั้นตอนนี้เพิ่มเครื่องหมายลบหากnแปลกเพื่อเติมเต็มสองส่วน


@ MartinBüttnerขอบคุณ ฉันพลาดโอกาสที่จะเป็นไปได้ในตอนแรก รหัสใหม่จะจัดการส่วนเติมเต็มของสองอย่างได้ดีขึ้น
BeetDemGuise

2
คุณสามารถกอล์ฟที่มากขึ้นอีกนิด: คือ['','-'][n%2] '-'*(n%2)
Justin

2

Pyth , 33 32 22

v_%"%032db0"vsc%Q^2 32

คำอธิบาย:

                 Q             Evaluated input.
                %Q^2 32        Q mod 2^32. Same 32 bit binary representation as Q.
             vsc%Q^2 32        Convert to binary string, then that to decimal int.
   %"%032db0"vsc%Q^2 32        Pad above number to 32 bits, and append b0.
  _%"%032db0"vsc%Q^2 32        Reverse it.
 v_%"%032db0"vsc%Q^2 32        Eval and print. Due to leading "0b", eval as binary.

โรงแรมพร้อมสนามกอล์ฟ:

33 -> 32: ย้ายเพิ่มไปก่อนย้อนกลับเพื่อบันทึกใบเสนอราคาปลายทาง

32 -> 22: ใช้ Q mod 2 ^ 32 แทนเครื่องจักรที่ซับซ้อน รวมทั้งสองสตริงเข้าด้วยกัน

กรณีทดสอบ:

$ cat rev_bits 
v_%"%032db0"vsc%Q^2 32

$ ./pyth.py rev_bits <<< -984802906
1704506019

$ ./pyth.py rev_bits <<< 486
1736441856

$ ./pyth.py rev_bits <<< 0
0

มันทำงานกับผลลัพธ์เป็นตัวเลขขนาดใหญ่ 32 มีบิตซ้ายสุดที่ 1 หรือไม่ ในกรณีนี้ควรส่งออกจำนวนเต็มลบ
edc65

@ edc65 ฉันกำลังส่งออกจำนวนเต็ม 32 บิตที่ไม่ได้ลงชื่อ
isaacg

2

GNU dc, 27 ไบต์

0?[2~rssr2*+dlsz34>m]dsmx+p

เอาท์พุท:

$ dc revbits.dc <<< 15
4026531840
$ dc revbits.dc <<< 255
4278190080
$ dc revbits.dc <<< 65535
4294901760
$ dc revbits.dc <<< 4294901760
65535
$ dc revbits.dc <<< 4278190080
255
$ dc revbits.dc <<< 4026531840
15
$ 

Bash + coreutils 45 ไบต์

n=`dc -e2do32^n$1p`
dc -e2i`rev<<<${n: -32}`p

เอาท์พุท:

$ ./revbits.sh 15
4026531840
$ ./revbits.sh 255
4278190080
$ ./revbits.sh 65535
4294901760
$ ./revbits.sh 4294901760
65535
$ ./revbits.sh 4278190080
255
$ ./revbits.sh 4026531840
15
$ 

ฟังก์ชัน C ขนาด 89 ไบต์

แนวคิดเช่นเดียวกับ/codegolf//a/36289/11259 - การใช้แฮ็กที่เป็นทวิปบิดสแตนฟอร์ดแฮ็ก ไม่ชนะกอล์ฟ แต่น่าสนใจ:

// 89 byte function:
i;r(v){for(i=1;i<32;i*=2)v=v>>i&(1L<<32)/((1<<i)+1)|(v&(1L<<32)/((1<<i)+1))<<i;return v;}

// Test program:
#include <stdio.h>

int main (int argc, char **argv)
{
    printf("r(0x0000000f) = 0x%08x\n", r(0x0000000f));
    printf("r(0x000000ff) = 0x%08x\n", r(0x000000ff));
    printf("r(0x0000ffff) = 0x%08x\n", r(0x0000ffff));
    printf("r(0xffffffff) = 0x%08x\n", r(0xffffffff));
    printf("r(0x0f0f0f0f) = 0x%08x\n", r(0x0f0f0f0f));
    printf("r(0xf0f0f0f0) = 0x%08x\n", r(0xf0f0f0f0));
}

เอาท์พุท:

$ ./revbits 
r(0x0000000f) = 0xf0000000
r(0x000000ff) = 0xff000000
r(0x0000ffff) = 0xffff0000
r(0xffffffff) = 0xffffffff
r(0x0f0f0f0f) = 0xf0f0f0f0
r(0xf0f0f0f0) = 0x0f0f0f0f
$

2

ฟังก์ชั่น Java, 64 ตัวอักษร

 int r(int n){int r=0,i=32;for(;i-->0;n>>=1)r=r<<1|n&1;return r;}

ควรทำงานในซี


2

PHP, 46 ไบต์

รุ่นออนไลน์

for(;$i<32;)$t.=$argn>>$i++&1;echo bindec($t);

หรือ

<?=bindec(strrev(sprintf("%064b",$argn<<32)));

substrไม่จำเป็น (-12 bytes) คุณควรพูดถึงวิธีการเรียกใช้พวกเขา
ติตัส

1
@Titus คุณลอง testcase แล้ว-984802906หรือยัง
JörgHülsermann

1
รุ่นที่สองของคุณสามารถปรับปรุงให้ตรงกับรุ่นแรก:<?=bindec(strrev(sprintf("%064b",$argn<<32)));
Christoph


1

JS 115

นั่นดูไม่ดีเลย: D

n=+prompt();alert(eval('0b'+(Array(33).join(0)+(n<0?n>>>0:n).toString(2)).slice(-32).split('').reverse().join('')))

วิธีการ @Florian F ใน JS มีความยาว 53 ไบต์:

for(n=+prompt(r=0),i=32;i--;n>>=1)r=r<<1|n&1;alert(r)

1
it may be a functionกฎหมายถึงคุณไม่จำเป็นต้องแจ้งเตือนหรือพรอมต์
slebetman

1

C # 81 74

int R(int V){int l,r=l=0,i=1;for(;i>0;i*=2)r|=i*(1&V>>(31-l++));return r;}

การทำงานของบิตซึ่งมักจะทำได้สั้นกว่าในทุกภาษาโปรแกรม

โดยทั่วไปวนรอบพลังทั้งหมด 2 ถึงจำนวนเต็มสูงสุด + 1 (ซึ่งกลายเป็นพลังของสอง) และตั้งแต่ (2,147,483,647 + 1) = 0 ฉันสามารถวนไปที่ 0 บิตกะซ้ายไปขวาเพื่อย้ายบิตเป็นครั้งแรก ตำแหน่ง. บิตสุดท้ายที่ตำแหน่ง 32 ไป 31 ขั้นตอนไปทางขวาวินาทีสุดท้ายไปที่ 30 เป็นต้นดังนั้นโดยใช้ตัวดำเนินการ AND กับ 1 ฉันจะรู้ว่ามันคือ 1 หรือ 0 ถ้าเป็น 1 ฉันจะเพิ่มค่า i ปัจจุบันลงในผลลัพธ์และ กลับมา

int R(int V)
{
    int l,r=l=0,i=1;
    for(;i>0;i*=2)
        r|=i*(1&(V>>(31-l++)));
    return r;
 }

สิ่งเล็ก ๆ แต่คุณสามารถเริ่มต้นได้iเมื่อคุณประกาศและบันทึก byte โดยการลบi++จาก for for loop และแทนที่จะเปรียบเทียบผลลัพธ์ที่1&...มี 0 คุณสามารถลบคำสั่ง if ทั้งหมดและคูณiด้วยผลลัพธ์ที่ให้r|=i*(1&(V>>(31-l++)));ภายในลูป
VisualMelon

ฉลาด! ฉันรู้สึกว่าฉันขาดอะไรไป ขอบคุณ!
WozzeC

1

C # 142

using System;using System.Linq;int f(int n){return Convert.ToInt32(new string(Convert.ToString(n,2).PadLeft(32,'0').Reverse().ToArray()),2);}

ขยาย

int f(int n)
{
    return Convert.ToInt32(
        new string(
            Convert.ToString(n, 2)
            .PadLeft(32, '0')
            .Reverse()
            .ToArray()), 2);
}


1

C ++, 160

นี่ไม่ใช่อันที่สั้นที่สุด แต่ใช้การดำเนินการเพียง 24 ครั้งเท่านั้น
นำมาจากหนังสือ Delight ของแฮกเกอร์

แข็งแรงเล่นกอล์ฟ:

typedef unsigned U;U R(U&x){U a=-1u/3,b=-1u/5,c=-1u/17,d=65280;x=(x&a)*2|(x/2)&a;x=(x&b)*4|(x/4)&b;x=(x&c)<<4|(x>>4)&c;x=(x<<24)|((x&d)<<8)|((x>>8)&d)|(x>>24);}

Ungolfed:

unsigned R(unsigned x) {
    x = (x & 0x55555555) <<  1 | (x >>  1) & 0x55555555; 
    x = (x & 0x33333333) <<  2 | (x >>  2) & 0x33333333; 
    x = (x & 0x0F0F0F0F) <<  4 | (x >>  4) & 0x0F0F0F0F; 
    x = (x << 24) | ((x & 0xFF00) << 8) | ((x >> 8) & 0xFF00) | (x >> 24); 
    return x; 
} 

1
นี่คือคำถามที่รหัสกอล์ฟ โปรดลองลดจำนวนอักขระในโซลูชันของคุณไม่ใช่จำนวนการใช้งาน
FUZxxl

1

Haskell, 145 - ไม่มีการใช้งานระดับบิต

การบิดเป็นเกลียวทำให้ฉันเป็นสิ่งที่ตรงกันข้ามของ Haskell ดังนั้นฉันจึงหลีกเลี่ยงการใช้ตัวดำเนินการระดับบิตใด ๆ โปรแกรมที่ได้นั้นไม่ใช่ผู้เข้าแข่งขันที่สั้นที่สุด แต่ฉันคิดว่าการใช้คณิตศาสตร์แทนการใช้ทวิตเตอร์เป็นเรื่องที่น่าสนใจอย่างน้อย

import Data.Tuple
import Data.List
f m=foldl1((+).(*2))$take 32$(unfoldr(\n->if n==0 then Nothing else Just$swap$divMod n 2)$mod m$2^32)++[0,0..]

คำอธิบาย

f m=foldl1((+).(*2))$take 32$(unfoldr(\n->if n==0 then Nothing else Just$swap$divMod n 2)$mod m$2^32)++[0,0..]
    |------5-------|---4----|--------------------------2---------------------------------|----1-----|---3----|
  1. ใช้ modulo เพื่อนำผลลัพธ์ไปสู่ช่วง 32- บิต
  2. สร้างรายการของ0และ1 s บิตที่มีนัยสำคัญน้อยที่สุดก่อนโดยการหารด้วย 2 ซ้ำ ๆ และนำส่วนที่เหลือ
  3. เชื่อมต่อรายการที่ไม่มีที่สิ้นสุดของ 0ท้าย s ไปยังจุดสิ้นสุดของรายการนี้
  4. คว้า 32 อิลิเมนต์แรกของรายการ (ทั้งสองจำเป็นต้องมีเพื่อให้แน่ใจว่ารายการนั้นยาว 32 บิตจริง ๆ )
  5. แปลงรายการ0และ1เป็นจำนวนเต็มสมมติว่าบิตที่สำคัญที่สุดคือก่อน (ซ้ำสองครั้งและเพิ่ม)

ฉันไม่แน่ใจว่าสิ่งใดที่ถือว่า "ไลบรารี่มาตรฐาน" ใน Haskell ดังนั้นฉันจึงสันนิษฐานว่า Data.Tuple และ Data.List ก็โอเค (มันค่อนข้างมาตรฐาน)

นอกจากนี้ผลลัพธ์ยังเป็นจำนวนเต็ม 32 บิตที่ไม่ได้ลงนามตั้งแต่การเปลี่ยนแปลงซึ่งจะทำให้ฉันต้องเสียค่าไบต์: ฉันเถียงเรื่องนี้ภายใต้ "การละเว้นเป็นเกมฟรี"


ห้องสมุดมาตรฐาน: สิ่งที่มาพร้อมกับภาษา ซึ่งรวมถึงส่วนหัวของระบบสำหรับ C คลาส 4000+ และวิธีการใน Java (ส่วนใหญ่ไม่เกี่ยวข้อง)
Isiah Meadows

1

PHP, 46 41 ไบต์

ลองพวกเขาออนไลน์

while($i<32)$r=$r*2|$argn>>$i++&1;echo$r;

bitwise ... มากกว่าหรือน้อยกว่า php -nR '<code>'ทำงานเป็นท่อด้วย

PHP, 46 ไบต์

while($i<32)$r|=($argn>>$i&1)<<31-$i++;echo$r;

วิธีแก้ปัญหา bitwise บริสุทธิ์ ทำงานเป็นท่อด้วย-nRใช้เป็นท่อด้วย

PHP, 47 59 ไบต์

<?=bindec(str_pad(strrev(substr(decbin($argn),-32)),32,0));

อีกวิธีในตัว; -Fบันทึกไปยังแฟ้มและใช้เป็นท่อด้วย


0

Perl - 60

$_=unpack"N",pack"B*",scalar reverse unpack"B32",pack"N",$_

+1 สำหรับธง p (แจ้งให้เราทราบหากฉันนับผิด)

ทำงานด้วย:

echo 486 | perl -pe'$_=unpack"N",pack"B32",scalar reverse unpack"B32",pack"N",$_'

0

C ++ 69

int r(int n){int e=0,i=0;for(;i<32;i++)e|=((n>>i)&1)<<31-i;return e;}

@bebe เหล่านี้e;i;คืออะไร? การประกาศที่ไม่มีชนิดไม่ใช่ C ++ ที่ถูกต้อง สำหรับตัวแปรมันไม่ถูกต้องแม้แต่ C.
Ruslan

@Ruslan ฉันไม่รู้จัก '++' ในชื่อขออภัย (ฉันจะไม่เห็นด้วยกับคำสั่งที่สองของคุณ)
bebe

int r(int n){int e=0,i=0;for(;i<32;)e=e*2|1&n>>i++;return e;}61 bytes :)
Christoph

0

R, 45

f=function(x)packBits(intToBits(x)[32:1],"i")

ตัวอย่าง:

f(486)
# [1] 1736441856
f(-984802906)
# [1] 1704506019

เพียงแค่ขี้อายกับคำตอบของ Python คำหลักฟังก์ชั่นนั่นแหละ


0

ทับทิม, 43 41 ไบต์

def r(n)(0..31).inject(0){|a,b|a*2+n[b]}end

ใน Ruby การใช้เครื่องหมายดัชนีวงเล็บ (foo [i]) จะส่งกลับบิตที่ตำแหน่งที่ n

--Edit--

การปรับเปลี่ยนการinjectทำงานของการโกนสองสามไบต์

def r(n)z=0;32.times{|i|z=z*2+n[i]};z;end


0

Perl5: 46

sub r{for(0..31){$a=$a*2|$_[0]&1;$_[0]>>=1}$a}

ไม่มีอะไรแฟนซี มันเลื่อนเอาต์พุตไปทางซ้ายคัดลอก lsb ก่อนที่จะเลื่อนแหล่งที่มาทางขวา



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