25
\$\begingroup\$

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
\$\endgroup\$
4
  • 5
    \$\begingroup\$ Can we assume the number fits as an int for things like bit shifts? \$\endgroup\$
    – xnor
    Commented Jun 3, 2016 at 23:26
  • 1
    \$\begingroup\$ @xnor: I think that’s the default/community consensus (otherwise answers in C etc. would always be wrong)? So sure! :) \$\endgroup\$
    – lynn
    Commented Jun 4, 2016 at 12:57
  • \$\begingroup\$ @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 \$\endgroup\$ Commented Jun 6, 2016 at 2:09
  • 2
    \$\begingroup\$ I swap @Geobits with Minibits \$\endgroup\$
    – Optimizer
    Commented Jun 6, 2016 at 19:41

23 Answers 23

20
\$\begingroup\$

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
\$\endgroup\$
6
  • \$\begingroup\$ 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 ] \$\endgroup\$ Commented Jun 6, 2016 at 4:53
  • \$\begingroup\$ I added a C answer using your expression. All credit for the byte savings vs. Digital Trauma's C answer are due to this. \$\endgroup\$ Commented Jun 6, 2016 at 5:31
  • 2
    \$\begingroup\$ 26: lambda n:n+(n&4**n/3)*3>>1 \$\endgroup\$
    – xsot
    Commented Jun 6, 2016 at 10:17
  • \$\begingroup\$ @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. \$\endgroup\$
    – Dennis
    Commented Jun 6, 2016 at 20:54
  • \$\begingroup\$ @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.) \$\endgroup\$ Commented Jun 6, 2016 at 21:20
10
\$\begingroup\$

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.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ xnor'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. \$\endgroup\$ Commented Jun 6, 2016 at 5:26
9
\$\begingroup\$

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.
\$\endgroup\$
8
\$\begingroup\$

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.
\$\endgroup\$
1
  • \$\begingroup\$ That trick with the permutations is very good! \$\endgroup\$
    – Luis Mendo
    Commented Jun 3, 2016 at 23:36
7
\$\begingroup\$

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.
\$\endgroup\$
5
\$\begingroup\$

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)
\$\endgroup\$
4
  • \$\begingroup\$ Could n<<1 be n*2? \$\endgroup\$
    – user81655
    Commented Jun 4, 2016 at 14:26
  • \$\begingroup\$ @user81655 And I can use n/2 too! I don't know why I didn't think of those before. \$\endgroup\$
    – Neil
    Commented Jun 4, 2016 at 19:42
  • \$\begingroup\$ I´ve never seen >>> ... what is that? \$\endgroup\$
    – Titus
    Commented Jan 26, 2017 at 19:36
  • \$\begingroup\$ @Titus It's like >>> but it does an unsigned shift. >>>0 basically converts to a 32-bit unsigned integer. \$\endgroup\$
    – Neil
    Commented Jan 26, 2017 at 20:22
5
\$\begingroup\$

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.

\$\endgroup\$
5
\$\begingroup\$

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.
\$\endgroup\$
4
\$\begingroup\$

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
\$\endgroup\$
3
\$\begingroup\$

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
\$\endgroup\$
3
\$\begingroup\$

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!

\$\endgroup\$
2
  • 4
    \$\begingroup\$ I'm conflicted. I want to upvote the lower half of your answer, but downvote the upper half. \$\endgroup\$
    – Dennis
    Commented Jun 4, 2016 at 0:27
  • 1
    \$\begingroup\$ @Dennis Now I have those bits swapped. \$\endgroup\$
    – Leaky Nun
    Commented Jun 4, 2016 at 0:48
3
\$\begingroup\$

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.
\$\endgroup\$
2
  • 2
    \$\begingroup\$ Nice, but you can replace 1 2‚2 1‚ with 12Â for 8 bytes. \$\endgroup\$
    – Adnan
    Commented Jun 4, 2016 at 15:59
  • \$\begingroup\$ Nice answer! Here an 8-byte alternative: 4в2‰íJJC \$\endgroup\$ Commented Apr 11, 2019 at 8:16
3
\$\begingroup\$

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.

\$\endgroup\$
2
  • \$\begingroup\$ @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 \$\endgroup\$ Commented Jun 6, 2016 at 22:03
  • 2
    \$\begingroup\$ You can drop that space by rearranging the terms in the expression. \$\endgroup\$
    – xsot
    Commented Jun 6, 2016 at 23:01
2
\$\begingroup\$

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
)
\$\endgroup\$
1
  • \$\begingroup\$ use +('0b"+binary_string_here) instead of `parseInt(..., 2) \$\endgroup\$
    – Downgoat
    Commented Jun 3, 2016 at 23:33
1
\$\begingroup\$

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.

\$\endgroup\$
1
\$\begingroup\$

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

\$\endgroup\$
1
\$\begingroup\$

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.

\$\endgroup\$
1
\$\begingroup\$

Husk, 8 bytes

ḋṁo↔‰2B4

Try it online!

Same as the Jelly solution.

Husk, 9 8 bytes

ḋṁ↔C_2Θḋ

Try it online!

General method.

-1 byte from Jo King. (using Θ)

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Why is that a builtin? \$\endgroup\$
    – Razetime
    Commented Oct 5, 2020 at 8:26
0
\$\begingroup\$

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.

\$\endgroup\$
0
\$\begingroup\$

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
\$\endgroup\$
0
\$\begingroup\$

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
\$\endgroup\$
0
\$\begingroup\$

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))
\$\endgroup\$
0
\$\begingroup\$

x86 machine code - 19 bytes

Callable function, input in ebx output in eax.

Lisitng :

    16                                  global tukar_bits
    17                                  tukar_bits:
    18                                  
    19 00000016 89DA                    mov  edx, ebx
    20 00000018 8D0412                  lea  eax, [edx + edx]
    21 0000001B D1EA                    shr  edx, 1
    22 0000001D 81E255555555            and  edx, 0x55555555
    23 00000023 8D1452                  lea  edx, [edx + edx * 2]
    24 00000026 29D0                    sub  eax, edx
    25 00000028 C3                      ret

Try it online!, using x86-64 caller.


x86 machine code - 21 bytes

Callable function, input in ebxoutput in eax.

Listing :

     1                                  global tukar_bits
     2                                  tukar_bits:
     3                                  
     4 00000000 89D8                    mov  eax, ebx
     5 00000002 89C2                    mov  edx, eax
     6 00000004 2555555555              and  eax, 0x55555555
     7 00000009 D1EA                    shr  edx, 1
     8 0000000B 81E255555555            and  edx, 0x55555555
     9 00000011 8D0442                  lea  eax, [edx + eax * 2]
    10 00000014 C3                      ret

Try it online!, using x86-64 caller.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.