PWC192 - Binary Flip

TL;DR

Here we are with TASK #1 from The Weekly Challenge #192. Enjoy!

The challenge

You are given a positive integer, $n.

Write a script to find the binary flip.

Example 1

Input: $n = 5
Output: 2

First find the binary equivalent of the given integer, 101.
Then flip the binary digits 0 -> 1 and 1 -> 0 and we get 010.
So Binary 010 => Decimal 2.

Example 2

Input: $n = 4
Output: 3

Decimal 4 = Binary 100
Flip 0 -> 1 and 1 -> 0, we get 011.
Binary 011 = Decimal 3

Example 3

Input: $n = 6
Output: 1

Decimal 6 = Binary 110
Flip 0 -> 1 and 1 -> 0, we get 001.
Binary 001 = Decimal 1

The questions

Well well… not much of a definition, but an operative algorithm in the first example explains it pretty well.

We’re assuming that the positive integer $n fits in a variable, whatever the language and the system.

The solution

The result will always be (strictly) lower than the input. Why? The leftmost 1 bit in the input is turned onto a 0, so the resulting number is lower.

I know that there must be a clever way of doing it, especially in Raku. I’ll stick to the basics, though.

#!/usr/bin/env raku
use v6;
sub MAIN ($n = 5) { put binary-flip($n) }

sub binary-flip (Int $n is copy where * > 0) {
   my $mask = 0x01;
   my $result = 0;
   while $n {
      $result +|= $mask unless $n +& 1;
      $n +>= 1;
      $mask +<= 1;
   }
   return $result;
}

We’re getting bits out from the rightmost part and arranging them in with an always-doubling mask. Just plain bit handling.

The translation into Perl if pretty straightforward, with less input checks and slightly different operators:

#!/usr/bin/env perl
use v5.24;
use warnings;
use experimental 'signatures';
no warnings 'experimental::signatures';

say binary_flip(shift // 5);

sub binary_flip ($n) {
   my $mask = 0x01;
   my $result = 0;
   while ($n) {
      $result |= $mask unless $n & 0x01;
      $n >>= 1;
      $mask <<= 1;
   }
   return $result;
}

I guess this is everything, stay safe!


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