diff --git a/bit_manipulation/binary_and_operator.py b/bit_manipulation/binary_and_operator.py index f33b8b1c0ab4..701b3c88396f 100644 --- a/bit_manipulation/binary_and_operator.py +++ b/bit_manipulation/binary_and_operator.py @@ -1,49 +1,48 @@ +"""Bitwise AND helper. + +Return a zero-padded binary string representing ``a & b`` where the width is the +maximum bit length of the inputs. Only non-negative integers are accepted. + +>>> binary_and(25, 32) +'0b000000' +>>> binary_and(37, 50) +'0b100000' +>>> binary_and(21, 30) +'0b10100' +>>> binary_and(58, 73) +'0b0001000' +>>> binary_and(0, 255) +'0b00000000' +>>> binary_and(256, 256) +'0b100000000' + +Invalid inputs raise clear exceptions: + +>>> binary_and(0, -1) +Traceback (most recent call last): + ... +ValueError: inputs must be non-negative integers +>>> binary_and(0, 1.1) +Traceback (most recent call last): + ... +TypeError: inputs must be integers +>>> binary_and("0", "1") +Traceback (most recent call last): + ... +TypeError: inputs must be integers +""" + # https://www.tutorialspoint.com/python3/bitwise_operators_example.htm def binary_and(a: int, b: int) -> str: - """ - Take in 2 integers, convert them to binary, - return a binary number that is the - result of a binary and operation on the integers provided. - - >>> binary_and(25, 32) - '0b000000' - >>> binary_and(37, 50) - '0b100000' - >>> binary_and(21, 30) - '0b10100' - >>> binary_and(58, 73) - '0b0001000' - >>> binary_and(0, 255) - '0b00000000' - >>> binary_and(256, 256) - '0b100000000' - >>> binary_and(0, -1) - Traceback (most recent call last): - ... - ValueError: the value of both inputs must be positive - >>> binary_and(0, 1.1) - Traceback (most recent call last): - ... - ValueError: Unknown format code 'b' for object of type 'float' - >>> binary_and("0", "1") - Traceback (most recent call last): - ... - TypeError: '<' not supported between instances of 'str' and 'int' - """ + if not isinstance(a, int) or not isinstance(b, int): + raise TypeError("inputs must be integers") if a < 0 or b < 0: - raise ValueError("the value of both inputs must be positive") - - a_binary = format(a, "b") - b_binary = format(b, "b") - - max_len = max(len(a_binary), len(b_binary)) + raise ValueError("inputs must be non-negative integers") - return "0b" + "".join( - str(int(char_a == "1" and char_b == "1")) - for char_a, char_b in zip(a_binary.zfill(max_len), b_binary.zfill(max_len)) - ) + max_len = max(a.bit_length(), b.bit_length()) + return f"0b{(a & b):0{max_len}b}" if __name__ == "__main__": diff --git a/bit_manipulation/binary_or_operator.py b/bit_manipulation/binary_or_operator.py index 95f61f1da64e..ced9e4d2d4a4 100644 --- a/bit_manipulation/binary_or_operator.py +++ b/bit_manipulation/binary_or_operator.py @@ -1,45 +1,47 @@ +"""Bitwise OR helper. + +Return a zero-padded binary string representing ``a | b`` where the width is the +maximum bit length of the inputs. Only non-negative integers are accepted. + +>>> binary_or(25, 32) +'0b111001' +>>> binary_or(37, 50) +'0b110111' +>>> binary_or(21, 30) +'0b11111' +>>> binary_or(58, 73) +'0b1111011' +>>> binary_or(0, 255) +'0b11111111' +>>> binary_or(0, 256) +'0b100000000' + +Invalid inputs raise clear exceptions: + +>>> binary_or(0, -1) +Traceback (most recent call last): + ... +ValueError: inputs must be non-negative integers +>>> binary_or(0, 1.1) +Traceback (most recent call last): + ... +TypeError: inputs must be integers +>>> binary_or("0", "1") +Traceback (most recent call last): + ... +TypeError: inputs must be integers +""" + # https://www.tutorialspoint.com/python3/bitwise_operators_example.htm def binary_or(a: int, b: int) -> str: - """ - Take in 2 integers, convert them to binary, and return a binary number that is the - result of a binary or operation on the integers provided. - - >>> binary_or(25, 32) - '0b111001' - >>> binary_or(37, 50) - '0b110111' - >>> binary_or(21, 30) - '0b11111' - >>> binary_or(58, 73) - '0b1111011' - >>> binary_or(0, 255) - '0b11111111' - >>> binary_or(0, 256) - '0b100000000' - >>> binary_or(0, -1) - Traceback (most recent call last): - ... - ValueError: the value of both inputs must be positive - >>> binary_or(0, 1.1) - Traceback (most recent call last): - ... - TypeError: 'float' object cannot be interpreted as an integer - >>> binary_or("0", "1") - Traceback (most recent call last): - ... - TypeError: '<' not supported between instances of 'str' and 'int' - """ + if not isinstance(a, int) or not isinstance(b, int): + raise TypeError("inputs must be integers") if a < 0 or b < 0: - raise ValueError("the value of both inputs must be positive") - a_binary = str(bin(a))[2:] # remove the leading "0b" - b_binary = str(bin(b))[2:] - max_len = max(len(a_binary), len(b_binary)) - return "0b" + "".join( - str(int("1" in (char_a, char_b))) - for char_a, char_b in zip(a_binary.zfill(max_len), b_binary.zfill(max_len)) - ) + raise ValueError("inputs must be non-negative integers") + max_len = max(a.bit_length(), b.bit_length()) + return f"0b{(a | b):0{max_len}b}" if __name__ == "__main__": diff --git a/bit_manipulation/binary_xor_operator.py b/bit_manipulation/binary_xor_operator.py index 6206c70a99f6..3c69fdb135c0 100644 --- a/bit_manipulation/binary_xor_operator.py +++ b/bit_manipulation/binary_xor_operator.py @@ -1,49 +1,48 @@ +"""Bitwise XOR helper. + +Return a zero-padded binary string representing ``a ^ b`` where the width is the +maximum bit length of the inputs. Only non-negative integers are accepted. + +>>> binary_xor(25, 32) +'0b111001' +>>> binary_xor(37, 50) +'0b010111' +>>> binary_xor(21, 30) +'0b01011' +>>> binary_xor(58, 73) +'0b1110011' +>>> binary_xor(0, 255) +'0b11111111' +>>> binary_xor(256, 256) +'0b000000000' + +Invalid inputs raise clear exceptions: + +>>> binary_xor(0, -1) +Traceback (most recent call last): + ... +ValueError: inputs must be non-negative integers +>>> binary_xor(0, 1.1) +Traceback (most recent call last): + ... +TypeError: inputs must be integers +>>> binary_xor("0", "1") +Traceback (most recent call last): + ... +TypeError: inputs must be integers +""" + # https://www.tutorialspoint.com/python3/bitwise_operators_example.htm def binary_xor(a: int, b: int) -> str: - """ - Take in 2 integers, convert them to binary, - return a binary number that is the - result of a binary xor operation on the integers provided. - - >>> binary_xor(25, 32) - '0b111001' - >>> binary_xor(37, 50) - '0b010111' - >>> binary_xor(21, 30) - '0b01011' - >>> binary_xor(58, 73) - '0b1110011' - >>> binary_xor(0, 255) - '0b11111111' - >>> binary_xor(256, 256) - '0b000000000' - >>> binary_xor(0, -1) - Traceback (most recent call last): - ... - ValueError: the value of both inputs must be positive - >>> binary_xor(0, 1.1) - Traceback (most recent call last): - ... - TypeError: 'float' object cannot be interpreted as an integer - >>> binary_xor("0", "1") - Traceback (most recent call last): - ... - TypeError: '<' not supported between instances of 'str' and 'int' - """ + if not isinstance(a, int) or not isinstance(b, int): + raise TypeError("inputs must be integers") if a < 0 or b < 0: - raise ValueError("the value of both inputs must be positive") - - a_binary = str(bin(a))[2:] # remove the leading "0b" - b_binary = str(bin(b))[2:] # remove the leading "0b" - - max_len = max(len(a_binary), len(b_binary)) + raise ValueError("inputs must be non-negative integers") - return "0b" + "".join( - str(int(char_a != char_b)) - for char_a, char_b in zip(a_binary.zfill(max_len), b_binary.zfill(max_len)) - ) + max_len = max(a.bit_length(), b.bit_length()) + return f"0b{(a ^ b):0{max_len}b}" if __name__ == "__main__": diff --git a/bit_manipulation/is_even.py b/bit_manipulation/is_even.py index 6f95a1160797..f52f0228088d 100644 --- a/bit_manipulation/is_even.py +++ b/bit_manipulation/is_even.py @@ -1,17 +1,9 @@ def is_even(number: int) -> bool: - """ - return true if the input integer is even - Explanation: Lets take a look at the following decimal to binary conversions - 2 => 10 - 14 => 1110 - 100 => 1100100 - 3 => 11 - 13 => 1101 - 101 => 1100101 - from the above examples we can observe that - for all the odd integers there is always 1 set bit at the end - also, 1 in binary can be represented as 001, 00001, or 0000001 - so for any odd integer n => n&1 is always equals 1 else the integer is even + """Return True if the input integer is even using a bitwise check. + + Explanation: + In binary, even numbers always have the least significant bit cleared (0), + while odd numbers have it set (1). Therefore, ``n & 1 == 0`` implies even. >>> is_even(1) False @@ -27,8 +19,19 @@ def is_even(number: int) -> bool: True >>> is_even(101) False + >>> is_even(True) + Traceback (most recent call last): + ... + TypeError: input must be an integer + >>> is_even(3.14) + Traceback (most recent call last): + ... + TypeError: input must be an integer """ - return number & 1 == 0 + if not isinstance(number, int) or isinstance(number, bool): + # bool is a subclass of int; explicitly disallow it as a number here. + raise TypeError("input must be an integer") + return (number & 1) == 0 if __name__ == "__main__":