Solutions

Video

Alternative link

Code

metals = ['Fe', 'Al', 'Hg', 'Ti', 'Pb']
melting_points = [1811, 933, 234, 1941, 601]
boiling_points = [3134, 2743, 630, 3560, 2022]

for metal, mp, bp in zip(metals, melting_points, boiling_points):
    if mp > 500:
        phase = 'solid'
    elif bp > 500:
        phase = 'liquid'
    else:
        phase = 'gas'

    print(f'{metal} is a {phase} at 500 K')
from scipy import constants
def calc_rydberg_wavelength(n_i, n_f):
    '''
    Calculates wavelength of hydrogen emission signal corresponding to a transition
    between two energy levels with quantum numbers 
    n_i and n_f using the Rydberg equation.

    λ = (R (1/n_f^2 - 1/n_i^2))

    Arguments
    ---------
    n_i: int
        Quantum number of intial state (n_i>n_f)
    n_f: int
        Quantum number of final state (n_i>n_f)

    Returns
    -------
    float
        Wavelength of transition in nm
    '''

    iwavelength = constants.Rydberg * (1/n_f**2 - 1/n_i**2)

    wavelength = 1 / iwavelength
    wavelength *= 10**9

    return wavelength

# Lyman series
n_f = 1
lyman = [
    calc_rydberg_wavelength(n_i, n_f)
    for n_i in range(n_f + 1, n_f + 11)
]

# Balmer series
n_f = 2
balmer = [
    calc_rydberg_wavelength(n_i, n_f)
    for n_i in range(n_f + 1, n_f + 11)
]

# Paschen series
n_f = 3
paschen = [
    calc_rydberg_wavelength(n_i, n_f)
    for n_i in range(n_f + 1, n_f + 11)
]
import math

def basel(n):

    pi_approx = 0

    for k in range(1, n + 1):
        pi_approx += 1 / k**2

    return  math.sqrt(6 * pi_approx)

print(basel(1000))

def leibniz(n):

    pi_approx = 0

    for k in range(0, n+1):
        pi_approx += (-1)**k / (2 * k + 1)

    pi_approx *= 4

    return pi_approx

print(leibniz(1000))

def compare_leibniz_basel_pi(n):

    l_pi = leibniz(n)
    b_pi = basel(n)

    l_pi_diff = abs(l_pi - math.pi)
    b_pi_diff = abs(b_pi - math.pi)

    if l_pi_diff < b_pi_diff:
        print(f'With n={n:d}, the Leibniz formula is more accurate')
    else:
        print(f'With n={n:d}, the Basel formula is more accurate')

compare_leibniz_basel_pi(50)

4.

Block 1


The error occurs when we call the function calculate_product. The function is defined to take a single argument sequence, which is expected to be an iterable (like a list or tuple). However, when we call the function, we are passing multiple separate arguments instead of a single iterable. This will raise a TypeError because the function is not receiving the expected input type.

Instead, the code should be modified to pass a single list containing all the numbers we want to multiply together.

def calculate_product(sequence):
    '''
    Calculate the product of a sequence of numbers (n_1 * n_2 * n_3 * ...).

    Arguments
    ---------
    sequence: iterable
        A sequence of numbers to multiply together.

    Returns
    -------
    float
        The cumulative product of the numbers in the sequence.
    '''

    product = sequence[0]

    for number in sequence[1:]:
        product *= number

    return product

product_of_sequence = calculate_product([5.12, 6.79, 2.22, 0.19, 13.6])

print(f'The cumulative product = {product_of_sequence}')

Block 2


The error in this block is due to the order of the parameters in the function definition. In Python, parameters with default values must come after parameters without default values. Here, convert_to_lower has a default value, but it is placed before word, which does not have a default value. This will raise a SyntaxError.

To fix this, we need to switch the order of the parameters so that word comes first.

The function is also missing a return statement, so always returns None Therefore, we also need to add a return statement which returns the check variable.

def check_palindrome(word, convert_to_lower=False):
    '''
    Check if a word is a palindrome.

    Arguments
    ---------
    word: str
        The word to be checked.
    convert_to_lower: bool, default False
        If True, converts word to all lower case
        before comparing to reverse form.

    Returns
    -------
    bool
        True if word is a palindrome, False otherwise.
    '''

    # Convert to lower case if requested
    if convert_to_lower:
        word = word.lower()

    if word == word[::-1]:
        check = True
    else:
        check = False

    return check

example_word = 'Civic'

if check_palindrome(example_word, convert_to_lower=True):
    print(f'{example_word} is a palindrome.')
else:
    print(f'{example_word} is not a palindrome.')

Block 3


The function in this code is correct, but it is called incorrectly. The energies list should be created using a list comprehension, not by passing a list of v values to the function. Doing so will raise a TypeError because the function expects two scalar values, not a list.

Additionally, the variable energy is not defined in the print statement. We should be iterating over the energies list to print each energy value.

Furthermore, the energies that are printed are the energies of the vibrational states \(v=0, 1, 2\), not just the zero-point energy.

from scipy import constants

def harmonic_energy(v, omega):
    '''
    Calculate the energy of a quantum harmonic oscillator.

    Arguments 
    ---------
    v: int
        Quantum number labelling each energy eigenstate.
    omega: float
        Angular frequency of the oscillator in rad s^-1.

    Returns
    -------
    float
        The energy of the oscillator in Joules.
    '''

    energy = (v + 0.5) * constants.hbar * omega

    return energy

# Angular frequency of HCl
frequency_HCl = 5.40e14  # rad s^-1

energies = [
    harmonic_energy(v, frequency_HCl)
    for v in [0, 1, 2]
]

print(f'The energies of the first three vibrational states of HCl are')
for v, energy in enumerate(energies):
    print(f'v={v}: {energy:.2g} J')