Swap bits with their neighbours

26

5

Task description

Given an integer, swap its (2k–1)-th and 2k-th least significant bits for all integers k > 0. This is sequence A057300 in the OEIS.

(The number is assumed to have “infinitely many” leading zeroes. In practice, this simply means prepending a single 0 bit to odd-length numbers.)

enter image description here

This is , so the shortest code (in bytes) wins.

Test cases

0 -> 0
1 -> 2
9 -> 6
85 -> 170
220 -> 236
1827 -> 2835
47525 -> 30298

Lynn

Posted 2016-06-03T22:42:34.207

Reputation: 55 648

5Can we assume the number fits as an int for things like bit shifts? – xnor – 2016-06-03T23:26:55.257

1@xnor: I think that’s the default/community consensus (otherwise answers in C etc. would always be wrong)? So sure! :) – Lynn – 2016-06-04T12:57:29.030

@Lynn: C requires unsigned char array_of_bytes[1024] to work the way you expect (i.e. be a bitfield with 1024 * CHAR_BIT entries). I'd imagine most answers supporting arbitrary-length inputs would assume CHAR_BIT was even, though, since shifting bits between bytes is cumbersome. So you absolutely could put a requirement to support k up to some constant size, like 256 or something that's reasonable for AES, and languages without 256bit integer types would have to use loops. That might make SIMD vectors worth considering for an x86 asm answer :P – Peter Cordes – 2016-06-06T02:09:58.470

2I swap @Geobits with Minibits – Optimizer – 2016-06-06T19:41:04.280

Answers

9

Jelly, 10 9 7 bytes

b4d2UFḄ

Try it online! or verify all test cases.

How it works

b4d2UFḄ  Main link. Argument: n (integer)

b4       Convert n to base 4.
  d2     Divmod each quaternary digit x by 2, yielding [x : 2, x % 2].
    U    Upend; reverse each pair, yielding [x % 2, x : 2].
     F   Flatten the 2D list of binary digits.
      Ḅ  Convert from binary to integer.

Dennis

Posted 2016-06-03T22:42:34.207

Reputation: 196 637

20

Python 2, 26 bytes

lambda n:2*n-3*(4**n/3&n/2)

Bit tricks!

Say n has form ...ghfedcba in binary. Then, we can split it into every other bit as

n   = o + 2*e
n   = ...hgfedcba
o   = ...0g0e0c0a
2*e = ...h0f0d0b0

Then, the bit-switched result s can be expressed as s=2*o+e.

s   = 2*o + e
s   = ...ghefcdab
2*o = ...g0e0c0a0
e   = ...0h0f0d0b

We'd rather compute only one of e and o, so we express o=n-2*e and substitute

s=2*(n-2*e)+e = 2*n-3*e

So, now it remains to express e in terms of n. The number M=4**n/3 has form ...10101010101 in binary, which serves as a mask for the odd digits. The exponent n ensures that M is long enough. Taking the bitwise and of n/2 and this value gives e as desired.

n/2     = ...hgfedcb
M       = ...1010101
n/2 & M = ...h0f0d0b = e

We can instead express e in terms of o e=(n-o)/2, which gives s=(n+o*3)/2, which saves a byte thanks to an optimization from xsot.

lambda n:n+(n&4**n/3)*3>>1

xnor

Posted 2016-06-03T22:42:34.207

Reputation: 115 687

Great explanation, and nice trick to use the mask only once by subtracting from n. However, I prefer the opposite "odd" vs. "even" bit naming convention. The LSB is bit 0, which is even (even though it's the first bit). In SIMD programming, where shuffles often select elements with an index, the indices count from 0, so it's normal to consider the low element an even element. e.g. [ 3 2 1 0 ] – Peter Cordes – 2016-06-06T04:53:51.380

I added a C answer using your expression. All credit for the byte savings vs. Digital Trauma's C answer are due to this. – Peter Cordes – 2016-06-06T05:31:03.423

226: lambda n:n+(n&4**n/3)*3>>1 – xsot – 2016-06-06T10:17:49.830

@PeterCordes Your C code works for me with gcc 4.8.3 and default settings. f(x){return x+((x&~0U/3)*3)>>1;} returns 1 for input 2. – Dennis – 2016-06-06T20:54:16.390

@Dennis: Yeah, works for me in C, my bad. I was actually testing the expression in calc (aka apcalc), not actually C. I thought I'd be ok since I didn't need truncation to 32bit, or two's complement. I didn't think the expression looked right, so I was willing to believe my wrong tests. But anyway, I'm in need of a better REPL for developing bithacks. Any suggestions? (ideally Linux command line, like bc -l or calc, but actually exposing int32_t / uint32_t or something, not extended precision.) – Peter Cordes – 2016-06-06T21:20:44.613

@xsot Thanks! I remember you also this trick here.

– xnor – 2016-06-07T10:07:38.333

10

C function, 38

Bit-twiddling:

f(x){return(x&~0U/3*2)/2+(x&~0U/3)*2;}

Ideone.


Or for the fun of it:

C recursive function, 43

As per the OEIS formula, a(4n+k) = 4a(n) + a(k), 0 <= k <= 3

f(x){return x>3?4*f(x/4)+f(x%4):x%3?3-x:x;}

or

f(x){return x>3?4*f(x/4)+f(x%4):x%2*2+x/2;}

Ideone.

Digital Trauma

Posted 2016-06-03T22:42:34.207

Reputation: 64 644

1xnor's clever transformation of the expression gets this down to 32 bytes in C. I posted it as a separate answer, since it's a significantly different approach. – Peter Cordes – 2016-06-06T05:26:00.207

8

CJam, 16 14 13 bytes

ri4b4e!2=f=4b

Test it here.

Explanation

ri  e# Read input and convert to integer.
4b  e# Get base-4 digits.
4e! e# Push all permutations of [0 1 2 3].
2=  e# Select the third one which happens to be [0 2 1 3].
f=  e# For each base-4 digit select the value at that position in the previous
    e# list, which swaps 1s and 2s.
4b  e# Convert back from base 4.

Martin Ender

Posted 2016-06-03T22:42:34.207

Reputation: 184 808

That trick with the permutations is very good! – Luis Mendo – 2016-06-03T23:36:13.323

7

Pyth, 9 bytes

iXjQ4S2)4

Try it in the Pyth Compiler.

How it works

  jQ4      Convert the input (Q) to base 4.
 X   S2)   Translate [1, 2] to [2, 1].
i       4  COnvert from base 4 to integer.

Dennis

Posted 2016-06-03T22:42:34.207

Reputation: 196 637

5

JavaScript (ES6), 32 30 bytes

(n,m=0x55555555)=>n*2&~m|n/2&m

Only works up to 1073741823 due to the limitations of JavaScript's integers. 38 36 bytes works up to 4294967295:

(n,m=0x55555555)=>(n*2&~m|n/2&m)>>>0

Edit: Saved 2 bytes thanks to @user81655.

51 bytes works up to 4503599627370495:

n=>parseInt(n.toString(4).replace(/1|2/g,n=>3-n),4)

Neil

Posted 2016-06-03T22:42:34.207

Reputation: 95 035

Could n<<1 be n*2? – user81655 – 2016-06-04T14:26:55.493

@user81655 And I can use n/2 too! I don't know why I didn't think of those before. – Neil – 2016-06-04T19:42:00.517

I´ve never seen >>> ... what is that? – Titus – 2017-01-26T19:36:49.940

@Titus It's like >>> but it does an unsigned shift. >>>0 basically converts to a 32-bit unsigned integer. – Neil – 2017-01-26T20:22:11.467

5

x86 asm function: 14 bytes of machine code

uint64_t version: 24 bytes

x86-64 SysV calling convention (x in edi), but this same machine code will also work in 32bit mode. (Where the lea will decode as lea eax, [edi + eax*2], which gives identical results).

0000000000000040 <onemask_even>:
  40:   89 f8                   mov    eax,edi
  42:   25 55 55 55 55          and    eax,0x55555555
  47:   29 c7                   sub    edi,eax
  49:   d1 ef                   shr    edi,1
  4b:   8d 04 47                lea    eax,[rdi+rax*2]
  4e:   c3                      ret    
4f: <end>

0x4f - 0x40 = 14 bytes

This is compiler output from using xnor's excellent mask-once idea the opposite way. (And opposite terminology: the low bit is bit 0, which is even, not odd.)

unsigned onemask_even(unsigned x) {
  unsigned emask = ~0U/3;
  unsigned e = (x & emask);
  return e*2 + ((x - e) >> 1);
}

I didn't find any improvements over what the compiler does. I might have written it as mov eax, 0x555... / and eax, edi, but that's the same length.


The same function for 64bit integers takes 24 bytes (see the godbolt link). I don't see any way shorter than 10-byte movabs rax, 0x55... to generate the mask in a register. (x86's div instruction is clunky, so unsigned division of all-ones by 3 doesn't help.)

I did come up with a loop to generate the mask in rax, but it's 10 bytes (exactly the same length as the mov imm64).

# since 0x55 has its low bit set, shifting it out the top of RAX will set CF
0000000000000000 <swap_bitpairs64>:
   0:   31 c0                   xor    eax,eax      ; old garbage in rax could end the loop early
0000000000000002 <swap_bitpairs64.loop>:
   2:   48 c1 e0 08             shl    rax,0x8
   6:   b0 55                   mov    al,0x55      ; set the low byte
   8:   73 f8                   jnc    2 <swap_bitpairs64.loop>  ; loop until CF is set
000000000000000a <swap_bitpairs64.rest_of_function_as_normal>:
 # 10 bytes, same as   mov  rax, 0x5555555555555555
 # rax = 0x5555...
   a:   48 21 f8                and    rax,rdi
   ...

If we knew that none of the existing bytes in rax has their low bit set, we could skip the xor, and this would be 8 bytes long.

A previous version of this answer had a 10 byte loop using the loop insn, but it had a worst-case run-time of 0xFFFFFFFFFFFFFF08 iterations, because I only set cl.

Peter Cordes

Posted 2016-06-03T22:42:34.207

Reputation: 2 810

5

Oasis, 17 bytes (non-competing)

n4÷axxn4÷xxe+3120

Try it online!

Oasis is a language designed by Adnan which is specialized in sequences.

Currently, this language can do recursion and closed form.

We use this formula: a(4n+k) = 4a(n) + a(k), 0 <= k <= 3

To specify the base case is simple: the 3120 at the end simply means that a(0)=0, a(1)=2, a(2)=1, a(3)=3.

n4÷axxn4÷xxe+3120
                0  a(0) = 0
               2   a(1) = 2
              1    a(2) = 1
             3     a(3) = 3

n                  push n (input)
 4÷                integer-divide by 4
   a               a(n/4)
    xx             double twice; multiply by 4
                   now we have 4a(n/4)
      n            push n (input)
       4÷xx        integer-divide by 4 and then multiply by 4
                   since there is no modulo currently, n%4
                   is built as n-(n/4*4)
           e       we should have done a(n-(n/4*4)), but this
                   is a shortcut for a(n-x) where x is the top
                   of stack. Therefore, we now have a(n-n/4*4)
                   which is a(n%4).
            +      add.

Leaky Nun

Posted 2016-06-03T22:42:34.207

Reputation: 45 011

4

MATL, 10 bytes

BP2eP1ePXB

Try it online!

Modified version to generate the first terms of the sequence (OEIS A057300).

Explanation

B     % Take input implicitly. Convert to binary array
P     % Flip
2e    % Convert to two-row 2D array, padding with a trailing zero if needed. 
      % Because of the previous flip, this really corresponds to a leading zero
P     % Flip each column. This corresponds to swapping the bits
1e    % Reshape into a row
P     % Flip, to undo the initial flipping
XB    % Convert from binary array to number. Display implicitly

Luis Mendo

Posted 2016-06-03T22:42:34.207

Reputation: 87 464

3

zsh, 28 bytes

<<<$[`tr 12 21<<<$[[#4]$1]`]

Takes input as a command line argument, outputs on STDOUT.

It's not Bash-compatible because it uses zsh-specific base conversion syntax.

                       $1     input (first command line argument)
                 $[      ]    arithmetic expansion
                   [#4]       output in base 4
              <<<             pass the result of this to...
      tr                      the `tr' command
         12 21                and replace 1s with 2s, 2s with 1s
     `                    `   evaluate the result...
   $[                      ]  in another arithmetic expansion, to convert back
                                to base 10
<<<                           output the result on STDOUT

Doorknob

Posted 2016-06-03T22:42:34.207

Reputation: 68 138

3

Retina, 70 bytes

.+
$*
+`(1+)\1
$1x
x1
1
^
x
r`(.)(.)
$2$1
1
x@
+`@x
x@@
x*(@*)
$.1
0$

Test suite. (Slightly modified.)

Well, just for fun: 7 bytes

T`12`21

Takes base-4 as input, and outputs as base-4.

Try it online!

Leaky Nun

Posted 2016-06-03T22:42:34.207

Reputation: 45 011

4I'm conflicted. I want to upvote the lower half of your answer, but downvote the upper half. – Dennis – 2016-06-04T00:27:51.030

1@Dennis Now I have those bits swapped. – Leaky Nun – 2016-06-04T00:48:59.823

3

05AB1E, 8 bytes

4B12‡4ö

Thanks to @Adnan for -5 bytes!

Uses CP-1252 encoding.

Try It Online!

Explanation:

4B       - Take input and convert to base 4.
  12Â    - Push 12 bifurcated.
     ‡   - Transliterate [1, 2] to [2, 1].
      4ö - Convert to base 10.

George Gibson

Posted 2016-06-03T22:42:34.207

Reputation: 2 369

2Nice, but you can replace 1 2‚2 1‚ with 12Â for 8 bytes. – Adnan – 2016-06-04T15:59:43.123

Nice answer! Here an 8-byte alternative: 4в2‰íJJC

– Kevin Cruijssen – 2019-04-11T08:16:16.070

3

C, 32 30 29 bytes

f(x){return(x&~0U/3)*3+x>>1;}                // 30 bit version, see below

// less golfed:
f(x){return ((x & 0x55555555)*3 + x) >>1;}   //  >> is lower precedence than +

Algorithm copied from xsot's comment on xnor's Python answer. Instead of masking both ways, mask one way and combine.

This compiles to the same asm as the last version I tested, and it works (for x up to 0x3FFFFFFF, and for x above that as long as bit 30 isn't set, see below). In machine code, it's the same length as my existing asm answer.


The above version always clears the high bit of the result. The best safe version is 32 bytes:

g(x){return 2*x-3*(x/2U&~0U/3);}   // safe 32bit version, works for all x

The Python version doesn't have this problem, because python uses arbitrary-precision integer types when needed, instead of truncating to a fixed upper limit.

Peter Cordes

Posted 2016-06-03T22:42:34.207

Reputation: 2 810

@Dennis: Argh, yes, thanks. I made that last change after testing, and missed the difference in asm output. No wonder I was thinking it looked wrong; I had forgotten that >> was such low precedence. I don't golf often enough to remember exactly what the rules are, since compiler warnings suggesting parens in dangerous cases save me in real code. :P – Peter Cordes – 2016-06-06T22:03:12.167

2You can drop that space by rearranging the terms in the expression. – xsot – 2016-06-06T23:01:21.163

2

Javascript (ES6), 113 109 bytes

Saved 4 bytes thanks to Upgoat

n=>+('0b'+/(..)+$/.exec('0'+n.toString`2`)[0].split``.reduce((p,c)=>p.length-1?[p.join(c)]:[p[0],c],[''])[0],2)

How it works

n=>+('0b'+                              //parse as binary literal
    /(..)+$/.exec('0'+n.toString`2`)[0] //convert to binary string with an even number of digits
        .split``                        //convert to array
        .reduce((p,c)=>p.length-1?[p.join(c)]:[p[0],c],[''])
                                        //swap all numbers
)

ASCII-only

Posted 2016-06-03T22:42:34.207

Reputation: 4 687

use +('0b"+binary_string_here) instead of `parseInt(..., 2) – Downgoat – 2016-06-03T23:33:33.373

1

INTERCAL, 60 bytes

DOWRITEIN.1PLEASE.1<-!1~#21845'$.1~#43690DOREADOUT.1DOGIVEUP

Try it online!

Works for 16-bit integers, with I/O done in the most natural format for INTERCAL: the input is a series of decimal digits spelled out in one of several natural or constructed languages, and the output is in "butchered Roman numerals".

This is one of those rare challenges where INTERCAL's binary operators can actually be used at all intuitively, since repositioning bits is what they're all about. Select (~) takes the bits from its first argument corresponding to ones in its second argument and pads them to the right with zeroes, and mingle ($) interleaves the bits from its arguments such that the bits from the first argument are more significant. So the straightforward solution is to select out the less significant alternating bits (.1~#21845), select out the more significant alternating bits (.1~#43690), and interleave them back together in the opposite order. Fortunately for byte count, although INTERCAL's operators have no defined precedence (as the language's goal is to have no precedents), it turns out that the C-INTERCAL on TIO doesn't require much grouping for this particular expression, costing only one byte since '. can be abbreviated !.

With support for 32-bit integers:

INTERCAL, 67 bytes

DOWRITEIN:1PLEASE:1<-':1~#0$#65535'$:1~#65535$#0DOREADOUT:1DOGIVEUP

Try it online!

INTERCAL doesn't allow 32-bit literals, which actually makes this a bit easier to read, since it means the magic constants for selecting alternating bits have to be constructed by mingling two 16-bit literals together, where one's all zeroes and the other's all ones. (Actually, even if there were 32-bit literals, this would still be shorter. #0$#65535 is two bytes off #1431655765, and the same goes for the other one.) This communicates the whole process unnaturally well for INTERCAL.

An alternate approach with clumsy use of operand overloading:

INTERCAL, 71 bytes

DO:1<-:1/.2$.3PLEASEWRITEIN:2DO:1<-:2PLEASE:2<-.3$.2DOREADOUT:2DOGIVEUP

Try it online!

This does away with selecting altogether by declaring that :1 is .2 mingled with .3, setting :1 to the input, then outputting .3 mingled with .2. Since :1 was overloaded as .2$.3, DO :1 <- :2 assigns values to .2 and .3 such that :1 acquires the value of :2, which results in .2 containing the more significant alternating bits from :2 and .3 containing the less significant alternating bits. This would be the shorter of the two 32-bit solutions by four bytes if PLEASE WRITE IN :1 could replace PLEASE WRITE IN :2 DO :1 <- :2 with overloaded :1, but CALCULATING turns out to be necessary for using overloading. I also feel like there might be some shorter way to carry out the overloading itself than starting the program with DO:1<-:1/.2$.3, but since this is INTERCAL I also also feel like there can't be.

Unrelated String

Posted 2016-06-03T22:42:34.207

Reputation: 5 300

1

J, 20 bytes

4#.0 2 1 3{~4#.^:_1]

Usage

>> f =: 4#.0 2 1 3{~4#.^:_1]
>> f 85
<< 170

Where >> is STDIN and << is STDOUT.

Ungolfed

to_base   =: 4 #.^:_1 ]
transpose =: 0 2 1 3 {~ to_base
from_base =: 4 #. transpose

Three forks.

Sidenote

In the official interpreter, ^:_1 can be replaced by inv, saving 1 byte.

However, none of the online interpreters implement this.

Leaky Nun

Posted 2016-06-03T22:42:34.207

Reputation: 45 011

1

C#, 44 bytes

Based on the C implementation

int f(int n)=>n>3?4*f(n/4)+f(n%4):n%2*2+n/2;

Try it here: C# pad

Cheesebaron

Posted 2016-06-03T22:42:34.207

Reputation: 111

0

REXX, 88 bytes

n=x2b(d2x(arg(1)))
o=0
do while n>''
  parse var n a+1 b+1 n
  o=o||b||a
  end
say x2d(b2x(o))

idrougge

Posted 2016-06-03T22:42:34.207

Reputation: 641

0

Mathematica, 44 bytes

Fold[3#+##&,#~IntegerDigits~4/.{1->2,2->1}]&

Same approach as my CJam answer: convert to base-4, swap 1s and 2s, convert back. It also uses alephalpha's trick to replace FromDigits with a Fold operation to save one byte.

Martin Ender

Posted 2016-06-03T22:42:34.207

Reputation: 184 808

0

Actually, 16 bytes

4@¡"21""12"(t4@¿

Try it online!

Explanation:

4@¡"21""12"(t4@¿
4@¡               base 4 representation of n
   "21""12"(t     translate (swap 1s and 2s)
             4@¿  base 4 to decimal

Mego

Posted 2016-06-03T22:42:34.207

Reputation: 32 998

0

J, 22 bytes

([:,_2|.\,&0)&.(|.@#:)

Alternative approach based on array manipulation instead of the base 4 trick.

Usage

   f =: ([:,_2|.\,&0)&.(|.@#:)
   (,.f"0) 0 1 9 85 220 1827 47525
    0     0
    1     2
    9     6
   85   170
  220   236
 1827  2835
47525 30298

Explanation

([:,_2|.\,&0)&.(|.@#:)  Input: n
                   #:   Get the value as a list of base 2 digits
                |.@     Reverse it
(           )&.         Apply to the list of base 2 digits
         ,&0            Append a zero to the end of the list
    _2  \               Split the list into nonoverlapping sublists of size 2
      |.                Reverse each sublist
 [:,                    Flatten the list of sublists into a list
             &.(    )   Apply the inverse of (reversed base 2 digits)
                        to convert back to a number and return it

miles

Posted 2016-06-03T22:42:34.207

Reputation: 15 654