## Perl Weekly Challenge 121: Invert Bit

These are some answers to the Week 121 of the Perl Weekly Challenge organized by Mohammad S. Anwar.

Spoiler Alert: This weekly challenge deadline is due on July 18, 2021 at 24:00. This blog post offers some solutions to this challenge, please don’t read on if you intend to complete the challenge on your own.

You are given integers `0 <= \$m <= 255` and `1 <= \$n <= 8`.

Write a script to invert `\$n` bit from the end of the binary representation of `\$m` and print the decimal representation of the new binary number.

Example:

``````Input: \$m = 12, \$n = 3
Output: 8

Binary representation of \$m = 00001100
Invert 3rd bit from the end = 00001000
Decimal equivalent of 00001000 = 8

Input \$m = 18, \$n = 4
Output: 26

Binary representation of \$m = 00010010
Invert 4th bit from the end = 00011010
Decimal equivalent of 00011010 = 26
``````

## Invert Bit in Raku

We use the fmt method to convert the input numeral into a binary string. We could also use the `base` method, but the `fmt` method makes it possible to also specify an output format on 8 digits in one step (with leading 0’s when needed). Then we use the substr to obtain the value of the `\$nth` bit from the right (using the `*-\$n` subscript for that), and we use the substr-rw to modify the relevant bit. Finally, we use the parse-base to convert back the result into its numeric equivalent.

``````use v6;

sub invert-bit (UInt \$m where * <=255, UInt \$n where 1 <= * <= 8) {
my \$bin = \$m.fmt("%08b");
# say \$bin;
my \$bit = \$bin.substr(*-\$n, 1);
\$bin.substr-rw(*-\$n, 1) = \$bit == 0 ?? 1 !! 0;
# say \$bin;
return \$bin.parse-base(2);
}
for 12, 3,
18, 4,
249, 1 {
say "\$^a \$^b => ", invert-bit \$^a, \$^b;
}
``````

This program displays the following output:

``````\$ raku ./invert-bit.raku
12 3 => 8
18 4 => 26
249 1 => 248
``````

## Invert Bit in Perl

The Perl program is essentially a port to Perl of the Raku program above. Since Perl doesn’t have a binary string to numeral conversion, we re-use the `bin2dec` subroutine implemented in a previous challenge. And we use `sprintf` to perform decimal to binary representation conversion.

``````use strict;
use warnings;
use feature qw/say/;

sub bin2dec {
my \$bin = shift;
my \$sum = 0;
for my \$i (split //, \$bin) {
\$sum = \$sum * 2 + \$i;
}
return \$sum;
}

sub invert_bit {
my (\$m, \$n) = @_;
my \$bin = sprintf "%08b", \$m;
# say \$bin;
my \$bit = substr \$bin, -\$n, 1;
substr \$bin, -\$n, 1, \$bit == 0 ? 1 : 0;
# say \$bin;
return bin2dec \$bin;
}
for my \$pair ( [12, 3], [18, 4], [249, 1] ) {
say "@\$pair => ", invert_bit @\$pair;
}
``````

This program displays the following output:

``````\$ perl ./invert-bit.pl
12 3 => 8
18 4 => 26
249 1 => 248
``````

## Wrapping up

Because of my volunteer activity involvement in a Covid-19 vaccination center this weekend, I won’t have time this week to work on task 2. The traveling salesman problem has been studied in detail over decades and is not particularly difficult to understand and implement, but it does require quite a bit of coding effort for which I don’t have any free time this week.

The next week Perl Weekly Challenge will start soon. If you want to participate in this challenge, please check https://perlweeklychallenge.org/ and make sure you answer the challenge before 23:59 BST (British summer time) on July 25, 2021. And, please, also spread the word about the Perl Weekly Challenge if you can. I am the author of the "Think Perl 6" book (O'Reilly, 2017) and I blog about the Perl 5 and Raku programming languages.