Peter
Peter Campbell Smith

Flipping easy and
distributing fairly

Weekly challenge 192 — 21 November 2022

Week 192 - 21 Nov 2022

Task 1

Task — Binary flip

You are given a positive integer, $n. Write a script to find the binary flip.

Examples


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

Analysis

Our first task this week is to take a positive integer, render it in binary, swap the zeroes for ones and vice versa, and output the result in decimal.

It's tempting to use the Perl bitwise not operator (~) to flip the bits, but inspection of the examples shows that's not quite what's wanted. The reason is that while we normally express 4, for example, as 100 in binary, the computer considers it to be 0000000000000100. Applying the ~ operator to that gives us 1111111111111011, which isn't the desired answer.

To get around that, note that the supplied number will always start with a 1 in its simple binary representation, so its flipped value will start with 0. And in its 16 (or whatever) bit representation, that will be preceded by a lot of 1s. So as it's just a string, we can safely just strip off all the leading 1s and the algorithm boils down to just two lines:

$flip = sprintf('%b', ~ $test);
$flip =~ s|^1+||;

Try it 

Try running the script with any input:



example: 23

Script


#!/usr/bin/perl

# Peter Campbell Smith - 2022-11-21
# PWC 192 task 1

use v5.28;
use utf8;
use warnings;

my (@tests, $test, $flip);

@tests = (5, 4, 6, 127, 128, 1234, 999999, 7294019678);

# loop over tests
while ($test = shift @tests) {
    $flip = sprintf('%b', $test);
    say qq[\nInput:  $test = 0b$flip];
    
    # 'not' the input and remove leading ones
    $flip = sprintf('%b', ~ $test);
    $flip =~ s|^1+||;
    say qq[Output: ] . oct('0b' . $flip) . qq[ = 0b$flip];   
}

Output


Input:  5 = 0b101
Output: 2 = 0b010

Input:  4 = 0b100
Output: 3 = 0b011

Input:  6 = 0b110
Output: 1 = 0b001

Input:  127 = 0b1111111
Output: 0 = 0b0000000

Input:  128 = 0b10000000
Output: 127 = 0b01111111

Input:  1234 = 0b10011010010
Output: 813 = 0b01100101101

Input:  999999 = 0b11110100001000111111
Output: 48576 = 0b00001011110111000000

Input:  7294019678 = 0b110110010110000011110100001011110
Output: 1295914913 = 0b001001101001111100001011110100001