Skip to content

Commit a6ffb3e

Browse files
1116 Print Zero Even Odd.py
1 parent f05596a commit a6ffb3e

File tree

1 file changed

+95
-0
lines changed

1 file changed

+95
-0
lines changed

1116 Print Zero Even Odd.py

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
#!/usr/bin/python3
2+
"""
3+
uppose you are given the following code:
4+
5+
class ZeroEvenOdd {
6+
public ZeroEvenOdd(int n) { ... } // constructor
7+
public void zero(printNumber) { ... } // only output 0's
8+
public void even(printNumber) { ... } // only output even numbers
9+
public void odd(printNumber) { ... } // only output odd numbers
10+
}
11+
The same instance of ZeroEvenOdd will be passed to three different threads:
12+
13+
Thread A will call zero() which should only output 0's.
14+
Thread B will call even() which should only ouput even numbers.
15+
Thread C will call odd() which should only output odd numbers.
16+
Each of the threads is given a printNumber method to output an integer. Modify
17+
the given program to output the series 010203040506... where the length of the
18+
series must be 2n.
19+
20+
21+
Example 1:
22+
23+
Input: n = 2
24+
Output: "0102"
25+
Explanation: There are three threads being fired asynchronously. One of them
26+
calls zero(), the other calls even(), and the last one calls odd(). "0102" is
27+
the correct output.
28+
Example 2:
29+
30+
Input: n = 5
31+
Output: "0102030405"
32+
"""
33+
from typing import Callable
34+
from threading import Lock
35+
36+
37+
class ZeroEvenOdd:
38+
def __init__(self, n):
39+
"""
40+
only use 3 locks, and zero() knows and commonds which lock to release,
41+
determing whether even() or odd() will run.
42+
"""
43+
self.n = n
44+
self.locks = [Lock() for _ in range(3)]
45+
self.locks[1].acquire()
46+
self.locks[2].acquire()
47+
48+
# printNumber(x) outputs "x", where x is an integer.
49+
def zero(self, printNumber: Callable[[int], None]) -> None:
50+
for i in range(self.n):
51+
self.locks[0].acquire()
52+
printNumber(0)
53+
if (i + 1) % 2 == 1:
54+
self.locks[1].release()
55+
else:
56+
self.locks[2].release()
57+
58+
def odd(self, printNumber: Callable[[int], None]) -> None:
59+
for i in range((self.n + 1) // 2):
60+
self.locks[1].acquire()
61+
printNumber(i * 2 + 1)
62+
self.locks[0].release()
63+
64+
def even(self, printNumber: Callable[[int], None]) -> None:
65+
for i in range(self.n // 2):
66+
self.locks[2].acquire()
67+
printNumber(i * 2 + 2)
68+
self.locks[0].release()
69+
70+
71+
class ZeroEvenOddError:
72+
def __init__(self, n):
73+
"""
74+
Like 1115, two layer of locks can do: zero and non-zero alternating,
75+
odd and even alternating. 4 locks required.
76+
77+
Using only 3 locks?
78+
"""
79+
self.n = n
80+
self.locks = [Lock(), Lock(), Lock(), Lock()]
81+
for i in range(1, len(self.locks)):
82+
self.locks[i].acquire()
83+
84+
# printNumber(x) outputs "x", where x is an integer.
85+
def zero(self, printNumber: 'Callable[[int], None]') -> None:
86+
with self.locks[0]:
87+
printNumber(0)
88+
89+
def even(self, printNumber: 'Callable[[int], None]') -> None:
90+
# cannot lock self.locks[1] from both "even" and "odd"
91+
pass
92+
93+
94+
def odd(self, printNumber: 'Callable[[int], None]') -> None:
95+
pass

0 commit comments

Comments
 (0)