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.)
This is code-golf, so the shortest code (in bytes) wins.
Test cases
0 -> 0
1 -> 2
9 -> 6
85 -> 170
220 -> 236
1827 -> 2835
47525 -> 30298
23 Answers 23
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
-
\$\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\$Peter Cordes– Peter Cordes2016年06月06日 04:53:51 +00:00Commented 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\$Peter Cordes– Peter Cordes2016年06月06日 05:31:03 +00:00Commented Jun 6, 2016 at 5:31
-
2\$\begingroup\$ 26:
lambda n:n+(n&4**n/3)*3>>1\$\endgroup\$xsot– xsot2016年06月06日 10:17:49 +00:00Commented 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– Dennis2016年06月06日 20:54:16 +00:00Commented 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, likebc -lorcalc, but actually exposingint32_t/uint32_tor something, not extended precision.) \$\endgroup\$Peter Cordes– Peter Cordes2016年06月06日 21:20:44 +00:00Commented Jun 6, 2016 at 21:20
C function, 38
Bit-twiddling:
f(x){return(x&~0U/3*2)/2+(x&~0U/3)*2;}
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;}
-
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\$Peter Cordes– Peter Cordes2016年06月06日 05:26:00 +00:00Commented Jun 6, 2016 at 5:26
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.
CJam, (削除) 16 (削除ここまで) (削除) 14 (削除ここまで) 13 bytes
ri4b4e!2=f=4b
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.
-
\$\begingroup\$ That trick with the permutations is very good! \$\endgroup\$Luis Mendo– Luis Mendo2016年06月03日 23:36:13 +00:00Commented Jun 3, 2016 at 23:36
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.
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)
-
\$\begingroup\$ Could
n<<1ben*2? \$\endgroup\$user81655– user816552016年06月04日 14:26:55 +00:00Commented Jun 4, 2016 at 14:26 -
\$\begingroup\$ @user81655 And I can use
n/2too! I don't know why I didn't think of those before. \$\endgroup\$Neil– Neil2016年06月04日 19:42:00 +00:00Commented Jun 4, 2016 at 19:42 -
\$\begingroup\$ I´ve never seen
>>>... what is that? \$\endgroup\$Titus– Titus2017年01月26日 19:36:49 +00:00Commented Jan 26, 2017 at 19:36 -
\$\begingroup\$ @Titus It's like
>>>but it does an unsigned shift.>>>0basically converts to a 32-bit unsigned integer. \$\endgroup\$Neil– Neil2017年01月26日 20:22:11 +00:00Commented Jan 26, 2017 at 20:22
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.
Oasis, 17 bytes (non-competing)
n4÷axxn4÷xxe+3120
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.
MATL, 10 bytes
BP2eP1ePXB
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
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
Retina, 70 bytes
.+ $* +`(1+)1円 1ドルx 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.
-
4\$\begingroup\$ I'm conflicted. I want to upvote the lower half of your answer, but downvote the upper half. \$\endgroup\$Dennis– Dennis2016年06月04日 00:27:51 +00:00Commented Jun 4, 2016 at 0:27
-
1\$\begingroup\$ @Dennis Now I have those bits swapped. \$\endgroup\$Leaky Nun– Leaky Nun2016年06月04日 00:48:59 +00:00Commented Jun 4, 2016 at 0:48
05AB1E, 8 bytes
4B12‡4ö
Thanks to @Adnan for -5 bytes!
Uses CP-1252 encoding.
Explanation:
4B - Take input and convert to base 4.
12Â - Push 12 bifurcated.
‡ - Transliterate [1, 2] to [2, 1].
4ö - Convert to base 10.
-
2\$\begingroup\$ Nice, but you can replace
1 2‚2 1‚with12Âfor 8 bytes. \$\endgroup\$Adnan– Adnan2016年06月04日 15:59:43 +00:00Commented Jun 4, 2016 at 15:59 -
\$\begingroup\$ Nice answer! Here an 8-byte alternative:
4в2‰íJJC\$\endgroup\$Kevin Cruijssen– Kevin Cruijssen2019年04月11日 08:16:16 +00:00Commented Apr 11, 2019 at 8:16
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.
-
\$\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\$Peter Cordes– Peter Cordes2016年06月06日 22:03:12 +00:00Commented Jun 6, 2016 at 22:03 -
2\$\begingroup\$ You can drop that space by rearranging the terms in the expression. \$\endgroup\$xsot– xsot2016年06月06日 23:01:21 +00:00Commented Jun 6, 2016 at 23:01
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
)
-
\$\begingroup\$ use
+('0b"+binary_string_here)instead of `parseInt(..., 2) \$\endgroup\$Downgoat– Downgoat2016年06月03日 23:33:33 +00:00Commented Jun 3, 2016 at 23:33
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.
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
INTERCAL, 60 bytes
DOWRITEIN.1PLEASE.1<-!1~#21845'$.1~#43690DOREADOUT.1DOGIVEUP
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
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
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.
Husk, 8 bytes
ḋṁo↔‰2B4
Same as the Jelly solution.
Husk, (削除) 9 (削除ここまで) 8 bytes
ḋṁ↔C_2Θḋ
General method.
-1 byte from Jo King. (using Θ)
-
1\$\begingroup\$ Why is that a builtin? \$\endgroup\$Razetime– Razetime2020年10月05日 08:26:07 +00:00Commented Oct 5, 2020 at 8:26
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.
Actually, 16 bytes
4@¡"21""12"(t4@¿
Explanation:
4@¡"21""12"(t4@¿
4@¡ base 4 representation of n
"21""12"(t translate (swap 1s and 2s)
4@¿ base 4 to decimal
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
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))
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.
Explore related questions
See similar questions with these tags.
unsigned char array_of_bytes[1024]to work the way you expect (i.e. be a bitfield with 1024 *CHAR_BITentries). I'd imagine most answers supporting arbitrary-length inputs would assumeCHAR_BITwas even, though, since shifting bits between bytes is cumbersome. So you absolutely could put a requirement to supportkup 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\$