lb = 20080915McKinney Chapter 2 - Practice - Sec 02
FINA 6333 for Spring 2025
Announcements
- Check your email inbox for an invitation to a free six-month subscription to DataCamp
- I added a few short courses to our course group
- These short courses are completely optional
- DataCamp has lots of resources to help you learn Python, R, SQL, Excel, etc.
- Here are links to a few finance newsletters I strongly suggest:
- Matt Levine: https://www.bloomberg.com/account/newsletters/money-stuff
- Byrne Hobart: https://capitalgains.thediff.co/subscribe?ref=I0N1NGdmJq&_bhlid=7fecfad9eb7fd8bcdb529e945e11346b5897acdc
- Clifford Asness: https://www.aqr.com/Insights/Perspectives
- Owen Lamont: https://www.acadian-asset.com/investment-insights/owenomics#
Five-Minute Review
Practice
Extract the year, month, and day from an 8-digit date (i.e., YYYYMMDD format) using // (integer division) and % (modulo division).
lb20080915
lb // 10_000 # // is integer division2008
lb % 10_000 # % is modulo or remainder division915
(lb % 10_000) // 1009
lb % 10015
What happened here?
- Floor or integer division
//drops the digits on the right side (one digit per zero) - Modulo or remainder division
%keeps the diggits on the right side (one digit per zero)
Here is solution that approximates Excel’s LEFT(), MID(), and RIGHT(). This works, but is not very Pythonic.
int(str(lb)[:4])2008
int(str(lb)[4:6])9
int(str(lb)[7:8])5
Write a function date that takes an 8-digit date argument and returns a year, month, and date tuple (e.g., return (year, month, day)).
def date(ymd):
year = ymd // 10_000 # // is integer division
month = (ymd % 10_000) // 100
day = ymd % 100
return (year, month, day)date(lb)(2008, 9, 15)
date(20250110)(2025, 1, 10)
Write a function date_2 that takes an 8-digit date as either integer or string.
def date_2(ymd):
# if type(ymd) is str:
#
if isinstance(ymd, str):
ymd = int(ymd)
return date(ymd)The isinstance(ymd, str) is better than type(ymd) == str because the isinstance() function also tests for all sub-classes of str. More here: https://stackoverflow.com/questions/152580/whats-the-canonical-way-to-check-for-type-in-python/.
date_2(str(lb))(2008, 9, 15)
date_2('20250110')(2025, 1, 10)
Write a function date_3 that takes a list of 8-digit dates as integers or strings.
dates_in = [20080915, 20250110]def date_3(dates_in):
dates_out = []
for d in dates_in:
# dates_out += [date_2(d)] # alternative
dates_out.append(date_2(d))
return dates_outI have a slight preference for .append() over += [] because .append() modifies the list the list in place instead of making a copy. However, the speed differences in most cases in this course will be negligible. More here: https://www.geeksforgeeks.org/difference-between-and-append-in-python/.
date_3(dates_in)[(2008, 9, 15), (2025, 1, 10)]
Write a for loop that prints the squares of integers from 1 to 10.
print('a', 'b', 'c', sep = '---')a---b---c
for i in range(1, 11):
print(i**2, end=' ')1 4 9 16 25 36 49 64 81 100
Write a for loop that prints the squares of even integers from 1 to 10.
for i in range(1, 11):
if i % 2 == 0:
print(i**2, end=' ')4 16 36 64 100
for i in range(2, 11, 2):
print(i**2, end=' ')4 16 36 64 100
Write a for loop that sums the squares of integers from 1 to 10.
total = 0
for i in range(1, 11):
total += i**2
total385
Write a for loop that sums the squares of integers from 1 to 10 but stops before the sum exceeds 50.
total = 0 # Initialize sum to zero
for i in range(1, 11): # Loop from 1 to 10
# Check if adding the square of i would exceed 50
if (total + i**2) > 50:
# 'break' exits the loop completely, stopping further iterations
# 'continue' would skip to the next iteration without executing further code in this cycle
break
# Add the square of i to total
total += i**2
# Print the final sum (implicit return in this case since it is the last line in the code cell)
total30
FizzBuzz
Solve FizzBuzz.
Here is some pseudo code. The test for multiples of 3 and 5 must come first, otherwise it would never run!
# for i in range(1, 101):
# # test for multiple of 3 & 5
# # print fizzbuzz
# # test for multiple of 3
# # print fizz
# # test for multiple of 5
# # print buzz
# # otherwise print iHere is my favorite FizzBuzz solution.
for i in range(1, 101):
if (i % 3 == 0) & (i % 5 == 0):
print('FizzBuzz', end=' ')
elif (i % 3 == 0):
print('Fizz', end=' ')
elif (i % 5 == 0):
print('Buzz', end=' ')
else:
print(i, end=' ')1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz 16 17 Fizz 19 Buzz Fizz 22 23 Fizz Buzz 26 Fizz 28 29 FizzBuzz 31 32 Fizz 34 Buzz Fizz 37 38 Fizz Buzz 41 Fizz 43 44 FizzBuzz 46 47 Fizz 49 Buzz Fizz 52 53 Fizz Buzz 56 Fizz 58 59 FizzBuzz 61 62 Fizz 64 Buzz Fizz 67 68 Fizz Buzz 71 Fizz 73 74 FizzBuzz 76 77 Fizz 79 Buzz Fizz 82 83 Fizz Buzz 86 Fizz 88 89 FizzBuzz 91 92 Fizz 94 Buzz Fizz 97 98 Fizz Buzz
Use ternary expressions to make your FizzBuzz solution more compact.
Here is a compact FizzBuzz solution. I consider the solution above easier to read and troubleshoot. The compact solution below uses the trick that we can multiply a string by True to return the string itself or by or False to return an empty string.
for i in range(1, 101):
print('Fizz'*(i%3==0) + 'Buzz'*(i%5==0) if (i%3==0) or (i%5==0) else i, end=' ')1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz 16 17 Fizz 19 Buzz Fizz 22 23 Fizz Buzz 26 Fizz 28 29 FizzBuzz 31 32 Fizz 34 Buzz Fizz 37 38 Fizz Buzz 41 Fizz 43 44 FizzBuzz 46 47 Fizz 49 Buzz Fizz 52 53 Fizz Buzz 56 Fizz 58 59 FizzBuzz 61 62 Fizz 64 Buzz Fizz 67 68 Fizz Buzz 71 Fizz 73 74 FizzBuzz 76 77 Fizz 79 Buzz Fizz 82 83 Fizz Buzz 86 Fizz 88 89 FizzBuzz 91 92 Fizz 94 Buzz Fizz 97 98 Fizz Buzz
Here is an even more compact FizzBuzz solution. The trick below is that Python’s or returns its first truthy value. - If the concatenated string ('Fizz'*(i%3==0) + 'Buzz'*(i%5==0)) is not an empty string, which is falsy in Python, the or evaluates to that string. - If the string is empty, which means i is not divisible by 3 or 5, the or evaluates to i.
for i in range(1, 101):
print('Fizz'*(i%3==0) + 'Buzz'*(i%5==0) or i, end=' ')1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz 16 17 Fizz 19 Buzz Fizz 22 23 Fizz Buzz 26 Fizz 28 29 FizzBuzz 31 32 Fizz 34 Buzz Fizz 37 38 Fizz Buzz 41 Fizz 43 44 FizzBuzz 46 47 Fizz 49 Buzz Fizz 52 53 Fizz Buzz 56 Fizz 58 59 FizzBuzz 61 62 Fizz 64 Buzz Fizz 67 68 Fizz Buzz 71 Fizz 73 74 FizzBuzz 76 77 Fizz 79 Buzz Fizz 82 83 Fizz Buzz 86 Fizz 88 89 FizzBuzz 91 92 Fizz 94 Buzz Fizz 97 98 Fizz Buzz
Triangle
Write a function triangle that accepts a positive integer \(N\) and prints a numerical triangle of height \(N-1\). For example, triangle(N=6) should print:
1
22
333
4444
55555
def triangle(N):
for i in range(1, N):
print(str(i) * i)triangle(6)1
22
333
4444
55555
The solution above works because a multiplying a string by i concatenates i copies of that string.
'Test' + 'Test' + 'Test''TestTestTest'
'Test' * 3'TestTestTest'
Two Sum
Write a function two_sum that does the following.
Given a list of integers nums and an integer target, return the indices of the two numbers that add up to target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
You can return the answer in any order.
Here are some examples:
Example 1:
Input: nums = [2,7,11,15], target = 9
Output: [0,1]
Explanation: Because nums[0] + nums[1] == 9, we return [0, 1].
Example 2:
Input: nums = [3,2,4], target = 6
Output: [1,2]
Example 3:
Input: nums = [3,3], target = 6
Output: [0,1]
I saw this question on LeetCode.
def two_sum(nums, target):
for i in range(1, len(nums)):
for j in range(i):
if nums[i] + nums[j] == target:
return [j, i]two_sum(nums = [2,7,11,15], target = 9)[0, 1]
two_sum(nums = [3,2,4], target = 6)[1, 2]
two_sum(nums = [3,3], target = 6)[0, 1]
Best Time
Write a function best_time that solves the following.
You are given a list prices where prices[i] is the price of a given stock on the \(i^{th}\) day.
You want to maximize your profit by choosing a single day to buy one stock and choosing a different day in the future to sell that stock.
Return the maximum profit you can achieve from this transaction. If you cannot achieve any profit, return 0.
Here are some examples:
Example 1:
Input: prices = [7,1,5,3,6,4]
Output: 5
Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5. Note that buying on day 2 and selling on day 1 is not allowed because you must buy before you sell.
Example 2:
Input: prices = [7,6,4,3,1]
Output: 0
Explanation: In this case, no transactions are done and the max profit = 0.
I saw this question on LeetCode.
def max_profit(prices):
# We start by assuming the first price is the lowest we've seen so far
min_price = prices[0]
# We initialize our maximum profit to zero, as no profit has been calculated yet
max_profit = 0
# Loop through each price in the list of prices
for price in prices:
# If the current price is lower than our lowest price seen, update min_price
min_price = price if price < min_price else min_price
# Calculate the profit if we were to sell at the current price
profit = price - min_price
# If this profit is better than our max profit so far, update max_profit
max_profit = profit if profit > max_profit else max_profit
# After checking all prices, return the maximum profit we've found
return max_profitmax_profit(prices=[7,1,5,3,6,4])5
max_profit(prices=[7,6,4,3,1])0
We could replace the ternary statements with the min() and max() functions for a little more compact code.
def max_profit_2(prices):
min_price = prices[0]
max_profit = 0
for price in prices:
# Update min_price if current price is lower
min_price = min(min_price, price)
# Calculate profit by selling at the current price
current_profit = price - min_price
# Update max_profit if the current_profit is higher
max_profit = max(max_profit, current_profit)
return max_profitmax_profit_2(prices=[7,1,5,3,6,4])5
max_profit_2(prices=[7,6,4,3,1])0