Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamic Programming |Buy & sell stock with transaction fee #60

Merged
merged 2 commits into from
Nov 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions DIRECTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@
* Dollar Bills
* [Make Change](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/dollar_bills/make_change.py)
* Dynamic Programming
* Buy Sell Stock
* [Test Max Profit](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/dynamic_programming/buy_sell_stock/test_max_profit.py)
* [Test Max Profit Three](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/dynamic_programming/buy_sell_stock/test_max_profit_three.py)
* [Test Max Profit Two](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/dynamic_programming/buy_sell_stock/test_max_profit_two.py)
* [Test Max Profit With Fee](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/dynamic_programming/buy_sell_stock/test_max_profit_with_fee.py)
* Domino Tromino Tiling
* [Test Domino Tromino Tiling](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/dynamic_programming/domino_tromino_tiling/test_domino_tromino_tiling.py)
* Duffle Bug Value
Expand Down Expand Up @@ -335,10 +340,6 @@
* [Test Max Consecutive Ones](https://github.com/BrianLusina/PythonSnips/blob/master/puzzles/arrays/max_consecutive_ones/test_max_consecutive_ones.py)
* Max Number Of Ksum Pairs
* [Test Max Number Of Ksum Pairs](https://github.com/BrianLusina/PythonSnips/blob/master/puzzles/arrays/max_number_of_ksum_pairs/test_max_number_of_ksum_pairs.py)
* Max Profit
* [Test Max Profit](https://github.com/BrianLusina/PythonSnips/blob/master/puzzles/arrays/max_profit/test_max_profit.py)
* [Test Max Profit Three](https://github.com/BrianLusina/PythonSnips/blob/master/puzzles/arrays/max_profit/test_max_profit_three.py)
* [Test Max Profit Two](https://github.com/BrianLusina/PythonSnips/blob/master/puzzles/arrays/max_profit/test_max_profit_two.py)
* Maximum Average Subarray
* [Test Max Average Subarray](https://github.com/BrianLusina/PythonSnips/blob/master/puzzles/arrays/maximum_average_subarray/test_max_average_subarray.py)
* Maxlen Contiguous Binary Subarray
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,46 @@ Input: prices = [7,6,4,3,1]
Output: 0
Explanation: In this case, no transaction is done, i.e. max profit = 0.
```

---

# Best Time To Buy and Sell Stock With Transaction Fee

You are given an array prices where prices[i] is the price of a given stock on the ith day, and an integer fee
representing a transaction fee.

Find the maximum profit you can achieve. You may complete as many transactions as you like, but you need to pay the
transaction fee for each transaction.

Note:

You may not engage in multiple transactions simultaneously (i.e., you must sell the stock before you buy again).
The transaction fee is only charged once for each stock purchase and sale.

Example 1:

```text
Input: prices = [1,3,2,8,4,9], fee = 2
Output: 8
Explanation: The maximum profit can be achieved by:
- Buying at prices[0] = 1
- Selling at prices[3] = 8
- Buying at prices[4] = 4
- Selling at prices[5] = 9
The total profit is ((8 - 1) - 2) + ((9 - 4) - 2) = 8.
```

Example 2:

```text
Input: prices = [1,3,7,5,10,3], fee = 3
Output: 6
```

# Related topics

- Arrays
- Dynamic Programming
- Greedy


Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import math
from typing import List


Expand Down Expand Up @@ -93,3 +94,29 @@ def max_profit_3(prices: List[int]) -> int:
profit = max(profit, forward_profit[day] + backward_profit[day])

return profit


def max_profit_with_fee(prices: List[int], fee: int) -> int:
# initially, there is no cash
initial_cash = -math.inf
# initial profit is 0
current_profit = 0

for price in prices:
# Maximum cash in hand with shares
# Either
# 1. withold prev share in which case your cash in hand will not change,
# 2. or assume there was no currently bought share but you want to buy it today -
# In this case: your current cash in hand with shares will be your previous cash
# in hand without shares minus buying price of the share today.
initial_cash = max(initial_cash, current_profit - price)

# Maximum cash in hand without shares
# Either
# 1. withold money without shares in which case your cash in hand will not change,
# 2. or assume you previously bought the share and you are going to sell that today -
# In this case : your current cash in hand without shares will be your previous cash
# in hand with shares plus the current selling price minus transaction fee
current_profit = max(current_profit, initial_cash + price - fee)

return current_profit
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import unittest

from . import max_profit_with_fee


class MaxProfitWithFeeTestCases(unittest.TestCase):
def test_empty_array(self):
nums = []
expected = 0
actual = max_profit_with_fee(nums, 4)
self.assertEqual(expected, actual)

def test_prices_are_same(self):
nums = [1, 1, 1, 1]
expected = 0
actual = max_profit_with_fee(nums, 4)
self.assertEqual(expected, actual)

def test_single_element_array(self):
nums = [1]
expected = 0
actual = max_profit_with_fee(nums, 1)
self.assertEqual(expected, actual)

def test_4(self):
"""should return 8 for prices=1,3,2,8,4,9 and fee of 2"""
nums = [1, 3, 2, 8, 4, 9]
fee = 2
expected = 8
actual = max_profit_with_fee(nums, fee)
self.assertEqual(expected, actual)

def test_5(self):
"""should return 6 for prices=1,3,7,5,10,3 and fee of 3"""
nums = [1, 3, 7, 5, 10, 3]
fee = 3
expected = 6
actual = max_profit_with_fee(nums, fee)
self.assertEqual(expected, actual)

def test_6(self):
"""should return 13 for prices=[1,4,6,2,8,3,10,14] and fee of 3"""
nums = [1, 4, 6, 2, 8, 3, 10, 14]
fee = 3
expected = 13
actual = max_profit_with_fee(nums, fee)
self.assertEqual(expected, actual)


if __name__ == "__main__":
unittest.main()
Loading