More Looping Answers
Tuple Exercises
Hint
If you get stuck for a minute or more, try searching Google or using help.
If you’re stuck for more than a few minutes, some of these links might be helpful for some of the exercises below:
Hot Dog Packs
File: Edit the hotdog_counts function in the tuples.py file that is in the exercises directory.
Test: Run python test.py hotdog_counts in your exercises directory.
Exercise: We’re hosting a party and we need to know how many hot dog buns and hot dogs we need.
Buns and dogs are sold in packs of different sizes:
8 buns are in 1 pack of buns
10 hot dogs are in 1 pack of dogs
Create a function hotdog_counts which accepts the number of guests and returns a two-item tuple containing the number of bun packs and the number of dog packs we need (bun packs first, dog packs second).
>>> from tuples import hotdog_counts
>>> hotdog_counts(7)
(1, 1)
>>> hotdog_counts(10)
(2, 1)
>>> hotdog_counts(14)
(2, 2)
>>> hotdog_counts(20)
(3, 2)
>>> hotdog_counts(21)
(3, 3)
Hint
You’ll need to calculate how many packs are needed by dividing and rounding up. Use math.ceil() to round upward, or use integer division with a trick.
Answers
Using math.ceil:
import math
def hotdog_counts(guests):
"""Return tuple of bun packs and dog packs needed for given guests."""
bun_packs = math.ceil(guests / 8)
dog_packs = math.ceil(guests / 10)
return (bun_packs, dog_packs)
Using integer division trick:
def hotdog_counts(guests):
"""Return tuple of bun packs and dog packs needed for given guests."""
bun_packs = (guests + 7) // 8 # Add 7 to round up when dividing by 8
dog_packs = (guests + 9) // 10 # Add 9 to round up when dividing by 10
return (bun_packs, dog_packs)
Parse Time
File: Edit the parse_time function in the file functions.py that is in the exercises directory.
Test: Run python test.py parse_time in your exercises directory.
Exercise: Edit the function parse_time so that it takes an input time string in the format of “minutes:seconds”, uses tuple unpacking to extract the minutes and seconds, calculates and returns the total number of seconds.
You can assume the string will contain at least one digit each for minutes and seconds.
>>> from functions import parse_time
>>> parse_time("4:03")
243
>>> parse_time("0:12")
12
>>> parse_time("1:10")
70
Answers
def parse_time(time_string):
"""Return total seconds from string of minutes:seconds."""
minutes, seconds = time_string.split(':')
return int(minutes) * 60 + int(seconds)
Format Time
File: Edit the format_time function in the file functions.py that is in the exercises directory.
Test: Run python test.py format_time in your exercises directory.
Exercise: Edit the function format_time so that it takes an integer value of seconds and calculates minutes and seconds, then returns a string of “minutes:seconds”. If the value of seconds is less than 10, a zero should be prefixed so the seconds are always 2 digits.
>>> from functions import format_time
>>> format_time(90061)
'1501:01'
>>> format_time(0)
'0:00'
>>> format_time(3600)
'60:00'
>>> format_time(301)
'5:01'
>>> format_time(3715)
'61:55'
>>> format_time(61)
'1:01'
>>> format_time(119)
'1:59'
>>> format_time(333)
'5:33'
Answers
def format_time(seconds):
"""Return a minutes:seconds string based on input seconds."""
minutes, seconds = divmod(seconds, 60)
return f"{minutes}:{seconds:02d}"
Swap Ends
File: Edit the swap_ends function in the tuples.py file that is in the exercises directory.
Test: Run python test.py swap_ends in your exercises directory.
Exercise: Edit the function swap_ends so that it swaps the first and last items in a given list, in-place.
>>> from tuples import swap_ends
>>> numbers = [1, 2, 3, 4, 5]
>>> swap_ends(numbers)
>>> numbers
[5, 2, 3, 4, 1]
Answers
def swap_ends(sequence):
"""Swap the first and last items in the given list."""
sequence[0], sequence[-1] = sequence[-1], sequence[0]
Earliest
File: Edit the get_earliest function in the tuples.py file that is in the exercises directory.
Test: Run python test.py get_earliest in your exercises directory.
Exercise: Make function get_earliest that accepts two dates in MM/DD/YYYY format and returns the date that is earliest.
>>> from tuples import get_earliest
>>> get_earliest("01/27/1832", "01/27/1756")
'01/27/1756'
>>> get_earliest("02/29/1972", "12/21/1946")
'12/21/1946'
>>> get_earliest("03/21/1946", "02/24/1946")
'02/24/1946'
>>> get_earliest("06/24/1958", "06/21/1958")
'06/21/1958'
Note
Want to test this out manually (instead of using python test.py)?
You could could create a file called get_earliest_test.py with your own test code:
from tuples import get_earliest
print('Calling get_earliest("01/27/1832", "01/27/1756")')
print("Expected: 01/27/1756")
print(" Actual:", get_earliest("01/27/1832", "01/27/1756"))
print()
print('Calling get_earliest("02/29/1972", "12/21/1946")')
print("Expected: 12/21/1946")
print(" Actual:", get_earliest("02/29/1972", "12/21/1946"))
print()
print('Calling get_earliest("03/21/1946", "02/24/1946")')
print("Expected: 02/24/1946")
print(" Actual:", get_earliest("03/21/1946", "02/24/1946"))
print()
print('Calling get_earliest("06/24/1958", "06/21/1958")')
print("Expected: 06/21/1958")
print(" Actual:", get_earliest("06/24/1958", "06/21/1958"))
Then you can run that file to test your code:
$ python get_earliest_test.py
Answers
With tuple unpacking and if statement:
def get_earliest(date1, date2):
"""Return earliest of two MM/DD/YYYY-formatted date strings."""
(m1, d1, y1) = date1.split('/')
(m2, d2, y2) = date2.split('/')
if (y1, m1, d1) < (y2, m2, d2):
return date1
else:
return date2
With inline if:
def get_earliest(date1, date2):
"""Return earliest of two MM/DD/YYYY-formatted date strings."""
(m1, d1, y1) = date1.split('/')
(m2, d2, y2) = date2.split('/')
return date1 if (y1, m1, d1) < (y2, m2, d2) else date2
Name Key
File: Edit the name_key function in the tuples.py file that is in the exercises directory.
Test: Run python test.py name_key in your exercises directory.
Exercise: Write a function name_key that accepts a full name string and returns a last-first name tuple:
To test locally:
>>> from tuples import name_key
>>> suzanne = "Suzanne Smith"
>>> michael = "Michael Gambino"
>>> name_key(michael)
('Gambino', 'Michael')
>>> name_key(suzanne)
('Smith', 'Suzanne')
Answers
def name_key(name):
"""Return last-first name tuple from first-last name string."""
first, last = name.split()
return last, first
Sort Names
File: Edit the sort_names function in the tuples.py file that is in the exercises directory.
Test: Run python test.py sort_names in your exercises directory.
Exercise: Write a function sort_names that accepts a list of full name strings and returns a sorted list (using sorted with key).
The built-in sorted function accepts a key argument that determines how values should be sorted in a given iterable. You can use the name_key function you created above as the key argument.
Let’s use this function to sort a list of names. Names should be sorted by last name followed by first name (when the last names are equal).
>>> from tuples import sort_names
>>> names = ["Jill Moore", "Ben Speigel", "Tanya Jackson", "Evelyn Moore"]
>>> sort_names(names)
['Tanya Jackson', 'Evelyn Moore', 'Jill Moore', 'Ben Speigel']
Answers
def name_key(name):
"""Return last-first name tuple from first-last name string."""
first, last = name.split()
return last, first
def sort_names(names):
"""Return given first-last name tuples sorted by last name."""
return sorted(names, key=name_key)
Counting Exercises
Line Numbers
This is the line_numbers.py exercise in the modules directory that we saw earlier in the Introduction to Files section. Create the file line_numbers.py in the modules sub-directory of the exercises directory. To test it, run python test.py line_numbers.py from your exercises directory.
Write a program that accepts a file as its only argument and prints out the lines in the files with a line number displayed in front of them. See if you can improve the code with what we have learned in this section.
Example:
If my_file.txt contains:
This file
is two lines long.
No wait, it's three lines long!
Running:
$ python line_numbers.py my_file.txt
Should print out:
1 This file
2 is two lines long.
3 No wait, it's three lines long!
Answers
import sys
filename = sys.argv[1]
with open(filename) as my_file:
for lineno, line in enumerate(my_file, start=1):
print(lineno, line, end='')
Guess in 3
Create a program guess.py in the modules sub-directory of the exercises directory. To test it, run python test.py guess.py from your exercises directory.
The program below generates a random number from 1 to 8 and gives the user 3 guesses to guess the number correctly. After each guess the program says either “Correct”, “Too high” or “Too low”.
Once a correct guess is made, the program ends. If the final guess is incorrect, the user is shown a message noting the correct number.
Your task: Refactor this code to use a for loop for readability’s sake.
import random
number = random.randint(1, 8)
print("I have selected a number between 1 and 8.")
print("You have 3 attempts to guess it correctly.")
guess = int(input("1) Enter your guess: "))
if guess < number:
print("Too low")
guess = int(input("2) Enter your guess: "))
if guess < number:
print("Too low")
guess = int(input("3) Enter your guess: "))
if guess < number:
print("Too low")
print(f"Incorrect. The correct number was {number}.")
elif guess > number:
print("Too high")
print(f"Incorrect. The correct number was {number}.")
else:
print("Correct! You've guessed the number!")
elif guess > number:
print("Too high")
guess = int(input("3) Enter your guess: "))
if guess < number:
print("Too low")
print(f"Incorrect. The correct number was {number}.")
elif guess > number:
print("Too high")
print(f"Incorrect. The correct number was {number}.")
else:
print("Correct! You've guessed the number!")
else:
print("Correct! You've guessed the number!")
elif guess > number:
print("Too high")
guess = int(input("2) Enter your guess: "))
if guess < number:
print("Too low")
guess = int(input("3) Enter your guess: "))
if guess < number:
print("Too low")
print(f"Incorrect. The correct number was {number}.")
elif guess > number:
print("Too high")
print(f"Incorrect. The correct number was {number}.")
else:
print("Correct! You've guessed the number!")
elif guess > number:
print("Too high")
guess = int(input("3) Enter your guess: "))
if guess < number:
print("Too low")
print(f"Incorrect. The correct number was {number}.")
elif guess > number:
print("Too high")
print(f"Incorrect. The correct number was {number}.")
else:
print("Correct! You've guessed the number!")
else:
print("Correct! You've guessed the number!")
else:
print("Correct! You've guessed the number!")
Hint
Use a for loop with range(3) to iterate through the attempts. You can use break to exit the loop early when the correct guess is made, and for-else to handle the case where all guesses are exhausted.
Answers
Using a for loop with break:
import random
number = random.randint(1, 8)
print("I have selected a number between 1 and 8.")
print("You have 3 attempts to guess it correctly.")
for attempt in range(1, 4):
guess = int(input(f"{attempt}) Enter your guess: "))
if guess == number:
print("Correct! You've guessed the number!")
break
elif guess < number:
print("Too low")
else:
print("Too high")
else:
print(f"Incorrect. The correct number was {number}.")
Alternative with for-else construct:
import random
number = random.randint(1, 8)
print("I have selected a number between 1 and 8.")
print("You have 3 attempts to guess it correctly.")
for attempt in range(1, 4):
guess = int(input(f"{attempt}) Enter your guess: "))
if guess == number:
print("Correct! You've guessed the number!")
break
elif guess < number:
print("Too low")
else:
print("Too high")
else:
# This executes only if the loop wasn't broken
print(f"Incorrect. The correct number was {number}.")
Factors
Edit the get_factors function in the ranges.py file so that it returns the factors of a given number.
To test it, run python test.py get_factors in your exercises directory.
To test locally:
>>> from ranges import get_factors
>>> get_factors(2)
[1, 2]
>>> get_factors(6)
[1, 2, 3, 6]
>>> get_factors(100)
[1, 2, 4, 5, 10, 20, 25, 50, 100]
Note
Want to test this out manually (instead of using python test.py)?
You could could create a file called get_factors_test.py with your own test code:
from ranges import get_factors
print("Calling get_factors(2)")
print("Expected: [1, 2]")
print(" Actual:", get_factors(2))
print()
print("Calling get_factors(6)")
print("Expected: [1, 2, 3, 6]")
print(" Actual:", get_factors(6))
print()
print("Calling get_factors(100)")
print("Expected: [1, 2, 4, 5, 10, 20, 25, 50, 100]")
print(" Actual:", get_factors(100))
Then you can run that file to test your code:
$ python get_factors_test.py
Answers
def get_factors(number):
"""Return a list of all factors of the given number."""
factors = []
for x in range(1, number + 1):
if number % x == 0:
factors.append(x)
return factors
Range Check
Edit the is_range function in the ranges.py file so that it returns True if the given list could be represented with a range of numbers (ignoring step), and False otherwise.
To test it, run python test.py is_range in your exercises directory.
To test locally:
>>> from ranges import is_range
>>> is_range([5, 6, 7, 8])
True
>>> is_range([5, 6, 8])
False
>>> is_range([0, 2, 1, 3])
False
>>> is_range([0, 1, 2, 3])
True
Answers
def is_range(numbers):
"""Return True if given list could be represented by range with step 1."""
first, last = numbers[0], numbers[-1]
return list(range(first, last+1)) == numbers
Annual Return
This is the annual_return function in the ranges.py file.
This function is meant to model financial investments (whether in a bank, stock, or some other asset that increases at a particular average rate each year).
The annual_return function should accept these keyword arguments:
startis the starting amount of moneyannual_yieldis the percentage that the money will increase each year on averageyearsis the number of years for which the money will be yielding a return (whether invested or in the interest-earning account)annual_contributionis the amount of money that should be added at the end of every year.
Assuming a start value of $5,000, an annual yield of 7%, an annual contribution of $5,000, and 30 years of investment, the annual_return function should return an list like this:
>>> returns = annual_return(
... start=5000,
... annual_yield=0.07,
... years=30,
... annual_contribution=5000,
... )
>>> for amount in returns:
... print(f"${amount:,.2f}")
...
$10,350.00
$16,074.50
$22,199.72
$28,753.70
$35,766.45
$43,270.11
$51,299.01
$59,889.94
$69,082.24
$78,918.00
$89,442.26
$100,703.21
$112,752.44
$125,645.11
$139,440.27
$154,201.09
$169,995.16
$186,894.82
$204,977.46
$224,325.88
$245,028.70
$267,180.70
$290,883.35
$316,245.19
$343,382.35
$372,419.12
$403,488.45
$436,732.65
$472,303.93
$510,365.21
Note that the annual contribution is added at the end of the year, but the annual yield is computed based on the starting amount at the beginning of each year (this is compounding interest which is the way stocks and bank accounts frequently work).
Answers
def annual_return(start=0, annual_yield=0, years=0, annual_contribution=0):
"""Return list that models annual return for a financial asset."""
returns = []
amount = start
for year in range(years):
amount += amount*annual_yield+annual_contribution
returns.append(amount)
return returns
Primality
Edit the is_prime function in the ranges.py file so that it returns True if a number is prime and False otherwise.
To test it, run python test.py is_prime in your exercises directory.
To test locally:
>>> from ranges import is_prime
>>> is_prime(21)
False
>>> is_prime(23)
True
Answers
def is_prime(candidate):
"""Return True if candidate number is prime."""
if candidate < 2:
return False
for n in range(2, candidate):
if candidate % n == 0:
return False
return True
More performant:
from math import sqrt
def is_prime(candidate):
"""Return True if candidate number is prime."""
if candidate < 2:
return False
for n in range(2, int(sqrt(candidate))+1):
if candidate % n == 0:
return False
return True
Power List By Index
Edit the power_list function in the ranges.py file so that it accepts a list and returns a new list that contains each number raised to the i-th power where i is the index of that number in the given list.
To test it, run python test.py power_list in your exercises directory.
To test locally:
>>> from ranges import power_list
>>> power_list([3, 2, 5])
[1, 2, 25]
>>> numbers = [78, 700, 82, 16, 2, 3, 9.5]
>>> power_list(numbers)
[1, 700, 6724, 4096, 16, 243, 735091.890625]
Answers
With enumerate (most idiomatic):
def power_list(numbers):
"""Return a list that contains each number raised to the i-th power."""
powers = []
for i, number in enumerate(numbers):
powers.append(number ** i)
return powers
With range:
def power_list(nums):
"""Return a list that contains each number raised to the i-th power."""
new_list = []
for i in range(len(nums)):
new_list.append(nums[i] ** i)
return new_list
Reverse Difference
This is the reverse_difference exercise in ranges.py. Edit the ranges.py file in the exercises directory to implement this exercise. To test it, run python test.py reverse_difference in your exercises directory.
Make a function reverse_difference that accepts a list of numbers and returns a new copy of the list with the reverse of the list subtracted.
Hint: Use enumerate. We will see a better way to do this later on.
Example usage:
>>> from ranges import reverse_difference
>>> reverse_difference([9, 8, 7, 6])
[3, 1, -1, -3]
>>> reverse_difference([1, 2, 3, 4, 5])
[-4, -2, 0, 2, 4]
>>> reverse_difference([3, 2, 1, 0])
[3, 1, -1, -3]
>>> reverse_difference([0, 0])
[0, 0]
Answers
def reverse_difference(numbers):
"""Return list of reversed numbers subtracted from itself."""
reversed_nums = list(reversed(numbers))
differences = []
for i, n in enumerate(numbers):
differences.append(n - reversed_nums[i])
return differences
with_previous
Edit the function with_previous in ranges.py so that it accepts a sequence (list, string, etc.) and returns a new list that includes a tuple of each item and the previous item (the item just before it). The first “previous item” should be None.
To test it, run python test.py with_previous in your exercises directory.
Hint: Use enumerate. We will see a better way to do this later on.
It should work like this:
>>> from ranges import with_previous
>>> numbers = [1, 2, 3, 4]
>>> with_previous(numbers)
[(1, None), (2, 1), (3, 2), (4, 3)]
Answers
def with_previous(sequence):
"""Provide each list item with item before it."""
new_sequence = []
for i, item in enumerate(sequence):
if i == 0:
new_sequence.append((item, None))
else:
new_sequence.append((item, sequence[i-1]))
return new_sequence
Or, using Python’s version of the “ternary” operator:
def with_previous(sequence):
"""Provide each list item with item before it."""
new_sequence = []
for i, item in enumerate(sequence):
previous = sequence[i - 1] if i else None
new_sequence.append((item, previous))
return new_sequence
Identity Matrix
File: Edit the identity function in the ranges.py file so that it takes as input a number size for the size of the matrix and returns an identity matrix of size x size elements.
To test it, run python test.py identity in your exercises directory.
An identity matrix is a square matrix with ones on the main diagonal and zeros elsewhere. A 3 by 3 identity matrix looks like:
[[1, 0, 0], [0, 1, 0], [0, 0, 1]]
To test locally:
>>> from ranges import identity
>>> identity(3)
[[1, 0, 0], [0, 1, 0], [0, 0, 1]]
>>> identity(4)
[[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]
>>> identity(2)
[[1, 0], [0, 1]]
Answers
With an if statement:
def identity(size):
"""Return an identity matrix of size x size"""
matrix = []
for col in range(size):
new_row = []
for row in range(size):
if row == col:
new_row.append(1)
else:
new_row.append(0)
matrix.append(new_row)
return matrix
Or, we could take advantage of the internal values of True and False. This is considered by many to be a legal and reasonable thing to do in Python.
def identity(size):
"""Return an identity matrix of size x size"""
matrix = []
for col in range(size):
new_row = []
for row in range(size):
new_row.append(int(row == col))
matrix.append(new_row)
return matrix
Matrix Addition
This is the matrix_add exercise in ranges.py. Edit the ranges.py file in the exercises directory to implement this exercise. To test it, run python test.py matrix_add in your exercises directory.
Edit the function matrix_add to accept two matrices (lists of lists of numbers) and return one matrix that includes each corresponding number in the two lists added together.
Hint: Use enumerate. We will see a better way to do this later on.
You should assume the lists of lists provided will always be the same size/shape.
>>> from ranges import matrix_add
>>> m1 = [[1, 2], [3, 4]]
>>> m2 = [[5, 6], [7, 8]]
>>> matrix_add(m1, m2)
[[6, 8], [10, 12]]
>>> m1 = [[1, 2, 3], [0, 4, 2]]
>>> m2 = [[4, 2, 1], [5, 7, 0]]
>>> matrix_add(m1, m2)
[[5, 4, 4], [5, 11, 2]]
Answers
def matrix_add(matrix1, matrix2):
"""Add corresponding numbers in given 2-D matrices."""
combined = []
for i, row1 in enumerate(matrix1):
row = []
for j, number in enumerate(row1):
row.append(number + matrix2[i][j])
combined.append(row)
return combined
Pythagorean Triples
Edit the triples function in the ranges.py file so that it takes a number and returns a list of tuples of 3 integers where each tuple is a Pythagorean triple, and the integers are all less than the input number.
To test it, run python test.py triples in your exercises directory.
A Pythagorean triple is a group of 3 integers a, b, and c, such that they satisfy the formula a**2 + b**2 = c**2
To test locally:
>>> from ranges import triples
>>> triples(15)
[(3, 4, 5), (5, 12, 13), (6, 8, 10)]
>>> triples(30)
[(3, 4, 5), (5, 12, 13), (6, 8, 10), (7, 24, 25), (8, 15, 17), (9, 12, 15), (10, 24, 26), (12, 16, 20), (15, 20, 25), (20, 21, 29)]
Answers
def triples(num):
"""Return list of Pythagorean triples less than input num"""
triples_list = []
for a in range(1, num):
for b in range(a+1, num):
for c in range(b+1, num):
if a**2 + b**2 == c**2:
triples_list.append((a, b, c))
return triples_list
Zip Exercises
Hint
If you get stuck for a minute or more, try searching Google or using help.
If you’re stuck for more than a few minutes, some of these links might be helpful for some of the exercises below:
Reverse Difference
This is the reverse_difference exercise we saw earlier in ranges.py. Edit the ranges.py file in the exercises directory to implement this exercise. To test it, run python test.py reverse_difference in your exercises directory.
The function reverse_difference accepts a list of numbers and returns a new copy of the list with the reverse of the list subtracted.
Re-write the code to use the zip function.
Example usage:
>>> from ranges import reverse_difference
>>> reverse_difference([9, 8, 7, 6])
[3, 1, -1, -3]
>>> reverse_difference([1, 2, 3, 4, 5])
[-4, -2, 0, 2, 4]
>>> reverse_difference([3, 2, 1, 0])
[3, 1, -1, -3]
>>> reverse_difference([0, 0])
[0, 0]
Note
Want to test this out manually (instead of using python test.py)?
You could could create a file called reverse_difference_test.py with your own test code:
from ranges import reverse_difference
print("Calling reverse_difference([9, 8, 7, 6])")
print("Expected: [3, 1, -1, -3]")
print(" Actual:", reverse_difference([9, 8, 7, 6]))
print()
print("Calling reverse_difference([1, 2, 3, 4, 5])")
print("Expected: [-4, -2, 0, 2, 4]")
print(" Actual:", reverse_difference([1, 2, 3, 4, 5]))
print()
print("Calling reverse_difference([3, 2, 1, 0])")
print("Expected: [3, 1, -1, -3]")
print(" Actual:", reverse_difference([3, 2, 1, 0]))
Then you can run that file to test your code:
$ python reverse_difference_test.py
Answers
def reverse_difference(numbers):
"""Return list of reversed numbers subtracted from numbers."""
differences = []
for n, m in zip(numbers, reversed(numbers)):
differences.append(n - m)
return differences
Matrix Addition
This is the matrix_add exercise we saw earlier in ranges.py. Edit the ranges.py file in the exercises directory to implement this exercise. To test it, run python test.py matrix_add in your exercises directory.
The function matrix_add accepts two matrices (lists of lists of numbers) and returns one matrix that includes each corresponding number in the two lists added together.
You should assume the lists of lists provided will always be the same size/shape.
Re-write the function to use the zip function.
>>> from ranges import matrix_add
>>> m1 = [[1, 2], [3, 4]]
>>> m2 = [[5, 6], [7, 8]]
>>> matrix_add(m1, m2)
[[6, 8], [10, 12]]
>>> m1 = [[1, 2, 3], [0, 4, 2]]
>>> m2 = [[4, 2, 1], [5, 7, 0]]
>>> matrix_add(m1, m2)
[[5, 4, 4], [5, 11, 2]]
Answers
def matrix_add(matrix1, matrix2):
"""Add corresponding numbers in given 2-D matrices."""
combined = []
for row1, row2 in zip(matrix1, matrix2):
row = []
for n, m in zip(row1, row2):
row.append(n + m)
combined.append(row)
return combined
Parse two-line CSV data
This is the parse_row exercise in ranges.py. Edit the ranges.py file in the exercises directory to implement this exercise. To test it, run python test.py parse_row in your exercises directory.
Make a function parse_row that accepts a string consisting of two lines of comma-separated data and parses it, returning a dictionary where the keys are elements from the first row and the values are from the second row.
Example usage:
>>> from ranges import parse_row
>>> color_data = "purple,indigo,red,blue,green\n0.15,0.25,0.3,0.05,0.25"
>>> parse_row(color_data)
{'purple': '0.15', 'indigo': '0.25', 'red': '0.3', 'blue': '0.05', 'green': '0.25'}
Answers
Without unpacking:
def parse_row(input_data):
"""Return dictionary of keys from first CSV row and values from second."""
rows = input_data.split("\n")
row1 = rows[0].split(",")
row2 = rows[1].split(",")
new_dict = dict(zip(row1, row2))
return new_dict
With unpacking (more idiomatic):
def parse_row(input_data):
"""Return dictionary of keys from first CSV row and values from second."""
color_row, ratio_row = input_data.split("\n")
colors = color_row.split(",")
ratios = ratio_row.split(",")
return dict(zip(colors, ratios))
with_previous
This is the with_previous exercise we’ve seen before in in ranges.py. It accepts a list and returns a new list that includes a tuple of each item and the previous item (the item just before it). The first “previous item” should be None.
To test it, run python test.py with_previous in your exercises directory.
Re-write the code to use the zip function.
It should work like this:
>>> from ranges import with_previous
>>> numbers = [1, 2, 3, 4]
>>> with_previous(numbers)
[(1, None), (2, 1), (3, 2), (4, 3)]
Answers
def with_previous(sequence):
"""Provide each list item with item before it."""
return list(zip(sequence, [None] + list(sequence)))
With *, which we haven’t learned about yet:
def with_previous(sequence):
"""Provide each list item with item before it."""
return list(zip(sequence, [None, *sequence]))
Interleave
This is the interleave in ranges.py. The function accepts two iterables and returns a list with the items in each iterable “interleaved” (item 0 from iterable 1, then item 0 from iterable 2, then item 1 from iterable 1, and so on). Assume the two lists have the same length.
To test it, run python test.py interleave in your exercises directory.
Re-write the code to use the zip function.
Example:
>>> from ranges import interleave
>>> interleave([1, 2, 3, 4], [5, 6, 7, 8])
[1, 5, 2, 6, 3, 7, 4, 8]
>>> interleave([1, 4, 7], [2, 5, 8])
[1, 2, 4, 5, 7, 8]
Answers
def interleave(iterable1, iterable2):
"""Return list of one item at a time from each given iterable."""
interleaved = []
for group in zip(iterable1, iterable2):
for item in group:
interleaved.append(item)
return interleaved