You have a list of integers, and for each index you want to find the product of every integer except the integer at that index.

Write a function get_products_of_all_ints_except_at_index() that takes a list of integers and returns a list of the products.

For example, given:

[1, 7, 3, 4]

your function would return:

[84, 12, 28, 21]

by calculating:

[7 * 3 * 4, 1 * 3 * 4, 1 * 7 * 4, 1 * 7 * 3]

Do not use division in your solution.


In [106]:
from functools import reduce

def get_products_of_all_ints_except_at_index(arr):
    results = []
    
    if len(arr) < 2:
        raise Exception("Arrays too short, can't do it")
    
    for index, value in enumerate(arr):
        new_array = arr[0:index] + arr[index+1:]
        product = reduce((lambda x, y: x * y), new_array)
        results.append(product)
    return results

arr = [1, 7, 3, 4]
print(get_products_of_all_ints_except_at_index(arr))

# arr = [1]
# print(get_products_of_all_ints_except_at_index(arr))

arr = [1, 2]
print(get_products_of_all_ints_except_at_index(arr))


[84, 12, 28, 21]
[2, 1]

In [ ]:

Apple Stocks

Write an efficient function that takes stock_prices_yesterday and returns the best profit I could have made from 1 purchase and 1 sale of 1 Apple stock yesterday.


In [31]:
from IPython.core.display import Image, display
from IPython.display import Image, Markdown
import random

In [32]:
def get_max_profit(stock_prices):
    '''returns the best profit I could have made from 1 purchase and 1 sale of 1 Apple stock yesterday.
       have to buy before selling
       O(n^2) Solution
    '''
    max_profit = 0
    
    for inner_index in range(len(stock_prices)):
        for outer_index in range(len(stock_prices)):
            earlier_time = min(inner_index, outer_index)
            later_time = max(inner_index, outer_index)
            
            # Get the earlier/later prices for correct ordering
            earlier_price = stock_prices[earlier_time]
            later_price = stock_prices[later_time]
            
            potential_profit = later_price - earlier_price
            max_profit = max(max_profit, potential_profit)
    return max_profit
                
stock_prices_yesterday = []
print(get_max_profit(stock_prices_yesterday) == 0)
    
stock_prices_yesterday = [6]
print(get_max_profit(stock_prices_yesterday) == 0)

stock_prices_yesterday = [10, 7, 5, 8, 11, 9]
print(get_max_profit(stock_prices_yesterday) == 6)


True
True
True

In [54]:
def get_max_profit(stock_prices):
    '''returns the best profit I could have made from 1 purchase and 1 sale of 1 Apple stock yesterday.
       have to buy before selling
       O(n^2) Solution
    '''
    max_profit = 0
    
    for inner_index in range(len(stock_prices)):
        for outer_index in range(len(stock_prices[inner_index:])):
            earlier_time = min(inner_index, outer_index)
            later_time = max(inner_index, outer_index)
            
            # Get the earlier/later prices for correct ordering
            earlier_price = stock_prices[earlier_time]
            later_price = stock_prices[later_time]
            
            potential_profit = later_price - earlier_price
            max_profit = max(max_profit, potential_profit)
    return max_profit
                
stock_prices_yesterday = []
print(get_max_profit(stock_prices_yesterday) == 0)
    
stock_prices_yesterday = [6]
print(get_max_profit(stock_prices_yesterday) == 0)

stock_prices_yesterday = [10, 7, 5, 8, 11, 9]
print(get_max_profit(stock_prices_yesterday) == 6)  #incorrect


True
True
False

Need to do better than O(n^2), so it'll probably be either O(n log n) or O(n). Let's try a greedy approach.


In [80]:
def get_max_profit(stock_prices):
    '''returns the best profit I could have made from 1 purchase and 1 sale of 1 Apple stock yesterday.
       have to buy before selling.
       Came up with this on my own! Runtime is O(n)
    '''
    if len(stock_prices) < 2:
        return 0
    
    min_buy = stock_prices[0]
    max_sell = stock_prices[1]
    print(min_buy, max_sell)
    for time in range(len(stock_prices)-1):
        
        if time == 0:
            continue
            
        buy = stock_prices[time]
        sell = stock_prices[time+1]
        
        min_buy = min(min_buy, buy)
        max_sell = max(max_sell, sell)
        print(min_buy, max_sell)
            
    return max_sell - min_buy
        
# stock_prices_yesterday = []
# print(get_max_profit(stock_prices_yesterday) == 0)
    
# stock_prices_yesterday = [6]
# print(get_max_profit(stock_prices_yesterday) == 0)

stock_prices_yesterday = [10, 7, 5, 8, 11, 9]
print(get_max_profit(stock_prices_yesterday))

# stock_prices_yesterday = [4, 3, 2, 1]
# print(get_max_profit(stock_prices_yesterday))

# stock_prices_yesterday = [4, 4, 4, 4]
# print(get_max_profit(stock_prices_yesterday))


10 7
7 7
5 8
5 11
5 11
6

In [83]:
def get_max_profit(stock_prices_yesterday):

    # make sure we have at least 2 prices
    if len(stock_prices_yesterday) < 2:
        raise IndexError('Getting a profit requires at least 2 prices')

    # we'll greedily update min_price and max_profit, so we initialize
    # them to the first price and the first possible profit
    min_price = stock_prices_yesterday[0]
    max_profit = stock_prices_yesterday[1] - stock_prices_yesterday[0]

    for index, current_price in enumerate(stock_prices_yesterday):

        # skip the first (0th) time
        # we can't sell at the first time, since we must buy first,
        # and we can't buy and sell at the same time!
        # if we took this out, we'd try to buy *and* sell at time 0.
        # this would give a profit of 0, which is a problem if our
        # max_profit is supposed to be *negative*--we'd return 0.
        if index == 0:
            continue

        # see what our profit would be if we bought at the
        # min price and sold at the current price
        potential_profit = current_price - min_price

        # update max_profit if we can do better
        max_profit = max(max_profit, potential_profit)

        # update min_price so it's always
        # the lowest price we've seen so far
        min_price  = min(min_price, current_price)

    return max_profit

stock_prices_yesterday = [10, 7, 5, 8, 11, 9]
print(get_max_profit(stock_prices_yesterday))

stock_prices_yesterday = [4, 3, 2, 1]
print(get_max_profit(stock_prices_yesterday))

stock_prices_yesterday = [4, 4, 4, 4]
print(get_max_profit(stock_prices_yesterday))


6
-1
0

In [ ]: