--- tags: CS50 --- # (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](https://cs50.harvard.edu/x/2022/labs/6/) :::spoiler (點擊展開) 符合 `style50` 風格的程式碼 ```python # 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() ``` ::: 執行 ![](https://hackmd.io/_uploads/ryy2h7nmi.png) ![](https://hackmd.io/_uploads/H192nXhQo.png) 驗證 ![](https://hackmd.io/_uploads/ByM92m27s.png) --- ### 作業: [Hello](https://cs50.harvard.edu/x/2022/psets/6/hello/) ```python from cs50 import get_string # get prompt from name name = get_string("What is your name? \n") print(f"hello, {name}") ``` 執行 ![](https://hackmd.io/_uploads/B1eZ3Lnms.png) 驗證 ![](https://hackmd.io/_uploads/r1Cj3Uh7i.png) --- ### 作業: [Mario-less](https://cs50.harvard.edu/x/2022/psets/6/mario/less/) :::spoiler (點擊展開) 符合 `style50` 風格的程式碼 ```python 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("") ``` ::: 執行 ![](https://hackmd.io/_uploads/H1hWmv2Xo.png) 驗證 ![](https://hackmd.io/_uploads/HJSlXDnXi.png) --- ### 作業: [Mario-more](https://cs50.harvard.edu/x/2022/psets/6/mario/more/) :::spoiler (點擊展開) 符合 `style50` 風格的程式碼 ```python 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("") ``` ::: 執行 ![](https://hackmd.io/_uploads/H19UQv2Xs.png) 驗證 ![](https://hackmd.io/_uploads/By5sXP3Qi.png) --- ### 作業: [Cash](https://cs50.harvard.edu/x/2022/psets/6/cash/) :::spoiler (點擊展開) 符合 `style50` 風格的程式碼 ```python 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) ``` ::: 執行 ![](https://hackmd.io/_uploads/S1yB8DhXj.png) 驗證 ![](https://hackmd.io/_uploads/SkBJ8vhmi.png) --- ### 作業: [Credit](https://cs50.harvard.edu/x/2022/psets/6/credit/) :::spoiler (點擊展開) 符合 `style50` 風格的程式碼 ```python 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") ``` ::: 執行 ![](https://hackmd.io/_uploads/S1rx9D2mj.png) 驗證 ![](https://hackmd.io/_uploads/rkv2dP3mi.png) --- ### 作業: [Readability](https://cs50.harvard.edu/x/2022/psets/6/readability/) :::spoiler (點擊展開) 符合 `style50` 風格的程式碼 ```python 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)}") ``` ::: 執行 ![](https://hackmd.io/_uploads/BJFaLvnQi.png) 驗證 ![](https://hackmd.io/_uploads/B1GSPDnmo.png) --- ### 作業: [DNA](https://cs50.harvard.edu/x/2022/psets/6/dna/) :::spoiler (點擊展開) 符合 `style50` 風格的程式碼 ```python 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() ``` ::: 執行 ![](https://hackmd.io/_uploads/BkrpiDhmj.png) 驗證 ![](https://hackmd.io/_uploads/SJRrhD2Qs.png)