Swap the Endianness

As most of you probably know, (byte-addressable) hardware memories can be divided into two categories - little-endian and big-endian. In little-endian memories the bytes are numbered starting with 0 at the little (least significant) end and in big-endian ones the other way round.

Fun fact: These terms are based on Jonathan Swift's book Gulliver's Travels where the Lilliputian king ordered his citizens to break their eggs on the little end (thus the little-endians) and the rebels would break theirs on the big end.

How swapping works

Suppose we have an unsigned integer (32bit) 12648430 in memory, in a big-endian machine that might look as follows:

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


By inverting the byte-order we get the hexadecimal integer 0xEEFFC000 which is 4009738240 in decimal.

Write a program/function that receives an unsigned 32bit integer in decimal and outputs the resulting integer when swapping the endianness as described above.

Rules

• Input will always be in the range 0 to 4294967295
• Output can be printed to STDOUT (trailing newlines/spaces are fine) or returned
• Input and output are in decimal
• Behavior on invalid input is left undefined

Test cases

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

• For a function answer, does "input and output are in decimal" mean either a string of digit characters or array of digit values is required? Or can a function answer use its language's natural integer value representation, which in most cases has absolutely nothing to do with "decimal"? – aschepler Nov 25 '17 at 18:40
• @aschepler The language's integer value, eg. 42 is given in decimal but technically it's in binary in C for example. You can of course type 0x2a, what I wanted to prevent is taking input as a string like "2a" or the like. – ბიმო Nov 25 '17 at 19:19
• Related (as this challenge is just making sure to pad to 32 bits first) – FlipTack Nov 26 '17 at 13:48

x86_32 machine language, 3 bytes

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


This is a bit of a cheat. The Pascal register calling convention (see Wikipedia) is a bit like __fastcall, except it passes the first parameter in eax, and eax also contains the return value. It's also callee-cleanup, but since we don't use the stack for anything other than the return pointer we don't need to do anything. This allows us to avoid a mov or xchg and just use bswap directly.

• May want to note that bswap requires an 80486 or higher :) – ceilingcat Nov 29 '17 at 15:59
• @ceilingcat Very true, although I'm sure that's implicitly the case for many other solutions here due to compiler or toolchain restrictions! – Polynomial Nov 30 '17 at 13:53

x86_64 machine language Linux, 5 4 bytes

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


Thanks to @peter ferrie for -1.

Try it online!

• that's not a decimal return value. I don't think that counts. Besides, you could xchg edi,eax for 4 bytes. – peter ferrie Nov 25 '17 at 18:27

C (gcc) , 20, 29 17 bytes

@hvd's suggestion.

__builtin_bswap32


Try it online!

#include<byteswap.h>
bswap_32


include should be import.

Japt, 10 14 bytes

sG ùT8 ò w ¬nG


Try it

Explanation

Convert input integer to a base-16 string (sG), use 0 to pad the start to length 8 (ùT8), split to an array of 2 character strings (ò), reverse (w), rejoin to a string (¬) and convert back to base-10 (nG).

• You know, what might be a handy feature is to have more functions like y that, when given a function a function, apply their normal transformation, run the function, and then invert the transformation. In this case I think that would allow it to be shortened to sG_ò w ¬ for 8 bytes. Or if ò did that too, it could even be sG_ò2_w for 7... – ETHproductions Nov 25 '17 at 18:23
• @ETHproductions I support it; the under-&. adverb in J does this and it's sometimes really helpful in golfing. Coding in all the inversions might be tedious, though. – cole Nov 25 '17 at 18:36
• @ETHproductions: the more "overloading", the better :) I wrote this up while pulling pints and originally had sG_òw..., could not, for the life of me, figure out why it wouldn't work! I realised my mistake(s) eventually! – Shaggy Nov 25 '17 at 23:10
• Doesn't seem to work for input less than 2<<24... – Neil Nov 26 '17 at 14:18
• Thanks, @Neil; will get that fixed later on. Looks like it'll cost me 4 bytes. – Shaggy Nov 26 '17 at 14:26

Jelly, 10 bytes

⁴4*+b⁹ḊṚḅ⁹


Try it online!

• Alternative 10 bytes I can find: d⁹²¤d⁹FUḅ⁹ – user202729 Nov 26 '17 at 3:10

Python 2, 44 bytes

f=lambda x,i=3:x and(x%256)<<8*i|f(x>>8,i-1)


Try it online!

• You can save a byte recursing with i*8 rather than i, starting from i=24. – xnor Nov 25 '17 at 20:01
• And the parens around the x%256 aren't necessary. – xnor Nov 25 '17 at 20:08

APL+WIN 14 bytes

256⊥⌽(4⍴256)⊤⎕


Explanation

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

• Would 256⊥⌽⎕⊤⍨4⍴256 work for -1 byte? – Erik the Outgolfer Nov 25 '17 at 18:16
• The ⍨ operator is not available in APL+WIN so the answer is no but it could well be yes for Dyalog APL – Graham Nov 25 '17 at 18:33

C#, 70 68 bytes

This is probably not optimal.

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

Try it online!

• You can move the assignment into the return expression and then use expression-bodied member syntax: uint e(uint n)=>((n=n>>16|n<<16)&0xFF00FF00)>>8|(n&0xFF00FF)<<8; for 64 bytes. – hvd Nov 26 '17 at 12:01
• @hvd That's not showing as valid expression-bodied syntax for me. I was however able to use the shift rearrangement trick to shave 2 bytes off. – Polynomial Nov 26 '17 at 13:20
• I copied and pasted from my comment into your TIO link to make sure there were no typos or anything like that and exactly the way it is in my comment, it works: TIO link – hvd Nov 26 '17 at 15:46
• I noticed 0xFF00FF00 is the complement of 0xFF00FF and wonder if you can take advantage of that? But declaring it a variable takes too many characters – PrincePolka Nov 26 '17 at 21:08
• Oh! Good to check the constants indeed: you can use 0xFF00FF twice by >>ing before &ing, and you can then shorten 0xFF00FF to ~0u/257: uint e(uint n)=>((n=n>>16|n<<16)>>8&~0u/257)|(n&~0u/257)<<8; for 60. TIO link – hvd Nov 26 '17 at 22:07

Wolfram Language (Mathematica), 24 bytes

IntegerReverse[#,256,4]&


Try it online!

Reverses the input interpreted as an integer in base 256 with 4 digits.

05AB1E, 12 10 bytes

3F₁‰R})₁β


Try it online! Explanation:

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

• This doesn't seem to be a valid solution. The "padding" you do is actually repeating the list of bytes to length 4. – Erik the Outgolfer Nov 25 '17 at 17:44
• @EriktheOutgolfer Bah, I wish the documentation would actually say that... – Neil Nov 25 '17 at 17:47

JavaScript (ES6), 45 43 bytes

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

• Starting with t=0 saves 2 bytes: f=(n,p=t=0)=>t++<4?f(n>>>8,p*256+n%256):p – Arnauld Nov 25 '17 at 22:31

05AB1E, 9 bytes

žJ+₁в¦R₁β


Try it online!

-1 thanks to Neil.

MATL, 12 10 bytes

7Y%1Z%P7Z%


Explanation

        % 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


JavaScript (ES6), 51 45 bytes

Saved 6 bytes with @Neil's help

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


Test cases

let f=

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

console.log(f(0         )) // -> 0
console.log(f(1         )) // -> 16777216
console.log(f(42        )) // -> 704643072
console.log(f(128       )) // -> 2147483648
console.log(f(16885952  )) // -> 3232235777
console.log(f(704643072 )) // -> 42
console.log(f(3735928559)) // -> 4022250974
console.log(f(4009738240)) // -> 12648430
console.log(f(4026531839)) // -> 4294967279
console.log(f(4294967295)) // -> 4294967295

• Nice, best I could get with recursion was f=(n,p=0,t=4)=>t?f(n/256|0,p*256+n%256,t-1):p. – ETHproductions Nov 25 '17 at 17:56
• @ETHproductions ...that's shorter? – Erik the Outgolfer Nov 25 '17 at 17:57
• @ETHproductions That's definitely shorter. You should post it. – Arnauld Nov 25 '17 at 18:00
• 46 bytes: n=>(n>>>24|n>>8&65280|n<<8&16711680|n<<24)>>>0 – Neil Nov 25 '17 at 18:02
• @hvd No worries. You can either add it as an alternate version or replace the existing one entirely. Up to you! – Arnauld Nov 27 '17 at 21:59

J, 16 bytes

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


Try it online!

Working on shortening the right-hand expression. I think I can shave off a few bytes by making this work with a beta J version. I swear I saw on here that you can end a train with a noun in a new beta version...

Explanation

|.&.((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


Convert to 4 digits base 256, reverse the digits, then convert back to decimal. Basically, perform the algorithm that is provided in the OP. This is perhaps the one time where it's helpful that J's mixed base conversion requires you to specify the number of digits, although it would be 2 fewer bytes if I could end the train in a noun ((#:~4#256) instead).

Excel VBA, 103 92 Bytes

Anonymous VBE immediate window function that takes input from range [A1] converts to hex, reverses bytes, and outputs to the VBE immediate window

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

• Can I test this somewhere? Could you add an online interpreter, please? – ბიმო Nov 25 '17 at 18:04
• @BruceForte No, unfortunately there are no online interpretters for any of the variants of VBA, however, if you have a copy of Excel on your computer, you can access the VBE by pressing Alt + F11, and then the immediate window by pressing Ctrl + G. For this anonymous function you would then paste your input into cell A1 and the code above into the immediate window and press enter – Taylor Scott Nov 25 '17 at 18:07
• Oh - and sometimes VBA is a bit funky (and the Mac version is imperically worse than the windows version) so this, and unless otherwise stated all, VBA solutions assume the default 32-Bit Windows version – Taylor Scott Nov 25 '17 at 18:10

PPC Assembly (32-bit), 8 bytes

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


How this works:

• PPC calling convention puts the first 32-bit word parameter into SP+24, and shadows that address into GPR3.
• LWBRX takes load GPR3 (third operand) and zero-extends it (second operand) into EA, then reads 4 bytes in reverse order and stores it into GPR3 (first operand).
• GPR3 holds the return value.
• BLR returns from the function (branches to the address in the LR register)

Unfortunately there aren't any online PPC assembly emulators that I could find to demonstrate. Sorry!

Befunge, 62 61 or 49 bytes

0&0v!p22:/3g22/*:*82\+%*:*82+<
@.$_:28*:*%00p\28*:**00g28*:*^  Try it online! This is using standard Befunge on the reference interpreter, and we thus need to account for the fact that memory cells are 8-bit signed, and correct for possible signed overflow. On implementations with unsigned memory cells (e.g. PyFunge), or where the range is greater than 8 bits (e.g. FBBI), we can get away without those checks, saving 12 bytes. 0&0v!p22:/3g22/*:*82\+g< @.$_:28*:*%00p\28*:**00^


Although note that PyFunge has a bug processing integer input, so when testing on TIO you need to follow the number in the input field with a space or line break.

Octave, 10 bytes

@swapbytes


Try it online!

This may be the first time that Octave has the exact same score as its golfing derivative, MATL. Of course, in this case, it's Octave that has the built-in, rather than MATL, making it a lot easier.

Defines a handle to the built-in swapbytes, which takes any data type, swaps the endianness and outputs the result. In this case, the input is a 32-bit unsigned integer.

C#,  44  36 bytes

n=>n>>24|n>>8&65280|n&65280<<8|n<<24


Try it online!

This was originally based on Polynomial's C# answer, who suggested I post a new answer with my improvements on it, but the approach taken in Arnauld's JavaScript answer turned out to be even shorter in C#.

R, 86 bytes

I thought there was already an answer (or two) in R for this question, but I must have been mistaken or they had the same issues that I had with R not doing signed ints. That issue took out any builtins that could have helped. I tried the 256 base conversion, but it ended up being to long, but I think there is still room for someone smarter than me to do that. Then I ended up with the following which it a base 2 conversion swapping the order in a recursive function.

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)


Try it online!

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

• you were right about base 256 being shorter! – Giuseppe Nov 28 '17 at 2:32
• @Giuseppe, you are going to put hat one up aren't you – MickyT Nov 28 '17 at 17:21

R, 41 bytes

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


Try it online!

Verify all test cases!

Uses a base-256 conversion as MickyT suggested here. R does not have unsigned 32-bit integers, nor does it have 64-bit integers. This prevents us from using bitwise operations but this approach (and likely MickyT's) is probably still shorter since R's bitwise operators are quite verbose.

Utilizes number 4 of this tip, taking into account that we're never getting a number as large as 256^4.

n%/%256^(0:3)%%256 extracts the bytes, and %*%, the matrix product, is the dot product in this situation, with 256^(3:0) effecting the reversed order of bytes. %*% will return a 1x1 matrix containing the endian-reversed value.

Perl 5-p, 21 bytes

$_=unpack V,pack N,$_


Try it online!

CP-1610 assembly, 6 DECLEs = 8 bytes

This code is intended to be run on an Intellivision.

A CP-1610 opcode is encoded with a 10-bit value, known as a 'DECLE'. This function is 6 DECLEs long, starting at $480C and ending at$4811.

The CP-1610 has 16-bit registers, so we're using two of them (R0 and R1) to store a 32-bit value.

                               ROMW  10           ; use 10-bit ROM

ORG   $4800 ; start program at address$4800

;; example call
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


Execution dump

 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

• Why is this 7.5 bytes? I think it should be 8 bytes. – Erik the Outgolfer Nov 26 '17 at 10:34
• @EriktheOutgolfer Fair enough. Updated accordingly. – Arnauld Nov 26 '17 at 10:42
• @EriktheOutgolfer Because 60 bits equals 7.5 bytes? – Jeppe Stig Nielsen Nov 26 '17 at 15:45
• @JeppeStigNielsen That's true, but a file can never be 7.5 bytes long, it will be pre- or post-padded with 0s. – Erik the Outgolfer Nov 26 '17 at 15:50
• @EriktheOutgolfer Technically, this could really be stored inside a 10-bit ROM. Here is an example spec sheet. (Today, we're using 16-bit ROM for Intellivision homebrew games, but back in the day, memory chips were so expensive that using 10-bit was a real money saver.) – Arnauld Nov 26 '17 at 16:01

C# (.NET Core), 72+31=103 bytes

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


Try it online!

+31 for using System;using System.Linq;

I was hoping to use Array.Reverse inline, but it wasn't to be (see alternative below).

C# (.NET Core), 87+13=100 bytes

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


Try it online!

+13 for using System;

This solution care of @JeppeStigNielsen; removing the restriction of having everything inline saved 3 bytes.

• Because you can save using System.Linq;, it can still be cheaper to use x=>{var a=BitConverter.GetBytes(x);Array.Reverse(a);return BitConverter.ToUInt32(a,0);}. – Jeppe Stig Nielsen Nov 26 '17 at 15:42

REXX, 42 bytes

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


Try it online!

Ungolfed:

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


Swift, 28 bytes

{(n:UInt32)in n.byteSwapped}


ARM machine language Linux, 8 bytes

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


To try this yourself, compile and run the following on a Raspberry Pi or Android device running GNUroot

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


Perl 5, 27 bytes

say hex unpack H8,pack I,<>


Try it online!

K4, 18 bytes

Solution:

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


Examples:

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


Explanation:

There are no unsigned ints, so takes input as a long.

Convert into boolean array (64bits), reshape, reverse, take first 8 bytes, convert back to long.

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


Bonus:

19 byte version in oK which you can Try online!

2/,/8#|12 8#(64#2)\