From a47770d66920fa6b7263a73cd70b3c5434ac574c Mon Sep 17 00:00:00 2001 From: larkeith Date: Wed, 18 Mar 2020 17:00:09 -0700 Subject: [PATCH 1/4] Work on assignment --- eating_cookies/eating_cookies.py | 107 ++++++++++++-- eating_cookies/test_eating_cookies.py | 26 ++-- knapsack/README.md | 8 +- knapsack/knapsack.py | 33 ++--- knapsack/test_knapsack.py | 197 +++++++++++++------------- making_change/README.md | 88 ++++++------ making_change/making_change.py | 74 ++++++++-- making_change/test_making_change.py | 43 +++--- recipe_batches/README.md | 18 +-- recipe_batches/recipe_batches.py | 12 +- recipe_batches/test_recipe_batches.py | 12 +- rock_paper_scissors/rps.py | 12 +- rock_paper_scissors/test_rps.py | 18 +-- stock_prices/stock_prices.py | 12 +- stock_prices/test_stock_prices.py | 16 +-- 15 files changed, 412 insertions(+), 264 deletions(-) mode change 100644 => 100755 eating_cookies/eating_cookies.py mode change 100644 => 100755 eating_cookies/test_eating_cookies.py mode change 100644 => 100755 knapsack/knapsack.py mode change 100644 => 100755 knapsack/test_knapsack.py mode change 100644 => 100755 making_change/making_change.py mode change 100644 => 100755 making_change/test_making_change.py mode change 100644 => 100755 recipe_batches/recipe_batches.py mode change 100644 => 100755 recipe_batches/test_recipe_batches.py mode change 100644 => 100755 rock_paper_scissors/rps.py mode change 100644 => 100755 rock_paper_scissors/test_rps.py mode change 100644 => 100755 stock_prices/stock_prices.py mode change 100644 => 100755 stock_prices/test_stock_prices.py diff --git a/eating_cookies/eating_cookies.py b/eating_cookies/eating_cookies.py old mode 100644 new mode 100755 index 62655d803..d35e8bddf --- a/eating_cookies/eating_cookies.py +++ b/eating_cookies/eating_cookies.py @@ -1,16 +1,105 @@ -#!/usr/bin/python +#!/usr/bin/env python + import sys +from typing import Hashable, Any + + +class Memoizer: + ''' + Class to facilitate memoization of function returns. + + Attributes: + functions ( + Dict[ + callable: Dict[ + Tuple[frozenset, frozenset]: Object + ] + ] + ) + A dictionary of functions: dictionary of args: results + + Methods: + get_result: Gets the result of a function call, either + by returning the stored result or by running the + function if no stored results are found. + ''' + + def __init__(self): + ''' + Inits a new Memoizer. + ''' + + self.functions = {} + + def get_result(self, function: callable, *args, **kwargs) -> Any: + ''' + Gets the result of a function call with specific arguments. + If the function has been called through get_result before with these + parameters in this Memoizer, this will return the memoized result. + Otherwise, it will run the function and memoize the new result. + + Args: + function (callable): The function to run. + This should *always* be idempotent or nullipotent. + *args: Variable length argument list. Passed to function. + **kwargs: Arbitrary keyword arguments. Passed to function. + + Returns: + Object: The return value of function. + ''' + + if function not in self.functions: + self.functions[function] = {} + + params = (frozenset(args), frozenset(kwargs)) + + if params in self.functions[function]: + return self.functions[function][params] + else: + self.functions[function][params] = function(*args, **kwargs) + return self.functions[function][params] + + # The cache parameter is here for if you want to implement -# a solution that is more efficient than the naive +# a solution that is more efficient than the naive # recursive solution -def eating_cookies(n, cache=None): - pass +def eating_cookies_recursive(n, cache=None): + if n < 0: + return 0 + elif n == 0: + return 1 + + if cache is None: + cache = Memoizer() + for i in range(n): + cache.get_result( + eating_cookies_recursive, + i, + cache=cache + ) + + permutations = 0 + can_eat = [1, 2, 3] + for cookie_count in can_eat: + permutations += cache.get_result( + eating_cookies_recursive, + n - cookie_count, + cache=cache + ) + + return permutations + + +eating_cookies = eating_cookies_recursive + if __name__ == "__main__": - if len(sys.argv) > 1: - num_cookies = int(sys.argv[1]) - print("There are {ways} ways for Cookie Monster to eat {n} cookies.".format(ways=eating_cookies(num_cookies), n=num_cookies)) - else: - print('Usage: eating_cookies.py [num_cookies]') \ No newline at end of file + if len(sys.argv) > 1: + num_cookies = int(sys.argv[1]) + print("There are {ways} ways for Cookie Monster to eat {n} cookies.".format(ways=eating_cookies(num_cookies), n=num_cookies)) + else: + print('Usage: eating_cookies.py [num_cookies]') + + diff --git a/eating_cookies/test_eating_cookies.py b/eating_cookies/test_eating_cookies.py old mode 100644 new mode 100755 index 1a4644786..3316da22c --- a/eating_cookies/test_eating_cookies.py +++ b/eating_cookies/test_eating_cookies.py @@ -1,20 +1,24 @@ +#!/usr/bin/env python + + import unittest from eating_cookies import eating_cookies + class Test(unittest.TestCase): - def test_eating_cookies_small_n(self): - self.assertEqual(eating_cookies(0), 1) - self.assertEqual(eating_cookies(1), 1) - self.assertEqual(eating_cookies(2), 2) - self.assertEqual(eating_cookies(5), 13) - self.assertEqual(eating_cookies(10), 274) + def test_eating_cookies_small_n(self): + self.assertEqual(eating_cookies(0), 1) + self.assertEqual(eating_cookies(1), 1) + self.assertEqual(eating_cookies(2), 2) + self.assertEqual(eating_cookies(5), 13) + self.assertEqual(eating_cookies(10), 274) - def test_eating_cookies_large_n(self): - self.assertEqual(eating_cookies(50, [0 for i in range(51)]), 10562230626642) - self.assertEqual(eating_cookies(100, [0 for i in range(101)]), 180396380815100901214157639) - self.assertEqual(eating_cookies(500, [0 for i in range(501)]), 1306186569702186634983475450062372018715120191391192207156664343051610913971927959744519676992404852130396504615663042713312314219527) + def test_eating_cookies_large_n(self): + self.assertEqual(eating_cookies(50), 10562230626642) + self.assertEqual(eating_cookies(100), 180396380815100901214157639) + self.assertEqual(eating_cookies(500), 1306186569702186634983475450062372018715120191391192207156664343051610913971927959744519676992404852130396504615663042713312314219527) if __name__ == '__main__': - unittest.main() + unittest.main() diff --git a/knapsack/README.md b/knapsack/README.md index 149a19ca3..5f072168d 100644 --- a/knapsack/README.md +++ b/knapsack/README.md @@ -42,8 +42,8 @@ You can run all of the tests with `python test_knapsack.py`, or run the tests in ## Hints 1. Base cases you might want to consider for a naive recursive implementation of this problem are: - * What if there are no items left to consider? - * What if the item I'm considering is too large to fit in my bag's remaining capacity? -2. In order to move towards one of our base cases, we'll pick up an item from the pile to consider, and add it to a copy of our bag. Now we have two versions of our bag, one with the item we're considering, and one without. All we have to do now is pick the bag that yields us a higher value. -3. As far as caching for this problem is concerned, a simple hash table or array is not going to suffice, because each solution now depends upon two parameters: the number of items in our pile to consider, as well as the capacity of our bag. So we'll need a 2x2 matrix in order to cache our answers adequately. + * What if there are no items left to consider? + * What if the item I'm considering is too large to fit in my bag's remaining capacity? +2. In order to move towards one of our base cases, we'll pick up an item from the pile to consider, and add it to a copy of our bag. Now we have two versions of our bag, one with the item we're considering, and one without. All we have to do now is pick the bag that yields us a higher value. +3. As far as caching for this problem is concerned, a simple hash table or array is not going to suffice, because each solution now depends upon two parameters: the number of items in our pile to consider, as well as the capacity of our bag. So we'll need a 2x2 matrix in order to cache our answers adequately. 4. Here's another way we might consider tackling this problem: what if we iterated through every single element in our pile and assign each one a value given by its value/weight ratio. Then we can sort all of the items based on this assigned value such that those items with a higher value/weight ratio are at the top of our sorted list of items. From there, we can just grab off the items at the top of our list until our bag is full. What would be the runtime complexity of this scheme? Would it work in every single scenario for any pile of items? diff --git a/knapsack/knapsack.py b/knapsack/knapsack.py old mode 100644 new mode 100755 index a130284f1..3fe16eb48 --- a/knapsack/knapsack.py +++ b/knapsack/knapsack.py @@ -5,22 +5,23 @@ Item = namedtuple('Item', ['index', 'size', 'value']) + def knapsack_solver(items, capacity): - pass - + pass + if __name__ == '__main__': - if len(sys.argv) > 1: - capacity = int(sys.argv[2]) - file_location = sys.argv[1].strip() - file_contents = open(file_location, 'r') - items = [] - - for line in file_contents.readlines(): - data = line.rstrip().split() - items.append(Item(int(data[0]), int(data[1]), int(data[2]))) - - file_contents.close() - print(knapsack_solver(items, capacity)) - else: - print('Usage: knapsack.py [filename] [capacity]') \ No newline at end of file + if len(sys.argv) > 1: + capacity = int(sys.argv[2]) + file_location = sys.argv[1].strip() + file_contents = open(file_location, 'r') + items = [] + + for line in file_contents.readlines(): + data = line.rstrip().split() + items.append(Item(int(data[0]), int(data[1]), int(data[2]))) + + file_contents.close() + print(knapsack_solver(items, capacity)) + else: + print('Usage: knapsack.py [filename] [capacity]') diff --git a/knapsack/test_knapsack.py b/knapsack/test_knapsack.py old mode 100644 new mode 100755 index 33e82a291..0ad6b658f --- a/knapsack/test_knapsack.py +++ b/knapsack/test_knapsack.py @@ -5,105 +5,106 @@ Item = namedtuple('Item', ['index', 'size', 'value']) + class Test(unittest.TestCase): - def setUp_small(self): - file_contents = open('data/small1.txt', 'r') - self.small_1_items = [] - - for line in file_contents.readlines(): - data = line.rstrip().split() - self.small_1_items.append(Item(int(data[0]), int(data[1]), int(data[2]))) - - file_contents.close() - - file_contents = open('data/small2.txt', 'r') - self.small_2_items = [] - - for line in file_contents.readlines(): - data = line.rstrip().split() - self.small_2_items.append(Item(int(data[0]), int(data[1]), int(data[2]))) - - file_contents.close() - - file_contents = open('data/small3.txt', 'r') - self.small_3_items = [] - - for line in file_contents.readlines(): - data = line.rstrip().split() - self.small_3_items.append(Item(int(data[0]), int(data[1]), int(data[2]))) - - file_contents.close() - - def cleanUp_small(self): - del self.small_1_items - del self.small_2_items - del self.small_3_items - - def setUp_medium(self): - file_contents = open('data/medium1.txt', 'r') - self.medium_1_items = [] - - for line in file_contents.readlines(): - data = line.rstrip().split() - self.medium_1_items.append(Item(int(data[0]), int(data[1]), int(data[2]))) - - file_contents.close() - - file_contents = open('data/medium2.txt', 'r') - self.medium_2_items = [] - - for line in file_contents.readlines(): - data = line.rstrip().split() - self.medium_2_items.append(Item(int(data[0]), int(data[1]), int(data[2]))) - - file_contents.close() - - file_contents = open('data/medium3.txt', 'r') - self.medium_3_items = [] - - for line in file_contents.readlines(): - data = line.rstrip().split() - self.medium_3_items.append(Item(int(data[0]), int(data[1]), int(data[2]))) - - file_contents.close() - - def cleanUp_medium(self): - del self.medium_1_items - del self.medium_2_items - del self.medium_3_items - - def setUp_large(self): - file_contents = open('data/large1.txt', 'r') - self.large_1_items = [] - - for line in file_contents.readlines(): - data = line.rstrip().split() - self.large_1_items.append(Item(int(data[0]), int(data[1]), int(data[2]))) - - file_contents.close() - - def cleanUp_large(self): - del self.large_1_items - - def test_with_small_input(self): - self.setUp_small() - self.assertEqual(knapsack_solver(self.small_1_items, 100), {'Value': 197, 'Chosen': [1, 7, 8]}) - self.assertEqual(knapsack_solver(self.small_2_items, 100), {'Value': 259, 'Chosen': [1, 9, 10]}) - self.assertEqual(knapsack_solver(self.small_3_items, 100), {'Value': 129, 'Chosen': [4, 5, 7, 9]}) - self.cleanUp_small() - - def test_with_medium_input(self): - self.setUp_medium() - self.assertEqual(knapsack_solver(self.medium_1_items, 100), {'Value': 1042, 'Chosen': [44, 49, 60, 77, 80, 83, 94, 104, 107, 117, 127, 134, 157, 160, 170]}) - self.assertEqual(knapsack_solver(self.medium_2_items, 100), {'Value': 969, 'Chosen': [1, 10, 27, 28, 66, 120, 139, 145, 153, 155, 174, 188, 191]}) - self.assertEqual(knapsack_solver(self.medium_3_items, 100), {'Value': 868, 'Chosen': [9, 14, 15, 47, 68, 108, 116, 120, 133, 154, 158, 161, 164, 170, 181, 198]}) - self.cleanUp_medium() - - def test_with_large_input(self): - self.setUp_large() - self.assertEqual(knapsack_solver(self.large_1_items, 100), {'Value': 2640, 'Chosen': [44, 83, 104, 107, 134, 160, 239, 271, 295, 297, 308, 335, 337, 370, 373, 420, 432, 561, 566, 623, 648, 671, 693, 704, 737, 782, 795, 796, 814, 844, 866, 907, 909, 913, 935, 949, 987, 997]}) - self.cleanUp_large() + def setUp_small(self): + file_contents = open('data/small1.txt', 'r') + self.small_1_items = [] + + for line in file_contents.readlines(): + data = line.rstrip().split() + self.small_1_items.append(Item(int(data[0]), int(data[1]), int(data[2]))) + + file_contents.close() + + file_contents = open('data/small2.txt', 'r') + self.small_2_items = [] + + for line in file_contents.readlines(): + data = line.rstrip().split() + self.small_2_items.append(Item(int(data[0]), int(data[1]), int(data[2]))) + + file_contents.close() + + file_contents = open('data/small3.txt', 'r') + self.small_3_items = [] + + for line in file_contents.readlines(): + data = line.rstrip().split() + self.small_3_items.append(Item(int(data[0]), int(data[1]), int(data[2]))) + + file_contents.close() + + def cleanUp_small(self): + del self.small_1_items + del self.small_2_items + del self.small_3_items + + def setUp_medium(self): + file_contents = open('data/medium1.txt', 'r') + self.medium_1_items = [] + + for line in file_contents.readlines(): + data = line.rstrip().split() + self.medium_1_items.append(Item(int(data[0]), int(data[1]), int(data[2]))) + + file_contents.close() + + file_contents = open('data/medium2.txt', 'r') + self.medium_2_items = [] + + for line in file_contents.readlines(): + data = line.rstrip().split() + self.medium_2_items.append(Item(int(data[0]), int(data[1]), int(data[2]))) + + file_contents.close() + + file_contents = open('data/medium3.txt', 'r') + self.medium_3_items = [] + + for line in file_contents.readlines(): + data = line.rstrip().split() + self.medium_3_items.append(Item(int(data[0]), int(data[1]), int(data[2]))) + + file_contents.close() + + def cleanUp_medium(self): + del self.medium_1_items + del self.medium_2_items + del self.medium_3_items + + def setUp_large(self): + file_contents = open('data/large1.txt', 'r') + self.large_1_items = [] + + for line in file_contents.readlines(): + data = line.rstrip().split() + self.large_1_items.append(Item(int(data[0]), int(data[1]), int(data[2]))) + + file_contents.close() + + def cleanUp_large(self): + del self.large_1_items + + def test_with_small_input(self): + self.setUp_small() + self.assertEqual(knapsack_solver(self.small_1_items, 100), {'Value': 197, 'Chosen': [1, 7, 8]}) + self.assertEqual(knapsack_solver(self.small_2_items, 100), {'Value': 259, 'Chosen': [1, 9, 10]}) + self.assertEqual(knapsack_solver(self.small_3_items, 100), {'Value': 129, 'Chosen': [4, 5, 7, 9]}) + self.cleanUp_small() + + def test_with_medium_input(self): + self.setUp_medium() + self.assertEqual(knapsack_solver(self.medium_1_items, 100), {'Value': 1042, 'Chosen': [44, 49, 60, 77, 80, 83, 94, 104, 107, 117, 127, 134, 157, 160, 170]}) + self.assertEqual(knapsack_solver(self.medium_2_items, 100), {'Value': 969, 'Chosen': [1, 10, 27, 28, 66, 120, 139, 145, 153, 155, 174, 188, 191]}) + self.assertEqual(knapsack_solver(self.medium_3_items, 100), {'Value': 868, 'Chosen': [9, 14, 15, 47, 68, 108, 116, 120, 133, 154, 158, 161, 164, 170, 181, 198]}) + self.cleanUp_medium() + + def test_with_large_input(self): + self.setUp_large() + self.assertEqual(knapsack_solver(self.large_1_items, 100), {'Value': 2640, 'Chosen': [44, 83, 104, 107, 134, 160, 239, 271, 295, 297, 308, 335, 337, 370, 373, 420, 432, 561, 566, 623, 648, 671, 693, 704, 737, 782, 795, 796, 814, 844, 866, 907, 909, 913, 935, 949, 987, 997]}) + self.cleanUp_large() if __name__ == '__main__': - unittest.main() \ No newline at end of file + unittest.main() diff --git a/making_change/README.md b/making_change/README.md index 224aa299e..8c6fdd0fb 100644 --- a/making_change/README.md +++ b/making_change/README.md @@ -1,18 +1,18 @@ # Making Change You work as a bank teller, handling people's bank transactions (this is your -part-time gig while you're studying at Lambda). +part-time gig while you're studying at Lambda). One day one of the wealthiest and also most eccentric patrons of the bank walks up to your stall. They hand you some cash and tell you they want you to figure out exactly how many ways there are to make change for the amount of money they plopped down in front of you using only pennies, nickels, dimes, quarters, and -half-dollars. +half-dollars. Since this is a bank, you have an infinite supply of coinange. Write a function `making_change` that receives as input an amount of money in cents as well as an array of coin denominations and calculates the total number of ways in which -change can be made for the input amount using the given coin denominations. +change can be made for the input amount using the given coin denominations. For example, `making_change(10)` should return 4, since there are 4 ways to make change for 10 cents using pennies, nickels, dimes, quarters, and half-dollars: @@ -22,14 +22,14 @@ change for 10 cents using pennies, nickels, dimes, quarters, and half-dollars: 3. We can use 2 nickels 4. We can use a single dime -## Testing +## Testing For this problem, there's a test that tests your implementation with small inputs (amounts of change up to 300 cents). There's also a separate test that -tests your implementation with large inputs (amounts of change >= 350 cents). +tests your implementation with large inputs (amounts of change >= 350 cents). You'll find that without implementing performance optimizations into your -solution, your solution will likely hang on the large input test. +solution, your solution will likely hang on the large input test. To run the tests separately, run `python test_making_change.py -k small` in order to run just the small input test. Run `python test_making_change.py -k @@ -42,44 +42,44 @@ making_change.py [amount]` ## Hints * This problem can be thought of as a more difficult version of the eating - cookies problem. + cookies problem. * As far as base cases go, again, think about some cases where we'd want the - recursion to stop executing. What should happen when the amount of cents - given is 0? What should happen when the amount of cents given is negative? - What about when we've used up all of the available coin denominations? + recursion to stop executing. What should happen when the amount of cents + given is 0? What should happen when the amount of cents given is negative? + What about when we've used up all of the available coin denominations? * As far as performance optimizations go, caching/memoization might be one - avenue we could go down. + avenue we could go down. * Building up values in our cache in an iterative fashion might also be a good - way to go about improving our implementation. - - Here's a general idea: we can initialize a cache as a list (a dictionary - would work fine as well) of 0s with a length equal to the amount we're - looking to make change for. Each value of the list will represent the number - of ways to make `i` cents, where `i` are the indices of the list. So - `cache[10] == 4` from our example above. Since we know there is one way to - make 0 cents in change, we'll initialize `cache[0] = 1` (you can seed entries - for additional values as well, though you don't actually need to). - - Now that we've initialized our cache, we'll start building it up. We have an - initial value in our cache, so we'll want to build up subsequent answers in - terms of this initial value. So, for a given coin, we can loop through all of - the higher amounts between our coin and the amount (i.e., `for higher_amount - in range(coin, amount + 1)`). If we take the difference between the higher - amount and the value of our coin, we can start building up the values in our - cache. - - To go into a little more detail, let's walk through a small example. If we - imagine our coin is a penny, in the first loop iteration, `higher_amount` is - going to be 1 (since it will at first be the same value as our coin). If we - take the difference between `higher_amount` and our coin value, we get 0. We - already have a value for 0 in our cache; it's 1. So now we've just figured - out 1 way to 1 cent from a penny. Add that answer to our cache. - - Next up, on the next iteration, `higher_amount` will now be 2. The difference - between `higher_amount` and our coin value now is 1. Well we just figured out - an answer for 1, so now we have an answer for 2. Add that to our cache. - - Once this loop finishes, we'll have figured out all of the ways to make - different amounts using the current coin. At that point, all we have to do is - perform that loop for every single coin, and then return the answer in our - cache for the original amount! + way to go about improving our implementation. + + Here's a general idea: we can initialize a cache as a list (a dictionary + would work fine as well) of 0s with a length equal to the amount we're + looking to make change for. Each value of the list will represent the number + of ways to make `i` cents, where `i` are the indices of the list. So + `cache[10] == 4` from our example above. Since we know there is one way to + make 0 cents in change, we'll initialize `cache[0] = 1` (you can seed entries + for additional values as well, though you don't actually need to). + + Now that we've initialized our cache, we'll start building it up. We have an + initial value in our cache, so we'll want to build up subsequent answers in + terms of this initial value. So, for a given coin, we can loop through all of + the higher amounts between our coin and the amount (i.e., `for higher_amount + in range(coin, amount + 1)`). If we take the difference between the higher + amount and the value of our coin, we can start building up the values in our + cache. + + To go into a little more detail, let's walk through a small example. If we + imagine our coin is a penny, in the first loop iteration, `higher_amount` is + going to be 1 (since it will at first be the same value as our coin). If we + take the difference between `higher_amount` and our coin value, we get 0. We + already have a value for 0 in our cache; it's 1. So now we've just figured + out 1 way to 1 cent from a penny. Add that answer to our cache. + + Next up, on the next iteration, `higher_amount` will now be 2. The difference + between `higher_amount` and our coin value now is 1. Well we just figured out + an answer for 1, so now we have an answer for 2. Add that to our cache. + + Once this loop finishes, we'll have figured out all of the ways to make + different amounts using the current coin. At that point, all we have to do is + perform that loop for every single coin, and then return the answer in our + cache for the original amount! diff --git a/making_change/making_change.py b/making_change/making_change.py old mode 100644 new mode 100755 index 9adad4470..7af2fe664 --- a/making_change/making_change.py +++ b/making_change/making_change.py @@ -1,17 +1,69 @@ -#!/usr/bin/python +#!/usr/bin/env python import sys -def making_change(amount, denominations): - pass +from typing import Hashable, Any, Iterable + + +def make_hashable(obj) -> Hashable: + try: + hash(obj) # Isinstance Hashable fails on nested objects + return obj + except TypeError: + if isinstance(obj, dict): + return tuple(sorted((make_hashable((key, value)) for key, value in obj.items()))) + elif isinstance(obj, Iterable): + return tuple((make_hashable(value) for value in obj)) + try: + return frozenset(obj) + except TypeError: + result = [] + for item in obj: + result.append(make_hashable(item)) + return tuple(result) + + +# The cache parameter is here for if you want to implement +# a solution that is more efficient than the naive +# recursive solution +def making_change(n, denominations, denomination_counts=None, parent_denominations=None): + if n < 0: + return 0 + elif n == 0: + return 1 + + if denomination_counts is None: + denomination_counts = set() + if parent_denominations is None: + parent_denominations = { + denomination: 0 for denomination in denominations + } + + # print(denomination_counts) + + combinations = 0 + for denomination in denominations: + new_denominations = parent_denominations.copy() + new_denominations[denomination] += 1 + if make_hashable(new_denominations) not in denomination_counts: + if n - denomination >= 0: + denomination_counts.add(make_hashable(new_denominations)) + combinations += making_change( + n - denomination, + denominations, + denomination_counts=denomination_counts, + parent_denominations=new_denominations, + ) + + return combinations if __name__ == "__main__": - # Test our your implementation from the command line - # with `python making_change.py [amount]` with different amounts - if len(sys.argv) > 1: - denominations = [1, 5, 10, 25, 50] - amount = int(sys.argv[1]) - print("There are {ways} ways to make {amount} cents.".format(ways=making_change(amount, denominations), amount=amount)) - else: - print("Usage: making_change.py [amount]") \ No newline at end of file + # Test our your implementation from the command line + # with `python making_change.py [amount]` with different amounts + if len(sys.argv) > 1: + denominations = [1, 5, 10, 25, 50] + amount = int(sys.argv[1]) + print("There are {ways} ways to make {amount} cents.".format(ways=making_change(amount, denominations), amount=amount)) + else: + print("Usage: making_change.py [amount]") \ No newline at end of file diff --git a/making_change/test_making_change.py b/making_change/test_making_change.py old mode 100644 new mode 100755 index 8e0505daa..51214b5b1 --- a/making_change/test_making_change.py +++ b/making_change/test_making_change.py @@ -1,30 +1,31 @@ import unittest -from making_change import making_change +from making_change import making_change + class Test(unittest.TestCase): - def setUp(self): - self.denominations = [1, 5, 10, 25, 50] + def setUp(self): + self.denominations = [1, 5, 10, 25, 50] - def test_making_change_small_amount(self): - self.assertEqual(making_change(0, self.denominations), 1) - self.assertEqual(making_change(1, self.denominations), 1) - self.assertEqual(making_change(5, self.denominations), 2) - self.assertEqual(making_change(10, self.denominations), 4) - self.assertEqual(making_change(20, self.denominations), 9) - self.assertEqual(making_change(30, self.denominations), 18) - self.assertEqual(making_change(100, self.denominations), 292) - self.assertEqual(making_change(200, self.denominations), 2435) - self.assertEqual(making_change(300, self.denominations), 9590) + def test_making_change_small_amount(self): + self.assertEqual(making_change(0, self.denominations), 1) + self.assertEqual(making_change(1, self.denominations), 1) + self.assertEqual(making_change(5, self.denominations), 2) + self.assertEqual(making_change(10, self.denominations), 4) + self.assertEqual(making_change(20, self.denominations), 9) + self.assertEqual(making_change(30, self.denominations), 18) + self.assertEqual(making_change(100, self.denominations), 292) + self.assertEqual(making_change(200, self.denominations), 2435) + self.assertEqual(making_change(300, self.denominations), 9590) - def test_making_change_large_amount(self): - self.assertEqual(making_change(350, self.denominations), 16472) - self.assertEqual(making_change(400, self.denominations), 26517) - self.assertEqual(making_change(1000, self.denominations), 801451) - self.assertEqual(making_change(2000, self.denominations), 11712101) - self.assertEqual(making_change(5000, self.denominations), 432699251) - self.assertEqual(making_change(10000, self.denominations), 6794128501) + def test_making_change_large_amount(self): + self.assertEqual(making_change(350, self.denominations), 16472) + self.assertEqual(making_change(400, self.denominations), 26517) + self.assertEqual(making_change(1000, self.denominations), 801451) + self.assertEqual(making_change(2000, self.denominations), 11712101) + self.assertEqual(making_change(5000, self.denominations), 432699251) + self.assertEqual(making_change(10000, self.denominations), 6794128501) if __name__ == '__main__': - unittest.main() \ No newline at end of file + unittest.main() \ No newline at end of file diff --git a/recipe_batches/README.md b/recipe_batches/README.md index 1cb922ded..462b43b70 100644 --- a/recipe_batches/README.md +++ b/recipe_batches/README.md @@ -4,28 +4,28 @@ Write a function that receives a recipe in the form of a dictionary, as well as ```python { - 'eggs': 5, - 'butter': 10, - 'sugar': 8, - 'flour': 15 + 'eggs': 5, + 'butter': 10, + 'sugar': 8, + 'flour': 15 } ``` -The keys will be the ingredient names, with their associated values being the amounts. In the case of the recipe dictionary, these amounts will represent the amount of each ingredient needed for the recipe, while in the case of the ingredients dictionary, the amounts represent the amounts available to you. +The keys will be the ingredient names, with their associated values being the amounts. In the case of the recipe dictionary, these amounts will represent the amount of each ingredient needed for the recipe, while in the case of the ingredients dictionary, the amounts represent the amounts available to you. -Your function should output the maximum number of whole batches that can be made for the supplied recipe using the ingredients available to you, as indicated by the second dictionary. +Your function should output the maximum number of whole batches that can be made for the supplied recipe using the ingredients available to you, as indicated by the second dictionary. For example ```python # should return 0 since we don't have enough butter! recipe_batches( - { 'milk': 100, 'butter': 50, 'flour': 5 }, - { 'milk': 138, 'butter': 48, 'flour': 51 } + { 'milk': 100, 'butter': 50, 'flour': 5 }, + { 'milk': 138, 'butter': 48, 'flour': 51 } ) ``` -## Testing +## Testing Run the test file by executing `python test_recipe_batches.py`. diff --git a/recipe_batches/recipe_batches.py b/recipe_batches/recipe_batches.py old mode 100644 new mode 100755 index c845950c5..fddbe4e2e --- a/recipe_batches/recipe_batches.py +++ b/recipe_batches/recipe_batches.py @@ -3,12 +3,12 @@ import math def recipe_batches(recipe, ingredients): - pass + pass if __name__ == '__main__': - # Change the entries of these dictionaries to test - # your implementation with different inputs - recipe = { 'milk': 100, 'butter': 50, 'flour': 5 } - ingredients = { 'milk': 132, 'butter': 48, 'flour': 51 } - print("{batches} batches can be made from the available ingredients: {ingredients}.".format(batches=recipe_batches(recipe, ingredients), ingredients=ingredients)) \ No newline at end of file + # Change the entries of these dictionaries to test + # your implementation with different inputs + recipe = { 'milk': 100, 'butter': 50, 'flour': 5 } + ingredients = { 'milk': 132, 'butter': 48, 'flour': 51 } + print("{batches} batches can be made from the available ingredients: {ingredients}.".format(batches=recipe_batches(recipe, ingredients), ingredients=ingredients)) \ No newline at end of file diff --git a/recipe_batches/test_recipe_batches.py b/recipe_batches/test_recipe_batches.py old mode 100644 new mode 100755 index ba0c63190..ff1398217 --- a/recipe_batches/test_recipe_batches.py +++ b/recipe_batches/test_recipe_batches.py @@ -3,12 +3,12 @@ class Test(unittest.TestCase): - def test_recipe_batches(self): - self.assertEqual(recipe_batches({ 'milk': 100, 'flour': 4, 'sugar': 10, 'butter': 5 }, { 'milk': 1288, 'flour': 9, 'sugar': 95 }), 0) - self.assertEqual(recipe_batches({ 'milk': 100, 'butter': 50, 'cheese': 10 }, { 'milk': 198, 'butter': 52, 'cheese': 10 }), 1) - self.assertEqual(recipe_batches({ 'milk': 2, 'sugar': 40, 'butter': 20 }, { 'milk': 5, 'sugar': 120, 'butter': 500 }), 2) - self.assertEqual(recipe_batches({ 'milk': 2 }, { 'milk': 200}), 100) + def test_recipe_batches(self): + self.assertEqual(recipe_batches({ 'milk': 100, 'flour': 4, 'sugar': 10, 'butter': 5 }, { 'milk': 1288, 'flour': 9, 'sugar': 95 }), 0) + self.assertEqual(recipe_batches({ 'milk': 100, 'butter': 50, 'cheese': 10 }, { 'milk': 198, 'butter': 52, 'cheese': 10 }), 1) + self.assertEqual(recipe_batches({ 'milk': 2, 'sugar': 40, 'butter': 20 }, { 'milk': 5, 'sugar': 120, 'butter': 500 }), 2) + self.assertEqual(recipe_batches({ 'milk': 2 }, { 'milk': 200}), 100) if __name__ == '__main__': - unittest.main() \ No newline at end of file + unittest.main() \ No newline at end of file diff --git a/rock_paper_scissors/rps.py b/rock_paper_scissors/rps.py old mode 100644 new mode 100755 index 0fc53356e..ad752c9c9 --- a/rock_paper_scissors/rps.py +++ b/rock_paper_scissors/rps.py @@ -3,12 +3,12 @@ import sys def rock_paper_scissors(n): - pass + pass if __name__ == "__main__": - if len(sys.argv) > 1: - num_plays = int(sys.argv[1]) - print(rock_paper_scissors(num_plays)) - else: - print('Usage: rps.py [num_plays]') \ No newline at end of file + if len(sys.argv) > 1: + num_plays = int(sys.argv[1]) + print(rock_paper_scissors(num_plays)) + else: + print('Usage: rps.py [num_plays]') \ No newline at end of file diff --git a/rock_paper_scissors/test_rps.py b/rock_paper_scissors/test_rps.py old mode 100644 new mode 100755 index 9bcefd746..224ed5e26 --- a/rock_paper_scissors/test_rps.py +++ b/rock_paper_scissors/test_rps.py @@ -1,16 +1,16 @@ import unittest -from rps import rock_paper_scissors +from rps import rock_paper_scissors class Test(unittest.TestCase): - def test_rock_paper_scissors_output(self): - self.assertEqual(rock_paper_scissors(0), [[]]) - self.assertEqual(rock_paper_scissors(1), [['rock'], ['paper'], ['scissors']]) - self.assertEqual(rock_paper_scissors(2), [['rock', 'rock'], ['rock', 'paper'], ['rock', 'scissors'], ['paper', 'rock'], ['paper', 'paper'], ['paper', 'scissors'], ['scissors', 'rock'], ['scissors', 'paper'], ['scissors', 'scissors']]) - self.assertEqual(rock_paper_scissors(3), [['rock', 'rock', 'rock'], ['rock', 'rock', 'paper'], ['rock', 'rock', 'scissors'], ['rock', 'paper', 'rock'], ['rock', 'paper', 'paper'], ['rock', 'paper', 'scissors'], ['rock', 'scissors', 'rock'], ['rock', 'scissors', 'paper'], ['rock', 'scissors', 'scissors'], ['paper', 'rock', 'rock'], ['paper', 'rock', 'paper'], ['paper', 'rock', 'scissors'], ['paper', 'paper', 'rock'], ['paper', 'paper', 'paper'], ['paper', 'paper', 'scissors'], ['paper', 'scissors', 'rock'], ['paper', 'scissors', 'paper'], ['paper', 'scissors', 'scissors'], ['scissors', 'rock', 'rock'], ['scissors', 'rock', 'paper'], ['scissors', 'rock', 'scissors'], ['scissors', 'paper', 'rock'], ['scissors', 'paper', 'paper'], ['scissors', 'paper', 'scissors'], ['scissors', 'scissors', 'rock'], ['scissors', 'scissors', 'paper'], ['scissors', 'scissors', 'scissors']]) - self.assertEqual(rock_paper_scissors(4), [['rock', 'rock', 'rock', 'rock'], ['rock', 'rock', 'rock', 'paper'], ['rock', 'rock', 'rock', 'scissors'], ['rock', 'rock', 'paper', 'rock'], ['rock', 'rock', 'paper', 'paper'], ['rock', 'rock', 'paper', 'scissors'], ['rock', 'rock', 'scissors', 'rock'], ['rock', 'rock', 'scissors', 'paper'], ['rock', 'rock', 'scissors', 'scissors'], ['rock', 'paper', 'rock', 'rock'], ['rock', 'paper', 'rock', 'paper'], ['rock', 'paper', 'rock', 'scissors'], ['rock', 'paper', 'paper', 'rock'], ['rock', 'paper', 'paper', 'paper'], ['rock', 'paper', 'paper', 'scissors'], ['rock', 'paper', 'scissors', 'rock'], ['rock', 'paper', 'scissors', 'paper'], ['rock', 'paper', 'scissors', 'scissors'], ['rock', 'scissors', 'rock', 'rock'], ['rock', 'scissors', 'rock', 'paper'], ['rock', 'scissors', 'rock', 'scissors'], ['rock', 'scissors', 'paper', 'rock'], ['rock', 'scissors', 'paper', 'paper'], ['rock', 'scissors', 'paper', 'scissors'], ['rock', 'scissors', 'scissors', 'rock'], ['rock', 'scissors', 'scissors', 'paper'], ['rock', 'scissors', 'scissors', 'scissors'], ['paper', 'rock', 'rock', 'rock'], ['paper', 'rock', 'rock', 'paper'], ['paper', 'rock', 'rock', 'scissors'], ['paper', 'rock', 'paper', 'rock'], ['paper', 'rock', 'paper', 'paper'], ['paper', 'rock', 'paper', 'scissors'], ['paper', 'rock', 'scissors', 'rock'], ['paper', 'rock', 'scissors', 'paper'], ['paper', 'rock', 'scissors', 'scissors'], ['paper', 'paper', 'rock', 'rock'], ['paper', 'paper', 'rock', 'paper'], ['paper', 'paper', 'rock', 'scissors'], ['paper', 'paper', 'paper', 'rock'], ['paper', 'paper', 'paper', 'paper'], ['paper', 'paper', 'paper', 'scissors'], ['paper', 'paper', 'scissors', 'rock'], ['paper', 'paper', 'scissors', 'paper'], ['paper', 'paper', 'scissors', 'scissors'], ['paper', 'scissors', 'rock', 'rock'], ['paper', 'scissors', 'rock', 'paper'], ['paper', 'scissors', 'rock', 'scissors'], ['paper', 'scissors', 'paper', 'rock'], ['paper', 'scissors', 'paper', 'paper'], ['paper', 'scissors', 'paper', 'scissors'], ['paper', 'scissors', 'scissors', 'rock'], ['paper', 'scissors', 'scissors', 'paper'], ['paper', 'scissors', 'scissors', 'scissors'], ['scissors', 'rock', 'rock', 'rock'], ['scissors', 'rock', 'rock', 'paper'], ['scissors', 'rock', 'rock', 'scissors'], ['scissors', 'rock', 'paper', 'rock'], ['scissors', 'rock', 'paper', 'paper'], ['scissors', 'rock', 'paper', 'scissors'], ['scissors', 'rock', 'scissors', 'rock'], ['scissors', 'rock', 'scissors', 'paper'], ['scissors', 'rock', 'scissors', 'scissors'], ['scissors', 'paper', 'rock', 'rock'], ['scissors', 'paper', 'rock', 'paper'], ['scissors', 'paper', 'rock', 'scissors'], ['scissors', 'paper', 'paper', 'rock'], ['scissors', 'paper', 'paper', 'paper'], ['scissors', 'paper', 'paper', 'scissors'], ['scissors', 'paper', 'scissors', 'rock'], ['scissors', 'paper', 'scissors', 'paper'], ['scissors', 'paper', 'scissors', 'scissors'], ['scissors', 'scissors', 'rock', 'rock'], ['scissors', 'scissors', 'rock', 'paper'], ['scissors', 'scissors', 'rock', 'scissors'], ['scissors', 'scissors', 'paper', 'rock'], ['scissors', 'scissors', 'paper', 'paper'], ['scissors', 'scissors', 'paper', 'scissors'], ['scissors', 'scissors', 'scissors', 'rock'], ['scissors', 'scissors', 'scissors', 'paper'], ['scissors', 'scissors', 'scissors', 'scissors']]) - self.assertEqual(rock_paper_scissors(5), [['rock', 'rock', 'rock', 'rock', 'rock'], ['rock', 'rock', 'rock', 'rock', 'paper'], ['rock', 'rock', 'rock', 'rock', 'scissors'], ['rock', 'rock', 'rock', 'paper', 'rock'], ['rock', 'rock', 'rock', 'paper', 'paper'], ['rock', 'rock', 'rock', 'paper', 'scissors'], ['rock', 'rock', 'rock', 'scissors', 'rock'], ['rock', 'rock', 'rock', 'scissors', 'paper'], ['rock', 'rock', 'rock', 'scissors', 'scissors'], ['rock', 'rock', 'paper', 'rock', 'rock'], ['rock', 'rock', 'paper', 'rock', 'paper'], ['rock', 'rock', 'paper', 'rock', 'scissors'], ['rock', 'rock', 'paper', 'paper', 'rock'], ['rock', 'rock', 'paper', 'paper', 'paper'], ['rock', 'rock', 'paper', 'paper', 'scissors'], ['rock', 'rock', 'paper', 'scissors', 'rock'], ['rock', 'rock', 'paper', 'scissors', 'paper'], ['rock', 'rock', 'paper', 'scissors', 'scissors'], ['rock', 'rock', 'scissors', 'rock', 'rock'], ['rock', 'rock', 'scissors', 'rock', 'paper'], ['rock', 'rock', 'scissors', 'rock', 'scissors'], ['rock', 'rock', 'scissors', 'paper', 'rock'], ['rock', 'rock', 'scissors', 'paper', 'paper'], ['rock', 'rock', 'scissors', 'paper', 'scissors'], ['rock', 'rock', 'scissors', 'scissors', 'rock'], ['rock', 'rock', 'scissors', 'scissors', 'paper'], ['rock', 'rock', 'scissors', 'scissors', 'scissors'], ['rock', 'paper', 'rock', 'rock', 'rock'], ['rock', 'paper', 'rock', 'rock', 'paper'], ['rock', 'paper', 'rock', 'rock', 'scissors'], ['rock', 'paper', 'rock', 'paper', 'rock'], ['rock', 'paper', 'rock', 'paper', 'paper'], ['rock', 'paper', 'rock', 'paper', 'scissors'], ['rock', 'paper', 'rock', 'scissors', 'rock'], ['rock', 'paper', 'rock', 'scissors', 'paper'], ['rock', 'paper', 'rock', 'scissors', 'scissors'], ['rock', 'paper', 'paper', 'rock', 'rock'], ['rock', 'paper', 'paper', 'rock', 'paper'], ['rock', 'paper', 'paper', 'rock', 'scissors'], ['rock', 'paper', 'paper', 'paper', 'rock'], ['rock', 'paper', 'paper', 'paper', 'paper'], ['rock', 'paper', 'paper', 'paper', 'scissors'], ['rock', 'paper', 'paper', 'scissors', 'rock'], ['rock', 'paper', 'paper', 'scissors', 'paper'], ['rock', 'paper', 'paper', 'scissors', 'scissors'], ['rock', 'paper', 'scissors', 'rock', 'rock'], ['rock', 'paper', 'scissors', 'rock', 'paper'], ['rock', 'paper', 'scissors', 'rock', 'scissors'], ['rock', 'paper', 'scissors', 'paper', 'rock'], ['rock', 'paper', 'scissors', 'paper', 'paper'], ['rock', 'paper', 'scissors', 'paper', 'scissors'], ['rock', 'paper', 'scissors', 'scissors', 'rock'], ['rock', 'paper', 'scissors', 'scissors', 'paper'], ['rock', 'paper', 'scissors', 'scissors', 'scissors'], ['rock', 'scissors', 'rock', 'rock', 'rock'], ['rock', 'scissors', 'rock', 'rock', 'paper'], ['rock', 'scissors', 'rock', 'rock', 'scissors'], ['rock', 'scissors', 'rock', 'paper', 'rock'], ['rock', 'scissors', 'rock', 'paper', 'paper'], ['rock', 'scissors', 'rock', 'paper', 'scissors'], ['rock', 'scissors', 'rock', 'scissors', 'rock'], ['rock', 'scissors', 'rock', 'scissors', 'paper'], ['rock', 'scissors', 'rock', 'scissors', 'scissors'], ['rock', 'scissors', 'paper', 'rock', 'rock'], ['rock', 'scissors', 'paper', 'rock', 'paper'], ['rock', 'scissors', 'paper', 'rock', 'scissors'], ['rock', 'scissors', 'paper', 'paper', 'rock'], ['rock', 'scissors', 'paper', 'paper', 'paper'], ['rock', 'scissors', 'paper', 'paper', 'scissors'], ['rock', 'scissors', 'paper', 'scissors', 'rock'], ['rock', 'scissors', 'paper', 'scissors', 'paper'], ['rock', 'scissors', 'paper', 'scissors', 'scissors'], ['rock', 'scissors', 'scissors', 'rock', 'rock'], ['rock', 'scissors', 'scissors', 'rock', 'paper'], ['rock', 'scissors', 'scissors', 'rock', 'scissors'], ['rock', 'scissors', 'scissors', 'paper', 'rock'], ['rock', 'scissors', 'scissors', 'paper', 'paper'], ['rock', 'scissors', 'scissors', 'paper', 'scissors'], ['rock', 'scissors', 'scissors', 'scissors', 'rock'], ['rock', 'scissors', 'scissors', 'scissors', 'paper'], ['rock', 'scissors', 'scissors', 'scissors', 'scissors'], ['paper', 'rock', 'rock', 'rock', 'rock'], ['paper', 'rock', 'rock', 'rock', 'paper'], ['paper', 'rock', 'rock', 'rock', 'scissors'], ['paper', 'rock', 'rock', 'paper', 'rock'], ['paper', 'rock', 'rock', 'paper', 'paper'], ['paper', 'rock', 'rock', 'paper', 'scissors'], ['paper', 'rock', 'rock', 'scissors', 'rock'], ['paper', 'rock', 'rock', 'scissors', 'paper'], ['paper', 'rock', 'rock', 'scissors', 'scissors'], ['paper', 'rock', 'paper', 'rock', 'rock'], ['paper', 'rock', 'paper', 'rock', 'paper'], ['paper', 'rock', 'paper', 'rock', 'scissors'], ['paper', 'rock', 'paper', 'paper', 'rock'], ['paper', 'rock', 'paper', 'paper', 'paper'], ['paper', 'rock', 'paper', 'paper', 'scissors'], ['paper', 'rock', 'paper', 'scissors', 'rock'], ['paper', 'rock', 'paper', 'scissors', 'paper'], ['paper', 'rock', 'paper', 'scissors', 'scissors'], ['paper', 'rock', 'scissors', 'rock', 'rock'], ['paper', 'rock', 'scissors', 'rock', 'paper'], ['paper', 'rock', 'scissors', 'rock', 'scissors'], ['paper', 'rock', 'scissors', 'paper', 'rock'], ['paper', 'rock', 'scissors', 'paper', 'paper'], ['paper', 'rock', 'scissors', 'paper', 'scissors'], ['paper', 'rock', 'scissors', 'scissors', 'rock'], ['paper', 'rock', 'scissors', 'scissors', 'paper'], ['paper', 'rock', 'scissors', 'scissors', 'scissors'], ['paper', 'paper', 'rock', 'rock', 'rock'], ['paper', 'paper', 'rock', 'rock', 'paper'], ['paper', 'paper', 'rock', 'rock', 'scissors'], ['paper', 'paper', 'rock', 'paper', 'rock'], ['paper', 'paper', 'rock', 'paper', 'paper'], ['paper', 'paper', 'rock', 'paper', 'scissors'], ['paper', 'paper', 'rock', 'scissors', 'rock'], ['paper', 'paper', 'rock', 'scissors', 'paper'], ['paper', 'paper', 'rock', 'scissors', 'scissors'], ['paper', 'paper', 'paper', 'rock', 'rock'], ['paper', 'paper', 'paper', 'rock', 'paper'], ['paper', 'paper', 'paper', 'rock', 'scissors'], ['paper', 'paper', 'paper', 'paper', 'rock'], ['paper', 'paper', 'paper', 'paper', 'paper'], ['paper', 'paper', 'paper', 'paper', 'scissors'], ['paper', 'paper', 'paper', 'scissors', 'rock'], ['paper', 'paper', 'paper', 'scissors', 'paper'], ['paper', 'paper', 'paper', 'scissors', 'scissors'], ['paper', 'paper', 'scissors', 'rock', 'rock'], ['paper', 'paper', 'scissors', 'rock', 'paper'], ['paper', 'paper', 'scissors', 'rock', 'scissors'], ['paper', 'paper', 'scissors', 'paper', 'rock'], ['paper', 'paper', 'scissors', 'paper', 'paper'], ['paper', 'paper', 'scissors', 'paper', 'scissors'], ['paper', 'paper', 'scissors', 'scissors', 'rock'], ['paper', 'paper', 'scissors', 'scissors', 'paper'], ['paper', 'paper', 'scissors', 'scissors', 'scissors'], ['paper', 'scissors', 'rock', 'rock', 'rock'], ['paper', 'scissors', 'rock', 'rock', 'paper'], ['paper', 'scissors', 'rock', 'rock', 'scissors'], ['paper', 'scissors', 'rock', 'paper', 'rock'], ['paper', 'scissors', 'rock', 'paper', 'paper'], ['paper', 'scissors', 'rock', 'paper', 'scissors'], ['paper', 'scissors', 'rock', 'scissors', 'rock'], ['paper', 'scissors', 'rock', 'scissors', 'paper'], ['paper', 'scissors', 'rock', 'scissors', 'scissors'], ['paper', 'scissors', 'paper', 'rock', 'rock'], ['paper', 'scissors', 'paper', 'rock', 'paper'], ['paper', 'scissors', 'paper', 'rock', 'scissors'], ['paper', 'scissors', 'paper', 'paper', 'rock'], ['paper', 'scissors', 'paper', 'paper', 'paper'], ['paper', 'scissors', 'paper', 'paper', 'scissors'], ['paper', 'scissors', 'paper', 'scissors', 'rock'], ['paper', 'scissors', 'paper', 'scissors', 'paper'], ['paper', 'scissors', 'paper', 'scissors', 'scissors'], ['paper', 'scissors', 'scissors', 'rock', 'rock'], ['paper', 'scissors', 'scissors', 'rock', 'paper'], ['paper', 'scissors', 'scissors', 'rock', 'scissors'], ['paper', 'scissors', 'scissors', 'paper', 'rock'], ['paper', 'scissors', 'scissors', 'paper', 'paper'], ['paper', 'scissors', 'scissors', 'paper', 'scissors'], ['paper', 'scissors', 'scissors', 'scissors', 'rock'], ['paper', 'scissors', 'scissors', 'scissors', 'paper'], ['paper', 'scissors', 'scissors', 'scissors', 'scissors'], ['scissors', 'rock', 'rock', 'rock', 'rock'], ['scissors', 'rock', 'rock', 'rock', 'paper'], ['scissors', 'rock', 'rock', 'rock', 'scissors'], ['scissors', 'rock', 'rock', 'paper', 'rock'], ['scissors', 'rock', 'rock', 'paper', 'paper'], ['scissors', 'rock', 'rock', 'paper', 'scissors'], ['scissors', 'rock', 'rock', 'scissors', 'rock'], ['scissors', 'rock', 'rock', 'scissors', 'paper'], ['scissors', 'rock', 'rock', 'scissors', 'scissors'], ['scissors', 'rock', 'paper', 'rock', 'rock'], ['scissors', 'rock', 'paper', 'rock', 'paper'], ['scissors', 'rock', 'paper', 'rock', 'scissors'], ['scissors', 'rock', 'paper', 'paper', 'rock'], ['scissors', 'rock', 'paper', 'paper', 'paper'], ['scissors', 'rock', 'paper', 'paper', 'scissors'], ['scissors', 'rock', 'paper', 'scissors', 'rock'], ['scissors', 'rock', 'paper', 'scissors', 'paper'], ['scissors', 'rock', 'paper', 'scissors', 'scissors'], ['scissors', 'rock', 'scissors', 'rock', 'rock'], ['scissors', 'rock', 'scissors', 'rock', 'paper'], ['scissors', 'rock', 'scissors', 'rock', 'scissors'], ['scissors', 'rock', 'scissors', 'paper', 'rock'], ['scissors', 'rock', 'scissors', 'paper', 'paper'], ['scissors', 'rock', 'scissors', 'paper', 'scissors'], ['scissors', 'rock', 'scissors', 'scissors', 'rock'], ['scissors', 'rock', 'scissors', 'scissors', 'paper'], ['scissors', 'rock', 'scissors', 'scissors', 'scissors'], ['scissors', 'paper', 'rock', 'rock', 'rock'], ['scissors', 'paper', 'rock', 'rock', 'paper'], ['scissors', 'paper', 'rock', 'rock', 'scissors'], ['scissors', 'paper', 'rock', 'paper', 'rock'], ['scissors', 'paper', 'rock', 'paper', 'paper'], ['scissors', 'paper', 'rock', 'paper', 'scissors'], ['scissors', 'paper', 'rock', 'scissors', 'rock'], ['scissors', 'paper', 'rock', 'scissors', 'paper'], ['scissors', 'paper', 'rock', 'scissors', 'scissors'], ['scissors', 'paper', 'paper', 'rock', 'rock'], ['scissors', 'paper', 'paper', 'rock', 'paper'], ['scissors', 'paper', 'paper', 'rock', 'scissors'], ['scissors', 'paper', 'paper', 'paper', 'rock'], ['scissors', 'paper', 'paper', 'paper', 'paper'], ['scissors', 'paper', 'paper', 'paper', 'scissors'], ['scissors', 'paper', 'paper', 'scissors', 'rock'], ['scissors', 'paper', 'paper', 'scissors', 'paper'], ['scissors', 'paper', 'paper', 'scissors', 'scissors'], ['scissors', 'paper', 'scissors', 'rock', 'rock'], ['scissors', 'paper', 'scissors', 'rock', 'paper'], ['scissors', 'paper', 'scissors', 'rock', 'scissors'], ['scissors', 'paper', 'scissors', 'paper', 'rock'], ['scissors', 'paper', 'scissors', 'paper', 'paper'], ['scissors', 'paper', 'scissors', 'paper', 'scissors'], ['scissors', 'paper', 'scissors', 'scissors', 'rock'], ['scissors', 'paper', 'scissors', 'scissors', 'paper'], ['scissors', 'paper', 'scissors', 'scissors', 'scissors'], ['scissors', 'scissors', 'rock', 'rock', 'rock'], ['scissors', 'scissors', 'rock', 'rock', 'paper'], ['scissors', 'scissors', 'rock', 'rock', 'scissors'], ['scissors', 'scissors', 'rock', 'paper', 'rock'], ['scissors', 'scissors', 'rock', 'paper', 'paper'], ['scissors', 'scissors', 'rock', 'paper', 'scissors'], ['scissors', 'scissors', 'rock', 'scissors', 'rock'], ['scissors', 'scissors', 'rock', 'scissors', 'paper'], ['scissors', 'scissors', 'rock', 'scissors', 'scissors'], ['scissors', 'scissors', 'paper', 'rock', 'rock'], ['scissors', 'scissors', 'paper', 'rock', 'paper'], ['scissors', 'scissors', 'paper', 'rock', 'scissors'], ['scissors', 'scissors', 'paper', 'paper', 'rock'], ['scissors', 'scissors', 'paper', 'paper', 'paper'], ['scissors', 'scissors', 'paper', 'paper', 'scissors'], ['scissors', 'scissors', 'paper', 'scissors', 'rock'], ['scissors', 'scissors', 'paper', 'scissors', 'paper'], ['scissors', 'scissors', 'paper', 'scissors', 'scissors'], ['scissors', 'scissors', 'scissors', 'rock', 'rock'], ['scissors', 'scissors', 'scissors', 'rock', 'paper'], ['scissors', 'scissors', 'scissors', 'rock', 'scissors'], ['scissors', 'scissors', 'scissors', 'paper', 'rock'], ['scissors', 'scissors', 'scissors', 'paper', 'paper'], ['scissors', 'scissors', 'scissors', 'paper', 'scissors'], ['scissors', 'scissors', 'scissors', 'scissors', 'rock'], ['scissors', 'scissors', 'scissors', 'scissors', 'paper'], ['scissors', 'scissors', 'scissors', 'scissors', 'scissors']]) + def test_rock_paper_scissors_output(self): + self.assertEqual(rock_paper_scissors(0), [[]]) + self.assertEqual(rock_paper_scissors(1), [['rock'], ['paper'], ['scissors']]) + self.assertEqual(rock_paper_scissors(2), [['rock', 'rock'], ['rock', 'paper'], ['rock', 'scissors'], ['paper', 'rock'], ['paper', 'paper'], ['paper', 'scissors'], ['scissors', 'rock'], ['scissors', 'paper'], ['scissors', 'scissors']]) + self.assertEqual(rock_paper_scissors(3), [['rock', 'rock', 'rock'], ['rock', 'rock', 'paper'], ['rock', 'rock', 'scissors'], ['rock', 'paper', 'rock'], ['rock', 'paper', 'paper'], ['rock', 'paper', 'scissors'], ['rock', 'scissors', 'rock'], ['rock', 'scissors', 'paper'], ['rock', 'scissors', 'scissors'], ['paper', 'rock', 'rock'], ['paper', 'rock', 'paper'], ['paper', 'rock', 'scissors'], ['paper', 'paper', 'rock'], ['paper', 'paper', 'paper'], ['paper', 'paper', 'scissors'], ['paper', 'scissors', 'rock'], ['paper', 'scissors', 'paper'], ['paper', 'scissors', 'scissors'], ['scissors', 'rock', 'rock'], ['scissors', 'rock', 'paper'], ['scissors', 'rock', 'scissors'], ['scissors', 'paper', 'rock'], ['scissors', 'paper', 'paper'], ['scissors', 'paper', 'scissors'], ['scissors', 'scissors', 'rock'], ['scissors', 'scissors', 'paper'], ['scissors', 'scissors', 'scissors']]) + self.assertEqual(rock_paper_scissors(4), [['rock', 'rock', 'rock', 'rock'], ['rock', 'rock', 'rock', 'paper'], ['rock', 'rock', 'rock', 'scissors'], ['rock', 'rock', 'paper', 'rock'], ['rock', 'rock', 'paper', 'paper'], ['rock', 'rock', 'paper', 'scissors'], ['rock', 'rock', 'scissors', 'rock'], ['rock', 'rock', 'scissors', 'paper'], ['rock', 'rock', 'scissors', 'scissors'], ['rock', 'paper', 'rock', 'rock'], ['rock', 'paper', 'rock', 'paper'], ['rock', 'paper', 'rock', 'scissors'], ['rock', 'paper', 'paper', 'rock'], ['rock', 'paper', 'paper', 'paper'], ['rock', 'paper', 'paper', 'scissors'], ['rock', 'paper', 'scissors', 'rock'], ['rock', 'paper', 'scissors', 'paper'], ['rock', 'paper', 'scissors', 'scissors'], ['rock', 'scissors', 'rock', 'rock'], ['rock', 'scissors', 'rock', 'paper'], ['rock', 'scissors', 'rock', 'scissors'], ['rock', 'scissors', 'paper', 'rock'], ['rock', 'scissors', 'paper', 'paper'], ['rock', 'scissors', 'paper', 'scissors'], ['rock', 'scissors', 'scissors', 'rock'], ['rock', 'scissors', 'scissors', 'paper'], ['rock', 'scissors', 'scissors', 'scissors'], ['paper', 'rock', 'rock', 'rock'], ['paper', 'rock', 'rock', 'paper'], ['paper', 'rock', 'rock', 'scissors'], ['paper', 'rock', 'paper', 'rock'], ['paper', 'rock', 'paper', 'paper'], ['paper', 'rock', 'paper', 'scissors'], ['paper', 'rock', 'scissors', 'rock'], ['paper', 'rock', 'scissors', 'paper'], ['paper', 'rock', 'scissors', 'scissors'], ['paper', 'paper', 'rock', 'rock'], ['paper', 'paper', 'rock', 'paper'], ['paper', 'paper', 'rock', 'scissors'], ['paper', 'paper', 'paper', 'rock'], ['paper', 'paper', 'paper', 'paper'], ['paper', 'paper', 'paper', 'scissors'], ['paper', 'paper', 'scissors', 'rock'], ['paper', 'paper', 'scissors', 'paper'], ['paper', 'paper', 'scissors', 'scissors'], ['paper', 'scissors', 'rock', 'rock'], ['paper', 'scissors', 'rock', 'paper'], ['paper', 'scissors', 'rock', 'scissors'], ['paper', 'scissors', 'paper', 'rock'], ['paper', 'scissors', 'paper', 'paper'], ['paper', 'scissors', 'paper', 'scissors'], ['paper', 'scissors', 'scissors', 'rock'], ['paper', 'scissors', 'scissors', 'paper'], ['paper', 'scissors', 'scissors', 'scissors'], ['scissors', 'rock', 'rock', 'rock'], ['scissors', 'rock', 'rock', 'paper'], ['scissors', 'rock', 'rock', 'scissors'], ['scissors', 'rock', 'paper', 'rock'], ['scissors', 'rock', 'paper', 'paper'], ['scissors', 'rock', 'paper', 'scissors'], ['scissors', 'rock', 'scissors', 'rock'], ['scissors', 'rock', 'scissors', 'paper'], ['scissors', 'rock', 'scissors', 'scissors'], ['scissors', 'paper', 'rock', 'rock'], ['scissors', 'paper', 'rock', 'paper'], ['scissors', 'paper', 'rock', 'scissors'], ['scissors', 'paper', 'paper', 'rock'], ['scissors', 'paper', 'paper', 'paper'], ['scissors', 'paper', 'paper', 'scissors'], ['scissors', 'paper', 'scissors', 'rock'], ['scissors', 'paper', 'scissors', 'paper'], ['scissors', 'paper', 'scissors', 'scissors'], ['scissors', 'scissors', 'rock', 'rock'], ['scissors', 'scissors', 'rock', 'paper'], ['scissors', 'scissors', 'rock', 'scissors'], ['scissors', 'scissors', 'paper', 'rock'], ['scissors', 'scissors', 'paper', 'paper'], ['scissors', 'scissors', 'paper', 'scissors'], ['scissors', 'scissors', 'scissors', 'rock'], ['scissors', 'scissors', 'scissors', 'paper'], ['scissors', 'scissors', 'scissors', 'scissors']]) + self.assertEqual(rock_paper_scissors(5), [['rock', 'rock', 'rock', 'rock', 'rock'], ['rock', 'rock', 'rock', 'rock', 'paper'], ['rock', 'rock', 'rock', 'rock', 'scissors'], ['rock', 'rock', 'rock', 'paper', 'rock'], ['rock', 'rock', 'rock', 'paper', 'paper'], ['rock', 'rock', 'rock', 'paper', 'scissors'], ['rock', 'rock', 'rock', 'scissors', 'rock'], ['rock', 'rock', 'rock', 'scissors', 'paper'], ['rock', 'rock', 'rock', 'scissors', 'scissors'], ['rock', 'rock', 'paper', 'rock', 'rock'], ['rock', 'rock', 'paper', 'rock', 'paper'], ['rock', 'rock', 'paper', 'rock', 'scissors'], ['rock', 'rock', 'paper', 'paper', 'rock'], ['rock', 'rock', 'paper', 'paper', 'paper'], ['rock', 'rock', 'paper', 'paper', 'scissors'], ['rock', 'rock', 'paper', 'scissors', 'rock'], ['rock', 'rock', 'paper', 'scissors', 'paper'], ['rock', 'rock', 'paper', 'scissors', 'scissors'], ['rock', 'rock', 'scissors', 'rock', 'rock'], ['rock', 'rock', 'scissors', 'rock', 'paper'], ['rock', 'rock', 'scissors', 'rock', 'scissors'], ['rock', 'rock', 'scissors', 'paper', 'rock'], ['rock', 'rock', 'scissors', 'paper', 'paper'], ['rock', 'rock', 'scissors', 'paper', 'scissors'], ['rock', 'rock', 'scissors', 'scissors', 'rock'], ['rock', 'rock', 'scissors', 'scissors', 'paper'], ['rock', 'rock', 'scissors', 'scissors', 'scissors'], ['rock', 'paper', 'rock', 'rock', 'rock'], ['rock', 'paper', 'rock', 'rock', 'paper'], ['rock', 'paper', 'rock', 'rock', 'scissors'], ['rock', 'paper', 'rock', 'paper', 'rock'], ['rock', 'paper', 'rock', 'paper', 'paper'], ['rock', 'paper', 'rock', 'paper', 'scissors'], ['rock', 'paper', 'rock', 'scissors', 'rock'], ['rock', 'paper', 'rock', 'scissors', 'paper'], ['rock', 'paper', 'rock', 'scissors', 'scissors'], ['rock', 'paper', 'paper', 'rock', 'rock'], ['rock', 'paper', 'paper', 'rock', 'paper'], ['rock', 'paper', 'paper', 'rock', 'scissors'], ['rock', 'paper', 'paper', 'paper', 'rock'], ['rock', 'paper', 'paper', 'paper', 'paper'], ['rock', 'paper', 'paper', 'paper', 'scissors'], ['rock', 'paper', 'paper', 'scissors', 'rock'], ['rock', 'paper', 'paper', 'scissors', 'paper'], ['rock', 'paper', 'paper', 'scissors', 'scissors'], ['rock', 'paper', 'scissors', 'rock', 'rock'], ['rock', 'paper', 'scissors', 'rock', 'paper'], ['rock', 'paper', 'scissors', 'rock', 'scissors'], ['rock', 'paper', 'scissors', 'paper', 'rock'], ['rock', 'paper', 'scissors', 'paper', 'paper'], ['rock', 'paper', 'scissors', 'paper', 'scissors'], ['rock', 'paper', 'scissors', 'scissors', 'rock'], ['rock', 'paper', 'scissors', 'scissors', 'paper'], ['rock', 'paper', 'scissors', 'scissors', 'scissors'], ['rock', 'scissors', 'rock', 'rock', 'rock'], ['rock', 'scissors', 'rock', 'rock', 'paper'], ['rock', 'scissors', 'rock', 'rock', 'scissors'], ['rock', 'scissors', 'rock', 'paper', 'rock'], ['rock', 'scissors', 'rock', 'paper', 'paper'], ['rock', 'scissors', 'rock', 'paper', 'scissors'], ['rock', 'scissors', 'rock', 'scissors', 'rock'], ['rock', 'scissors', 'rock', 'scissors', 'paper'], ['rock', 'scissors', 'rock', 'scissors', 'scissors'], ['rock', 'scissors', 'paper', 'rock', 'rock'], ['rock', 'scissors', 'paper', 'rock', 'paper'], ['rock', 'scissors', 'paper', 'rock', 'scissors'], ['rock', 'scissors', 'paper', 'paper', 'rock'], ['rock', 'scissors', 'paper', 'paper', 'paper'], ['rock', 'scissors', 'paper', 'paper', 'scissors'], ['rock', 'scissors', 'paper', 'scissors', 'rock'], ['rock', 'scissors', 'paper', 'scissors', 'paper'], ['rock', 'scissors', 'paper', 'scissors', 'scissors'], ['rock', 'scissors', 'scissors', 'rock', 'rock'], ['rock', 'scissors', 'scissors', 'rock', 'paper'], ['rock', 'scissors', 'scissors', 'rock', 'scissors'], ['rock', 'scissors', 'scissors', 'paper', 'rock'], ['rock', 'scissors', 'scissors', 'paper', 'paper'], ['rock', 'scissors', 'scissors', 'paper', 'scissors'], ['rock', 'scissors', 'scissors', 'scissors', 'rock'], ['rock', 'scissors', 'scissors', 'scissors', 'paper'], ['rock', 'scissors', 'scissors', 'scissors', 'scissors'], ['paper', 'rock', 'rock', 'rock', 'rock'], ['paper', 'rock', 'rock', 'rock', 'paper'], ['paper', 'rock', 'rock', 'rock', 'scissors'], ['paper', 'rock', 'rock', 'paper', 'rock'], ['paper', 'rock', 'rock', 'paper', 'paper'], ['paper', 'rock', 'rock', 'paper', 'scissors'], ['paper', 'rock', 'rock', 'scissors', 'rock'], ['paper', 'rock', 'rock', 'scissors', 'paper'], ['paper', 'rock', 'rock', 'scissors', 'scissors'], ['paper', 'rock', 'paper', 'rock', 'rock'], ['paper', 'rock', 'paper', 'rock', 'paper'], ['paper', 'rock', 'paper', 'rock', 'scissors'], ['paper', 'rock', 'paper', 'paper', 'rock'], ['paper', 'rock', 'paper', 'paper', 'paper'], ['paper', 'rock', 'paper', 'paper', 'scissors'], ['paper', 'rock', 'paper', 'scissors', 'rock'], ['paper', 'rock', 'paper', 'scissors', 'paper'], ['paper', 'rock', 'paper', 'scissors', 'scissors'], ['paper', 'rock', 'scissors', 'rock', 'rock'], ['paper', 'rock', 'scissors', 'rock', 'paper'], ['paper', 'rock', 'scissors', 'rock', 'scissors'], ['paper', 'rock', 'scissors', 'paper', 'rock'], ['paper', 'rock', 'scissors', 'paper', 'paper'], ['paper', 'rock', 'scissors', 'paper', 'scissors'], ['paper', 'rock', 'scissors', 'scissors', 'rock'], ['paper', 'rock', 'scissors', 'scissors', 'paper'], ['paper', 'rock', 'scissors', 'scissors', 'scissors'], ['paper', 'paper', 'rock', 'rock', 'rock'], ['paper', 'paper', 'rock', 'rock', 'paper'], ['paper', 'paper', 'rock', 'rock', 'scissors'], ['paper', 'paper', 'rock', 'paper', 'rock'], ['paper', 'paper', 'rock', 'paper', 'paper'], ['paper', 'paper', 'rock', 'paper', 'scissors'], ['paper', 'paper', 'rock', 'scissors', 'rock'], ['paper', 'paper', 'rock', 'scissors', 'paper'], ['paper', 'paper', 'rock', 'scissors', 'scissors'], ['paper', 'paper', 'paper', 'rock', 'rock'], ['paper', 'paper', 'paper', 'rock', 'paper'], ['paper', 'paper', 'paper', 'rock', 'scissors'], ['paper', 'paper', 'paper', 'paper', 'rock'], ['paper', 'paper', 'paper', 'paper', 'paper'], ['paper', 'paper', 'paper', 'paper', 'scissors'], ['paper', 'paper', 'paper', 'scissors', 'rock'], ['paper', 'paper', 'paper', 'scissors', 'paper'], ['paper', 'paper', 'paper', 'scissors', 'scissors'], ['paper', 'paper', 'scissors', 'rock', 'rock'], ['paper', 'paper', 'scissors', 'rock', 'paper'], ['paper', 'paper', 'scissors', 'rock', 'scissors'], ['paper', 'paper', 'scissors', 'paper', 'rock'], ['paper', 'paper', 'scissors', 'paper', 'paper'], ['paper', 'paper', 'scissors', 'paper', 'scissors'], ['paper', 'paper', 'scissors', 'scissors', 'rock'], ['paper', 'paper', 'scissors', 'scissors', 'paper'], ['paper', 'paper', 'scissors', 'scissors', 'scissors'], ['paper', 'scissors', 'rock', 'rock', 'rock'], ['paper', 'scissors', 'rock', 'rock', 'paper'], ['paper', 'scissors', 'rock', 'rock', 'scissors'], ['paper', 'scissors', 'rock', 'paper', 'rock'], ['paper', 'scissors', 'rock', 'paper', 'paper'], ['paper', 'scissors', 'rock', 'paper', 'scissors'], ['paper', 'scissors', 'rock', 'scissors', 'rock'], ['paper', 'scissors', 'rock', 'scissors', 'paper'], ['paper', 'scissors', 'rock', 'scissors', 'scissors'], ['paper', 'scissors', 'paper', 'rock', 'rock'], ['paper', 'scissors', 'paper', 'rock', 'paper'], ['paper', 'scissors', 'paper', 'rock', 'scissors'], ['paper', 'scissors', 'paper', 'paper', 'rock'], ['paper', 'scissors', 'paper', 'paper', 'paper'], ['paper', 'scissors', 'paper', 'paper', 'scissors'], ['paper', 'scissors', 'paper', 'scissors', 'rock'], ['paper', 'scissors', 'paper', 'scissors', 'paper'], ['paper', 'scissors', 'paper', 'scissors', 'scissors'], ['paper', 'scissors', 'scissors', 'rock', 'rock'], ['paper', 'scissors', 'scissors', 'rock', 'paper'], ['paper', 'scissors', 'scissors', 'rock', 'scissors'], ['paper', 'scissors', 'scissors', 'paper', 'rock'], ['paper', 'scissors', 'scissors', 'paper', 'paper'], ['paper', 'scissors', 'scissors', 'paper', 'scissors'], ['paper', 'scissors', 'scissors', 'scissors', 'rock'], ['paper', 'scissors', 'scissors', 'scissors', 'paper'], ['paper', 'scissors', 'scissors', 'scissors', 'scissors'], ['scissors', 'rock', 'rock', 'rock', 'rock'], ['scissors', 'rock', 'rock', 'rock', 'paper'], ['scissors', 'rock', 'rock', 'rock', 'scissors'], ['scissors', 'rock', 'rock', 'paper', 'rock'], ['scissors', 'rock', 'rock', 'paper', 'paper'], ['scissors', 'rock', 'rock', 'paper', 'scissors'], ['scissors', 'rock', 'rock', 'scissors', 'rock'], ['scissors', 'rock', 'rock', 'scissors', 'paper'], ['scissors', 'rock', 'rock', 'scissors', 'scissors'], ['scissors', 'rock', 'paper', 'rock', 'rock'], ['scissors', 'rock', 'paper', 'rock', 'paper'], ['scissors', 'rock', 'paper', 'rock', 'scissors'], ['scissors', 'rock', 'paper', 'paper', 'rock'], ['scissors', 'rock', 'paper', 'paper', 'paper'], ['scissors', 'rock', 'paper', 'paper', 'scissors'], ['scissors', 'rock', 'paper', 'scissors', 'rock'], ['scissors', 'rock', 'paper', 'scissors', 'paper'], ['scissors', 'rock', 'paper', 'scissors', 'scissors'], ['scissors', 'rock', 'scissors', 'rock', 'rock'], ['scissors', 'rock', 'scissors', 'rock', 'paper'], ['scissors', 'rock', 'scissors', 'rock', 'scissors'], ['scissors', 'rock', 'scissors', 'paper', 'rock'], ['scissors', 'rock', 'scissors', 'paper', 'paper'], ['scissors', 'rock', 'scissors', 'paper', 'scissors'], ['scissors', 'rock', 'scissors', 'scissors', 'rock'], ['scissors', 'rock', 'scissors', 'scissors', 'paper'], ['scissors', 'rock', 'scissors', 'scissors', 'scissors'], ['scissors', 'paper', 'rock', 'rock', 'rock'], ['scissors', 'paper', 'rock', 'rock', 'paper'], ['scissors', 'paper', 'rock', 'rock', 'scissors'], ['scissors', 'paper', 'rock', 'paper', 'rock'], ['scissors', 'paper', 'rock', 'paper', 'paper'], ['scissors', 'paper', 'rock', 'paper', 'scissors'], ['scissors', 'paper', 'rock', 'scissors', 'rock'], ['scissors', 'paper', 'rock', 'scissors', 'paper'], ['scissors', 'paper', 'rock', 'scissors', 'scissors'], ['scissors', 'paper', 'paper', 'rock', 'rock'], ['scissors', 'paper', 'paper', 'rock', 'paper'], ['scissors', 'paper', 'paper', 'rock', 'scissors'], ['scissors', 'paper', 'paper', 'paper', 'rock'], ['scissors', 'paper', 'paper', 'paper', 'paper'], ['scissors', 'paper', 'paper', 'paper', 'scissors'], ['scissors', 'paper', 'paper', 'scissors', 'rock'], ['scissors', 'paper', 'paper', 'scissors', 'paper'], ['scissors', 'paper', 'paper', 'scissors', 'scissors'], ['scissors', 'paper', 'scissors', 'rock', 'rock'], ['scissors', 'paper', 'scissors', 'rock', 'paper'], ['scissors', 'paper', 'scissors', 'rock', 'scissors'], ['scissors', 'paper', 'scissors', 'paper', 'rock'], ['scissors', 'paper', 'scissors', 'paper', 'paper'], ['scissors', 'paper', 'scissors', 'paper', 'scissors'], ['scissors', 'paper', 'scissors', 'scissors', 'rock'], ['scissors', 'paper', 'scissors', 'scissors', 'paper'], ['scissors', 'paper', 'scissors', 'scissors', 'scissors'], ['scissors', 'scissors', 'rock', 'rock', 'rock'], ['scissors', 'scissors', 'rock', 'rock', 'paper'], ['scissors', 'scissors', 'rock', 'rock', 'scissors'], ['scissors', 'scissors', 'rock', 'paper', 'rock'], ['scissors', 'scissors', 'rock', 'paper', 'paper'], ['scissors', 'scissors', 'rock', 'paper', 'scissors'], ['scissors', 'scissors', 'rock', 'scissors', 'rock'], ['scissors', 'scissors', 'rock', 'scissors', 'paper'], ['scissors', 'scissors', 'rock', 'scissors', 'scissors'], ['scissors', 'scissors', 'paper', 'rock', 'rock'], ['scissors', 'scissors', 'paper', 'rock', 'paper'], ['scissors', 'scissors', 'paper', 'rock', 'scissors'], ['scissors', 'scissors', 'paper', 'paper', 'rock'], ['scissors', 'scissors', 'paper', 'paper', 'paper'], ['scissors', 'scissors', 'paper', 'paper', 'scissors'], ['scissors', 'scissors', 'paper', 'scissors', 'rock'], ['scissors', 'scissors', 'paper', 'scissors', 'paper'], ['scissors', 'scissors', 'paper', 'scissors', 'scissors'], ['scissors', 'scissors', 'scissors', 'rock', 'rock'], ['scissors', 'scissors', 'scissors', 'rock', 'paper'], ['scissors', 'scissors', 'scissors', 'rock', 'scissors'], ['scissors', 'scissors', 'scissors', 'paper', 'rock'], ['scissors', 'scissors', 'scissors', 'paper', 'paper'], ['scissors', 'scissors', 'scissors', 'paper', 'scissors'], ['scissors', 'scissors', 'scissors', 'scissors', 'rock'], ['scissors', 'scissors', 'scissors', 'scissors', 'paper'], ['scissors', 'scissors', 'scissors', 'scissors', 'scissors']]) if __name__ == '__main__': - unittest.main() \ No newline at end of file + unittest.main() \ No newline at end of file diff --git a/stock_prices/stock_prices.py b/stock_prices/stock_prices.py old mode 100644 new mode 100755 index 9de20bc94..986072477 --- a/stock_prices/stock_prices.py +++ b/stock_prices/stock_prices.py @@ -3,13 +3,13 @@ import argparse def find_max_profit(prices): - pass + pass if __name__ == '__main__': - # This is just some code to accept inputs from the command line - parser = argparse.ArgumentParser(description='Find max profit from prices.') - parser.add_argument('integers', metavar='N', type=int, nargs='+', help='an integer price') - args = parser.parse_args() + # This is just some code to accept inputs from the command line + parser = argparse.ArgumentParser(description='Find max profit from prices.') + parser.add_argument('integers', metavar='N', type=int, nargs='+', help='an integer price') + args = parser.parse_args() - print("A profit of ${profit} can be made from the stock prices {prices}.".format(profit=find_max_profit(args.integers), prices=args.integers)) \ No newline at end of file + print("A profit of ${profit} can be made from the stock prices {prices}.".format(profit=find_max_profit(args.integers), prices=args.integers)) \ No newline at end of file diff --git a/stock_prices/test_stock_prices.py b/stock_prices/test_stock_prices.py old mode 100644 new mode 100755 index a04f8e762..687da4145 --- a/stock_prices/test_stock_prices.py +++ b/stock_prices/test_stock_prices.py @@ -1,14 +1,14 @@ import unittest -from stock_prices import find_max_profit +from stock_prices import find_max_profit class Test(unittest.TestCase): - def test_find_max_profit(self): - self.assertEqual(find_max_profit([10, 7, 5, 8, 11, 9]), 6) - self.assertEqual(find_max_profit([100, 90, 80, 50, 20, 10]), -10) - self.assertEqual(find_max_profit([1050, 270, 1540, 3800, 2]), 3530) - self.assertEqual(find_max_profit([100, 55, 4, 98, 10, 18, 90, 95, 43, 11, 47, 67, 89, 42, 49, 79]), 94) - + def test_find_max_profit(self): + self.assertEqual(find_max_profit([10, 7, 5, 8, 11, 9]), 6) + self.assertEqual(find_max_profit([100, 90, 80, 50, 20, 10]), -10) + self.assertEqual(find_max_profit([1050, 270, 1540, 3800, 2]), 3530) + self.assertEqual(find_max_profit([100, 55, 4, 98, 10, 18, 90, 95, 43, 11, 47, 67, 89, 42, 49, 79]), 94) + if __name__ == '__main__': - unittest.main() \ No newline at end of file + unittest.main() \ No newline at end of file From 8dd9666441936980b6c8c3c234fbda0bcb37e102 Mon Sep 17 00:00:00 2001 From: larkeith Date: Thu, 19 Mar 2020 10:43:10 -0700 Subject: [PATCH 2/4] Finish making_change --- making_change/making_change.py | 142 ++++++++++++++++++++++++--------- 1 file changed, 103 insertions(+), 39 deletions(-) diff --git a/making_change/making_change.py b/making_change/making_change.py index 7af2fe664..abcd52e61 100755 --- a/making_change/making_change.py +++ b/making_change/making_change.py @@ -5,59 +5,123 @@ from typing import Hashable, Any, Iterable -def make_hashable(obj) -> Hashable: - try: - hash(obj) # Isinstance Hashable fails on nested objects - return obj - except TypeError: - if isinstance(obj, dict): - return tuple(sorted((make_hashable((key, value)) for key, value in obj.items()))) - elif isinstance(obj, Iterable): - return tuple((make_hashable(value) for value in obj)) +class Memoizer: + ''' + Class to facilitate memoization of function returns. + + Attributes: + functions ( + Dict[ + callable: Dict[ + Tuple[frozenset, frozenset]: Object + ] + ] + ) + A dictionary of functions: dictionary of args: results + + Methods: + get_result: Gets the result of a function call, either + by returning the stored result or by running the + function if no stored results are found. + ''' + + def __init__(self): + ''' + Inits a new Memoizer. + ''' + + self.functions = {} + + def get_result(self, function: callable, *args, **kwargs) -> Any: + ''' + Gets the result of a function call with specific arguments. + If the function has been called through get_result before with these + parameters in this Memoizer, this will return the memoized result. + Otherwise, it will run the function and memoize the new result. + + Args: + function (callable): The function to run. + This should *always* be idempotent or nullipotent. + *args: Variable length argument list. Passed to function. + **kwargs: Arbitrary keyword arguments. Passed to function. + + Returns: + Object: The return value of function. + ''' + + if function not in self.functions: + self.functions[function] = {} + + params = (self.make_hashable(args), self.make_hashable(kwargs)) + + if params in self.functions[function]: + return self.functions[function][params] + else: + self.functions[function][params] = function(*args, **kwargs) + return self.functions[function][params] + + @staticmethod + def make_hashable(obj) -> Hashable: try: - return frozenset(obj) + hash(obj) # Isinstance Hashable fails on nested objects + return obj except TypeError: - result = [] - for item in obj: - result.append(make_hashable(item)) - return tuple(result) + if isinstance(obj, dict): + return tuple(sorted((Memoizer.make_hashable((key, value)) for key, value in obj.items()))) + elif isinstance(obj, Iterable): + return tuple((Memoizer.make_hashable(value) for value in obj)) + try: + return frozenset(obj) + except TypeError: + result = [] + for item in obj: + result.append(make_hashable(item)) + return tuple(result) -# The cache parameter is here for if you want to implement -# a solution that is more efficient than the naive -# recursive solution -def making_change(n, denominations, denomination_counts=None, parent_denominations=None): - if n < 0: +def making_change(amount, denominations, cache=None): + if amount < 0: return 0 - elif n == 0: + elif amount == 0: return 1 - if denomination_counts is None: - denomination_counts = set() - if parent_denominations is None: - parent_denominations = { - denomination: 0 for denomination in denominations - } + if not isinstance(denominations, tuple): + # This is faster than using make_hashable + denominations = tuple(denominations) - # print(denomination_counts) + if cache is None: + cache = Memoizer() + + # Fill the cache from simple cases to complex + # to avoid recursion limits + for i in range(amount): + cache.get_result( + making_change, + i, + denominations, + cache=cache, + ) combinations = 0 - for denomination in denominations: - new_denominations = parent_denominations.copy() - new_denominations[denomination] += 1 - if make_hashable(new_denominations) not in denomination_counts: - if n - denomination >= 0: - denomination_counts.add(make_hashable(new_denominations)) - combinations += making_change( - n - denomination, - denominations, - denomination_counts=denomination_counts, - parent_denominations=new_denominations, - ) + inversed_denominations = cache.get_result( + inverse_sort, + denominations, + ) + for i, denomination in enumerate(inversed_denominations): + combinations += cache.get_result( + making_change, + amount - denomination, + inversed_denominations[i:], + cache=cache + ) return combinations +def inverse_sort(tup): + return tuple(sorted(tup, reverse=True)) + + if __name__ == "__main__": # Test our your implementation from the command line # with `python making_change.py [amount]` with different amounts From af8d4cbd239684078fb6316705668a752942d6bc Mon Sep 17 00:00:00 2001 From: larkeith Date: Thu, 19 Mar 2020 10:47:04 -0700 Subject: [PATCH 3/4] Add shebang --- making_change/test_making_change.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/making_change/test_making_change.py b/making_change/test_making_change.py index 51214b5b1..b5c62c7f5 100755 --- a/making_change/test_making_change.py +++ b/making_change/test_making_change.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python + import unittest from making_change import making_change From 36aae4ba071bafb24578f7eb9d84ea4d256b318e Mon Sep 17 00:00:00 2001 From: larkeith Date: Thu, 19 Mar 2020 14:36:53 -0700 Subject: [PATCH 4/4] Finish main assignment --- eating_cookies/eating_cookies.py | 22 ++++- knapsack/knapsack.py | 136 +++++++++++++++++++++++++- knapsack/test_knapsack.py | 2 + making_change/making_change.py | 18 ++-- making_change/test_making_change.py | 2 +- recipe_batches/README.md | 4 +- recipe_batches/recipe_batches.py | 20 +++- recipe_batches/test_recipe_batches.py | 13 ++- rock_paper_scissors/rps.py | 16 ++- rock_paper_scissors/test_rps.py | 7 +- stock_prices/stock_prices.py | 13 ++- stock_prices/test_stock_prices.py | 5 +- 12 files changed, 220 insertions(+), 38 deletions(-) diff --git a/eating_cookies/eating_cookies.py b/eating_cookies/eating_cookies.py index d35e8bddf..0ee45255b 100755 --- a/eating_cookies/eating_cookies.py +++ b/eating_cookies/eating_cookies.py @@ -2,8 +2,9 @@ import sys +import json -from typing import Hashable, Any +from typing import Hashable, Any, Iterable class Memoizer: @@ -33,7 +34,7 @@ def __init__(self): self.functions = {} - def get_result(self, function: callable, *args, **kwargs) -> Any: + def get_result(self, function: callable, *args, assume_hashable_args=True, **kwargs) -> Any: ''' Gets the result of a function call with specific arguments. If the function has been called through get_result before with these @@ -53,7 +54,10 @@ def get_result(self, function: callable, *args, **kwargs) -> Any: if function not in self.functions: self.functions[function] = {} - params = (frozenset(args), frozenset(kwargs)) + if assume_hashable_args: + params = (tuple(args), self.make_hashable(kwargs)) + else: + params = (self.make_hashable(args), self.make_hashable(kwargs)) if params in self.functions[function]: return self.functions[function][params] @@ -61,6 +65,18 @@ def get_result(self, function: callable, *args, **kwargs) -> Any: self.functions[function][params] = function(*args, **kwargs) return self.functions[function][params] + @staticmethod + def make_hashable(obj) -> Hashable: + try: + hash(obj) # Isinstance Hashable fails on nested objects + return obj + except TypeError: + if isinstance(obj, dict): + return tuple(sorted((Memoizer.make_hashable((key, value)) for key, value in obj.items()))) + elif isinstance(obj, Iterable): + return tuple((Memoizer.make_hashable(value) for value in obj)) + return json.dumps(obj) + # The cache parameter is here for if you want to implement # a solution that is more efficient than the naive diff --git a/knapsack/knapsack.py b/knapsack/knapsack.py index 3fe16eb48..5aab33951 100755 --- a/knapsack/knapsack.py +++ b/knapsack/knapsack.py @@ -1,13 +1,143 @@ -#!/usr/bin/python +#!/usr/bin/env python import sys + from collections import namedtuple +from pprint import pprint +from typing import Iterable, Hashable, Any Item = namedtuple('Item', ['index', 'size', 'value']) +class Memoizer: + ''' + Class to facilitate memoization of function returns. + + Attributes: + functions ( + Dict[ + callable: Dict[ + Tuple[frozenset, frozenset]: Object + ] + ] + ) + A dictionary of functions: dictionary of args: results + + Methods: + get_result: Gets the result of a function call, either + by returning the stored result or by running the + function if no stored results are found. + ''' + + def __init__(self): + ''' + Inits a new Memoizer. + ''' + + self.functions = {} + + def get_result(self, function: callable, *args, assume_hashable_args=True, **kwargs) -> Any: + ''' + Gets the result of a function call with specific arguments. + If the function has been called through get_result before with these + parameters in this Memoizer, this will return the memoized result. + Otherwise, it will run the function and memoize the new result. + + Args: + function (callable): The function to run. + This should *always* be idempotent or nullipotent. + *args: Variable length argument list. Passed to function. + **kwargs: Arbitrary keyword arguments. Passed to function. + + Returns: + Object: The return value of function. + ''' + + if function not in self.functions: + self.functions[function] = {} + + if assume_hashable_args: + params = (tuple(args), self.make_hashable(kwargs)) + else: + params = (self.make_hashable(args), self.make_hashable(kwargs)) + + if params in self.functions[function]: + return self.functions[function][params] + else: + self.functions[function][params] = function(*args, **kwargs) + return self.functions[function][params] + + @staticmethod + def make_hashable(obj) -> Hashable: + try: + hash(obj) # Isinstance Hashable fails on nested objects + return obj + except TypeError: + if isinstance(obj, dict): + return tuple(sorted((Memoizer.make_hashable((key, value)) for key, value in obj.items()))) + elif isinstance(obj, Iterable): + return tuple((Memoizer.make_hashable(value) for value in obj)) + return json.dumps(obj) + + +def knapsack_inner(items, capacity, cache=None): + if cache is None: + cache = Memoizer() + for lower_capacity in range(0, capacity, 10): + print(lower_capacity) + cache.get_result( + knapsack_inner, items, lower_capacity, cache=cache, assume_hashable_args=False + ) + + options = {} + for item in items: + if item.size > capacity: + continue + + new_items = items[:] + new_items.remove(item) + new_capacity = capacity - item.size + + result = cache.get_result( + knapsack_inner, new_items, new_capacity, cache=cache, assume_hashable_args=False + ) + + options[item] = { + 'value': item.value + result['value'], + 'weight': item.size + result['weight'], + 'best_option': result['best_option'], + } + + best_option = {'value': 0, 'weight': 0} + best_item = None + for item, option in options.items(): + if option['value'] > best_option['value']: + best_option = option + best_item = item + + retval = { + 'value': best_option['value'], + 'weight': best_option['weight'], + 'best_option': {best_item: best_option} + } + + return retval + + def knapsack_solver(items, capacity): - pass + results = knapsack_inner(items, capacity) + items = [] + current_item = results + while None not in current_item['best_option']: + item = list(current_item['best_option'].keys())[0] + items.append(item) + current_item = current_item['best_option'][item] + + retval = { + 'Value': results['value'], + 'Chosen': [item.index for item in items] + } + return retval if __name__ == '__main__': @@ -22,6 +152,6 @@ def knapsack_solver(items, capacity): items.append(Item(int(data[0]), int(data[1]), int(data[2]))) file_contents.close() - print(knapsack_solver(items, capacity)) + pprint(knapsack_solver(items, capacity)) else: print('Usage: knapsack.py [filename] [capacity]') diff --git a/knapsack/test_knapsack.py b/knapsack/test_knapsack.py index 0ad6b658f..f239afb40 100755 --- a/knapsack/test_knapsack.py +++ b/knapsack/test_knapsack.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python + import sys import unittest from collections import namedtuple diff --git a/making_change/making_change.py b/making_change/making_change.py index abcd52e61..1445253a3 100755 --- a/making_change/making_change.py +++ b/making_change/making_change.py @@ -1,6 +1,7 @@ #!/usr/bin/env python import sys +import json from typing import Hashable, Any, Iterable @@ -32,7 +33,7 @@ def __init__(self): self.functions = {} - def get_result(self, function: callable, *args, **kwargs) -> Any: + def get_result(self, function: callable, *args, assume_hashable_args=True, **kwargs) -> Any: ''' Gets the result of a function call with specific arguments. If the function has been called through get_result before with these @@ -52,7 +53,10 @@ def get_result(self, function: callable, *args, **kwargs) -> Any: if function not in self.functions: self.functions[function] = {} - params = (self.make_hashable(args), self.make_hashable(kwargs)) + if assume_hashable_args: + params = (tuple(args), self.make_hashable(kwargs)) + else: + params = (self.make_hashable(args), self.make_hashable(kwargs)) if params in self.functions[function]: return self.functions[function][params] @@ -70,13 +74,7 @@ def make_hashable(obj) -> Hashable: return tuple(sorted((Memoizer.make_hashable((key, value)) for key, value in obj.items()))) elif isinstance(obj, Iterable): return tuple((Memoizer.make_hashable(value) for value in obj)) - try: - return frozenset(obj) - except TypeError: - result = [] - for item in obj: - result.append(make_hashable(item)) - return tuple(result) + return json.dumps(obj) def making_change(amount, denominations, cache=None): @@ -130,4 +128,4 @@ def inverse_sort(tup): amount = int(sys.argv[1]) print("There are {ways} ways to make {amount} cents.".format(ways=making_change(amount, denominations), amount=amount)) else: - print("Usage: making_change.py [amount]") \ No newline at end of file + print("Usage: making_change.py [amount]") diff --git a/making_change/test_making_change.py b/making_change/test_making_change.py index b5c62c7f5..721d614b3 100755 --- a/making_change/test_making_change.py +++ b/making_change/test_making_change.py @@ -30,4 +30,4 @@ def test_making_change_large_amount(self): if __name__ == '__main__': - unittest.main() \ No newline at end of file + unittest.main() diff --git a/recipe_batches/README.md b/recipe_batches/README.md index 462b43b70..7f2b8b6fa 100644 --- a/recipe_batches/README.md +++ b/recipe_batches/README.md @@ -20,8 +20,8 @@ For example ```python # should return 0 since we don't have enough butter! recipe_batches( - { 'milk': 100, 'butter': 50, 'flour': 5 }, - { 'milk': 138, 'butter': 48, 'flour': 51 } + {'milk': 100, 'butter': 50, 'flour': 5}, + {'milk': 138, 'butter': 48, 'flour': 51} ) ``` diff --git a/recipe_batches/recipe_batches.py b/recipe_batches/recipe_batches.py index fddbe4e2e..6363c6780 100755 --- a/recipe_batches/recipe_batches.py +++ b/recipe_batches/recipe_batches.py @@ -1,14 +1,24 @@ -#!/usr/bin/python +#!/usr/bin/env python import math + def recipe_batches(recipe, ingredients): - pass + max_batches = None + for ingredient, requires in recipe.items(): + have = ingredients.get(ingredient, 0) + can_make = have // requires + if max_batches is None: + max_batches = can_make + if can_make < max_batches: + max_batches = can_make + + return max_batches if __name__ == '__main__': # Change the entries of these dictionaries to test # your implementation with different inputs - recipe = { 'milk': 100, 'butter': 50, 'flour': 5 } - ingredients = { 'milk': 132, 'butter': 48, 'flour': 51 } - print("{batches} batches can be made from the available ingredients: {ingredients}.".format(batches=recipe_batches(recipe, ingredients), ingredients=ingredients)) \ No newline at end of file + recipe = {'milk': 10, 'butter': 5, 'flour': 5} + ingredients = {'milk': 132, 'butter': 48, 'flour': 51} + print("{batches} batches can be made from the available ingredients: {ingredients}.".format(batches=recipe_batches(recipe, ingredients), ingredients=ingredients)) diff --git a/recipe_batches/test_recipe_batches.py b/recipe_batches/test_recipe_batches.py index ff1398217..6685dde4f 100755 --- a/recipe_batches/test_recipe_batches.py +++ b/recipe_batches/test_recipe_batches.py @@ -1,14 +1,17 @@ +#!/usr/bin/env python + import unittest from recipe_batches import recipe_batches + class Test(unittest.TestCase): def test_recipe_batches(self): - self.assertEqual(recipe_batches({ 'milk': 100, 'flour': 4, 'sugar': 10, 'butter': 5 }, { 'milk': 1288, 'flour': 9, 'sugar': 95 }), 0) - self.assertEqual(recipe_batches({ 'milk': 100, 'butter': 50, 'cheese': 10 }, { 'milk': 198, 'butter': 52, 'cheese': 10 }), 1) - self.assertEqual(recipe_batches({ 'milk': 2, 'sugar': 40, 'butter': 20 }, { 'milk': 5, 'sugar': 120, 'butter': 500 }), 2) - self.assertEqual(recipe_batches({ 'milk': 2 }, { 'milk': 200}), 100) + self.assertEqual(recipe_batches({'milk': 100, 'flour': 4, 'sugar': 10, 'butter': 5}, {'milk': 1288, 'flour': 9, 'sugar': 95}), 0) + self.assertEqual(recipe_batches({'milk': 100, 'butter': 50, 'cheese': 10}, {'milk': 198, 'butter': 52, 'cheese': 10}), 1) + self.assertEqual(recipe_batches({'milk': 2, 'sugar': 40, 'butter': 20}, {'milk': 5, 'sugar': 120, 'butter': 500}), 2) + self.assertEqual(recipe_batches({'milk': 2}, {'milk': 200}), 100) if __name__ == '__main__': - unittest.main() \ No newline at end of file + unittest.main() diff --git a/rock_paper_scissors/rps.py b/rock_paper_scissors/rps.py index ad752c9c9..91ae22aef 100755 --- a/rock_paper_scissors/rps.py +++ b/rock_paper_scissors/rps.py @@ -1,9 +1,19 @@ -#!/usr/bin/python +#!/usr/bin/env python import sys + def rock_paper_scissors(n): - pass + if n == 0: + return[[]] + available_plays = ['rock', 'paper', 'scissors'] + plays = [] + for play in available_plays: + for subplay in rock_paper_scissors(n - 1): + plays.append( + [play] + subplay + ) + return plays if __name__ == "__main__": @@ -11,4 +21,4 @@ def rock_paper_scissors(n): num_plays = int(sys.argv[1]) print(rock_paper_scissors(num_plays)) else: - print('Usage: rps.py [num_plays]') \ No newline at end of file + print('Usage: rps.py [num_plays]') diff --git a/rock_paper_scissors/test_rps.py b/rock_paper_scissors/test_rps.py index 224ed5e26..f895617f1 100755 --- a/rock_paper_scissors/test_rps.py +++ b/rock_paper_scissors/test_rps.py @@ -1,5 +1,8 @@ +#!/usr/bin/env python + import unittest -from rps import rock_paper_scissors +from . import rock_paper_scissors + class Test(unittest.TestCase): @@ -13,4 +16,4 @@ def test_rock_paper_scissors_output(self): if __name__ == '__main__': - unittest.main() \ No newline at end of file + unittest.main() diff --git a/stock_prices/stock_prices.py b/stock_prices/stock_prices.py index 986072477..6f2badc43 100755 --- a/stock_prices/stock_prices.py +++ b/stock_prices/stock_prices.py @@ -1,9 +1,16 @@ -#!/usr/bin/python +#!/usr/bin/env python import argparse + def find_max_profit(prices): - pass + if len(prices) == 2: + return prices[1] - prices[0] + best = prices[1] - prices[0] + for price in prices[1:]: + if price - prices[0] > best: + best = price - prices[0] + return max(best, find_max_profit(prices[1:])) if __name__ == '__main__': @@ -12,4 +19,4 @@ def find_max_profit(prices): parser.add_argument('integers', metavar='N', type=int, nargs='+', help='an integer price') args = parser.parse_args() - print("A profit of ${profit} can be made from the stock prices {prices}.".format(profit=find_max_profit(args.integers), prices=args.integers)) \ No newline at end of file + print("A profit of ${profit} can be made from the stock prices {prices}.".format(profit=find_max_profit(args.integers), prices=args.integers)) diff --git a/stock_prices/test_stock_prices.py b/stock_prices/test_stock_prices.py index 687da4145..72bf0230a 100755 --- a/stock_prices/test_stock_prices.py +++ b/stock_prices/test_stock_prices.py @@ -1,6 +1,9 @@ +#!/usr/bin/env python + import unittest from stock_prices import find_max_profit + class Test(unittest.TestCase): def test_find_max_profit(self): @@ -11,4 +14,4 @@ def test_find_max_profit(self): if __name__ == '__main__': - unittest.main() \ No newline at end of file + unittest.main()