From b4689761d9ca284a3f6f3b6c096eb37d5b96fec6 Mon Sep 17 00:00:00 2001 From: William Carroll Date: Sun, 1 Mar 2020 21:30:25 +0000 Subject: [PATCH] Solve InterviewCake's highest-product-of-3 Write a function that returns the highest product of three integers within a list of integers. This solution uses a greedy algorithm that solves for the answer in linear time. The space complexity is constant. --- .../deepmind/part_two/highest-product-of-3.py | 81 +++++++++++++++++++ scratch/deepmind/part_two/todo.org | 2 +- 2 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 scratch/deepmind/part_two/highest-product-of-3.py diff --git a/scratch/deepmind/part_two/highest-product-of-3.py b/scratch/deepmind/part_two/highest-product-of-3.py new file mode 100644 index 000000000..8ebb5cf29 --- /dev/null +++ b/scratch/deepmind/part_two/highest-product-of-3.py @@ -0,0 +1,81 @@ +import unittest +import sys +import trace + + +def highest_product_of_3(xs): + if len(xs) < 3: + raise Exception("List needs to contain at least three elements.") + hp3 = xs[0] * xs[1] * xs[2] + hp2 = xs[0] * xs[1] + lp2 = xs[0] * xs[1] + hn = max(xs[0], xs[1]) + ln = min(xs[0], xs[1]) + for x in xs[2:]: + hp3 = max(hp3, hp2 * x, lp2 * x) + hp2 = max(hp2, hn * x, ln * x) + lp2 = min(lp2, hn * x, ln * x) + hn = max(hn, x) + ln = min(ln, x) + return hp3 + + +# Tests +class Test(unittest.TestCase): + def test_short_list(self): + actual = highest_product_of_3([1, 2, 3, 4]) + expected = 24 + self.assertEqual(actual, expected) + + def test_longer_list(self): + actual = highest_product_of_3([6, 1, 3, 5, 7, 8, 2]) + expected = 336 + self.assertEqual(actual, expected) + + def test_list_has_one_negative(self): + actual = highest_product_of_3([-5, 4, 8, 2, 3]) + expected = 96 + self.assertEqual(actual, expected) + + def test_list_has_two_negatives(self): + actual = highest_product_of_3([-10, 1, 3, 2, -10]) + expected = 300 + self.assertEqual(actual, expected) + + def test_list_is_all_negatives(self): + actual = highest_product_of_3([-5, -1, -3, -2]) + expected = -6 + self.assertEqual(actual, expected) + + def test_error_with_empty_list(self): + with self.assertRaises(Exception): + highest_product_of_3([]) + + def test_error_with_one_number(self): + with self.assertRaises(Exception): + highest_product_of_3([1]) + + def test_error_with_two_numbers(self): + with self.assertRaises(Exception): + highest_product_of_3([1, 1]) + + def test_custom(self): + actual = highest_product_of_3([9, 5, 2, 1, 7, 3]) + expected = 9 * 7 * 5 + self.assertEqual(actual, expected) + + +unittest.main(verbosity=2) + + +def main(): + highest_product_of_3([-5, -1, -3, -2]) + + +tracer = trace.Trace(ignoredirs=[sys.prefix, sys.exec_prefix], + trace=0, + count=1) + +tracer.run('main()') +r = tracer.results() +r.write_results(show_missing=True, coverdir=".") diff --git a/scratch/deepmind/part_two/todo.org b/scratch/deepmind/part_two/todo.org index ae73aed01..ed3cc5627 100644 --- a/scratch/deepmind/part_two/todo.org +++ b/scratch/deepmind/part_two/todo.org @@ -11,7 +11,7 @@ ** DONE Top Scores * Greedy Algorithms ** DONE Apple Stocks -** TODO Highest Product of 3 +** DONE Highest Product of 3 ** TODO Product of All Other Numbers ** TODO Cafe Order Checker ** TODO In-Place Shuffle