Try   HackMD

(2022年) CS50 week6

其實之前就已經修完 CS50 了,不過因應 2022 年將課堂作業的系統
c9.io 換到 github codespace + vscode 整合
打算來重溫一下裡面的作業,並暖身一下 C 語言的手感

由於已經有許多前輩分享課程與作業的心得
加上官網教材的投影片、重點筆記、教學影片都非常完整
故不再做詳細的紀錄,專注在作業 (Lab, Problem sets) 上面

https://cs50.harvard.edu/x/2022/weeks/6/


Lab6: World Cup

(點擊展開) 符合 style50 風格的程式碼
# Simulate a sports tournament

import csv
import sys
import random

# Number of simluations to run
N = 1000


def main():

    # Ensure correct usage
    if len(sys.argv) != 2:
        sys.exit("Usage: python tournament.py FILENAME")

    teams = []
    filename = sys.argv[1]
    with open(filename) as file:
        reader = csv.DictReader(file)
        for row in reader:
            row["rating"] = int(row["rating"])
            teams.append(row)

    counts = {}
    for i in range(N):
        winner = simulate_tournament(teams)
        if winner in counts:
            counts[winner] += 1
        else:
            counts[winner] = 1

    # Print each team's chances of winning, according to simulation
    for team in sorted(counts, key=lambda team: counts[team], reverse=True):
        print(f"{team}: {counts[team] * 100 / N:.1f}% chance of winning")


def simulate_game(team1, team2):
    """Simulate a game. Return True if team1 wins, False otherwise."""
    rating1 = team1["rating"]
    rating2 = team2["rating"]
    probability = 1 / (1 + 10 ** ((rating2 - rating1) / 600))
    return random.random() < probability


def simulate_round(teams):
    """Simulate a round. Return a list of winning teams."""
    winners = []

    # Simulate games for all pairs of teams
    for i in range(0, len(teams), 2):
        if simulate_game(teams[i], teams[i + 1]):
            winners.append(teams[i])
        else:
            winners.append(teams[i + 1])

    return winners


def simulate_tournament(teams):
    """Simulate a tournament. Return name of winning team."""
    while len(teams) > 1:
        teams = simulate_round(teams)
    return teams[0]["team"]


if __name__ == "__main__":
    main()

執行

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

驗證

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →


作業: Hello

from cs50 import get_string

# get prompt from name
name = get_string("What is your name? \n")

print(f"hello, {name}")

執行

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

驗證

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →


作業: Mario-less

(點擊展開) 符合 style50 風格的程式碼
from cs50 import get_int

height = get_int("Height: ")

# height must be 1 ~ 8
while (height <= 0 or height > 8):
    height = get_int("Enter height from 1 to 8: ")

# head lopp: print each line (assembled content and \n in end)
for i in range(height):
    # loop for left space
    for j in range(height - i - 1):
        print(" ", end="")

    # loop for left brick
    for k in range(i + 1):
        print("#", end="")

    print("")

執行

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

驗證

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →


作業: Mario-more

(點擊展開) 符合 style50 風格的程式碼
from cs50 import get_int

height = get_int("Height: ")

# height must be 1 ~ 8
while (height <= 0 or height > 8):
    height = get_int("Enter height from 1 to 8: ")

# head lopp: print each line (assembled content and \n in end)
for i in range(height):
    # loop for left space
    for j in range(height - i - 1):
        print(" ", end="")

    # loop for left brick
    for k in range(i + 1):
        print("#", end="")

    print("  ", end="")

    # loop for right brick
    for k in range(i + 1):
        print("#", end="")

    print("")

執行

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

驗證

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →


作業: Cash

(點擊展開) 符合 style50 風格的程式碼
import cs50

cash = cs50.get_float("Change owed: ")
if cash > 0:
    coin = round(cash*100)
    coins = 0
    q = 0
    d = 0
    n = 0
    p = 0

    # Get quarters values (25¢)
    q = int(coin/25)
    # Calulate dime value (10¢)
    d = int((coin % 25) / 10)
    # Calulate nickels value (5¢)
    n = int(((coin % 25) % 10) / 5)
    # Calulate pennies value (1¢)
    p = int(((coin % 25) % 10) % 5)

    coins += q + d + n + p

    print(coins)

執行

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

驗證

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →


作業: Credit

(點擊展開) 符合 style50 風格的程式碼
from cs50 import get_string

# validate card number


def validateCardNumber(card_num):
    total = 0

    for index, n in enumerate(card_num):
        digit = int(n)

        # if index is even
        if (index % 2 == 0):
            total += digit
        else:
            digit_num = digit * 2

            if (digit_num < 9):
                total += digit_num
            else:
                x, y = str(digit_num)
                total += int(x)
                total += int(y)

    return total % 10 == 0


card_number = get_string("Card Number: ")
valid_card_number = validateCardNumber(card_number)

if (valid_card_number == False):
    print("INVALID")
    pass

# classification card type
# American Express: 15 digit, start with 34, 37
# MasterCard: 16 digit, start with 51, 52, 53, 54, 55
# Visa: 13 or 16 digit, start with 4
first_two = card_number[0:2]

if len(card_number) == 16:
    if (first_two[0] == '4'):
        print("VISA")
    elif ((int(first_two) >= 51) and (int(first_two) <= 55)):
        print("MASTERCARD")
    else:
        print("INVALID")

elif len(card_number) == 15:
    is_AMEX = (first_two == '34' or first_two == '37')
    print("AMEX") if is_AMEX else print("INVALID")

elif len(card_number) == 13:
    is_VISA = (first_two[0] == '4')
    print("VISA") if is_VISA else print("INVALID")

else:
    print("INVALID")

執行

驗證


作業: Readability

(點擊展開) 符合 style50 風格的程式碼
from cs50 import get_string

text = get_string("Text: ")
letter_count = 0
word_count = 1 if (len(text) > 0) else 0
sentence_count = 0

for i in range(len(text)):
    c = text[i].upper()

    # count letters (in ASCII, A ~ Z is 65 ~ 90)
    if (ord(c) >= 65 and ord(c) <= 90):
        letter_count += 1

    # count sentences (in '!', '.', '?)
    if (c == '!' or c == '.' or c == '?'):
        sentence_count += 1

    # count words (in ' ')
    if (c == ' '):
        word_count += 1

# formula: Coleman-Liau index
# index = 0.0588 * L - 0.296 * S - 15.8
# L is the average number of letters per 100 words in the text
# S is the average number of sentences per 100 words in the text
L = letter_count / float(word_count) * 100
S = sentence_count / float(word_count) * 100
CL_index = 0.0588 * L - 0.296 * S - 15.8

if (CL_index < 1):
    print("Before Grade 1")
elif (CL_index >= 16):
    print("Grade 16+")
else:
    print(f"Grade {round(CL_index)}")

執行

驗證


作業: DNA

(點擊展開) 符合 style50 風格的程式碼
from sys import argv, exit
import csv


def main():
    # Check for command-line usage
    if len(argv) != 3:
        print("Usage: python dna.py data.csv sequence.txt")
        exit(1)

    str_keys = []
    profiles = []

    # Read database file into a variable

    # read database file
    # using `with` means need not close the file
    with open(argv[1], mode="r") as database:
        reader = csv.DictReader(database)
        str_keys = reader.fieldnames[1:]
        # e.g. str_keys => ['AGATC', 'AATG', 'TATC']

        for row in reader:
            profiles.append(row)

    # build dict of STRs size
    # e.g. str_dict => [{'AGATC': 0}, {'AATG': 0}, {'TATC': 0}]
    str_dict = dict.fromkeys(str_keys, 0)

    # Read DNA sequence file into a variable
    with open(argv[2], mode="r") as sequence_file:
        sequence = sequence_file.readline()

        for STR in str_keys:
            # find and count str max repeats, and record to dict
            str_dict[STR] = find_repeats(sequence, STR)

    # print(str_keys)
    # print(profiles)
    # print(str_dict)

    # find match person
    for profile in profiles:
        match_count = 0

        for STR in str_keys:
            # compare repeat times in each STR column
            if int(profile[STR]) != str_dict[STR]:
                continue

            match_count += 1

        if match_count == len(str_keys):
            print(profile['name'])
            exit(0)

    print("No match")
    exit(1)


def longest_match(sequence, subsequence):
    """Returns length of longest run of subsequence in sequence."""

    # Initialize variables
    longest_run = 0
    subsequence_length = len(subsequence)
    sequence_length = len(sequence)

    # Check each character in sequence for most consecutive runs of subsequence
    for i in range(sequence_length):

        # Initialize count of consecutive runs
        count = 0

        # Check for a subsequence match in a "substring" (a subset of characters) within sequence
        # If a match, move substring to next potential match in sequence
        # Continue moving substring and checking for matches until out of consecutive matches
        while True:

            # Adjust substring start and end
            start = i + count * subsequence_length
            end = start + subsequence_length

            # If there is a match in the substring
            if sequence[start:end] == subsequence:
                count += 1

            # If there is no match in the substring
            else:
                break

        # Update most consecutive matches found
        longest_run = max(longest_run, count)

    # After checking for runs at each character in seqeuence, return longest run found
    return longest_run


def find_repeats(sequence, STR):
    str_len = len(STR)
    max_repeats = 0

    for i in range(len(sequence)):
        repeats = 0

        # compare match STR
        str_slice = i + str_len
        if (sequence[i:str_slice] == STR):
            repeats += 1

            # continue compare and add to repeats
            while sequence[i:str_slice] == sequence[str_slice:str_slice + str_len]:
                repeats += 1
                i += str_len
                str_slice += str_len

        # update max repeats
        if repeats > max_repeats:
            max_repeats = repeats

    return max_repeats


if __name__ == "__main__":
    main()

執行

驗證