# ETOOBUSY đźš€ minimal blogging for the impatient

# PWC120 - Swap Odd/Even bits

**TL;DR**

Here we are with TASK #1 from the Perl Weekly Challenge #120. Enjoy!

# The challenge

You are given a positive integer

`$N`

less than or equal to 255.Write a script to swap the odd positioned bit with even positioned bit and print the decimal equivalent of the new binary representation.

Example`Input: $N = 101 Output: 154 Binary representation of the given number is 01 10 01 01. The new binary representation after the odd/even swap is 10 01 10 10. The decimal equivalent of 10011010 is 154. Input: $N = 18 Output: 33 Binary representation of the given number is 00 01 00 10. The new binary representation after the odd/even swap is 00 10 00 01. The decimal equivalent of 100001 is 33.`

# The questions

Asking questions in this challenge is actually nit-picking a lot. Or maybe not.

I would only object that itâ€™s not entirely clear which odd-positioned bit should be swapped with which even-positioned bit. From here, itâ€™s easy to e.g. say that weâ€™re swapping 0 with 7, 1 with 6, 2 with 5, etc.

So the question is: should pairing consider that, considering a binary representation where the position of the least significant bit in the byte is 0, the bit in position $2k$ should be swapped with the bit in position $2k + 1$?

Another question is: should we swap *all* pairs of odd/even bits? The
first example seems to imply that this is indeed the case, because every
bit changes.

# The solution

Letâ€™s look at the bit numbering for our octet:

```
7 5 3 1
6 4 2 0
```

To swap each pair of odd/even bits, we have to move all odd bits to the right and all even bits to the left:

```
7 5 3 1
6 4 2 0
```

This is easily accomplished using the *bit shift* operators, widely
available in many languages. For Perl we have `>>`

and `<<`

respectively, for Raku we have `+>`

and `+<`

(respectively).

How to isolate the odd bits from the even bits, then? This can be done
by *masking* the input with values that force the unwanted bits to 0:

```
1 0 1 0 1 0 1 0 <- 170 (decimal)
0 1 0 1 0 1 0 1 <- 85 (decimal)
```

Again, masking is usually available in many languages by means of the
AND operator (`&`

in Perl, `+&`

in Raku).

Last, we re-assemble the two parts together. This is done using the OR
operator on the two parts (`|`

in Perl and `+|`

in Raku).

Letâ€™s get to the solutions then.

Raku:

```
#!/usr/bin/env raku
use v6;
sub soeb (Int:D $N where 0 < * <= 255) {$N +& 170 +> 1 +| $N +& 85 +< 1}
put soeb(+$_) for @*ARGS ?? @*ARGS !! <101 18>
```

Itâ€™s easy to account for â€śnon-negative integers below or equal to 255â€ť
by changing the `0 < * <= 255`

into `0 <= * <= 255`

.

Perl:

```
#!/usr/bin/env perl
use v5.24;
sub soeb { ($_[0] & 170) >> 1 | ($_[0] & 85) << 1 }
say soeb($_) for @ARGV ? @ARGV : qw< 101 18 >;
```

I knowâ€¦ weâ€™re losing the check on the input parameter here, but I guess itâ€™s fine for this challenge.

Stay safe everyone!

*Comments? Octodon, Twitter, GitHub, Reddit, or drop me a line!*