lb = 20080915McKinney Chapter 2 - Practice - Sec 04
FINA 6333 for Spring 2025
HELLO! NIRAMAY!
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)).
import thisThe Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
def date(ymd):
year = ymd // 10_000 # // is integer division
month = (ymd % 10_000) // 100
day = ymd % 100
return (year, month, day)lb20080915
%whodate lb this
date(lb)(2008, 9, 15)
date(20250110)(2025, 1, 10)
type(date(20250110))tuple
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)date_2(lb)(2008, 9, 15)
date_2(str(lb))(2008, 9, 15)
date_2(20250110)(2025, 1, 10)
date_2('20250110')(2025, 1, 10)
Write a function date_3 that takes a list of 8-digit dates as integers or strings.
ymds = [20080915, '20250110']
ymds[20080915, '20250110']
This markdown cell is for italicized and bold text!
def date_3(ymds):
ymds_out = []
for ymd in ymds:
ymds_out.append(date_2(ymd))
return ymds_outdate_3(ymds)[(2008, 9, 15), (2025, 1, 10)]
Write a for loop that prints the squares of integers from 1 to 10.
print(1, 2, 3, sep='---')1---2---3
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