You have the four functions:
printFizz
that prints the word"fizz"
to the console,printBuzz
that prints the word"buzz"
to the console,printFizzBuzz
that prints the word"fizzbuzz"
to the console, andprintNumber
that prints a given integer to the console.
You are given an instance of the class FizzBuzz that has four functions: fizz, buzz, fizzbuzz and number. The same instance of FizzBuzz will be passed to four different threads:
Thread A: calls
fizz()
that should output the word"fizz"
.Thread B: calls
buzz()
that should output the word"buzz"
.Thread C: calls
fizzbuzz()
that should output the word"fizzbuzz"
.Thread D: calls
number()
that should only output the integers.
Modify the given class to output the series [1, 2, "fizz", 4, "buzz", ...] where the ith token (1-indexed) of the series is:
"fizzbuzz" if i is divisible by 3 and 5,
"fizz" if i is divisible by 3 and not 5,
"buzz" if i is divisible by 5 and not 3, or
i if i is not divisible by 3 or 5.
Implement the FizzBuzz class:
FizzBuzz(int n) Initializes the object with the number n that represents the length of the sequence that should be printed.
void fizz(printFizz) Calls printFizz to output "fizz".
void buzz(printBuzz) Calls printBuzz to output "buzz".
void fizzbuzz(printFizzBuzz) Calls printFizzBuzz to output "fizzbuzz".
void number(printNumber) Calls printnumber to output the numbers.
Example 1:
Input: n = 15
Output: [1,2,"fizz",4,"buzz","fizz",7,8,"fizz","buzz",11,"fizz",13,14,"fizzbuzz"]
Example 2:
Input: n = 5
Output: [1,2,"fizz",4,"buzz"]
Logic
loop through
n
, n times.check for every value of n ranging from 1 to n, if it mets the condition
Print out the right word.
Code Logic
for i in range(1,self.n+1):
if "condition is true":
"printWord()"
Let's understand this First!
Let's assume the order of thread execution is as follows Thread A
, Thread B
, Thread C
and Thread D
. The first step would be to write the logic of the code in the each of methods that run our functions to suit what each method is suppose to print out.
We loop through n and check if each value of n ranging from 1 to n mets the condition in the method. Unfortunately, Knowing the order of the thread and that Thread A runs first which automatically calls buzz method.
This would leave us in a complex situtation because Thread A would have to run n number of times before Thread B picks up. Sadly this is not we want to achieve. We want a situation where Thread A pauses after the first iteration permitting Thread B to run and then, Thread C picks up after Thread B's first iteration and same for Thread D. In other words, I want to keep all threads in sync.
To achieve this, we can use a threading object called barrier
Think of barrier as a delay that interupts a thread from continuing it's operation giving room to the next thread to carry out it's function and any other threads before the initial thread picks up from where it's last stop.
Code
from threading import Barrier
class FizzBuzz:
def __init__(self, n: int):
self.n = n
self.block = Barrier(4)
# printFizz() outputs "fizz"
def fizz(self, printFizz: 'Callable[[], None]') -> None:
for i in range(1,self.n+1):
if i%5!=0 and i%3==0:
printFizz()
self.block.wait()
# printBuzz() outputs "buzz"
def buzz(self, printBuzz: 'Callable[[], None]') -> None:
for i in range(1,self.n+1):
if i%3!=0 and i %5 ==0:
printBuzz()
self.block.wait()
# printFizzBuzz() outputs "fizzbuzz"
def fizzbuzz(self, printFizzBuzz: 'Callable[[], None]') -> None:
for i in range(1,self.n+1):
if i%5==0 and i%3==0:
printFizzBuzz()
self.block.wait()
# printNumber(x) outputs "x", where x is an integer.
def number(self, printNumber: 'Callable[[int], None]') -> None:
for i in range(1,self.n+1):
if (i % 3) !=0 and (i%5) !=0:
printNumber(i)
self.block.wait()
Understanding the Code
- Initialize barrier to 4, making it understand that 4 threads would be in sync. This would mean all 4 thread must hit the wait
self.block = Barrier(4)
-
Starting our Program, Thread A calls Buzz method, The loop begins from 1 then our
if
statement is skipped because the condition is false which leads to the next line of codeself.bar.wait()
. This preventsbuzz
method from running next iteration and giving control to next thread which isThread B
.
# printBuzz() outputs "buzz"
def buzz(self, printBuzz: 'Callable[[], None]') -> None:
for i in range(1,self.n+1):
if i%3!=0 and i %5 ==0:
printBuzz()
self.block.wait()
The advantage of this approach is that all threads would remain blocked when they call wait()
until the barrier reaches the specified number of threads waiting to be blocked before they get unblocked.
Top comments (0)