I wrote the following code for solving the Rod-Cutting Problem using dynamic programming:
Rod Cutting Problem: Given a rod of length n inches and an array of prices that contains prices of all pieces of size smaller than n. Determine the maximum value obtainable by cutting up the rod and selling the pieces and also find the size of the pieces to be cut.
import random
prices = {x:random.randrange(x, 2*x) for x in range(1,101)}
def find_optimum_revenue(length, prices, memo={}):
'''This function finds the maximum possible revenue
that can be generated by cutting a rod of
length = length and the prices for each rod of length n
is stored in prices such that prices[n] finds the price
of the rod.'''
if length == 1: # Base Case: You can't cut a rod of length == 1
return prices[1]
elif length in memo:
return memo[length]
else:
# The first list will contain all the possible revenues after
# cutting the rod. We add the list [prices[length]] to add the
# possibility that we may sell the rod as is and not cut it.
possible_revenues = [find_optimum_revenue(half, prices, memo) + \
find_optimum_revenue
(length - half, prices, memo) \
for half in range(1, length//2+1)] + [prices[length]]
memo[length] = max(possible_revenues) # Saving in dictionary for future use
return memo[length]
get_price = lambda pieces: sum(prices[rod] for rod in pieces)
def find_optimum_cuts(length, prices, memo={}):
'''This function finds the length of pieces to be cut so
as to generate the maximum revenue that can be generated
by cutting a rod of length = length and the prices for
each rod of length n is stored in prices such that prices[n]
finds the price of the rod.'''
if length == 1: # Base Case: You can't cut a rod of length == 1
return (1,)
elif length in memo:
return memo[length]
else:
# The first list will contain all the possible revenues after
# cutting the rod. We add the list [prices[length]] to add the
# possibility that we may sell the rod as is and not cut it.
best_cuts = [find_optimum_cuts(half, prices, memo) + \
find_optimum_cuts(length - half, prices, memo) \
for half in range(1, length//2+1)] + [(length,)]
memo[length] = max(best_cuts, key=get_price) # Saving in dictionary for future use
return memo[length]
print(find_optimum_revenue(100, prices))
print(find_optimum_cuts(100, prices))
It works correctly for all the test cases I have tried and is not broken. The first function finds the maximum revenue and the second the pieces to be cut. I am thinking of merging them as it would save time. The prices
list contains the prices of different sizes of rods. Is it possible to reduce the time and memory consumption and make the code better and more Pythonic? Also, can you please tell me its time complexity? I believe it to be \$O(n^2)\$ but I am not sure.