From 7271c0d64acf4881636f08c4c2dcb00cbe757798 Mon Sep 17 00:00:00 2001 From: Sanders Lin <45224617+SandersLin@users.noreply.github.com> Date: Sat, 13 Jul 2019 15:12:54 +0800 Subject: [PATCH] Update rod_cutting.py (#995) * Update rod_cutting.py A hopefully clearer implementation without dependence on global variables. * Update rod_cutting.py added doctests * Update rod_cutting.py * Update rod_cutting.py --- dynamic_programming/rod_cutting.py | 95 +++++++++++++++--------------- 1 file changed, 47 insertions(+), 48 deletions(-) diff --git a/dynamic_programming/rod_cutting.py b/dynamic_programming/rod_cutting.py index 34350cb82..c3111dcfc 100644 --- a/dynamic_programming/rod_cutting.py +++ b/dynamic_programming/rod_cutting.py @@ -1,58 +1,57 @@ -### PROBLEM ### -""" -We are given a rod of length n and we are given the array of prices, also of -length n. This array contains the price for selling a rod at a certain length. -For example, prices[5] shows the price we can sell a rod of length 5. -Generalising, prices[x] shows the price a rod of length x can be sold. -We are tasked to find the optimal solution to sell the given rod. -""" +from typing import List -### SOLUTION ### -""" -Profit(n) = max(1 int: + """ + Given a rod of length n and array of prices that indicate price at each length. + Determine the maximum value obtainable by cutting up the rod and selling the pieces + + >>> rod_cutting([1,5,8,9],4) + 10 + >>> rod_cutting([1,1,1],3) + 3 + >>> rod_cutting([1,2,3], -1) + Traceback (most recent call last): + ValueError: Given integer must be greater than 1, not -1 + >>> rod_cutting([1,2,3], 3.2) + Traceback (most recent call last): + TypeError: Must be int, not float + >>> rod_cutting([], 3) + Traceback (most recent call last): + AssertionError: prices list is shorted than length: 3 + + -When we receive a rod, we have two options: -a) Don't cut it and sell it as is (receiving prices[length]) -b) Cut it and sell it in two parts. The length we cut it and the rod we are -left with, which we have to try and sell separately in an efficient way. -Choose the maximum price we can get. -""" + Args: + prices: list indicating price at each length, where prices[0] = 0 indicating rod of zero length has no value + length: length of rod -def CutRod(n): - if(n == 1): - #Cannot cut rod any further - return prices[1] + Returns: + Maximum revenue attainable by cutting up the rod in any way. + """ - noCut = prices[n] #The price you get when you don't cut the rod - yesCut = [-1 for x in range(n)] #The prices for the different cutting options + prices.insert(0, 0) + if not isinstance(length, int): + raise TypeError('Must be int, not {0}'.format(type(length).__name__)) + if length < 0: + raise ValueError('Given integer must be greater than 1, not {0}'.format(length)) + assert len(prices) - 1 >= length, "prices list is shorted than length: {0}".format(length) - for i in range(1,n): - if(solutions[i] == -1): - #We haven't calulated solution for length i yet. - #We know we sell the part of length i so we get prices[i]. - #We just need to know how to sell rod of length n-i - yesCut[i] = prices[i] + CutRod(n-i) - else: - #We have calculated solution for length i. - #We add the two prices. - yesCut[i] = prices[i] + solutions[n-i] + return rod_cutting_recursive(prices, length) - #We need to find the highest price in order to sell more efficiently. - #We have to choose between noCut and the prices in yesCut. - m = noCut #Initialize max to noCut - for i in range(n): - if(yesCut[i] > m): - m = yesCut[i] - - solutions[n] = m - return m +def rod_cutting_recursive(prices: List[int],length: int) -> int: + #base case + if length == 0: + return 0 + value = float('-inf') + for firstCutLocation in range(1,length+1): + value = max(value, prices[firstCutLocation]+rod_cutting_recursive(prices,length - firstCutLocation)) + return value +def main(): + assert rod_cutting([1,5,8,9,10,17,17,20,24,30],10) == 30 + # print(rod_cutting([],0)) -### EXAMPLE ### -length = 5 -#The first price, 0, is for when we have no rod. -prices = [0, 1, 3, 7, 9, 11, 13, 17, 21, 21, 30] -solutions = [-1 for x in range(length+1)] +if __name__ == '__main__': + main() -print(CutRod(length))