-
Notifications
You must be signed in to change notification settings - Fork 0
/
Question1.py
159 lines (116 loc) · 4.13 KB
/
Question1.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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
from typing import List, Tuple
def restaurantFinder(d: int, revenues: List[int]) -> Tuple[int, List[int]]:
"""
This function takes as input a list of site revenues and a distance parameter and uses dynamic programming
to compute the most optimal set of sites to build to maximise revenue.
Approach description:
The approach is simple. For the first d+1 elements (where d is the distance constraint), the maximum revenue will
be the i(th) index itself.
:Input:
d: the distance constraint
revenues: list of revenues of each site
:Output,return or post condition:
Tuple (maximum revenue, list of site indexes in order)
:Time complexity:
----------------------
The dominant factor is the for loop which runs from 1 to len(revenues) which means it is at worst O(N) since the
for loop scales linearly with the size of the revenues list.
Best case = Worst case = O(N)
:Aux space complexity:
----------------------
The only auxiliary space being taken up is by the max_rev list and the tracking list which is always initiated to
the size of the input revenues list and so it will scale linearly with the input.
Best case = Worst case = O(N)
"""
# Base case if no list of revenues is provided or if only one site is available
if len(revenues) == 0 or sum(revenues) == 0:
return 0, []
elif len(revenues) == 1:
return revenues[0], [len(revenues)]
# Memoization
max_rev = [0] * len(revenues)
tracking = [None] * len(revenues)
two = d + 1 # Rename this back to s later
max_rev[0] = revenues[0]
tracking[0] = None
print(revenues)
print(max_rev)
print(tracking)
print()
for i in range(1, len(revenues)):
last_best_rev_i = i - two
prev_site_index = i - 1
if last_best_rev_i < 0:
if max_rev[prev_site_index] >= revenues[i]:
max_value = max_rev[prev_site_index]
if tracking[prev_site_index] is not None:
pos = tracking[prev_site_index]
else:
pos = prev_site_index
else:
max_value = revenues[i]
pos = None
max_rev[i] = max_value
tracking[i] = pos
print(revenues)
print(max_rev)
print(tracking)
print()
continue
by_policy_value = revenues[i] + max_rev[last_best_rev_i]
prev_value = max_rev[prev_site_index]
if by_policy_value >= prev_value:
max_rev[i] = by_policy_value
if last_best_rev_i < two and tracking[last_best_rev_i] is not None:
tracking[i] = tracking[last_best_rev_i]
else:
tracking[i] = last_best_rev_i
else:
# We found a new max revenue, and we will add to tracking the site that lead to this new max
max_rev[i] = prev_value
tracking[i] = prev_site_index
print(revenues)
print(max_rev)
print(tracking)
print()
max_value, pos = find_max(max_rev)
track = []
backtrack(tracking, pos, track)
return max_value, [i + 1 for i in track]
def find_max(arr: List[int]):
"""
:Input:
:Output,return or post condition:
:Time complexity:
----------------------
:Aux space complexity:
----------------------
"""
max_value_i = 0
max_value = arr[max_value_i]
for i in range(len(arr)):
curr_val = arr[i]
if curr_val > max_value:
max_value = curr_val
max_value_i = i
return max_value, max_value_i
def backtrack(tracking: List[int], i: int, result: List[int]):
"""
:Input:
:Output,return or post condition:
:Time complexity:
----------------------
:Aux space complexity:
----------------------
"""
if tracking[i] is None:
result.append(i)
return i
backtrack(tracking, tracking[i], result)
if tracking[i] != i:
result.append(i)
return i
if __name__ == '__main__':
rev = [50, 10, 12, 65, 40, 95, 100, 12, 20, 30]
d = 1
print(restaurantFinder(d, rev))