-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathprofitable-schemes.py
88 lines (78 loc) · 3.05 KB
/
profitable-schemes.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# 879. Profitable Schemes
# 🔴 Hard
#
# https://leetcode.com/problems/profitable-schemes/
#
# Tags: Array - Dynamic Programming
import json
import os
import timeit
from functools import cache
from typing import List
# Iterate over the indexes of the jobs, gang members and profit,
# computing the result of doing and skipping this job, if we go over
# the maximum allowed gang members, we return 0, this combination is
# not valid, if we reach the end of the array, we return 1 if we
# achieved the minimum profit and 0 if we didn't.
#
# Time complexity: O(n*mp*g) - Where n is the max number of gang members
# we can choose, mp is the minimum profit we need to make and g is the
# length of the profit and group arrays, these three are the ranges of
# the three parameters to the function that we are using to compute the
# results, since we are memoizing the function, that is the maximum
# number of times we may call it.
# Space complexity: O(n*mp*g) - The size of the cache, the call stack
# can grow to size g.
#
# Runtime 3903 ms Beats 26.67%
# Memory 682.3 MB Beats 5.71%
class Memoization:
def profitableSchemes(
self, n: int, minProfit: int, group: List[int], profit: List[int]
) -> int:
# Explore the possibilities
# idx: the index we are checking.
# p: the profit up to that point.
# g: the number of people pooled up to that point.
# return: the number of profitable schemes of that branch.
@cache
def dfs(i: int, p: int, g: int) -> int:
# Base case, we went over the group size limit.
if g > n:
return 0
# Base case, we run out of indexes.
if i == len(group):
return int(p == minProfit)
return dfs(
i + 1, min(minProfit, p + profit[i]), g + group[i]
) + dfs(i + 1, p, g)
# Return the result of the initial call.
return dfs(0, 0, 0) % (10**9 + 7)
# TODO: add the dynamic programming solution.
def test():
executors = [
Memoization,
]
__location__ = os.path.realpath(
os.path.join(os.getcwd(), os.path.dirname(__file__))
)
filename = os.path.splitext(os.path.basename(__file__))[0] + ".json"
with open(os.path.join(__location__, filename)) as json_file:
tests = json.load(json_file)
for executor in executors:
start = timeit.default_timer()
for _ in range(1):
for col, t in enumerate(tests):
sol = executor()
result = sol.profitableSchemes(t[0], t[1], t[2], t[3])
exp = t[4]
assert result == exp, (
f"\033[93m» {result} <> {exp}\033[91m for"
+ f" test {col} using \033[1m{executor.__name__}"
)
stop = timeit.default_timer()
used = str(round(stop - start, 5))
cols = "{0:20}{1:10}{2:10}"
res = cols.format(executor.__name__, used, "seconds")
print(f"\033[92m» {res}\033[0m")
test()