Skip to content

Commit 5fb6644

Browse files
author
Jessica Yung
committed
fix(interviewcake): fix p3 greedy alg solution, add test
1 parent 07efef5 commit 5fb6644

File tree

1 file changed

+140
-0
lines changed

1 file changed

+140
-0
lines changed

interview-cake/p1_to_p3.py

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
import unittest
2+
from itertools import islice
3+
4+
5+
def get_max_profit(stock_prices_yesterday):
6+
"""Uses greedy approach. A greedy algorithm iterates through the problem space taking the optimal solution "so far,"
7+
until it reaches the end.
8+
9+
The greedy approach is only optimal if the problem has "optimal substructure," which means stitching together
10+
optimal solutions to sub-problems yields an optimal solution.
11+
"""
12+
if len(stock_prices_yesterday) < 2:
13+
raise IndexError("Getting a profit requires at least 2 prices.")
14+
min_price = stock_prices_yesterday[0]
15+
max_profit = stock_prices_yesterday[1] - stock_prices_yesterday[0]
16+
for index, price in enumerate(stock_prices_yesterday):
17+
if index == 0:
18+
continue
19+
current_price = price
20+
potential_profit = current_price - min_price
21+
22+
max_profit = max(max_profit, potential_profit)
23+
24+
min_price = min(min_price, current_price)
25+
return max_profit
26+
27+
28+
def get_product_of_all_ints_except_at_index(int_list):
29+
# Create list
30+
products = [None] * len(int_list)
31+
# print(products)
32+
cum_product = int_list[0]
33+
# print("First int: ", cum_product)
34+
products[0] = 1
35+
# Product of all numbers before int
36+
for i in range(1, len(int_list)):
37+
# print("before: ", i, cum_product)
38+
products[i] = cum_product
39+
cum_product *= int_list[i]
40+
# Product of all numbers after int
41+
after_product = int_list[-1]
42+
for j in range(2, len(int_list)+1):
43+
# print("after: ", len(int_list)+1-j, after_product)
44+
products[-j] *= after_product
45+
after_product *= int_list[-j]
46+
# print(products)
47+
return products
48+
49+
50+
def product(list_of_ints):
51+
return list_of_ints[0] * list_of_ints[1] * list_of_ints[2]
52+
53+
54+
def max_three(list_of_ints):
55+
sorted_list_of_ints = sorted(list_of_ints)
56+
return sorted_list_of_ints[:3]
57+
58+
59+
def min_three(list_of_ints):
60+
sorted_list_of_ints = sorted(list_of_ints)
61+
return sorted_list_of_ints[-3:]
62+
63+
64+
def highest_product_from_list_of_ints(list_of_ints):
65+
if len(list_of_ints) == 3:
66+
return product(list_of_ints)
67+
elif min(list_of_ints) >= 0:
68+
return product(max_three(list_of_ints))
69+
elif max(list_of_ints) <= 0:
70+
return product(min_three(list_of_ints))
71+
# If some are positive and some are negative
72+
else:
73+
# Sort in ascending order
74+
sorted_list_of_ints = sorted(list_of_ints)
75+
# We want one positive and
76+
# two neg or two pos, depending on which product is larger.
77+
if sorted_list_of_ints[1] < 0 or sorted_list_of_ints[-3] > 0:
78+
max_1 = sorted_list_of_ints[-1]
79+
max_pos = sorted_list_of_ints[-2] * sorted_list_of_ints[-3]
80+
max_neg = sorted_list_of_ints[0] * sorted_list_of_ints[1]
81+
max_2_3 = max(max_pos, max_neg)
82+
if max_2_3 > 0:
83+
return max_1 * max_2_3
84+
elif 0 in list_of_ints:
85+
return 0
86+
else:
87+
# The remaining alternative: Product is negative.
88+
# Precisely one negative number, two positive numbers and no zeroes.
89+
# That means we have precisely three integers. This case was covered.
90+
return "Error"
91+
92+
93+
def highest_product_from_list_of_ints_greedy(list_of_ints):
94+
highest_product_of_three = list_of_ints[0] * list_of_ints[1] * list_of_ints[2]
95+
# print(list_of_ints[0], "*", list_of_ints[1], "*", list_of_ints[2], "=", highest_product_of_three)
96+
highest = list_of_ints[0]
97+
lowest = list_of_ints[0]
98+
max_product_two = list_of_ints[0] * list_of_ints[1]
99+
min_product_two = list_of_ints[0] * list_of_ints[1]
100+
# Go through list
101+
for current in islice(list_of_ints, 2, None):
102+
# print("int: ", int)
103+
highest_product_of_three = max(current * max_product_two, current * min_product_two, highest_product_of_three)
104+
max_product_two = max(highest * current, lowest * current, max_product_two)
105+
min_product_two = min(lowest * current, lowest * current, min_product_two)
106+
highest = max(highest, current)
107+
lowest = min(lowest, current)
108+
# print("hpo3: ", highest_product_of_three, ", maxp2: ", max_product_two, ", minp2: ", min_product_two,
109+
# ", highest: ", highest, ", lowest: ", lowest)
110+
# print("highest product of three final: ", highest_product_of_three)
111+
return highest_product_of_three
112+
113+
# LOGIC:
114+
# PPP -> max*max_product_two
115+
# PPN -> min*max_product_two
116+
# PNN -> min*min_product_two
117+
# NNN -> max*min_product_two
118+
# NN...0 or PPN0 -> the 0 kicks in during highest_product_of_three = max(...)
119+
120+
121+
class Tests(unittest.TestCase):
122+
def test_p2_get_product_of_all_ints_except_at_index(self):
123+
numbers = [1, 2, 3]
124+
self.assertEqual(get_product_of_all_ints_except_at_index(numbers), [6, 3, 2])
125+
126+
def test_highest_product_from_list_of_ints(self):
127+
self.assertEqual(highest_product_from_list_of_ints([10, 2, 0, 3, -5]), 60)
128+
self.assertEqual(highest_product_from_list_of_ints([1000, 2, 0, -100]), 0)
129+
self.assertEqual(highest_product_from_list_of_ints([-10, -5, 1, 2, 3, 4]), 200)
130+
self.assertEqual(highest_product_from_list_of_ints([-10, -10, 1, 3, 2]), 300)
131+
132+
def test_highest_product_from_list_of_ints_greedy(self):
133+
self.assertEqual(highest_product_from_list_of_ints_greedy([10, 2, 0, 3, -5]), 60)
134+
self.assertEqual(highest_product_from_list_of_ints_greedy([1000, 2, 0, -100]), 0)
135+
self.assertEqual(highest_product_from_list_of_ints_greedy([-10, -5, 1, 2, 3, 4]), 200)
136+
self.assertEqual(highest_product_from_list_of_ints_greedy([-10, -10, 1, 3, 2]), 300)
137+
self.assertEqual(highest_product_from_list_of_ints_greedy([1, 2, -3]), -6)
138+
139+
if __name__ == '__main__':
140+
unittest.main()

0 commit comments

Comments
 (0)