3
\$\begingroup\$

The task:

Given an unsigned 8-bit integer, swap its even and odd bits. The 1st and 2nd bit should be swapped, the 3rd and 4th bit should be swapped, and so on.

For example, 10101010 should be 01010101. 11100010 should be 11010001.

Bonus: Can you do this in one line?

My solutions:

// imperative:
function swap8BitInteger(bytes){
  let copiedBytes = '';
  for(let i = 0; i < bytes.length; i+=2) {
    copiedBytes+= `${bytes[i+1]}${bytes[i]}`;
  }
  return copiedBytes;
}

console.log(swap8BitInteger('11100010'));

// I don't know wether this qualifies as a one-liner
const swap8BitInteger2 = bytes => bytes.split('').reduce((acc, bit, idx) => {acc[idx % 2 === 0 ? idx + 1 : idx - 1] = bit;return acc;}, []).join('');

console.log(swap8BitInteger2('11100010'));

// Not sure wether this is still readable
const swap8BitInteger3 = bytes => bytes.split('').reduce((acc, _, idx) => idx % 2 ? acc : acc + bytes[idx + 1] + bytes[idx], '');

console.log(swap8BitInteger3('11100010'));

Would be interested to see an even shorter (and/or more readable) solution.

\$\endgroup\$
  • \$\begingroup\$ Are the input and output really supposed to be strings, and not 8-bit integers are the question said? \$\endgroup\$ – harold Feb 13 at 12:21
  • \$\begingroup\$ JS doesn't have (8 bit) Integer types. It only got numbers, i.e. leading zeros can't be displayed, therefore I took a string representation of an 8 bit Integer. \$\endgroup\$ – thadeuszlay Feb 13 at 12:41
  • \$\begingroup\$ That is just a display issue, of course a JS Number can easily hold 8 bits \$\endgroup\$ – harold Feb 13 at 12:46
4
\$\begingroup\$

OMDG arrays to manipulate bits

Bit manipulation is the most basic type of operation a computer can do. These days it can mess with 64 bit in one go. JS number (as signed int 32) is limited to 32 (to keep us in our place)

BTW JS has 8, 16, 32bit signed and unsigned arrays.

In JS you can write binary numbers with the 0b prefix. Eg 0b111 is 7

To swap even odd, you shift all bits to the left << 1 (same as * 2) and mask out & 0b10101010 the odd bits. The for the even you shift all bits to the right >> 1 similar to /2, mask out the even bits & 0b101010101 and add or or the result of the previous shift.

Example show two ways of doing the same thing.

const swapEvenOdd = char => ((char << 1) & 0b10101010) | ((char >> 1) & 0b1010101);

const swapEvenOdd2 = char => ((char * 2) & 170) + ((char / 2) & 85);


console.log(swapEvenOdd(0b01100110).toString(2).padStart(8,"0"))
console.log(swapEvenOdd2(0b01100110).toString(2).padStart(8,"0"))

\$\endgroup\$
  • \$\begingroup\$ Im deeply ashamed for not having know this. -.-“ \$\endgroup\$ – thadeuszlay Feb 13 at 15:56
  • 1
    \$\begingroup\$ @thadeuszlay LOL not to worry, binary maths is a dying art in the world of programming. This not the first time I have seen strings and arrays used to manipulate bits. \$\endgroup\$ – Blindman67 Feb 13 at 15:59
  • \$\begingroup\$ Can you please explain to me each single step and why it is needed? E.g. why is & 0b10101010 needed and afterwards | and then ((char >> 1) & 0b1010101)? \$\endgroup\$ – thadeuszlay Feb 13 at 18:02
  • \$\begingroup\$ @thadeuszlay The rundown on bitwise operators developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… The char & 0b1010 the right side is a mask. It removes any bits that are 0 in the mask from char. eg 4bit c = 1001 1001<<1=0010 then 0010&1010=0010 then after or | shift right and mask 1001>>1=0100 (if JS had unsigned char (8bit) then would use >>> to remove extra top bit) then 0100&0101=0100. Then the or 0100 | 0010 = 0110 which is the answer \$\endgroup\$ – Blindman67 Feb 13 at 21:21
  • \$\begingroup\$ Ah, I now understand. Binary math isn't that difficult after all. \$\endgroup\$ – thadeuszlay Feb 16 at 11:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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