[IN]: import string
[IN]: generate_cipher(string.ascii_lowercase, 13)
[OUT]: nopqrstuvwxyzabcdefghijkln
You just need to implement the generate_cipher ( ) function. The tests
run several test cases to validate the solution.
Solution:
def generate_cipher(alphabet, key=2):
cipher = ''
for letter in alphabet:
new_idx = (alphabet.index(letter) + key) % len(alphabet)
cipher += alphabet[new_idx]
return cipher
44. In cryptography, a Caesar cipher is one of the simplest and most widely
known encryption techniques. It is a type of substitution cipher in which each
letter in the string is replaced by a letter some fixed number of positions
down the alphabet.
An example of the encryption. Consider only capital letters in English (let's
just call it alphabet):
ABCDEFGHIJKLMNOPQRSTUVWXYZ
Shifting the above alphabet by a certain number (key = 2) gives us the cipher:
CDEFGHIJKLMNOPQRSTUVWXYZAB
Let's put it together:
ABCDEFGHIJKLMNOPQRSTUVWXYZ
CDEFGHIJKLMNOPQRSTUVWXYZAB
Note that for the last letters of the alphabet (Y, Z) the initial letters are
matched.
Note that for the last letters of the alphabet (Y, Z) the initial letters are
matched.
Having an alphabet and a cipher, we can start encrypting. Consider the
message below:
'ATTACK AT DAWN!'
Using the Caesar cipher with an offset of 2 (key = 2) we get:
CVVCEM CV FCYP!
A function called generate_cipher( ) has been implemented that generates the
Caesar cipher for the alphabet and key:
def generate_cipher(alphabet, key=2):
cipher = ''
for letter in alphabet:
new_idx = (alphabet.index(letter) + key) % len(alphabet)
cipher += alphabet[new_idx]
return cipher
Implement a function called encrypt( ) that takes three arguments:
• alphabet - the alphabet we want to use for encryption
• message - the message we want to encrypt
• key - key, offset
In the implementation, you can use the generate_cipher() function. If
any character in the message is not in the alphabet, add it as it is (for
example, a space or an exclamation point).
Example:
[IN]: import string
[IN]: encrypt(string.ascii_uppercase, 'PYTHON', 2)
[OUT]: RAVJQP
Example:
[IN]: import string
[IN]: encrypt(string.ascii_uppercase, 'ATTACK AT DAWN!', 2)
[OUT]: CVVCEM CV FCYP!
Example:
[IN]: import string
[IN]: encrypt(string.ascii_uppercase, 1 STOP THE ATTACK!', 13)
[OUT]: FGBC GUR NGGNPX!
You just need to implement the encrypt () function. The tests run several test
cases to validate the solution.
Solution:
import string
def generate_cipher(alphabet, key=2):
cipher = ''
for letter in alphabet:
new_idx = (alphabet.index(letter) + key) % len(alphabet)
cipher += alphabet[new_idx]
return cipher
def encrypt(alphabet, message, key):
cipher = generate_cipher(alphabet, key)
result = ''
for letter in message:
if letter not in alphabet:
result += letter
else:
result += cipher[alphabet.index(letter)]
return result
45. In cryptography, a Caesar cipher is one of the simplest and most widely
known encryption techniques. It is a type of substitution cipher in which each
letter in the string is replaced by a letter some fixed number of positions
down the alphabet.
An example of the encryption. Consider only capital letters in English (let's
just call it alphabet):
ABCDEFGHIJKLMNOPQRSTUVWXYZ
Shifting the above alphabet by a certain number (key = 2) gives us the cipher:
CDEFGHIJKLMNOPQRSTUVWXYZAB
Let's put it together:
ABCDEFGHIJKLMNOPQRSTUVWXYZ
CDEFGHIJKLMNOPQRSTUVWXYZAB
Note that for the last letters of the alphabet (Y, Z) the initial letters are
matched.
Note that for the last letters of the alphabet (Y, Z) the initial letters are
matched.
Having an alphabet and a cipher, we can start encrypting. Consider the
message below:
'ATTACK AT DAWN!'
Using the Caesar cipher with an offset of 2 (key = 2) we get:
CVVCEM CV FCYP!
A function called generate_cipher( ) has been implemented that generates the
Caesar cipher for the alphabet and key:
You are one of Caesar's commanders and you need to decode a
message that is critical to the success of your mission. Implement a
function called decrypt( ) that takes three arguments:
• alphabet - the alphabet we use for encryption
• message - the message we want to decrypt
• key - key, offset and decrypt the message.
In the implementation, you can use the encrypt( ) function.
In the implementation, you can use the encrypt( ) function.
Example:
[IN]: import string
[IN]: decrypt(string.ascii_uppercase, 'RAVJQP', 2)
[OUT]: PYTHON
Example:
[IN]: import string
[IN]: decrypt(string.ascii_uppercase, 'CVVCEM CV FCYP!', 2)
[OUT]: ATTACK AT DAWN!
Example:
[IN]: import string
[IN]: decrypt(string_ascii_uppercase, 1FGBC GUR NGGNPX!1, 13)
[OUT]: STOP THE ATTACK!
You just need to implement the decrypt () function. The tests run several test
cases to validate the solution.
import string
def generate_cipher(alphabet, key):
cipher = ''
for letter in alphabet:
new_idx = (alphabet.index(letter) + key) % len(alphabet)
cipher += alphabet[new_idx]
return cipher
def encrypt(alphabet, message, key):
cipher = generate_cipher(alphabet, key)
result = ''
for letter in message:
if letter not in alphabet:
result += letter
else:
result += cipher[alphabet.index(letter)]
return result
Solution:
import string
def generate_cipher(alphabet, key):
cipher = ''
for letter in alphabet:
new_idx = (alphabet.index(letter) + key) % len(alphabet)
cipher += alphabet[new_idx]
return cipher
def encrypt(alphabet, message, key):
cipher = generate_cipher(alphabet, key)
result = ''
for letter in message:
if letter not in alphabet:
result += letter
else:
result += cipher[alphabet.index(letter)]
return result
def decrypt(alphabet, message, key):
key = (-1) * key
return encrypt(alphabet, message, key)
46. In cryptography, a Caesar cipher is one of the simplest and most
widely known encryption techniques. It is a type of substitution cipher
in which each letter in the string is replaced by a letter some fixed
number of positions down the alphabet.
An example of the encryption. Consider only capital letters in English
(let's just call it alphabet):
ABCDEFGHIJKLMNOPQRSTUVWXYZ
Shifting the above alphabet by a certain number (key = 2) gives us the
cipher:
CDEFGHIJKLMNOPQRSTUVWXYZAB
Let's put it together:
ABCDEFGHIJKLMNOPQRSTUVWXYZ
CDEFGHIJKLMNOPQRSTUVWXYZAB
Note that for the last letters of the alphabet (Y, Z) the initial letters are
matched.
Note that for the last letters of the alphabet (Y, Z) the initial letters are
matched.
ATTACK AT DAWN!
Using the Caesar cipher with an offset of 2 (key = 2) we get:
'CVVCEM CV FCYP!'
Implement a solution to this problem using the object-oriented
programming (OOP) paradigm. Steps to do in this exercise:
1. Create a class named CaesarCipher
2. In the init() method set two instance attributes: alphabet and key.
3. Implement a read-only property called cipher that stores the cipher
You only need to implement CaesarCipher class. The tests run several test cases to validate the
solution.
Solution:
class CaesarCipher:
def __init__(self, alphabet, key):
self.alphabet = alphabet
self.key = key
@property
def cipher(self):
result = ''
for letter in self.alphabet:
new_idx = (self.alphabet.index(letter) + self.key) %
len(self.alphabet)
result += self.alphabet[new_idx]
return result
47. In cryptography, a Caesar cipher is one of the simplest and
most widely known encryption techniques. It is a type of substitution
cipher in which each letter in the string is replaced by a letter some
fixed number of positions down the alphabet.
An example of the encryption. Consider only capital letters in English
(let's just call it alphabet):
ABCDEFGHIJKLMNOPQRSTUVWXYZ
Shifting the above alphabet by a certain number (key = 2) gives us the
cipher:
CDEFGHIJKLMNOPQRSTUVWXYZAB
Let's put it together:
ABCDEFGHIJKLMNOPQRSTUVWXYZ
CDEFGHIJKLMNOPQRSTUVWXYZAB
Note that for the last letters of the alphabet (Y, Z) the initial letters are
matched.
Note that for the last letters of the alphabet (Y, Z) the initial letters are
matched.
ATTACK AT DAWN!
Using the Caesar cipher with an offset of 2 (key = 2) we get:
'CVVCEM CV FCYP!'
Implement a solution to this problem using the object-oriented
programming (OOP) paradigm. The CaesarCipher class is given:
class CaesarCipher:
def __init__(self, alphabet, key):
self.alphabet = alphabet
self.key = key
@property
def cipher(self):
result = ''
for letter in self.alphabet:
new_idx = (self.alphabet.index(letter) + self.key) % len(self.alphabet)
result += self.alphabet[new_idx]
return result
Follow the next steps in this exercise:
1. Implement an encrypt ( ) method that encrypts the message (message
argument)
2. Implement a decrypt ( ) method that decrypts the message (message
argument)
You just need to implement these methods. The tests run several test cases to
validate the solution.
Solution:
class CaesarCipher:
def __init__(self, alphabet, key):
self.alphabet = alphabet
self.key = key
@property
def cipher(self):
result = ''
for letter in self.alphabet:
new_idx = (self.alphabet.index(letter) + self.key) %
len(self.alphabet)
result += self.alphabet[new_idx]
return result
def encrypt(self, message):
result = ''
for letter in message:
if letter not in self.alphabet:
result += letter
else:
result += self.cipher[self.alphabet.index(letter)]
return result
def decrypt(self, message):
result = ''
for letter in message:
if letter not in self.alphabet:
result += letter
else:
result += self.alphabet[self.cipher.index(letter)]
return result
48. Monte Carlo methods are a broad class of computational
algorithms that rely on repeated random sampling to obtain numerical
results. The underlying concept is to use randomness to solve problems
that might be deterministic in principle. They are often used in physical
and mathematical problems and are most useful when it is difficult or
impossible to use other approaches.
Let's use the Monte Carlo method to approximate Pi. Consider the
coordinate system in RA2 space and a circle with a radius of 1 centered
at (0,0). The area of the circle is equal to Pi. Let's add a square on this
circle with vertices at (1,1 ), (1, -1 ), (-1, -1 ), (-1,1 ). The side of this
square is equal to 2 and its area is equal to 4.
Our task is to draw points from the given square according to the
uniform distribution and check whether the drawn point falls into the
circle. The probability of such an event is equal to the area of the circle
with radius 1, which is exactly Pi.
We choose the number of simulations freely, but basically the more
simulations we run, the better the approximation of Pi will be obtained.
The area of a circle can be calculated from the formula:
area of the circle = area of the square * (number of points drawn inside
the circle / number of all points drawn
Since we know that the area of the circle is equal to Pi, we can
substitute:
Pi = area of the square * (number of points drawn inside the circle /
number of all points drawn
In this exercise, implement a function called
generate_random_point() that generates a point with coordinates
between [-1,1] using the uniform distribution.
Use the built-in random module in your solution.
Example:
[IN]: generate_random_point()
[OUT]: (-0.7682761681456314, -0.00899286964820889)
Example:
[IN]: generate_random_point()
[OUT]: (-0.7744055968106591, -0.7127923185103238)
You just need to implement the generate_random_point( ) function.
The tests run several test cases to validate the solution.
Solution:
import random
def generate_random_point():
return random.uniform(-1, 1), random.uniform(-1, 1)
49. Monte Carlo methods are a broad class of computational
algorithms that rely on repeated random sampling to obtain numerical
results. The underlying concept is to use randomness to solve problems
that might be deterministic in principle. They are often used in physical
and mathematical problems and are most useful when it is difficult or
impossible to use other approaches.
Let's use the Monte Carlo method to approximate Pi. Consider the
coordinate system in RA2 space and a circle with a radius of 1 centered
at (0,0). The area of the circle is equal to Pi. Let's add a square on this
circle with vertices at (1,1 ), (1, -1 ), (-1, -1 ), (-1,1 ). The side of this
square is equal to 2 and its area is equal to 4.
Our task is to draw points from the given square according to the
uniform distribution and check whether the drawn point falls into the
circle. The probability of such an event is equal to the area of the circle
with radius 1, which is exactly Pi.
We choose the number of simulations freely, but basically the more
simulations we run, the better the approximation of Pi will be obtained.
The area of a circle can be calculated from the formula:
area of the circle = area of the square * (number of points drawn inside
the circle / number of all points drawn
Since we know that the area of the circle is equal to Pi, we can
substitute:
Pi = area of the square * (number of points drawn inside the circle /
number of all points drawn
A function called generate_random_point() has been implemented,
which generates a point with coordinates between [-1,1] according to
the uniform distribution.
Implement a function called is_in_unit_circie() that checks if a given
point falls into a circle with a radius of 1. The function returns True if
the point is inside the circle, otherwise False.
Set a random seed to 20 and pseudo-randomly generate 15 points by
assigning them to a list called points. Then call the is_in_unit_circie()
function at each point in the list and assign it
Expected result:
[True, True, True, False, True, False, True, True, True, True, True,
True, True, False, True]
import random
# Set random seed here
def generate_random_point():
return random.uniform(-1, 1), random.uniform(-1, 1)
50. Monte Carlo methods are a broad class of computational algorithms that
rely on repeated random sampling to obtain numerical results. The
underlying concept is to use randomness to solve problems that might be
deterministic in principle. They are often used in physical and mathematical
problems and are most useful when it is difficult or impossible to use other
approaches.
Let's use the Monte Carlo method to approximate Pi. Consider the
coordinate system in RA2 space and a circle with a radius of 1 centered at
(0,0). The area of the circle is equal to Pi. Let's add a square on this circle
with vertices at (1,1 ), (1, -1 ), (-1, -1 ), (-1,1 ). The side of this square is
equal to 2 and its area is equal to 4.
Our task is to draw points from the given square according to the uniform
distribution and check whether the drawn point falls into the circle. The
probability of such an event is equal to the area of the circle with radius 1,
which is exactly Pi.
We choose the number of simulations freely, but basically the more
simulations we run, the better the approximation of Pi will be obtained.
The area of a circle can be calculated from the formula:
area of the circle = area of the square * (number of points drawn inside the
circle / number of all points drawn
Since we know that the area of the circle is equal to Pi, we can substitute:
Pi = area of the square * (number of points drawn inside the circle / number
of all points drawn
A function called generate_random_point() has been implemented, which
generates a point with coordinates between [-1,1] according to the uniform
distribution. And we also have the
is_in_unit_circle() function.
Random seed is set to 10. Implement the estimate( ) function which takes the
number of simulations as an argument and returns the approximate value of
Pi based on the Monte Carlo method.
Example:
[IN]: estimate(10000)
[OUT]: 3.1528
You just need to implement the estimate( ) function. The tests run
several test cases to validate the solution.
import random
random.seed(10)
def generate_random_point():
return random.uniform(-1, 1), random.uniform(-1, 1)
def is_in_unit_circle(point):
return point[0] ** 2 + point[1] ** 2 <= 1
Solution:
import random
random.seed(10)
def generate_random_point():
return random.uniform(-1, 1), random.uniform(-1, 1)
def is_in_unit_circle(point):
return point[0] ** 2 + point[1] ** 2 <= 1
def estimate(simulations):
points_in_circle = 0
for _ in range(simulations):
point = generate_random_point()
if is_in_unit_circle(point):
points_in_circle += 1
result = 4 * points_in_circle / simulations
return result
51. Monte Carlo methods are a broad class of computational
algorithms that rely on repeated random sampling to obtain numerical
results. The underlying concept is to use randomness to solve problems that
might be deterministic in principle. They are often used in physical and
mathematical problems and are most useful when it is difficult or impossible
to use other approaches.
Let's use the Monte Carlo method to approximate Pi. Consider the
coordinate system in RA2 space and a circle with a radius of 1 centered at
(0,0). The area of the circle is equal to Pi. Let's add a square on this circle
with vertices at (1,1 ), (1, -1 ), (-1, -1 ), (-1,1 ). The side of this square is
equal to 2 and its area is equal to 4.
Our task is to draw points from the given square according to the uniform
distribution and check whether the drawn point falls into the circle. The
probability of such an event is equal to the area of the circle with radius 1,
which is exactly Pi.
We choose the number of simulations freely, but basically the more
simulations we run, the better the approximation of Pi will be obtained.
The area of a circle can be calculated from the formula:
area of the circle = area of the square * (number of points drawn inside the
circle / number of all points drawn
Since we know that the area of the circle is equal to Pi, we can substitute:
Pi = area of the square * (number of points drawn inside the circle / number
of all points drawn
Random seed was set to 10.
Implement a solution to this problem using the object-oriented
programming (OOP) paradigm. Create a class named MonteCarlo that
contains:
• init ( ) method, which sets an instance attribute named simulations
• a static method called generate_random_point() , which generates a
point with coordinates of numbers from the interval [-1,1] according to
the uniform distribution
• a static method called is_in_unit_circie() , which checks if a given point
falls into a circle with a radius of 1. The method returns a logical value True
if the point is inside the
circle, on the contrary False
• a method called estimate() that estimates the Pi number and returns the
approximate value of Pi based on the Monte Carlo method.
Example:
[IN]: monte = MonteCarlo(simulations=lO0O) [IN]: monte.estimate()
[OUT]: 3.208
You only need to implement the MonteCarlo class. The tests run several test
cases to validate the solution.
Solution:
import random
random.seed(10)
class MonteCarlo:
def __init__(self, simulations):
self.simulations = simulations
@staticmethod
def generate_random_point():
return random.uniform(-1, 1), random.uniform(-1, 1)
@staticmethod
def is_in_unit_circle(point):
return point[0] ** 2 + point[1] ** 2 <= 1
def estimate(self):
points_in_circle = 0
for _ in range(self.simulations):
point = MonteCarlo.generate_random_point()
if MonteCarlo.is_in_unit_circle(point):
points_in_circle += 1
result = 4 * points_in_circle / self.simulations
return result
52. Binary number system is a positional numeral system employing 2
as the base and so requiring only two different symbols for its digits, 0
and 1, instead of the usual 10 different symbols needed in the decimal
system. The numbers from 0 to 10 are thus in binary 0,1,10,11,100,101,
110,111,1000,1001, and 1010.
For example, the number 10 in binary can be represented as 1010
because:
1 *23 + 0*22 + 1 *21 + 0*20 = 8 + 0 + 2 + 0 = 10
How to easily convert a number from decimal to binary?
We can use a simple algorithm:
1. Find the remainder when dividing a number by 2 (this will be the
rightmost number in binary)
2. Divide a number by 2 using integer division - [//
3. Repeat the above steps until the number is greater than 0.
Implement a function called decimal_to_binary() that converts a
number from decimal to binary using the above algorithm. Remember
about 0.
Python has a built-in function to convert a number to binary called bin(
), but we will not use it in this exercise.
Example:
[IN]: decimal_to_binary(123)
[OUT]: '1111011'
Example:
[IN]: decimal_to_binary(3456)
[OUT]: '110110000000'
Example:
[IN]: decinal_to_binary(0)
[OUT]: 'O'
You only need to implement the decimai_to_binary( ) function. The
tests run several test cases to validate the solution.
Solution:
def decimal_to_binary(number):
if number == 0:
return '0'
result = ''
while number > 0:
result += str(number % 2)
number = number // 2
return result[::-1]
53. Binary number system is a positional numeral system employing 2 as the
base and so requiring only two different symbols for its digits, 0 and 1,
instead of the usual 10 different symbols needed in the decimal system. The
numbers from 0 to 10 are thus in binary 0,1,10,11,100,101,
110,111,1000,1001, and 1010.
For example, the number 10 in binary can be represented as 1010 because:
1 *23 + 0*22 + 1 *21 + 0*20 = 8 + 0 + 2 + 0 = 10
def decimal_to_binary(number):
if number == 0:
return '0'
result = ''
while number > 0:
result += str(number % 2)
number = number // 2
return result[::-1]
Now consider a bitwise AND operation on binary numbers. The operation is
applied to pairs of natural numbers by performing operations on the digits of
the binary notation of these numbers. A bitwise AND takes two equal-length
binary representations and performs the logical AND operation on each pair
of the corresponding bits, which is equivalent to multiplying them. Thus, if
both bits in the compared position are 1, the bit in the resulting binary
representation is 1 (1 * 1 = 1); otherwise, the result is 0 (1 x o = 0 and 0x0 =
0). For example:
00001010
10001100
------------
00001000
The above decimal numbers are 10 and 140. Where the binary number
is shorter, we put extra zeros on the left side to perform the operation.
The result of this operation is the number 00001000, which is the
number 8 in decimal notation. We can write the whole operation as
follows:
10 & 140 = 8
Implement a function called bitwise_and() that takes two decimal
numbers as arguments and returns the result of the bitwise AND
operation in decimal. You can use int() to convert a number from
binary to decimal. In case any of the arguments are less than zero raise
the ValueError with the message:
'Both numbers must be positive.'
Example:
[IN]: bttwise_and(10, 140)
[OUT]: 8
Example:
[IN]: bttwise_and(25, 19)
[OUT]: 17
Example:
[IN]: bitwise_and(-25, 19)
[OUT]: ValueError: Both numbers must be positive.
You just need to implement the bitwise_and ( ) function. The tests run
several test cases to validate the solution.
Solution:
def decimal_to_binary(number):
if number == 0:
return '0'
result = ''
while number > 0:
result += str(number % 2)
number = number // 2
return result[::-1]
def bitwise_and(a, b):
if a < 0 or b < 0:
raise ValueError('Both numbers must be positive.')
a_bin = decimal_to_binary(a)
b_bin = decimal_to_binary(b)
max_length = max(len(a_bin), len(b_bin))
a_zfill = a_bin.zfill(max_length)
b_zfill = b_bin.zfill(max_length)
binary_and = [str(int(char_a == '1' and char_b == '1')) for
char_a, char_b in zip(a_zfill, b_zfill)]
binary_result = ''.join(binary_and)
decimal_result = int(binary_result, base=2)
return decimal_result
54. . Binary number system is a positional numeral system employing 2 as
the base and so requiring only two different symbols for its digits, 0 and 1,
instead of the usual 10 different symbols needed in the decimal system. The
numbers from 0 to 10 are thus in binary 0,1,10,11,100,101,
110,111,1000,1001, and 1010.
For example, the number 10 in binary can be represented as 1010 because:
1 *23 + 0*22 + 1 *21 + 0*20 = 8 + 0 + 2 + 0 = 10
def decimal_to_binary(number):
if number == 0:
return '0'
result = ''
while number > 0:
result += str(number % 2)
number = number // 2
return result[::-1]
Now consider a bitwise AND operation on binary numbers. The operation is
applied to pairs of natural numbers by performing operations on the digits of
the binary notation of these numbers. A bitwise AND takes two equal-length
binary representations and performs the logical AND operation on each pair
of the corresponding bits, which is equivalent to multiplying them. Thus, if
both bits in the compared position are 1, the bit in the resulting binary
representation is 1 (1 * 1 = 1); otherwise, the result is 0 (1 x o = 0 and 0x0 =
0). For example:
00001010
10001100
------------
00001000
The above decimal numbers are 10 and 140. Where the binary
number is shorter, we put extra zeros on the left side to perform the
operation. The result of this operation is the number 10001110, which
is the number 142 in decimal notation. We can write the whole
operation as follows:
10 I 140 = 142
Implement a function called bitwise_or( ) that takes two decimal
numbers as arguments and returns the result of the bitwise OR
operation in decimal. You can use int( ) to convert a number from
binary to decimal. In case any of the arguments are less than zero raise
the ValueError with the message:
Both numbers must be positive.'
Example:
[IN]: bitwise_or(10, 140)
[OUT]: 142
Example:
[IN]: bltwise_or(10, 3)
[OUT]: 11
Example:
[IN]: bitwise_or(-10, 3)
[OUT]: ValueError: Both numbers must be positive.
You just need to implement the bitwise_or( ) function. The tests run several
test cases to validate the solution.
def decimal_to_binary(number):
if number == 0:
return '0'
result = ''
while number > 0:
result += str(number % 2)
number = number // 2
return result[::-1]
Solution:
def decimal_to_binary(number):
if number == 0:
return '0'
result = ''
while number > 0:
result += str(number % 2)
number = number // 2
return result[::-1]
def bitwise_or(a, b):
if a < 0 or b < 0:
raise ValueError('Both numbers must be positive.')
a_bin = decimal_to_binary(a)
b_bin = decimal_to_binary(b)
max_length = max(len(a_bin), len(b_bin))
a_zfill = a_bin.zfill(max_length)
b_zfill = b_bin.zfill(max_length)
binary_or = [str(int(char_a == '1' or char_b == '1')) for char_a,
char_b in zip(a_zfill, b_zfill)]
binary_result = ''.join(binary_or)
decimal_result = int(binary_result, base=2)
return decimal_result
55. Binary number system is a positional numeral system employing 2 as the
base and so requiring only two different symbols for its digits, 0 and 1,
instead of the usual 10 different symbols needed in the decimal system. The
numbers from 0 to 10 are thus in binary 0,1,10,11,100,101,
110,111,1000,1001, and 1010.
For example, the number 10 in binary can be represented as 1010 because:
1 *23 + 0*22 + 1 *21 + 0*20 = 8 + 0 + 2 + 0 = 10
def decimal_to_binary(number):
if number == 0:
return '0'
result = ''
while number > 0:
result += str(number % 2)
number = number // 2
return result[::-1]
Now consider a bitwise AND operation on binary numbers. The operation is
applied to pairs of natural numbers by performing operations on the digits of
the binary notation of these numbers. A bitwise AND takes two equal-length
binary representations and performs the logical AND operation on each pair
of the corresponding bits, which is equivalent to multiplying them. Thus, if
both bits in the compared position are 1, the bit in the resulting binary
representation is 1 (1 * 1 = 1); otherwise, the result is 0 (1 x o = 0 and 0x0 =
0). For example:
00001010
10001100
------------
00001000
The above decimal numbers are 10 and 140. Where the binary
number is shorter, we put extra zeros on the left side to perform the
operation. The result of this operation is the number 10001110, which
is the number 142 in decimal notation. We can write the whole
operation as follows:
10 I 140 = 142
Implement a function called bitwise_xor( ) that takes two
decimal numbers as arguments and returns the result of the bitwise
XOR operation in decimal. You can use int( ) to convert a number from
binary to decimal. In case any of the arguments are less than zero raise
the ValueError with the message:
Both numbers must be positive.'
Example:
[IN]: bitwise_xor(25, 19)
[OUT]: 10
Example:
[IN]: bitwise_xor(10, 3)
[OUT]: 9
Example:
[IN]: bitwise_xor(-10, 3)
[OUT]: ValueError: Both numbers must be positive.
You just need to implement the bitwise_xor() function. The tests run several test cases to validate the
solution.
def decimal_to_binary(number):
if number == 0:
return '0'
result = ''
while number > 0:
result += str(number % 2)
number = number // 2
return result[::-1]
Solutions:
def decimal_to_binary(number):
if number == 0:
return '0'
result = ''
while number > 0:
result += str(number % 2)
number = number // 2
return result[::-1]
def bitwise_xor(a, b):
if a < 0 or b < 0:
raise ValueError('Both numbers must be positive.')
a_bin = decimal_to_binary(a)
b_bin = decimal_to_binary(b)
max_length = max(len(a_bin), len(b_bin))
a_zfill = a_bin.zfill(max_length)
b_zfill = b_bin.zfill(max_length)
binary_xor = [str(int(char_a != char_b)) for char_a, char_b
in zip(a_zfill, b_zfill)]
binary_result = ''.join(binary_xor)
decimal_result = int(binary_result, base=2)
return decimal_result
56. Functional programming. Consider the following problem. We have an
iterable object, for example a list [3, 6, 8, 10] and we would like to perform
the following operations on the elements of the list:
(((3 + 6)) + 8) + 10 = (9 + 8) + 10 = 17 + 10 = 27
So we take the first item of the list, add a second item to it, then add another
item, and so on until all items in the list are exhausted. The result will be the
single value 27 - the sum of all elements.
Note that we have three steps. Each step is adding two numbers. We can
represent such a single
step with a simple function, for example:
def add(x, y):
return x + y
or in a lambda notation (anonymous function):
lambda x, y: x + y
In conclusion, we reduce the iterable object to some final value usinq a
reducing function. There
are three steps in such a process:
1. Calling a function on the first two elements of the iterable object and
generating a partial result
2. Calling a function on a partial result and the next element of the iterable
object
3. Repeating the process until all elements in the iterable object are
exhausted, and return the result
Implement a function called reduce( ) that takes two arguments: • function -
function used to reduce an iterable object
• ¡terable - iterable object
and reduces the iterable object with the function (return the result). If an
empty iterable object passed, the function should return the value None.
Example:
[IN]: reduce(lambda x, y: x + y, [1, 2, 3, 4])
[OUT]: 10
Example:
[IN]: reduce(lambda x, y: x + y, [])
[OUT]: None
Example:
[IN]: reduce(lambda x, y: x + y, ['p', 'y',’t’,‘o’, 'n'])
[OUT]: 'python
Example:
[IN]: reduce(lambda x, y: x + y, [[3, 4], [8, 4], [9, 1]])
[OUT]: [3, 4, 8, 4, 9, 1]
You just need to implement the reduce( ) function. The tests run several
test cases to validate the solution.
Solution:
def reduce(function, iterable):
if len(iterable) == 0:
return None
result = iterable[0]
for item in iterable[1:]:
result = function(result, item)
return result
57. Functional programming. Consider the following problem.
We have an iterable object, for example a list [3, 6, 8, 10] and we
would like to perform the following operations on the elements of the
list:
(((3 + 6)) + 8) + 10 = (9 + 8) + 10 = 17 + 10 = 27
So we take the first item of the list, add a second item to it, then add
another item, and so on until all items in the list are exhausted. The
result will be the single value 27 - the sum of all elements.
Note that we have three steps. Each step is adding two numbers. We
can represent such a single
step with a simple function, for example:
def add(x, y):
return x + y
or in a lambda notation (anonymous function):
lambda x, y: x + y
In conclusion, we reduce the iterable object to some final value usinq a
reducing function. There
are three steps in such a process:
1. Calling a function on the first two elements of the iterable object
and generating a partial result
2. Calling a function on a partial result and the next element of the
iterable object
3. Repeating the process until all elements in the iterable object are
exhausted, and return the result
Modify the reduce( ) function from the previous exercise into a function
called reduce_with_start() so that it takes a third argument called start, which
will be the starting value in the reduction process.
Example:
[IN]: reduce_with_start(lambda x, y: x + y, [1, 2, 3, 4], 100) [
OUT]: 110
Example:
[IN]: reduce_with_start(lambda x, y: x + y, [], 200)
[OUT]: 2O0
[IN]: reduce_with_start(lambda x, y: x + y, [' ', ‘3','9'], 'python')
[OUT]: [6, 7, 4, 10, 3, 4, 8, 4, 9, 1]
You just need to implement the reduce_with_start ( ) function. The tests run
several test cases to validate the solution.
def reduce(function, iterable):
if len(iterable) == 0:
return None
result = iterable[0]
for item in iterable[1:]:
result = function(result, item)
return result
Solution:
def reduce(function, iterable):
if len(iterable) == 0:
return None
result = iterable[0]
for item in iterable[1:]:
result = function(result, item)
return result
def reduce_with_start(function, iterable, start):
if len(iterable) == 0:
return start
result = start
for item in iterable:
result = function(result, item)
return result
58. Class inheritance. Consider a built-in list class. One of the methods of this
class is the append() method, which appends an item at the end of the list:
>» help(list.append)
Help on method_descriptor: append(self, object, /)
Append object to the end of the list.
An element can be, for example, an object of class int, float, str, bool or
NoneType.
By inheriting from a list class create a class named IntList that allows you to
append only int objects with the append ( ) method. If you try to append an
object of a different type raise a TypeError with the message:
'The value must be an integer.1
Example:
[IN]: integers = IntList()
[IN]: integers.append(3)
[IN]: integers.append(40)
[IN]: print(integers)
[OUT]: [3, 40]
[IN]: integers.append('sql')
[OUT]: TypeError: The value must be an integer.
You only need to implement the IntList class. The tests run several test
cases to validate the solution.
Solution:
class IntList(list):
def append(self, value):
if not isinstance(value, int):
raise TypeError('The value must be an integer.')
return list.append(self, value)
59. Class inheritance. Consider the built-in diet class. We can add key: value
pairs to the dictionary, for example:
dict[key] = value
For this purpose, the descriptor diet. setitem ( ) is called. Equivalently
we have:
diet. setiten (key, value)
Inheriting from the diet class create a class named IntDict that allows you to
add only pairs to the
dictionary whose value is an int object. Raise a TypeError with the message
otherwise:
'The value must be an integer.'
Example:
[IN]: integers = IntDict()
[IN]: integers['one'] = 1
[IN]: print(integers)
[OUT]: {'one1: 1, 'two': 2}
Example:
[IN]: integers['one'] = 'uno'
[OUT]: TypeError: The value must be an integer.
You only need to implement the IntDict class. The tests run several test cases
to validate the solution.
Solution:
class IntDict(dict):
def __setitem__(self, key, value):
if not isinstance(value, int):
raise TypeError('The value must be an integer.')
return dict.__setitem__(self, key, value)
60. The Matrix class has been implemented. Please note that the following
condition:
if not all(isinstance(number, (int, float)) for row in array for number in row):
raise TypeError('The values must be of type int or float.')
checks if the elements of a matrix are instances of the int or float type.
However, we must remember that the bool class in Python is a built-in class
that inherits from the int class and the following:
checks if the elements of a matrix are instances of the int or float type.
However, we must remember that the bool class in Python is a built-in class
that inherits from the int class and the following:
isinstance(True, Int)
returns True. Thus, with our implementation, we are able to create a matrix:
[IN]: Matrix([[True, False], [True, True]])
[OUT]: [[True, False], [True, True]]
Modify the implementation of the Matrix class to eliminate this behavior.
class Matrix:
def __init__(self, array):
if not isinstance(array, list):
raise TypeError('To create a matrix you need to pass a nested list of
values.')
if len(array) != 0:
if not all(isinstance(row, list) for row in array):
raise TypeError('Each element of the array (nested list) must be a
list.')
if not all(len(row) for row in array):
raise TypeError('Columns must contain at least one item.')
column_length = len(array[0])
if not all(len(row) == column_length for row in array):
raise TypeError('All columns must be the same length.')
if not all(isinstance(number, (int, float)) for row in array for number
in row):
raise TypeError('The values must be of type int or float.')
self.array = array
else:
self.array = []
def __repr__(self):
return str(self.array)
Solution:
class Matrix:
def __init__(self, array):
if not isinstance(array, list):
raise TypeError('To create a matrix you need to pass a nested list
of values.')
if len(array) != 0:
if not all(isinstance(row, list) for row in array):
raise TypeError('Each element of the array (nested list) must
be a list.')
if not all(len(row) for row in array):
raise TypeError('Columns must contain at least one item.')
column_length = len(array[0])
if not all(len(row) == column_length for row in array):
raise TypeError('All columns must be the same length.')
if not all(type(number) in (int, float) for row in array for
number in row):
raise TypeError('The values must be of type int or float.')
self.array = array
else:
self.array = []
def __repr__(self):
return str(self.array)