エンディアンネスを交換する


20

おそらくご存知のように、(バイトアドレス指定可能な)ハードウェアメモリは、リトルエンディアンビッグエンディアンの 2つのカテゴリに分類できます。リトルエンディアンのメモリでは、バイトは、小さい(最下位の)終わりで0から始まり、ビッグエンディアンでは逆に番号が付けられます。

おもしろい事実:これらの用語はジョナサン・スウィフトの本「ガリバー旅行記」に基づいており、そこではリリプーティアン王が市民に小さな端で卵を割るように命じた(したがって、リトルエンディアンは反逆者は大きな端で彼らの卵を割るだろう)。

スワップの仕組み

12648430次のように見えるビッグエンディアンのマシンで、メモリ内に符号なし整数(32ビット)があるとします。

  addr: 0  1  2  3
memory: 00 C0 FF EE

バイトオーダーを反転させ、私たちは、16進数の整数取得0xEEFFC000である4009738240小数では。

あなたのタスク

上記のように、10進数の符号なし32ビット整数を受け取り、エンディアンネスを交換するときに結果の整数を出力するプログラム/関数を作成します。

ルール

  • 入力は常に次の範囲に0なります4294967295
  • 出力は、STDOUTに出力するか(末尾の改行/スペースは問題ありません)、または返すことができます
  • 入力と出力は10進数です
  • 無効な入力の動作は未定義のままです

テストケース

0 -> 0
1 -> 16777216
42 -> 704643072
128 -> 2147483648
12648430 -> 4009738240
16885952 -> 3232235777
704643072 -> 42
3735928559 -> 4022250974
4009738240 -> 12648430
4026531839 -> 4294967279
4294967295 -> 4294967295

関数の回答の場合、「入力と出力は10進数である」とは、数字の文字列または数字の値の配列が必要なことを意味しますか?または、関数の回答は、ほとんどの場合、「10進数」とはまったく関係のない言語の自然な整数値表現を使用できますか?
アシェプラー

1
@aschepler言語の整数値。4210進数で指定されますが、技術的には、たとえばCではバイナリです。もちろん0x2a、を入力することもできますが、防止したいのは、入力を文字列などとして取得することです"2a"
ბიმო

関連(この課題では、最初に32ビットにパディングすることを確認しているため)
-FlipTack

回答:


25

x86_32機械語、3バイト

endian_swap:        # to be called with PASCAL REGISTER calling convention
0f c8    bswap eax
c3       ret

これはちょっとしたごまかしです。Pascalレジスタ呼び出し規則(Wikipediaを参照)は、_fastに少し似ていますが、eaxの最初のパラメーターを渡し、eaxには戻り値も含まれます。呼び出し先のクリーンアップでもありますが、リターンポインター以外にはスタックを使用しないため、何もする必要はありません。これにより、movまたはxchgを回避し、bswapを直接使用できます。


bswap80486以上が必要なことに注意してください:)
ceilingcat

@ceilingcat非常に正しいですが、コンパイラーまたはツールチェーンの制限により、ここにある他の多くのソリューションの場合は暗黙のうちにそうなると確信しています!
多項式

10

x86_64機械語Linux、5 4バイト

0:       0f cf                   bswap  %edi
2:       97                      xchg   %eax,%edi
3:       c3                      retq 

-1の@peter ferrieに感謝します。

オンラインでお試しください!


これは10進数の戻り値ではありません。私はそれが重要だとは思わない。さらに、edi、eaxを4バイトxchgできます。
ピーターフェリー

@peterferrieうわー、私はちょうどあなたのウェブサイトを閲覧してPEヘッダーについて読んでいました!
-ceilingcat


6

Japt10 14バイト

sG ùT8 ò w ¬nG

それを試してみてください


説明

入力整数を基数16の文字列に変換(sG)、0長さ8に開始をùT8埋める(ò)、2文字の文字列の配列に分割()、逆(w)、文字列に再結合()、基数に¬戻す10(nG)。


ご存知のように、便利な機能とは、yそのような関数をさらに用意し、関数に関数を与えたときに、通常の変換を適用し、関数を実行してから変換を逆にすることです。この場合sG_ò w ¬、8バイトに短縮できると思います。または、もしそうならò、それはsG_ò2_w7のためでさえあるかもしれません
...-ETHproductions

@ETHproductions私はそれをサポートしています。アンダー&.Jでの副詞は、これを実行し、それがゴルフで、時には本当に便利です。ただし、すべての反転をコーディングするのは退屈かもしれません。
コール

@ETHproductions:「オーバーロード」が多ければ多いほど良い:)パイントを引っ張りながらこれを書きましたがsG_òw...、もともと持っていましたが、私の人生ではなぜ機能しないのかわかりませんでした!私は最終的に自分の間違いに気付きました!
シャギー

2 << 24未満の入力では機能しないようです
ニール

ありがとう、@ Neil; 後で修正されます。4バイトかかるようです。
シャギー



5

APL + WIN 14バイト

256⊥⌽(4⍴256)⊤⎕

説明

⎕ prompt for screen input
(4⍴256)⊤ 4 byte representation in base 256
⌽ reverse bytes
256⊥ bytes from base 256 to integer

1
256⊥⌽⎕⊤⍨4⍴256-1バイトのために働きますか?
エリックアウトゴルファー

答えは何であるので⍨オペレータは、APL + WINでは使用できませんが、それはうまくDyalog APLのためにそうかもしれない
グラハム・

5

C#70 68バイト

これはおそらく最適ではありません。

68:

Func<uint,uint>f=n=>((n=n>>16|n<<16)&0xFF00FF00)>>8|(n&0xFF00FF)<<8;

70:

uint e(uint n){n=n>>16|n<<16;return(n&0xFF00FF00)>>8|(n&0xFF00FF)<<8;}

オンラインでお試しください!


割り当てをreturn式に移動してから、式に準拠したメンバー構文(uint e(uint n)=>((n=n>>16|n<<16)&0xFF00FF00)>>8|(n&0xFF00FF)<<8;64バイト)を使用できます。
hvd

@hvdそれは、私にとって有効な表現形式の構文としては表示されません。しかし、シフト再配置のトリックを使用して2バイトを削ることができました。
多項式

私のコメントからTIOリンクにコピーして貼り付け、タイプミスなどがないことを確認し、私のコメントに正確に
一致するようにします。TIO

0xFF00FF00は0xFF00FFの補数であることに気付き、それを利用できるかどうか疑問に思いますか?しかし、変数として宣言すると文字が多すぎます
-PrincePolka

ああ!確かに定数をチェックするグッド:あなたが使用することができます0xFF00FFによって2回>>前にINGの&INGの、そしてあなたが短縮できる0xFF00FFまで~0u/257uint e(uint n)=>((n=n>>16|n<<16)>>8&~0u/257)|(n&~0u/257)<<8;60のためのTIOリンク
HVD


4

05AB1E12 10バイト

3F₁‰R`})₁β

オンラインでお試しください!説明:

  ₁         Integer constant 256
   ‰        [Div, Mod]
    R       Reverse
     `      Flatten to stack
3F    }     Repeat 3 times
       )    Collect results
        ₁β  Convert from base 256

1
これは有効な解決策ではないようです。あなたが実際に長さ4にバイトのリストを繰り返しているん「パディング」
エリックOutgolfer

@EriktheOutgolfer Bah、ドキュメンテーションが実際にそれを言うことを望みます...-
ニール

3

JavaScript(ES6)、45 43バイト

f=(n,p=0,t=4)=>t?f(n>>>8,p*256+n%256,t-1):p

1
t=02バイトの保存から開始:f=(n,p=t=0)=>t++<4?f(n>>>8,p*256+n%256):p
Arnauld


3

MATL12 10バイト

7Y%1Z%P7Z%

オンラインでお試しください!または、すべてのテストケースを確認します

説明

        % Implicitly input a number, read as a double
7Y%     % Cast to uint32
1Z%     % Convert to uint8 without changing underlying data. The result is 
        % an array of four uint8 numbers, each corresponding to a byte of
        % the original number's representation 
P       % Flip array
7Z%     % Convert back to uint32 without changing underlying data. The array
        % of four uint8 numbers is interpreted as one uint32 number.
        % Implicitly display

2

JavaScript(ES6)、 51 45バイト

@Neilの助けを借りて6バイトを保存しました

n=>(n>>>24|n>>8&65280|(n&65280)<<8|n<<24)>>>0

テストケース


ニース、再帰で得られた最高のものはでしたf=(n,p=0,t=4)=>t?f(n/256|0,p*256+n%256,t-1):p
-ETHproductions

@ETHproductions ...それは短いですか?
エリックアウトゴルファー

1
@ETHproductionsそれは間違いなく短いです。投稿してください。
アーナルド

46バイト:n=>(n>>>24|n>>8&65280|n<<8&16711680|n<<24)>>>0
ニール

1
@hvd心配ありません。代替バージョンとして追加するか、既存のバージョンを完全に置き換えることができます。あなた次第!
アーナルド

2

J、16バイト

|.&.((4#256)#:])

オンラインでお試しください!

右側の式の短縮に取り組んでいます。ベータJバージョンでこの作業を行うことにより、数バイトを削減できると思います。新しいベータ版では名詞で列車を終わらせることができるとここで見たと誓います...

説明

|.&.((4#256)#:])
    ((4#256)#:])  Convert to 4 two-byte blocks
            #:      Debase to
      4#256         4 digits base 256
  &.              Apply right function, left function, then inverse of right
|.                Reverse digits

256を基数とする4桁に変換し、桁を逆にしてから、10進数に戻します。基本的に、OPで提供されるアルゴリズムを実行します。これはおそらく、Jの混合基底変換で桁数を指定する必要があるのに役立つのはおそらく1回ですが、電車を名詞で終わらせることができれば2バイト少なくなります((#:~4#256)代わりに)。


2

Excel VBA、103 92バイト

範囲からの入力[A1]を16進数に変換し、バイトを反転し、VBEイミディエイトウィンドウに出力する匿名VBEイミディエイトウィンドウ関数

h=[Right(Rept(0,8)&Dec2Hex(A1),8)]:For i=0To 3:s=s+Mid(h,7-2*i,2):Next:[B1]=s:?[Hex2Dec(B1)]

これをどこかでテストできますか?オンライン通訳を追加してもらえますか?
ბიმო

2
@BruceForteいいえ、残念ながらVBAのバリアントにはオンラインインタープリターがありませんが、コンピューターにExcelのコピーがある場合は、Alt + F11を押してVBEにアクセスし、次にCtrlを押してイミディエイトウィンドウにアクセスできます+ G.この無名関数のためにあなたがして、セルA1にあなたの入力を貼り付けますし、すぐに窓やプレスに上記のコードを入力してください
テイラー・スコット

ああ-と時々 VBAは、ビットファンキーである(とMac版はWindows版よりもimperically悪いです)このように、それ以外のすべての記載がない限り、VBAソリューションは、デフォルトの32ビットWindowsのバージョンと仮定
テイラー・スコット

2

PPCアセンブリ(32ビット)、8バイト

endian_swap:    # WORD endian_swap(WORD)
7c 60 1c 2c     LWBRX 3,0,3
4e 80 00 20     BLR

仕組み:

  • PPC呼び出し規則は、最初の32ビットワードパラメーターをSP + 24に入れ、そのアドレスをGPR3にシャドウします。
  • LWBRXは、ロードGPR3(第3オペランド)を取得し、EAにゼロ拡張(第2オペランド)し、逆の順序で4バイトを読み取り、GPR3(第1オペランド)に格納します。
  • GPR3は戻り値を保持します。
  • BLRは関数から戻ります(LRレジスタのアドレスに分岐します)

残念ながら、デモンストレーションできるオンラインPPCアセンブリエミュレータはありません。ごめんなさい!


2

Befunge、62 61または49バイト

0&0v!p22:/3g22/*:*82\+%*:*82+<
@.$_:28*:*%00p\28*:**00g28*:*^

オンラインでお試しください!

これは、リファレンスインタープリターで標準のBefungeを使用しているため、メモリセルが8ビットで署名されており、署名付きオーバーフローの可能性を修正しているという事実を考慮する必要があります。

符号なしメモリセル(PyFungeなど)を使用した実装、または範囲が8ビット(FBBIなど)より大きい実装では、これらのチェックを行わずに12バイトを節約できます。

0&0v!p22:/3g22/*:*82\+g<
@.$_:28*:*%00p\28*:**00^

オンラインでFBBIをお試しください!
PyFungeをオンラインでお試しください!

PyFungeには整数入力を処理するバグがあることに注意してください。そのため、TIOでテストする場合は、入力フィールドの数字の後にスペースまたは改行を入れる必要があります。


2

オクターブ、10バイト

@swapbytes

オンラインでお試しください!

Octaveがゴルフの派生物であるMATLとまったく同じスコアを持つのはこれが初めてかもしれません。もちろん、この場合、MATLではなくOctaveが組み込まれているため、はるかに簡単です。

組み込みのハンドルを定義しますswapbytes。これは、任意のデータ型を取り、エンディアンネスを交換し、結果を出力します。この場合、入力は32ビットの符号なし整数です。



2

R、86バイト

この質問に対するRの回答(または2つ)は既にあると思っていましたが、間違っているか、Rで署名されたintを実行していないのと同じ問題があったに違いありません。その問題は、助けになりそうなビルトインを排除しました。256ベースの変換を試してみましたが、最終的には長くなりましたが、私よりも賢い誰かがそれを行う余地があると思います。その後、次のようになりました。これは、再帰関数で順序を交換するベース2変換です。

f=function(x,y=0,i=31)'if'(i+1,f(x-(2^i*z),y+(2^((3-i%/%8)*8+i%%8)*(z=2^i<=x)),i-1),y)

オンラインでお試しください!

f=function(x,y=0,i=31)       # set up the function and initial values
  'if'(i+1,                  # test for i >= 0
    f(                       # recursively call the function
      x-(2^i*z),             # remove 2^i from x when 2^i <= x
      y+(2^                  # add to y 2 to the power of
        ((3-i%/%8)*8+i%%8)   # calc to swap the order of the bytes
        *(z=2^i<=x)),        # when 2^i <= x
      i-1),                  # decrement i
   y)                        # return y

基数256が短くなるのは正しかった
ジュゼッペ

@ジュゼッペ、あなたは帽子を1つ置くつもりです
-MickyT

2

R、41バイト

function(n)n%/%256^(0:3)%%256%*%256^(3:0)

オンラインでお試しください!

すべてのテストケースを検証してください!

MickyTがここで提案しように、ベース256変換を使用します。Rには、符号なし32ビット整数も、64ビット整数もありません。これにより、ビット単位の操作を使用できなくなりますが、Rのビット単位演算子は非常に冗長であるため、このアプローチ(およびMickyTの可能性が高い)はおそらくまだ短いでしょう。

このヒントの 4番目を利用します256^4

n%/%256^(0:3)%%256は、バイトを抽出します。%*%行列積は、この状況でのドット積で256^(3:0)あり、バイトの順序が逆になります。エンディアン反転値を含む%*%1x1 matrixを返します。


1

CP-1610アセンブリ、6 DECLE = 8バイト

このコードは、Intellivisionで実行することを目的としています。

CP-1610オペコードは、「DECLE」として知られる10ビット値でエンコードされます。この関数の長さは6 DECLEで、480ドルから4811ドルで終わります。

CP-1610には16ビットのレジスタがあるため、そのうち2つ(R0とR1)を使用して32ビット値を格納しています。

                               ROMW  10           ; use 10-bit ROM

                               ORG   $4800        ; start program at address $4800

                               ;; example call
4800  0001                     SDBD               ; load 0xDEAD into R0
4801  02B8 00AD 00DE           MVII  #$DEAD, R0
4804  0001                     SDBD               ; load 0xBEEF into R1
4805  02B9 00EF 00BE           MVII  #$BEEF, R1

4808  0004 0148 000C           CALL  swap32       ; call our function

480B  0017                     DECR  PC           ; loop forever

                               ;; swap32 function
                       swap32  PROC

480C  0040                     SWAP  R0           ; 16-bit SWAP of R0
480D  0041                     SWAP  R1           ; 16-bit SWAP of R1

480E  01C1                     XORR  R0, R1       ; exchange R0 and R1
480F  01C8                     XORR  R1, R0       ; using 3 consecutive eXclusive OR
4810  01C1                     XORR  R0, R1

4811  00AF                     JR    R5           ; return

                               ENDP

実行ダンプ

 R0   R1   R2   R3   R4   R5   R6   R7    CPU flags  instruction
 ------------------------------------------------------------------
 0000 4800 0000 0000 01FE 1041 02F1 4800  ------iq   SDBD
 0000 4800 0000 0000 01FE 1041 02F1 4801  -----D-q   MVII #$DEAD,R0
 DEAD 4800 0000 0000 01FE 1041 02F1 4804  ------iq   SDBD
 DEAD 4800 0000 0000 01FE 1041 02F1 4805  -----D-q   MVII #$BEEF,R1
[DEAD BEEF]0000 0000 01FE 1041 02F1 4808  ------iq   JSR  R5,$480C

 DEAD BEEF 0000 0000 01FE 480B 02F1 480C  ------iq   SWAP R0
 ADDE BEEF 0000 0000 01FE 480B 02F1 480D  S------q   SWAP R1
 ADDE EFBE 0000 0000 01FE 480B 02F1 480E  S------q   XORR R0,R1
 ADDE 4260 0000 0000 01FE 480B 02F1 480F  ------iq   XORR R1,R0
 EFBE 4260 0000 0000 01FE 480B 02F1 4810  S-----iq   XORR R0,R1
[EFBE ADDE]0000 0000 01FE 480B 02F1 4811  S-----iq   MOVR R5,R7

 EFBE ADDE 0000 0000 01FE 480B 02F1 480B  ------iq   DECR R7

なぜこれは7.5バイトなのですか?8バイトにする必要があると思います。
エリックアウトゴルファー

@EriktheOutgolferまあまあ。それに応じて更新。
アーナウド

@EriktheOutgolfer 60ビットは7.5バイトに等しいので?
ジェッペスティグニールセン

@JeppeStigNielsenそれは本当ですが、ファイルの長さは7.5バイトになることはありません。0で事前または事後パディングされます。
エリックアウトゴルファー

@EriktheOutgolfer技術的には、これは実際に10ビットROM内に保存できますここでは例のスペックシートです。(今日、Intellivision自作ゲーム用に16ビットROMを使用していますが、当時はメモリチップが非常に高価であったため、10ビットを使用することは本当の節約になりました。)
Arnauld

1

C#(.NET Core)、72 + 31 = 103バイト

m=>BitConverter.ToUInt32(BitConverter.GetBytes(m).Reverse().ToArray(),0)

オンラインでお試しください!

+31 using System;using System.Linq;

私は使用したいと思っていました Array.Reverseインラインいましたが、ことはできませんでした(以下の代替案を参照)。

C#(.NET Core)、87 + 13 = 100バイト

m=>{var a=BitConverter.GetBytes(m);Array.Reverse(a);return BitConverter.ToUInt32(a,0);}

オンラインでお試しください!

+13 using System;

@JeppeStigNielsenのこのソリューションケア。インラインですべてを3バイト節約するという制限を取り除きました。


節約できるのでusing System.Linq;、使用する方が安くなりますx=>{var a=BitConverter.GetBytes(x);Array.Reverse(a);return BitConverter.ToUInt32(a,0);}
ジェッペスティグニールセン

1

REXX、42バイト

say c2d(left(reverse(d2c(arg(1))),4,'0'x))

オンラインでお試しください!

ゴルフをしていない:

n=arg(1) -- take n as argument
n=d2c(n) -- convert from decimal to character (bytes)
n=reverse(n) -- reverse characters
n=left(n,4,'0'x) -- extend to four bytes, padding with zeros
n=c2d(n) -- convert from bytes to decimal again
say n -- output result


1

ARMマシン言語Linux、8バイト

0:       e6bf0f30       rev     r0, r0
4:       e12fff1e       bx      lr

これを自分で試すには、GNUrootを実行しているRaspberry PiまたはAndroidデバイスで以下をコンパイルして実行します

#include<stdio.h>
#define f(x) ((unsigned int(*)(unsigned int))"0\xf\xbf\xe6\x1e\xff/\xe1")(x)
int main(){
  printf( "%u %u\n", 0, f(0) );
  printf( "%u %u\n", 1, f(1) );
  printf( "%u %u\n", 42, f(42) );
  printf( "%u %u\n", 128, f(128) );
  printf( "%u %u\n", 16885952, f(16885952) );
  printf( "%u %u\n", 704643072, f(704643072) );
  printf( "%u %u\n", 3735928559U, f(3735928559U) );
  printf( "%u %u\n", 4009738240U, f(4009738240U) );
  printf( "%u %u\n", 4026531839U, f(4026531839U) );
  printf( "%u %u\n", 4294967295U, f(4294967295U) );
}



1

K4、18バイト

溶液:

0b/:,/8#|12 8#0b\:

例:

q)\
  0b/:,/8#|12 8#0b\:0
0
  0b/:,/8#|12 8#0b\:1
16777216
  0b/:,/8#|12 8#0b\:42
704643072
  0b/:,/8#|12 8#0b\:4294967295
4294967295
  0b/:,/8#|12 8#0b\:4026531839
4294967279

説明:

符号なしintはないため、入力はlongになります。

ブール配列(64ビット)に変換し、形状を変更し、反転し、最初の8バイトを取得し、長整数に戻します。

0b/:,/8#|12 8#0b\: / the solution
              0b\: / convert to bits
         12 8#     / reshape into 12x8 grid (wraps)
        |          / reverse
      8#           / take first 8
    ,/             / flatten
0b/:               / convert to long

ボーナス:

オンラインで試すことができるoKの19バイトバージョン

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