lvrz.org

Perl Weekly Challenge 191

This week's first task is almost a continuation of task II.

Task 1: Binary Flip

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

My approach was the same for both the Go and Python solution, and I used the same algorithm as in the task explanation:

  1. find the binary equivalent of the given integer:
  1. flipping the binary digits:

Here's the code for both languages:

Python

import unittest

class TestSolutionI(unittest.TestCase):

    def binary_flip(self, n):
        mask = max(1, (1 << n.bit_length()) - 1)
        return n ^ mask

    def test_binary_flip(self):
        self.assertEqual(self.binary_flip(5), 2, "example 1")
        self.assertEqual(self.binary_flip(4), 3, "example 2")
        self.assertEqual(self.binary_flip(6), 1, "example 3")
        self.assertEqual(self.binary_flip(0), 1, "nasty edge case")
        self.assertEqual(self.binary_flip(-10), -7, "negative num edge case")


if __name__ == "__main__":
    unittest.main(verbosity=True)

Go

package main

import "math/bits"

func max(x, y int) int {
	if x > y {
		return x
	}
	return y
}

func BinaryFlip(n int) int {
	mask := max(1, (1<<(bits.Len(uint(n))) - 1))
	return n ^ mask
}

Task 2: Equal Distribution

You are given a list of integers greater than or equal to zero, @list.

Write a script to distribute the number so that each members are same.
If you succeed then print the total moves otherwise print -1.

Example 1:

Input: @list = (1, 0, 5)
Output: 4

Move #1: 1, 1, 4
(2nd cell gets 1 from the 3rd cell)

Move #2: 1, 2, 3
(2nd cell gets 1 from the 3rd cell)

Move #3: 2, 1, 3
(1st cell get 1 from the 2nd cell)

Move #4: 2, 2, 2
(2nd cell gets 1 from the 3rd cell)

Example 2:

Input: @list = (0, 2, 0)
Output: -1

It is not possible to make each same.

Example 3:

Input: @list = (0, 3, 0)
Output: 2

Move #1: 1, 2, 0
(1st cell gets 1 from the 2nd cell)

Move #2: 1, 1, 1
(3rd cell gets 1 from the 2nd cell)

When I initially sketched a solution for task II, I was going to approach it with Dynamic Programming and some bitmasks, until I realize that the solution was right in front of me. For example:

from statistics import mean
from unittest import main, TestCase

cases = [
    ([1, 0, 5], 4),
    ([0, 2, 0], -1),
    ([0, 3, 0], 2),
]

class TestSolutionII(TestCase):

    def equal_distro(self, _list):
        m = int(mean(_list))
        if m == 0:
            return -1
        else:
            return m + m

    def test_equal_distribution(self):
        for _input, output in cases:
            with self.subTest(_input=output):
                self.assertEqual(self.equal_distro(_input), output)


if __name__ == "__main__":
    main(verbosity=2)

Let's take Example 1:

The edge case on Example 2:

Moreover, we can extend this script to support reporting the desired distribution. We can simply refactor as follows:

def equal_distro(_list):
  from statistics import mean
  m = int(mean(_list))
  if m == 0:
    return -1
  else:
    print([m] * len(_list))
    return m + m

"""
>>> equal_distro([1, 0, 5])
[2, 2, 2]
4

>>> equal_distro([0, 2, 0])
-1

>>> equal_distro([0, 3, 0])
[1, 1, 1]
2
"""

This will give you the even distribution for each list that has a possible solution.

Happy hacking!

P.S: For the Go solutions. See here!


Reference

  1. https://docs.python.org/3/library/stdtypes.html#int.bit_length

#go #perl_weekly_challenge #python