home..

Team Test

Collaboration Review

Program Function and Purpose (Kyle Liang)

The following example programs demonstrate a variety of concepts provided by CollegeBoard and the teacher blog.

# Program with Output

print("Hello, World!")
Hello, World!
# Program with Input and Output

name = input("What is your name?\n> ")
print(f"Hello, {name}!")
What is your name?
> Kyle
Hello, Kyle!
# Program with a List

myFruits = ["apple", "banana", "cherry"]

def displayFruits():
    for i, fruit in enumerate(myFruits):
        print(f"{i}. {fruit}")

# Append to List
favFruit = input("What is your favorite fruit?\n> ")
if favFruit not in myFruits:
    myFruits.append(favFruit)
print(f"Great! You have {len(myFruits)}:")
displayFruits()

# Remove from List
ateFruit = input("Which fruit do you want to eat?\n> ")
if ateFruit not in myFruits:
    print("Huh? You don't have that type of fruit. You only have the following:")
else:
    print(f"Great! You ate the {ateFruit}. You now have the following fruits:")
    myFruits.remove(ateFruit)
displayFruits()

# Pop from List
print(f"Oops! The {myFruits[-1]} fell of the table. You now have these fruits:")
myFruits.pop()
displayFruits()
What is your favorite fruit?
> avacado
Great! You have 4:
0. apple
1. banana
2. cherry
3. avacado
Which fruit do you want to eat?
> banana
Great! You ate the banana. You now have the following fruits:
0. apple
1. cherry
2. avacado
Oops! The avacado fell of the table. You now have these fruits:
0. apple
1. cherry
# Program with a Dictionary

def displayFruits():
    for person in favFruits.keys():
        print(f"{person} has a {favFruits[person]}")

myFruits = ["apple", "banana", "cherry"]
people = ["Trevor", "Jason", "Ian"]

name = input("What's your name?\n> ")
people.append(name)
fruit = input("What's your favorite fruit?\n> ")
myFruits.append(fruit)
favFruits = dict()

# Creating a Dictionary from two lists (key-value pairs)
for person, fruit in zip(people, myFruits):
    favFruits[person] = fruit

# Editing a Key's Value
fruit = input(f"What! You don't like {favFruits[name]}. What is your real favorite fruit?\n> ")
favFruits[name] = fruit

# Appending to a Dictionary
teacher = input("Who is your CS teacher?\n> ")
fruit = input("What is there favorite fruit?\n> ")
favFruits[teacher] = fruit
print("Bruh...")
displayFruits()

# Removing from a Dictionary
flag = input(f"Do you like {teacher}? (YES/NO)\n> ")
if (flag == "NO"):
    favFruits.pop(teacher)
print("Bruh..................................")
displayFruits()
Bruh...
Trevor has a apple
Jason has a banana
Ian has a Banana
Mr. Mortensen has a Apple
Bruh..................................
Trevor has a apple
Jason has a banana
Ian has a Banana
Mr. Mortensen has a Apple
# Programming with Iteration

# Prime Factorization
# https://www.geeksforgeeks.org/sieve-of-eratosthenes/
def primeFactors(x):
    factors = []
    for i in range(2, x): # For-Loop
        while x % i == 0: # While-Loop
            factors.append(str(i))
            x /= i
    if (x > 1):
            factors.append(x)
    return factors

# Recursive Function to find Factorial
# https://www.geeksforgeeks.org/python-program-for-factorial-of-a-number/
def factorial(x):
    if (x <= 1):
        return 1
    return x*factorial(x-1) # Recursion

num = input("Enter a non-negative number (between 2 and 100 inclusive)\n> ")
if num.isnumeric():
    num = max(int(num) % 100, 2)
    print(f"Your number is {num}")
    print(f"The prime factors are: {' '.join(primeFactors(num))}")
    print(f"{num}! is: {factorial(num)}")

Enter a non-negative number (between 2 and 100 inclusive)
> 4
Your number is 4
The prime factors are: 2 2
4! is: 24
# Program with a Function to perform mathematical and/or a statistical calculations

def sqrt(x):
    return x**0.5

# Manhattan Distance
# https://www.geeksforgeeks.org/calculate-the-manhattan-distance-between-two-cells-of-given-2d-array/
def manhattanDist(x1, y1, x2, y2):
    return abs(x1-x2)+abs(y1-y2)

# Euclidean Distance
# https://www.geeksforgeeks.org/program-calculate-distance-two-points/
def euclideanDist(x1, y1, x2, y2):
    return sqrt((x1-x2)**2+(y1-y2)**2)

points = [
    (0, 0, 3, 4),
    (0, 0, 1, 1),
    (0, 0, 5, 12),
    (2, 3, 5, 8),
    (3, 1, 4, 1)
]

for x1, y1, x2, y2 in points:
    print(f"The Manhattan Distance between ({x1}, {y1}) and ({x2}, {y2}) is: {manhattanDist(x1, y1, x2, y2)}")
    print(f"The Euclidean Distance between ({x1}, {y1}) and ({x2}, {y2}) is: {euclideanDist(x1, y1, x2, y2)}")
    print()
    
The Manhattan Distance between (0, 0) and (3, 4) is: 7
The Euclidean Distance between (0, 0) and (3, 4) is: 5.0

The Manhattan Distance between (0, 0) and (1, 1) is: 2
The Euclidean Distance between (0, 0) and (1, 1) is: 1.4142135623730951

The Manhattan Distance between (0, 0) and (5, 12) is: 17
The Euclidean Distance between (0, 0) and (5, 12) is: 13.0

The Manhattan Distance between (2, 3) and (5, 8) is: 8
The Euclidean Distance between (2, 3) and (5, 8) is: 5.830951894845301

The Manhattan Distance between (3, 1) and (4, 1) is: 1
The Euclidean Distance between (3, 1) and (4, 1) is: 1.0
# Program with a Selection/Condition

from random import randint

num = -1
ans = randint(1, 101)
cnt = 0
while num != ans:
    num = input("Guess a number between 1 and 100 (inclusive)\n> ")
    if not num.isnumeric():
        print("Error: That's not a number... bruh...")
        break
    num = int(num)
    cnt += 1
    if num < ans:
        print("Your guess is too low!\n")
    elif num > ans:
        print("Your guess is too high!\n")
    else:
        print(f"Correct! {num} is the right answer! It took you {cnt} tries to guess correctly!\n")

Guess a number between 1 and 100 (inclusive)
> 50
Your guess is too low!

Guess a number between 1 and 100 (inclusive)
> 25
Your guess is too low!

Guess a number between 1 and 100 (inclusive)
> 75
Your guess is too low!

Guess a number between 1 and 100 (inclusive)
> 85
Your guess is too high!

Guess a number between 1 and 100 (inclusive)
> 80
Your guess is too low!

Guess a number between 1 and 100 (inclusive)
> 82
Your guess is too low!

Guess a number between 1 and 100 (inclusive)
> 83
Your guess is too low!

Guess a number between 1 and 100 (inclusive)
> 84
Correct! 84 is the right answer! It took you 8 tries to guess correctly!

Program Design and Development

Create a Visual Illustration of a program, algorithm, or process.

Share a program you modified + List and Iteration

For the city guesser game, I used images that a twitter bot had posted. However, doing this was not efficient, and the images were cropped exactly to the city borders, making some of them ugly and difficult to look at (I’m looking at you, Buckeye).

The existing twitter bot code can be found here: https://github.com/blu3r4d0n/places-bot

The code was ran locally and requires some shapefiles and directories that are not placed in here, so the code willnot work. A fun thing to do would be to create a py file, get a shapefile and make the proper directories to download some images of your own.

# This imports various libraries that will be used to download images
import geopandas as gpd
import us

import rasterio
import rasterio.mask
from xyzservices import TileProvider
from requests.exceptions import HTTPError

# Reads SHP file with data on cities
df = gpd.read_file("US_place_2020.shp")  
# Converts geometries to a new coordinate system
# https://geopandas.org/en/stable/docs/reference/api/geopandas.GeoSeries.to_crs.html
df=df.to_crs(epsg=3857)

import contextily as ctx
# Get the most extreme points in each direction based on city boundaries
west, south, east, north = bbox = df.iloc[0].geometry.bounds
# Save shapes to array
shapes=[df.geometry.iloc[0]]
# Store image in img variable, get image from Google Satellite
# https://contextily.readthedocs.io/en/latest/reference.html
try:
	img, ext = ctx.bounds2raster(west,south,east,north,"output.tif",zoom='auto',source=TileProvider.from_qms("Google Satellite")) #try with auto zoom level
except HTTPError:
        img, ext = ctx.bounds2raster(west,south,east,north,"output.tif",zoom=15,source=TileProvider.from_qms("Google Satellite")) #if that doesn't work try with 15, if this fails the program will crash
with rasterio.open("output.tif") as src:
	# Masks image based on coordinates from shapes array
	out_image, out_transform = rasterio.mask.mask(src,shapes,crop=True)  #mask the input iamge to polygon bounds 
	out_meta=src.meta


out_meta.update({"driver": "GTiff","height": out_image.shape[1],"width": out_image.shape[2],"transform": out_transform}) #update the metadata of image

# Save image to TIF file
with rasterio.open("masked.tif", "w", **out_meta) as dest:
	dest.write(out_image)
import tweepy
from secrets import *
# Set twitter access tokens, confirms the account that the program will post on
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)

api = tweepy.API(auth)

res = api.media_upload(filename)

media_id = res.media_id

# Post Image in post to twitter
api.create_media_metadata(media_id,f"An aerial image of {name}, {state} surrounded by white.")
api.update_status(status=f'GEOID {geoid} {name}, {state}',media_ids=[media_id])


#delete this row and save to shapefile
df=gpd.read_file("US_place_2020.shp")
df = df.iloc[1:]
df.to_file("US_place_2020.shp")
---------------------------------------------------------------------------

ModuleNotFoundError                       Traceback (most recent call last)

/tmp/ipykernel_1443/607856996.py in <module>
----> 1 import tweepy
      2 from secrets import *
      3 # Set twitter access tokens, confirms the account that the program will post on
      4 auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
      5 auth.set_access_token(access_token, access_token_secret)


ModuleNotFoundError: No module named 'tweepy'

This code was very nice, and helped me a lot with downloading the files, as I could not have made this myself. However, it didn’t do exactly what I wanted to do.

The first of the issues was relatively simple to fix, I just removed the section of code that posts the image to twitter, and then saved the file to a folder instead of as image.jpg. Code is below

    bg.paste(im, offset, im)
    size = 1980, 1080
    bg.thumbnail(size, Image.LANCZOS)
## Using California Shapefile, save to a folder called cities
## Name image name of city, followed by an underscore and two-letter abbreviation for california
    bg.save("cities/" + name + "_CA.jpg")
## Log to terminal where program left off
    print('Index: ' + str(index) + ', City: ' + name + " saved.")

The next issue was less of a code issue, and more of an access issue. I managed to eventually find the census website with shapefiles and other related data for all states at the following link: https://www.census.gov/cgi-bin/geo/shapefiles/index.php?year=2022&layergroup=Places

The third issue took by far the longest to resolve, mainly because I overthought it and was looking in the wrong places. My first thought was the look at all the possible options for the rasterio.mask.mask function, which I found here: https://rasterio.readthedocs.io/en/latest/api/rasterio.mask.html However, many of the descriptions were to a degree confusing, and after trying several of them, I realized all of them cropped the cities to the exact boundary anyways.

The second idea I had was to save the img variable directly to an output.tif file. However, I quickly realized that the ctx.bounds2raster and rasterio.mask.mask functions did not output the same type of image, and the program would give an error.

Then, I looked through documentation for some of these libraries and found the ctx.bounds2img function, which I hoped would successfully download the image, but again gave an error. Looking back, I realize now this is likely because of the code that was converting the tif file to a jpg, whereas this command may have already saved the image as a jpg file. But, I quickly realized that the original output.tif file had a perfectly cropped image, and I didn't need to do any more work to get that image to masked.tif, and simply replaced the masked.tif references in the rest of the program with output.tif and commented out the code cropping the image file to exact boundaries.

The last issue was easier to resolve, thankfully, and I simply added a for loop to repeat. The modified code is below: The program was ran locally on my computer, so output is not shown, but the modified program is also an example of lists and iteration, and the citynames and data are stored in df, and they are iterated through in the for loop in the line ‘for index, row in df.iterrows():’ until every single file is downloaded.

import geopandas as gpd
import us

import rasterio
import rasterio.mask
from xyzservices import TileProvider
from requests.exceptions import HTTPError
from PIL import Image
import contextily as ctx

# Read the GeoDataFrame
df = gpd.read_file("tl_2022_08_place.shp")
df = df.to_crs(epsg=3857)

start = -1

for index, row in df.iterrows():
    if index < start:
        continue

    west, south, east, north = row.geometry.bounds
    shapes = [row.geometry]
    try:
        img, ext = ctx.bounds2raster(west, south, east, north, "output.tif", zoom='auto', source=TileProvider.from_qms("Google Satellite")) #try with auto zoom level
    except HTTPError:
        img, ext = ctx.bounds2raster(west, south, east, north, "output.tif", zoom=15, source=TileProvider.from_qms("Google Satellite")) #if that doesn't work try with 15, if this fails the program will crash
    # with rasterio.open("output.tif") as src:
        # out_image, out_transform = rasterio.mask.mask(src, shapes, crop=True, filled=False)  #mask the input image to polygon bounds
        # out_meta = src.meta

    # out_meta.update({"driver": "GTiff", "height": img.shape[1], "width": img.shape[2], "transform": ext}) #update the metadata

    #with rasterio.open("masked.tif", "w") as dest:
    #    dest.write(img)


    # Get info for place
    name = row.NAME
    geoid = row.GEOID
    statefp = row.STATEFP
    state = us.states.lookup(statefp).name

    # Save the image as a JPG
    # im = Image.open("masked.tif")
    im = Image.open("output.tif")
    bg = Image.new("RGB", tuple([int(round(.05*x+x)) for x in im.size]), (255, 255, 255))
    img_w, img_h = im.size
    bg_w, bg_h = bg.size
    offset = ((bg_w - img_w) // 2, (bg_h - img_h) // 2)

    bg.paste(im, offset, im)
    size = 1980, 1080
    bg.thumbnail(size, Image.LANCZOS)
    bg.save("cities/" + name + "_CO.jpg")
    print('Index: ' + str(index) + ', City: ' + name + " saved.")

# Save the modified GeoDataFrame to a new shapefile
df.to_file("tl_2022_08_place.shp")

Show comments on a program that does a mathematical and/or statistical calculation

Approximating π

With help from ChatGPT. See here for more information on the logic behind this code: https://www.geeksforgeeks.org/estimating-value-pi-using-monte-carlo/

# pip install random
# pip install matplotlib

import random
import matplotlib.pyplot as plt

# Number of points to generate for the simulations
num_points_list = [10, 100, 1000, 10000, 100000, 1000000]

for num_points in num_points_list:
    # Initialize counters to keep track of points inside the quarter circle
    inside_circle = 0
    total_points = 0

    # Lists to store x and y coordinates for visualization
    x_inside = []
    y_inside = []
    x_outside = []
    y_outside = []

    # Generate random points and check if they are inside the quarter circle
    for _ in range(num_points):
        # Generate random x and y coordinates within the unit square [0, 1] x [0, 1]
        x = random.uniform(0, 1)
        y = random.uniform(0, 1)

        # Calculate the distance from the origin (0, 0)
        distance = x**2 + y**2

        # Check if the point is inside the quarter circle
        if distance <= 1:
            inside_circle += 1
            x_inside.append(x)  # Store x coordinate for visualization
            y_inside.append(y)  # Store y coordinate for visualization
        else:
            x_outside.append(x)  # Store x coordinate for visualization
            y_outside.append(y)  # Store y coordinate for visualization

    # Approximate pi using the Monte Carlo method
    pi_approximation = (inside_circle / num_points) * 4

    # Visualize the results
    plt.figure(figsize=(6, 6))
    plt.scatter(x_inside, y_inside, color='blue', marker='.', label='Inside Quarter Circle')
    plt.scatter(x_outside, y_outside, color='red', marker='.', label='Outside Quarter Circle')
    plt.title(f'Approximated Pi ({num_points} points): {pi_approximation:.5f}')
    plt.xlabel('X')
    plt.ylabel('Y')
    plt.xlim(0, 1)
    plt.ylim(0, 1)
    plt.gca().set_aspect('equal', adjustable='box')  # Ensure aspect ratio is equal for proper visualization
    plt.legend()
    plt.show()

    # Print the approximated value of pi
    # print(f"Approximated Pi ({num_points} points): {pi_approximation:.5f}")

png

png

png

png

png

/usr/lib/python3/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Creating legend with loc="best" can be slow with large amounts of data.
  fig.canvas.print_figure(bytes_io, **kw)

png

Identyfing and Correct Errors

Often, when we develop code the initial functionality is very simple. However, when we consider invalid conditions when using our code we often increase the complexity of our code or functions.

This program checks if a function has any syntax errors or not. Unfortunately, logic errors are much more difficult to catch, so for now this function does syntax errors.

# Cannot concatenate int and string types, will give error
def function_with_error():
    number = 123
    string = '123'
    print(number + string)

# function will print 123123
def function_without_error():
    string = '123'
    string2 = '123'
    print(string + string2)

def test_function(func):
    print('--------------------------------------------------')
    print('Testing function: ' + func)
    # try tests function, if error occurs will run code in except
    try: 
        eval(func)
    except:
        # print error occured if error occurs
        print('error occured while testing ' + func)
    else:
        print('No errors occured in ' + func + '!')
        print('Output is above.')

test_function('function_with_error()')
test_function('function_without_error()')
--------------------------------------------------
Testing function: function_with_error()
error occured while testing function_with_error()
--------------------------------------------------
Testing function: function_without_error()
123123
No errors occured in function_without_error()!
Output is above.

This is nice and all, being able to tell when an error occurs, but knowing that an error exists isn’t very useful, we would find that out either way from attempting to run it. A nice step would be the print the type of error that occurs. This is done as shown below.

# Cannot concatenate int and string types, will give error
def function_with_error():
    number = 123
    string = '123'
    print(number + string)

# function will print 123123
def function_with_error2():
    number = 12
    number2 = 0
    print (number / number2)

def test_function(func):
    print('--------------------------------------------------')
    print('Testing function: ' + func)
    # try tests function, if error occurs will run code in except
    try: 
        eval(func)
    # store exception type in variable error
    except Exception as error:
        # print error occured if error occurs
        print('The following error occured while testing ' + func + ': ')
        print(error)
    else:
        print('No errors occured in ' + func + '!')
        print('Output is above.')

test_function('function_with_error()')
test_function('function_with_error2()')
--------------------------------------------------
Testing function: function_with_error()
The following error occured while testing function_with_error(): 
unsupported operand type(s) for +: 'int' and 'str'
--------------------------------------------------
Testing function: function_with_error2()
The following error occured while testing function_with_error2(): 
division by zero

Error checking like this can also be done using if statements. See the program below, which uses if statements to check if an error occurs after the number is inputted.

def get_valid_number():
    while True:
        user_input = input("Please enter an integer between 1 and 100: ")
            # Checks if the input is a number with isdigit
        if user_input.isdigit():
            number = int(user_input)
            if 1 <= int(number) <= 100:
                return number
            elif int(number) > 100:
                print("Invalid input. Please enter a number between 1-100")
            elif int(number) < 1:
                print("Invalid input. Please enter a number between 1-100")
        elif user_input[0] == "-":
            print("Invalid input. Please enter a number between 1-100")
        else:
            print("Please enter an integer")
answer = get_valid_number()
if isinstance(answer, int):
    print(f"You entered a valid number: {answer}")
Please enter an integer between 1 and 100: 688
Invalid input. Please enter a number between 1-100
Please enter an integer between 1 and 100: 2
You entered a valid number: 2

© 2024    •  Powered by Soopr   •  Theme  Moonwalk