├── .gitattributes ├── LICENSE ├── README.md ├── Week0 ├── pvz.sb3 └── readme.md ├── Week1 ├── 1-hello.c ├── 2-mario-more.c ├── 3-credit-easy.c ├── 3-credit.c └── readme.md ├── Week2 ├── 0-scrabble.c ├── 1-readability.c ├── 2-substitution.c └── readme.md ├── Week3 ├── 0-sort.txt ├── 1-plurality.c ├── 2-runoff.c ├── 2-tideman.c └── readme.md ├── Week4 ├── 0-volume.c ├── 1-filter-less.c ├── 1-filter-more.c ├── 2-recover.c └── readme.md ├── Week5 ├── 0-inheritance.c ├── 1-speller-trie.c ├── 1-speller.c └── readme.md ├── Week6 ├── 0-world-cup.py ├── 1-hello.py ├── 2-mario-more.py ├── 3-credit.py ├── 4-readability-easy.py ├── 4-readability.py ├── 5-dna.py └── readme.md ├── Week7 ├── 0-songs.sql ├── 1-movies.sql ├── 2-answers.txt ├── 2-fiftyville.sql └── readme.md ├── Week8 ├── 0-trivia │ ├── index.html │ └── styles.css ├── 1-homepage │ ├── css │ │ ├── bootstrap.css │ │ └── styles.css │ ├── index.html │ ├── js │ │ └── bootstrap.bundle.js │ ├── pages │ │ ├── about.html │ │ └── works.html │ └── public │ │ ├── GG.jpg │ │ ├── cs.png │ │ ├── cs_1.png │ │ ├── cs_2.png │ │ ├── electronics.png │ │ ├── img.png │ │ ├── img_1.png │ │ ├── img_2.png │ │ ├── img_3.png │ │ ├── img_4.png │ │ ├── img_5.png │ │ ├── img_6.png │ │ ├── img_7.png │ │ └── img_8.png └── readme.md └── Week9 ├── 0-birthday ├── app.py ├── birthdays.db ├── requirements.txt ├── static │ └── styles.css └── templates │ └── index.html ├── 1-finance ├── app.py ├── finance.db ├── helpers.py ├── requirements.txt ├── static │ ├── favicon.ico │ └── styles.css └── templates │ ├── apology.html │ ├── buy.html │ ├── history.html │ ├── index.html │ ├── layout.html │ ├── login.html │ ├── quote.html │ ├── quoted.html │ ├── register.html │ └── sell.html └── readme.md /.gitattributes: -------------------------------------------------------------------------------- 1 | *.html linguist-vendored 2 | *.css linguist-vendored 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 CS Five 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Harvard CS50x 2022 2 | 3 | - [Course Link](https://cs50.harvard.edu/x/) 4 | - [Problem Set 8](https://pset8.netlify.app/) 5 | - [Final Project](https://github.com/mancuoj/watchlist) 6 | - [CS50P](https://github.com/mancuoj/CS50P) 7 | -------------------------------------------------------------------------------- /Week0/pvz.sb3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csfive/CS50x/80afc24a783855523cd3ff96ee50ca8793d0616d/Week0/pvz.sb3 -------------------------------------------------------------------------------- /Week0/readme.md: -------------------------------------------------------------------------------- 1 | ## Achievement 2 | 3 | - [x] Form 4 | - [x] .sb3 file 5 | 6 | ## Description 7 | 8 | 1. Submit [this form](https://forms.cs50.io/755f67a3-052d-44af-8d16-b0209fa4dafb). 9 | 2. Visit [this link](https://submit.cs50.io/invites/9770b67479384c4d8c37790779e466d9), log in with your GitHub account, and click **Authorize cs50**. Check the box indicating that you’d like to grant course staff access to your submissions, and click **Join course**. 10 | 3. Go to [submit.cs50.io/upload/cs50/problems/2022/x/scratch](https://submit.cs50.io/upload/cs50/problems/2022/x/scratch). Click “Choose File” and choose your `.sb3` file. Click **Submit**. 11 | -------------------------------------------------------------------------------- /Week1/1-hello.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(void) 5 | { 6 | string name = get_string("What is your name? "); 7 | printf("hello, %s\n", name); 8 | } 9 | -------------------------------------------------------------------------------- /Week1/2-mario-more.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(void) 5 | { 6 | int h; 7 | do 8 | { 9 | h = get_int("Height: "); 10 | } 11 | while (h < 1 || h > 8); 12 | 13 | for (int i = 1; i <= h; i++) 14 | { 15 | for (int j = h - i; j > 0; j--) 16 | { 17 | printf(" "); 18 | } 19 | 20 | for (int k = 0; k < i; k++) 21 | { 22 | printf("#"); 23 | } 24 | printf(" "); 25 | 26 | for (int k = 0; k < i; k++) 27 | { 28 | printf("#"); 29 | } 30 | printf("\n"); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Week1/3-credit-easy.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(void) 6 | { 7 | string num = get_string("Number: "); 8 | int len = strlen(num); 9 | 10 | if (len != 13 && len != 15 && len != 16) 11 | { 12 | printf("INVALID\n"); 13 | return 0; 14 | } 15 | 16 | bool flag = (len % 2 == 0) ? true : false; 17 | int checksum = 0; 18 | for (int i = 0; i < len; i++) 19 | { 20 | int tmp = num[i] - '0'; 21 | if (flag) 22 | { 23 | tmp *= 2; 24 | if (tmp >= 10) 25 | { 26 | checksum += tmp - 9; 27 | } 28 | else 29 | { 30 | checksum += tmp; 31 | } 32 | } 33 | else 34 | { 35 | checksum += tmp; 36 | } 37 | flag = !flag; 38 | } 39 | 40 | if (checksum % 10 != 0) 41 | { 42 | printf("INVALID\n"); 43 | } 44 | else 45 | { 46 | int check = (num[0] - '0') * 10 + (num[1] - '0'); 47 | if (check == 34 || check == 37) 48 | { 49 | printf("AMEX\n"); 50 | } 51 | else if (check >= 51 && check <= 55) 52 | { 53 | printf("MASTERCARD\n"); 54 | } 55 | else if (check / 10 == 4) 56 | { 57 | printf("VISA\n"); 58 | } 59 | else 60 | { 61 | printf("INVALID\n"); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Week1/3-credit.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(void) 5 | { 6 | long num; 7 | do 8 | { 9 | num = get_long("Number: "); 10 | } 11 | while (num <= 0); 12 | 13 | int checksum = 0; 14 | long checknum = num / 10; 15 | while (checknum > 0) 16 | { 17 | int remainder = checknum % 10 * 2; 18 | if (remainder < 10) 19 | { 20 | checksum += remainder; 21 | } 22 | else 23 | { 24 | checksum += remainder % 10; 25 | remainder /= 10; 26 | checksum += remainder; 27 | } 28 | checknum /= 100; 29 | } 30 | 31 | checknum = num; 32 | while (checknum > 0) 33 | { 34 | checksum += checknum % 10; 35 | checknum /= 100; 36 | } 37 | 38 | if (checksum % 10 != 0) 39 | { 40 | printf("INVALID\n"); 41 | } 42 | else 43 | { 44 | int length = 2; 45 | while (num >= 100) 46 | { 47 | num /= 10; 48 | length++; 49 | } 50 | 51 | if ((num == 34 || num == 37) && length == 15) 52 | { 53 | printf("AMEX\n"); 54 | } 55 | else if (num >= 51 && num <= 55 && length == 16) 56 | { 57 | printf("MASTERCARD\n"); 58 | } 59 | else if (num >= 40 && num <= 49 && (length == 13 || length == 16)) 60 | { 61 | printf("VISA\n"); 62 | } 63 | else 64 | { 65 | printf("INVALID\n"); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Week1/readme.md: -------------------------------------------------------------------------------- 1 | ## Achievement 2 | 3 | - [x] Hello 4 | - [ ] Mario (Less) 5 | - [x] Mario (More) 6 | - [ ] Cash 7 | - [x] Credit 8 | 9 | 10 | ## Description 11 | 12 | 1. Submit [Hello](https://cs50.harvard.edu/x/2022/psets/1/hello/) 13 | 2. Submit one of: 14 | - [this version of Mario](https://cs50.harvard.edu/x/2022/psets/1/mario/less/) if feeling less comfortable 15 | - [this version of Mario](https://cs50.harvard.edu/x/2022/psets/1/mario/more/) if feeling more comfortable 16 | 3. Submit one of: 17 | - [Cash](https://cs50.harvard.edu/x/2022/psets/1/cash/) if feeling less comfortable 18 | - [Credit](https://cs50.harvard.edu/x/2022/psets/1/credit/) if feeling more comfortable 19 | 20 | -------------------------------------------------------------------------------- /Week2/0-scrabble.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | // Points assigned to each letter of the alphabet 7 | int POINTS[] = {1, 3, 3, 2, 1, 4, 2, 4, 1, 8, 5, 1, 3, 1, 1, 3, 10, 1, 1, 1, 1, 4, 4, 8, 4, 10}; 8 | 9 | int compute_score(string word); 10 | 11 | int main(void) 12 | { 13 | // Get input words from both players 14 | string word1 = get_string("Player 1: "); 15 | string word2 = get_string("Player 2: "); 16 | 17 | // Score both words 18 | int score1 = compute_score(word1); 19 | int score2 = compute_score(word2); 20 | 21 | // TODO 22 | if (score1 == score2) 23 | { 24 | printf("Tie!\n"); 25 | } 26 | else if (score1 > score2) 27 | { 28 | printf("Player 1 wins!\n"); 29 | } 30 | else 31 | { 32 | printf("Player 2 wins!\n"); 33 | } 34 | } 35 | 36 | int compute_score(string word) 37 | { 38 | // TODO 39 | int score = 0; 40 | for (int i = 0, n = strlen(word); i < n; i++) 41 | { 42 | if (isalpha(word[i])) 43 | { 44 | int num = toupper(word[i]) - 'A'; 45 | score += POINTS[num]; 46 | } 47 | } 48 | return score; 49 | } 50 | -------------------------------------------------------------------------------- /Week2/1-readability.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int count_letters(string text); 8 | int count_words(string text); 9 | int count_sentences(string text); 10 | 11 | int main(void) 12 | { 13 | string text = get_string("Text: "); 14 | double l = count_letters(text) * 100.0 / count_words(text); 15 | double s = count_sentences(text) * 100.0 / count_words(text); 16 | int grade = (int)round(0.0588 * l - 0.296 * s - 15.8); 17 | 18 | if (grade < 1) 19 | { 20 | printf("Before Grade 1\n"); 21 | } 22 | else if (grade > 16) 23 | { 24 | printf("Grade 16+\n"); 25 | } 26 | else 27 | { 28 | printf("Grade %i\n", grade); 29 | } 30 | } 31 | 32 | int count_letters(string text) 33 | { 34 | int cnt = 0; 35 | for (int i = 0, n = strlen(text); i < n; i++) 36 | { 37 | if (isalnum(text[i])) 38 | { 39 | cnt++; 40 | } 41 | } 42 | return cnt; 43 | } 44 | 45 | int count_words(string text) 46 | { 47 | int cnt = 0; 48 | for (int i = 0, n = strlen(text); i < n; i++) 49 | { 50 | if (isspace(text[i])) 51 | { 52 | cnt++; 53 | } 54 | } 55 | return cnt + 1; 56 | } 57 | 58 | int count_sentences(string text) 59 | { 60 | int cnt = 0; 61 | for (int i = 0, n = strlen(text); i < n; i++) 62 | { 63 | if (text[i] == '.' || text[i] == '!' || text[i] == '?') 64 | { 65 | cnt++; 66 | } 67 | } 68 | return cnt; 69 | } 70 | -------------------------------------------------------------------------------- /Week2/2-substitution.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main(int argc, string argv[]) 7 | { 8 | if (argc != 2) 9 | { 10 | printf("Usage: ./substitution key\n"); 11 | return 1; 12 | } 13 | 14 | if (strlen(argv[1]) != 26) 15 | { 16 | printf("Key must contain 26 characters.\n"); 17 | return 1; 18 | } 19 | 20 | int exist[26] = {0}; 21 | string key = argv[1]; 22 | 23 | for (int i = 0; i < 26; i++) 24 | { 25 | exist[toupper(key[i]) - 'A']++; 26 | } 27 | 28 | for (int i = 0; i < 26; i++) 29 | { 30 | if (exist[i] != 1) 31 | { 32 | printf("Key must not contain repeated characters.\n"); 33 | return 1; 34 | } 35 | } 36 | 37 | string text = get_string("plaintext: "); 38 | for (int i = 0, n = strlen(text); i < n; i++) 39 | { 40 | if (isalpha(text[i])) 41 | { 42 | if (isupper(text[i])) 43 | { 44 | text[i] = toupper(key[text[i] - 'A']); 45 | } 46 | else 47 | { 48 | text[i] = tolower(key[text[i] - 'a']); 49 | } 50 | } 51 | } 52 | 53 | printf("ciphertext: %s\n", text); 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /Week2/readme.md: -------------------------------------------------------------------------------- 1 | ## Achievement 2 | 3 | - [x] Lab 2: Scrabble 4 | - [x] Readability 5 | - [ ] Caesar 6 | - [x] Substitution 7 | 8 | ## Description 9 | 10 | 0. [Lab 2: Scrabble](https://cs50.harvard.edu/x/2022/labs/2/#lab-2-scrabble) 11 | 1. Submit [Readability](https://cs50.harvard.edu/x/2022/psets/2/readability/) 12 | 2. Submit one of: 13 | - [Caesar](https://cs50.harvard.edu/x/2022/psets/2/caesar/), if feeling less comfortable 14 | - [Substitution](https://cs50.harvard.edu/x/2022/psets/2/substitution/), if feeling more comfortable 15 | -------------------------------------------------------------------------------- /Week3/0-sort.txt: -------------------------------------------------------------------------------- 1 | sort1 uses: Bubble sort 2 | 3 | How do you know?: Bubble sort is best in ordered sequences, worst in reverse sequences, the time complexity is n and n^2 4 | 5 | sort2 uses: Merge sort 6 | 7 | How do you know?: Merge sort is fast on average, nlogn 8 | 9 | sort3 uses: Selection sort 10 | 11 | How do you know?: Selection sort is slow on average, n^2 12 | -------------------------------------------------------------------------------- /Week3/1-plurality.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | // Max number of candidates 6 | #define MAX 9 7 | 8 | // Candidates have name and vote count 9 | typedef struct 10 | { 11 | string name; 12 | int votes; 13 | } candidate; 14 | 15 | // Array of candidates 16 | candidate candidates[MAX]; 17 | 18 | // Number of candidates 19 | int candidate_count; 20 | 21 | // Function prototypes 22 | bool vote(string name); 23 | void print_winner(void); 24 | 25 | int main(int argc, string argv[]) 26 | { 27 | // Check for invalid usage 28 | if (argc < 2) 29 | { 30 | printf("Usage: plurality [candidate ...]\n"); 31 | return 1; 32 | } 33 | 34 | // Populate array of candidates 35 | candidate_count = argc - 1; 36 | if (candidate_count > MAX) 37 | { 38 | printf("Maximum number of candidates is %i\n", MAX); 39 | return 2; 40 | } 41 | for (int i = 0; i < candidate_count; i++) 42 | { 43 | candidates[i].name = argv[i + 1]; 44 | candidates[i].votes = 0; 45 | } 46 | 47 | int voter_count = get_int("Number of voters: "); 48 | 49 | // Loop over all voters 50 | for (int i = 0; i < voter_count; i++) 51 | { 52 | string name = get_string("Vote: "); 53 | 54 | // Check for invalid vote 55 | if (!vote(name)) 56 | { 57 | printf("Invalid vote.\n"); 58 | } 59 | } 60 | 61 | // Display winner of election 62 | print_winner(); 63 | } 64 | 65 | // Update vote totals given a new vote 66 | bool vote(string name) 67 | { 68 | // TODO 69 | for (int i = 0; i < candidate_count; i++) 70 | { 71 | if (strcmp(candidates[i].name, name) == 0) 72 | { 73 | candidates[i].votes++; 74 | return true; 75 | } 76 | } 77 | return false; 78 | } 79 | 80 | // Print the winner (or winners) of the election 81 | void print_winner(void) 82 | { 83 | // TODO 84 | int max = 0; 85 | for (int i = 1; i < candidate_count; i++) 86 | { 87 | if (candidates[max].votes < candidates[i].votes) 88 | { 89 | max = i; 90 | } 91 | } 92 | 93 | for (int i = 0; i < candidate_count; i++) 94 | { 95 | if (candidates[max].votes == candidates[i].votes) 96 | { 97 | printf("%s\n", candidates[i].name); 98 | } 99 | } 100 | return; 101 | } 102 | -------------------------------------------------------------------------------- /Week3/2-runoff.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | // Max voters and candidates 6 | #define MAX_VOTERS 100 7 | #define MAX_CANDIDATES 9 8 | 9 | // preferences[i][j] is jth preference for voter i 10 | int preferences[MAX_VOTERS][MAX_CANDIDATES]; 11 | 12 | // Candidates have name, vote count, eliminated status 13 | typedef struct 14 | { 15 | string name; 16 | int votes; 17 | bool eliminated; 18 | } candidate; 19 | 20 | // Array of candidates 21 | candidate candidates[MAX_CANDIDATES]; 22 | 23 | // Numbers of voters and candidates 24 | int voter_count; 25 | int candidate_count; 26 | 27 | // Function prototypes 28 | bool vote(int voter, int rank, string name); 29 | void tabulate(void); 30 | bool print_winner(void); 31 | int find_min(void); 32 | bool is_tie(int min); 33 | void eliminate(int min); 34 | 35 | int main(int argc, string argv[]) 36 | { 37 | // Check for invalid usage 38 | if (argc < 2) 39 | { 40 | printf("Usage: runoff [candidate ...]\n"); 41 | return 1; 42 | } 43 | 44 | // Populate array of candidates 45 | candidate_count = argc - 1; 46 | if (candidate_count > MAX_CANDIDATES) 47 | { 48 | printf("Maximum number of candidates is %i\n", MAX_CANDIDATES); 49 | return 2; 50 | } 51 | for (int i = 0; i < candidate_count; i++) 52 | { 53 | candidates[i].name = argv[i + 1]; 54 | candidates[i].votes = 0; 55 | candidates[i].eliminated = false; 56 | } 57 | 58 | voter_count = get_int("Number of voters: "); 59 | if (voter_count > MAX_VOTERS) 60 | { 61 | printf("Maximum number of voters is %i\n", MAX_VOTERS); 62 | return 3; 63 | } 64 | 65 | // Keep querying for votes 66 | for (int i = 0; i < voter_count; i++) 67 | { 68 | 69 | // Query for each rank 70 | for (int j = 0; j < candidate_count; j++) 71 | { 72 | string name = get_string("Rank %i: ", j + 1); 73 | 74 | // Record vote, unless it's invalid 75 | if (!vote(i, j, name)) 76 | { 77 | printf("Invalid vote.\n"); 78 | return 4; 79 | } 80 | } 81 | 82 | printf("\n"); 83 | } 84 | 85 | // Keep holding runoffs until winner exists 86 | while (true) 87 | { 88 | // Calculate votes given remaining candidates 89 | tabulate(); 90 | 91 | // Check if election has been won 92 | bool won = print_winner(); 93 | if (won) 94 | { 95 | break; 96 | } 97 | 98 | // Eliminate last-place candidates 99 | int min = find_min(); 100 | bool tie = is_tie(min); 101 | 102 | // If tie, everyone wins 103 | if (tie) 104 | { 105 | for (int i = 0; i < candidate_count; i++) 106 | { 107 | if (!candidates[i].eliminated) 108 | { 109 | printf("%s\n", candidates[i].name); 110 | } 111 | } 112 | break; 113 | } 114 | 115 | // Eliminate anyone with minimum number of votes 116 | eliminate(min); 117 | 118 | // Reset vote counts back to zero 119 | for (int i = 0; i < candidate_count; i++) 120 | { 121 | candidates[i].votes = 0; 122 | } 123 | } 124 | return 0; 125 | } 126 | 127 | // Record preference if vote is valid 128 | bool vote(int voter, int rank, string name) 129 | { 130 | // TODO 131 | for (int i = 0; i < candidate_count; i++) 132 | { 133 | if (strcmp(candidates[i].name, name) == 0) 134 | { 135 | preferences[voter][rank] = i; 136 | return true; 137 | } 138 | } 139 | return false; 140 | } 141 | 142 | // Tabulate votes for non-eliminated candidates 143 | void tabulate(void) 144 | { 145 | // TODO 146 | for (int i = 0; i < voter_count; i++) 147 | { 148 | for (int j = 0; j < candidate_count; j++) 149 | { 150 | if (!candidates[preferences[i][j]].eliminated) 151 | { 152 | candidates[preferences[i][j]].votes++; 153 | break; 154 | } 155 | } 156 | } 157 | return; 158 | } 159 | 160 | // Print the winner of the election, if there is one 161 | bool print_winner(void) 162 | { 163 | // TODO 164 | for (int i = 0; i < candidate_count; i++) 165 | { 166 | if (candidates[i].votes > voter_count / 2) 167 | { 168 | printf("%s\n", candidates[i].name); 169 | return true; 170 | } 171 | } 172 | return false; 173 | } 174 | 175 | // Return the minimum number of votes any remaining candidate has 176 | int find_min(void) 177 | { 178 | // TODO 179 | int min = voter_count; 180 | for (int i = 0; i < candidate_count; i++) 181 | { 182 | if (candidates[i].votes < min && !candidates[i].eliminated) 183 | { 184 | min = candidates[i].votes; 185 | } 186 | } 187 | return min; 188 | } 189 | 190 | // Return true if the election is tied between all candidates, false otherwise 191 | bool is_tie(int min) 192 | { 193 | // TODO 194 | for (int i = 0; i < candidate_count; i++) 195 | { 196 | if (candidates[i].votes != min && !candidates[i].eliminated) 197 | { 198 | return false; 199 | } 200 | } 201 | return true; 202 | } 203 | 204 | // Eliminate the candidate (or candidates) in last place 205 | void eliminate(int min) 206 | { 207 | // TODO 208 | for (int i = 0; i < candidate_count; i++) 209 | { 210 | if (candidates[i].votes == min && !candidates[i].eliminated) 211 | { 212 | candidates[i].eliminated = true; 213 | } 214 | } 215 | return; 216 | } 217 | -------------------------------------------------------------------------------- /Week3/2-tideman.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | // Max number of candidates 6 | #define MAX 9 7 | 8 | // preferences[i][j] is number of voters who prefer i over j 9 | int preferences[MAX][MAX]; 10 | 11 | // locked[i][j] means i is locked in over j 12 | bool locked[MAX][MAX]; 13 | 14 | // Each pair has a winner, loser 15 | typedef struct 16 | { 17 | int winner; 18 | int loser; 19 | } pair; 20 | 21 | // Array of candidates 22 | string candidates[MAX]; 23 | pair pairs[MAX * (MAX - 1) / 2]; 24 | 25 | int pair_count; 26 | int candidate_count; 27 | 28 | // Function prototypes 29 | bool vote(int rank, string name, int ranks[]); 30 | void record_preferences(int ranks[]); 31 | void add_pairs(void); 32 | void sort_pairs(void); 33 | void lock_pairs(void); 34 | void print_winner(void); 35 | bool has_cycles(int loser, int winner); 36 | 37 | int main(int argc, string argv[]) 38 | { 39 | // Check for invalid usage 40 | if (argc < 2) 41 | { 42 | printf("Usage: tideman [candidate ...]\n"); 43 | return 1; 44 | } 45 | 46 | // Populate array of candidates 47 | candidate_count = argc - 1; 48 | if (candidate_count > MAX) 49 | { 50 | printf("Maximum number of candidates is %i\n", MAX); 51 | return 2; 52 | } 53 | for (int i = 0; i < candidate_count; i++) 54 | { 55 | candidates[i] = argv[i + 1]; 56 | } 57 | 58 | // Clear graph of locked in pairs 59 | for (int i = 0; i < candidate_count; i++) 60 | { 61 | for (int j = 0; j < candidate_count; j++) 62 | { 63 | locked[i][j] = false; 64 | } 65 | } 66 | 67 | pair_count = 0; 68 | int voter_count = get_int("Number of voters: "); 69 | 70 | // Query for votes 71 | for (int i = 0; i < voter_count; i++) 72 | { 73 | // ranks[i] is voter's ith preference 74 | int ranks[candidate_count]; 75 | 76 | // Query for each rank 77 | for (int j = 0; j < candidate_count; j++) 78 | { 79 | string name = get_string("Rank %i: ", j + 1); 80 | 81 | if (!vote(j, name, ranks)) 82 | { 83 | printf("Invalid vote.\n"); 84 | return 3; 85 | } 86 | } 87 | 88 | record_preferences(ranks); 89 | 90 | printf("\n"); 91 | } 92 | 93 | add_pairs(); 94 | sort_pairs(); 95 | lock_pairs(); 96 | print_winner(); 97 | return 0; 98 | } 99 | 100 | // Update ranks given a new vote 101 | bool vote(int rank, string name, int ranks[]) 102 | { 103 | // TODO 104 | for (int i = 0; i < candidate_count; i++) 105 | { 106 | if (strcmp(candidates[i], name) == 0) 107 | { 108 | ranks[rank] = i; 109 | return true; 110 | } 111 | } 112 | return false; 113 | } 114 | 115 | // Update preferences given one voter's ranks 116 | void record_preferences(int ranks[]) 117 | { 118 | // TODO 119 | for (int i = 0; i < candidate_count; i++) 120 | { 121 | for (int j = i + 1; j < candidate_count; j++) 122 | { 123 | preferences[ranks[i]][ranks[j]]++; 124 | } 125 | } 126 | 127 | return; 128 | } 129 | 130 | // Record pairs of candidates where one is preferred over the other 131 | void add_pairs(void) 132 | { 133 | // TODO 134 | for (int i = 0; i < candidate_count; i++) 135 | { 136 | pair new; 137 | for (int j = i + 1; j < candidate_count; j++) 138 | { 139 | if (preferences[i][j] > preferences[j][i]) 140 | { 141 | new.winner = i; 142 | new.loser = j; 143 | pairs[pair_count++] = new; 144 | } 145 | else if (preferences[i][j] < preferences[j][i]) 146 | { 147 | new.winner = j; 148 | new.loser = i; 149 | pairs[pair_count++] = new; 150 | } 151 | } 152 | } 153 | return; 154 | } 155 | 156 | // Sort pairs in decreasing order by strength of victory 157 | void sort_pairs(void) 158 | { 159 | // TODO 160 | for (int i = 0; i < pair_count; i++) 161 | { 162 | int max = i; 163 | for (int j = i + 1; j < pair_count; j++) 164 | { 165 | if (preferences[pairs[j].winner][pairs[j].loser] > preferences[pairs[max].winner][pairs[max].loser]) 166 | { 167 | max = j; 168 | } 169 | } 170 | 171 | pair tmp = pairs[i]; 172 | pairs[i] = pairs[max]; 173 | pairs[max] = tmp; 174 | } 175 | 176 | return; 177 | } 178 | 179 | bool has_cycles(int loser, int winner) 180 | { 181 | // Cyclic path exists 182 | if (loser == winner) 183 | { 184 | return true; 185 | } 186 | 187 | for (int i = 0; i < candidate_count; i++) 188 | { 189 | // Check path: loser -> i 190 | if (locked[loser][i]) 191 | { 192 | // Check path: i -> winner 193 | if (has_cycles(i, winner)) 194 | { 195 | return true; 196 | // If it returns true, loser -> i -> winner path exists 197 | // Add path: winner -> loser will create a cycle 198 | } 199 | } 200 | } 201 | 202 | return false; 203 | } 204 | 205 | // Lock pairs into the candidate graph in order, without creating cycles 206 | void lock_pairs(void) 207 | { 208 | // TODO 209 | for (int i = 0; i < pair_count; i++) 210 | { 211 | if (!has_cycles(pairs[i].loser, pairs[i].winner)) 212 | { 213 | locked[pairs[i].winner][pairs[i].loser] = true; 214 | } 215 | } 216 | return; 217 | } 218 | 219 | // Print the winner of the election 220 | void print_winner(void) 221 | { 222 | // TODO 223 | for (int i = 0; i < candidate_count; i++) 224 | { 225 | bool isLoser = false; 226 | for (int j = 0; j < candidate_count; j++) 227 | { 228 | // j -> i 229 | if (locked[j][i]) 230 | { 231 | isLoser = true; 232 | break; 233 | } 234 | } 235 | 236 | if (!isLoser) 237 | { 238 | printf("%s\n", candidates[i]); 239 | break; 240 | } 241 | } 242 | return; 243 | } 244 | -------------------------------------------------------------------------------- /Week3/readme.md: -------------------------------------------------------------------------------- 1 | ## Achievement 2 | 3 | - [x] Lab 3: Sort 4 | - [x] Plurality 5 | - [x] Runoff 6 | - [x] Tideman 7 | 8 | ## Description 9 | 10 | 0. [Lab 3: Sort](https://cs50.harvard.edu/x/2022/labs/3/#lab-3-sort) 11 | 1. Submit [Plurality](https://cs50.harvard.edu/x/2022/psets/3/plurality/) 12 | 2. Submit one of: 13 | - [Runoff](https://cs50.harvard.edu/x/2022/psets/3/runoff/), if feeling less comfortable 14 | - [Tideman](https://cs50.harvard.edu/x/2022/psets/3/tideman/), if feeling more comfortable 15 | -------------------------------------------------------------------------------- /Week4/0-volume.c: -------------------------------------------------------------------------------- 1 | // Modifies the volume of an audio file 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | // Number of bytes in .wav header 8 | const int HEADER_SIZE = 44; 9 | 10 | int main(int argc, char *argv[]) 11 | { 12 | // Check command-line arguments 13 | if (argc != 4) 14 | { 15 | printf("Usage: ./volume input.wav output.wav factor\n"); 16 | return 1; 17 | } 18 | 19 | // Open files and determine scaling factor 20 | FILE *input = fopen(argv[1], "r"); 21 | if (input == NULL) 22 | { 23 | printf("Could not open file.\n"); 24 | return 1; 25 | } 26 | 27 | FILE *output = fopen(argv[2], "w"); 28 | if (output == NULL) 29 | { 30 | printf("Could not open file.\n"); 31 | return 1; 32 | } 33 | 34 | // Convert a string to a floating-point number 35 | float factor = atof(argv[3]); 36 | 37 | // TODO: Copy header from input file to output file 38 | uint8_t header[HEADER_SIZE]; 39 | fread(header, HEADER_SIZE, 1, input); 40 | fwrite(header, HEADER_SIZE, 1, output); 41 | 42 | // TODO: Read samples from input file and write updated data to output file 43 | int16_t buffer; 44 | while (fread(&buffer, sizeof(int16_t), 1, input)) 45 | { 46 | buffer *= factor; 47 | fwrite(&buffer, sizeof(int16_t), 1, output); 48 | } 49 | 50 | // Close files 51 | fclose(input); 52 | fclose(output); 53 | } 54 | -------------------------------------------------------------------------------- /Week4/1-filter-less.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "helpers.h" 4 | 5 | // Convert image to grayscale 6 | void grayscale(int height, int width, RGBTRIPLE image[height][width]) 7 | { 8 | for (int i = 0; i < height; i++) 9 | { 10 | for (int j = 0; j < width; j++) 11 | { 12 | int rgbt = round((image[i][j].rgbtRed + image[i][j].rgbtGreen + image[i][j].rgbtBlue) / 3.0); 13 | image[i][j].rgbtRed = image[i][j].rgbtGreen = image[i][j].rgbtBlue = rgbt; 14 | } 15 | } 16 | } 17 | 18 | // Convert image to sepia 19 | void sepia(int height, int width, RGBTRIPLE image[height][width]) 20 | { 21 | for (int i = 0; i < height; i++) 22 | { 23 | for (int j = 0; j < width; j++) 24 | { 25 | int sr = round(0.393 * image[i][j].rgbtRed + 0.769 * image[i][j].rgbtGreen + 0.189 * image[i][j].rgbtBlue); 26 | int sg = round(0.349 * image[i][j].rgbtRed + 0.686 * image[i][j].rgbtGreen + 0.168 * image[i][j].rgbtBlue); 27 | int sb = round(0.272 * image[i][j].rgbtRed + 0.534 * image[i][j].rgbtGreen + 0.131 * image[i][j].rgbtBlue); 28 | image[i][j].rgbtRed = sr > 255 ? 255 : sr; 29 | image[i][j].rgbtGreen = sg > 255 ? 255 : sg; 30 | image[i][j].rgbtBlue = sb > 255 ? 255 : sb; 31 | } 32 | } 33 | return; 34 | } 35 | 36 | // Reflect image horizontally 37 | void reflect(int height, int width, RGBTRIPLE image[height][width]) 38 | { 39 | RGBTRIPLE tmp; 40 | for (int i = 0; i < height; i++) 41 | { 42 | for (int j = 0; j < width / 2; j++) 43 | { 44 | tmp = image[i][j]; 45 | image[i][j] = image[i][width - 1 - j]; 46 | image[i][width - 1 - j] = tmp; 47 | } 48 | } 49 | return; 50 | } 51 | 52 | // Blur image 53 | void blur(int height, int width, RGBTRIPLE image[height][width]) 54 | { 55 | RGBTRIPLE tmp[height][width]; 56 | for (int i = 0; i < height; i++) 57 | { 58 | for (int j = 0; j < width; j++) 59 | { 60 | double sr = 0, sg = 0, sb = 0, cnt = 0; 61 | for (int row = -1; row <= 1; row++) 62 | { 63 | for (int col = -1; col <= 1; col++) 64 | { 65 | if (i + row < 0 || i + row > height - 1) 66 | { 67 | continue; 68 | } 69 | if (j + col < 0 || j + col > width - 1) 70 | { 71 | continue; 72 | } 73 | cnt++; 74 | sr += image[i + row][j + col].rgbtRed; 75 | sg += image[i + row][j + col].rgbtGreen; 76 | sb += image[i + row][j + col].rgbtBlue; 77 | } 78 | } 79 | tmp[i][j].rgbtRed = round(sr / cnt); 80 | tmp[i][j].rgbtGreen = round(sg / cnt); 81 | tmp[i][j].rgbtBlue = round(sb / cnt); 82 | } 83 | } 84 | 85 | for (int i = 0; i < height; i++) 86 | { 87 | for (int j = 0; j < width; j++) 88 | { 89 | image[i][j] = tmp[i][j]; 90 | } 91 | } 92 | return; 93 | } 94 | -------------------------------------------------------------------------------- /Week4/1-filter-more.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "helpers.h" 4 | 5 | // Convert image to grayscale 6 | void grayscale(int height, int width, RGBTRIPLE image[height][width]) 7 | { 8 | for (int i = 0; i < height; i++) 9 | { 10 | for (int j = 0; j < width; j++) 11 | { 12 | int rgbt = round((image[i][j].rgbtRed + image[i][j].rgbtGreen + image[i][j].rgbtBlue) / 3.0); 13 | image[i][j].rgbtRed = image[i][j].rgbtGreen = image[i][j].rgbtBlue = rgbt; 14 | } 15 | } 16 | } 17 | 18 | // Reflect image horizontally 19 | void reflect(int height, int width, RGBTRIPLE image[height][width]) 20 | { 21 | RGBTRIPLE tmp; 22 | for (int i = 0; i < height; i++) 23 | { 24 | for (int j = 0; j < width / 2; j++) 25 | { 26 | tmp = image[i][j]; 27 | image[i][j] = image[i][width - 1 - j]; 28 | image[i][width - 1 - j] = tmp; 29 | } 30 | } 31 | return; 32 | } 33 | 34 | // Blur image 35 | void blur(int height, int width, RGBTRIPLE image[height][width]) 36 | { 37 | RGBTRIPLE tmp[height][width]; 38 | for (int i = 0; i < height; i++) 39 | { 40 | for (int j = 0; j < width; j++) 41 | { 42 | double sr = 0, sg = 0, sb = 0, cnt = 0; 43 | for (int row = -1; row <= 1; row++) 44 | { 45 | for (int col = -1; col <= 1; col++) 46 | { 47 | if (i + row < 0 || i + row > height - 1) 48 | { 49 | continue; 50 | } 51 | if (j + col < 0 || j + col > width - 1) 52 | { 53 | continue; 54 | } 55 | cnt++; 56 | sr += image[i + row][j + col].rgbtRed; 57 | sg += image[i + row][j + col].rgbtGreen; 58 | sb += image[i + row][j + col].rgbtBlue; 59 | } 60 | } 61 | tmp[i][j].rgbtRed = round(sr / cnt); 62 | tmp[i][j].rgbtGreen = round(sg / cnt); 63 | tmp[i][j].rgbtBlue = round(sb / cnt); 64 | } 65 | } 66 | 67 | for (int i = 0; i < height; i++) 68 | { 69 | for (int j = 0; j < width; j++) 70 | { 71 | image[i][j] = tmp[i][j]; 72 | } 73 | } 74 | return; 75 | } 76 | 77 | // Detect edges 78 | void edges(int height, int width, RGBTRIPLE image[height][width]) 79 | { 80 | RGBTRIPLE tmp[height][width]; 81 | double sobelx[9] = {-1, 0, 1, -2, 0, 2, -1, 0, 1}; 82 | double sobely[9] = {-1, -2, -1, 0, 0, 0, 1, 2, 1}; 83 | for (int i = 0; i < height; i++) 84 | { 85 | for (int j = 0; j < width; j++) 86 | { 87 | int cnt = -1; 88 | double rx = 0, ry = 0, gx = 0, gy = 0, bx = 0, by = 0; 89 | for (int row = -1; row <= 1; row++) 90 | { 91 | for (int col = -1; col <= 1; col++) 92 | { 93 | cnt++; 94 | if (i + row < 0 || i + row > height - 1) 95 | { 96 | continue; 97 | } 98 | if (j + col < 0 || j + col > width - 1) 99 | { 100 | continue; 101 | } 102 | rx += sobelx[cnt] * image[i + row][j + col].rgbtRed; 103 | ry += sobely[cnt] * image[i + row][j + col].rgbtRed; 104 | gx += sobelx[cnt] * image[i + row][j + col].rgbtGreen; 105 | gy += sobely[cnt] * image[i + row][j + col].rgbtGreen; 106 | bx += sobelx[cnt] * image[i + row][j + col].rgbtBlue; 107 | by += sobely[cnt] * image[i + row][j + col].rgbtBlue; 108 | } 109 | } 110 | tmp[i][j].rgbtRed = round(sqrt(rx * rx + ry * ry)) > 255 ? 255 : round(sqrt(rx * rx + ry * ry)); 111 | tmp[i][j].rgbtGreen = round(sqrt(gx * gx + gy * gy)) > 255 ? 255 : round(sqrt(gx * gx + gy * gy)); 112 | tmp[i][j].rgbtBlue = round(sqrt(bx * bx + by * by)) > 255 ? 255 : round(sqrt(bx * bx + by * by)); 113 | } 114 | } 115 | 116 | for (int i = 0; i < height; i++) 117 | { 118 | for (int j = 0; j < width; j++) 119 | { 120 | image[i][j] = tmp[i][j]; 121 | } 122 | } 123 | return; 124 | } 125 | -------------------------------------------------------------------------------- /Week4/2-recover.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | typedef uint8_t BYTE; 6 | const int BLOCK_SIZE = 512; 7 | 8 | int main(int argc, char *argv[]) 9 | { 10 | if (argc != 2) 11 | { 12 | printf("Usage: ./recover IMAGE\n"); 13 | return 1; 14 | } 15 | 16 | FILE *input = fopen(argv[1], "r"); 17 | if (input == NULL) 18 | { 19 | printf("Could not open file.\n"); 20 | return 1; 21 | } 22 | 23 | BYTE buffer[BLOCK_SIZE]; 24 | int cnt = 0; 25 | FILE *output = NULL; 26 | char filename[8]; 27 | 28 | // Repeat to read 512 bytes to a buffer 29 | while (fread(&buffer, BLOCK_SIZE, 1, input)) 30 | { 31 | // Check start of new JPEG 32 | if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0) 33 | { 34 | // Check first 35 | if (cnt) 36 | { 37 | fclose(output); 38 | } 39 | 40 | // Generate JPEG file 41 | sprintf(filename, "%03i.jpg", cnt); 42 | output = fopen(filename, "w"); 43 | cnt++; 44 | } 45 | 46 | // Already found JPEG 47 | if (cnt) 48 | { 49 | fwrite(&buffer, BLOCK_SIZE, 1, output); 50 | } 51 | } 52 | 53 | fclose(input); 54 | fclose(output); 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /Week4/readme.md: -------------------------------------------------------------------------------- 1 | ## Achievement 2 | 3 | - [x] Lab 4: Volume 4 | - [x] Filter (Less) 5 | - [x] Filter (More) 6 | - [x] Recover 7 | 8 | ## Description 9 | 10 | 0. [Lab 4: Volume](https://cs50.harvard.edu/x/2022/labs/4/) 11 | 1. Submit one of: 12 | - [this version of Filter](https://cs50.harvard.edu/x/2022/psets/4/filter/less/) if feeling less comfortable 13 | - [this version of Filter](https://cs50.harvard.edu/x/2022/psets/4/filter/more/) if feeling more comfortable 14 | 2. Submit [Recover](https://cs50.harvard.edu/x/2022/psets/4/recover/) 15 | -------------------------------------------------------------------------------- /Week5/0-inheritance.c: -------------------------------------------------------------------------------- 1 | // Simulate genetic inheritance of blood type 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | // Each person has two parents and two alleles 9 | typedef struct person 10 | { 11 | struct person *parents[2]; 12 | char alleles[2]; 13 | } person; 14 | 15 | const int GENERATIONS = 3; 16 | const int INDENT_LENGTH = 4; 17 | 18 | person *create_family(int generations); 19 | void print_family(person *p, int generation); 20 | void free_family(person *p); 21 | char random_allele(); 22 | 23 | int main(void) 24 | { 25 | // Seed random number generator 26 | srand(time(0)); 27 | 28 | // Create a new family with three generations 29 | person *p = create_family(GENERATIONS); 30 | 31 | // Print family tree of blood types 32 | print_family(p, 0); 33 | 34 | // Free memory 35 | free_family(p); 36 | } 37 | 38 | // Create a new individual with `generations` 39 | person *create_family(int generations) 40 | { 41 | // TODO: Allocate memory for new person 42 | person *new = malloc(sizeof(person)); 43 | if (new == NULL) 44 | { 45 | return NULL; 46 | } 47 | 48 | // If there are still generations left to create 49 | if (generations > 1) 50 | { 51 | // Create two new parents for current person by recursively calling create_family 52 | person *parent0 = create_family(generations - 1); 53 | person *parent1 = create_family(generations - 1); 54 | 55 | // TODO: Set parent pointers for current person 56 | new->parents[0] = parent0; 57 | new->parents[1] = parent1; 58 | 59 | // TODO: Randomly assign current person's alleles based on the alleles of their parents 60 | new->alleles[0] = parent0->alleles[rand() % 2]; 61 | new->alleles[1] = parent1->alleles[rand() % 2]; 62 | } 63 | 64 | // If there are no generations left to create 65 | else 66 | { 67 | // TODO: Set parent pointers to NULL 68 | new->parents[0] = NULL; 69 | new->parents[1] = NULL; 70 | 71 | // TODO: Randomly assign alleles 72 | new->alleles[0] = random_allele(); 73 | new->alleles[1] = random_allele(); 74 | } 75 | 76 | // TODO: Return newly created person 77 | return new; 78 | } 79 | 80 | // Free `p` and all ancestors of `p`. 81 | void free_family(person *p) 82 | { 83 | // TODO: Handle base case 84 | if (p == NULL) 85 | { 86 | return; 87 | } 88 | // TODO: Free parents recursively 89 | free_family(p->parents[0]); 90 | free_family(p->parents[1]); 91 | 92 | // TODO: Free child 93 | free(p); 94 | } 95 | 96 | // Print each family member and their alleles. 97 | void print_family(person *p, int generation) 98 | { 99 | // Handle base case 100 | if (p == NULL) 101 | { 102 | return; 103 | } 104 | 105 | // Print indentation 106 | for (int i = 0; i < generation * INDENT_LENGTH; i++) 107 | { 108 | printf(" "); 109 | } 110 | 111 | // Print person 112 | if (generation == 0) 113 | { 114 | printf("Child (Generation %i): blood type %c%c\n", generation, p->alleles[0], p->alleles[1]); 115 | } 116 | else if (generation == 1) 117 | { 118 | printf("Parent (Generation %i): blood type %c%c\n", generation, p->alleles[0], p->alleles[1]); 119 | } 120 | else 121 | { 122 | for (int i = 0; i < generation - 2; i++) 123 | { 124 | printf("Great-"); 125 | } 126 | printf("Grandparent (Generation %i): blood type %c%c\n", generation, p->alleles[0], p->alleles[1]); 127 | } 128 | 129 | // Print parents of current generation 130 | print_family(p->parents[0], generation + 1); 131 | print_family(p->parents[1], generation + 1); 132 | } 133 | 134 | // Randomly chooses a blood type allele. 135 | char random_allele() 136 | { 137 | int r = rand() % 3; 138 | if (r == 0) 139 | { 140 | return 'A'; 141 | } 142 | else if (r == 1) 143 | { 144 | return 'B'; 145 | } 146 | else 147 | { 148 | return 'O'; 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /Week5/1-speller-trie.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "dictionary.h" 7 | 8 | typedef struct node 9 | { 10 | bool is_word; 11 | struct node *son[27]; 12 | } node; 13 | 14 | node *root; 15 | int dict_size = 0; 16 | 17 | int index(const char c) 18 | { 19 | return (c == '\'') ? 26 : tolower(c) - 'a'; 20 | } 21 | 22 | bool check(const char *word) 23 | { 24 | node *cur = root; 25 | for (int i = 0; word[i]; i++) 26 | { 27 | // ' 28 | int idx = index(word[i]); 29 | if (cur->son[idx] == NULL) 30 | { 31 | return false; 32 | } 33 | cur = cur->son[idx]; 34 | } 35 | return cur->is_word; 36 | } 37 | 38 | bool load(const char *dictionary) 39 | { 40 | root = calloc(1, sizeof(node)); 41 | FILE *dict = fopen(dictionary, "r"); 42 | if (dict == NULL) 43 | { 44 | return false; 45 | } 46 | 47 | node *cur = root; 48 | char c; 49 | while ((c = fgetc(dict)) != EOF) 50 | { 51 | if (c == '\n') 52 | { 53 | cur->is_word = true; 54 | dict_size++; 55 | cur = root; 56 | } 57 | else 58 | { 59 | int idx = index(c); 60 | if (cur->son[idx] == NULL) 61 | { 62 | cur->son[idx] = calloc(1, sizeof(node)); 63 | } 64 | cur = cur->son[idx]; 65 | } 66 | } 67 | 68 | fclose(dict); 69 | return true; 70 | } 71 | 72 | unsigned int size(void) 73 | { 74 | return dict_size; 75 | } 76 | 77 | void free_nodes(node *cur) 78 | { 79 | for (int i = 0; i < 27; i++) 80 | { 81 | if (cur->son[i] != NULL) 82 | { 83 | free_nodes(cur->son[i]); 84 | } 85 | } 86 | free(cur); 87 | } 88 | 89 | bool unload(void) 90 | { 91 | free_nodes(root); 92 | return true; 93 | } 94 | -------------------------------------------------------------------------------- /Week5/1-speller.c: -------------------------------------------------------------------------------- 1 | // Implements a dictionary's functionality 2 | 3 | #include 4 | #include 5 | 6 | // fopen, fclose, fscanf 7 | #include 8 | // malloc, free 9 | #include 10 | // strcpy 11 | #include 12 | // strcasecmp 13 | #include 14 | 15 | #include "dictionary.h" 16 | 17 | // Represents a node in a hash table 18 | typedef struct node 19 | { 20 | char word[LENGTH + 1]; 21 | struct node *next; 22 | } node; 23 | 24 | // TODO: Choose number of buckets in hash table 25 | const unsigned int N = 26; 26 | 27 | // Hash table 28 | node *table[N]; 29 | int dict_size = 0; 30 | 31 | // Returns true if word is in dictionary, else false 32 | bool check(const char *word) 33 | { 34 | // TODO 35 | int num = hash(word); 36 | node *n = table[num]; 37 | while (n != NULL) 38 | { 39 | if (strcasecmp(word, n->word) == 0) 40 | { 41 | return true; 42 | } 43 | n = n->next; 44 | } 45 | return false; 46 | } 47 | 48 | // Hashes word to a number 49 | unsigned int hash(const char *word) 50 | { 51 | // TODO 52 | return toupper(word[0]) - 'A'; 53 | } 54 | 55 | // Loads dictionary into memory, returning true if successful, else false 56 | bool load(const char *dictionary) 57 | { 58 | // TODO 59 | FILE *dict = fopen(dictionary, "r"); 60 | if (dict == NULL) 61 | { 62 | return false; 63 | } 64 | 65 | char word[LENGTH + 1]; 66 | while (fscanf(dict, "%s", word) != EOF) 67 | { 68 | node *n = malloc(sizeof(node)); 69 | if (n == NULL) 70 | { 71 | return false; 72 | } 73 | strcpy(n->word, word); 74 | int num = hash(word); 75 | n->next = table[num]; 76 | table[num] = n; 77 | dict_size++; 78 | } 79 | 80 | fclose(dict); 81 | return true; 82 | } 83 | 84 | // Returns number of words in dictionary if loaded, else 0 if not yet loaded 85 | unsigned int size(void) 86 | { 87 | // TODO 88 | return dict_size; 89 | } 90 | 91 | // Unloads dictionary from memory, returning true if successful, else false 92 | bool unload(void) 93 | { 94 | // TODO 95 | for (int i = 0; i < N; i++) 96 | { 97 | node *n = table[i]; 98 | while (n != NULL) 99 | { 100 | node *tmp = n; 101 | n = n->next; 102 | free(tmp); 103 | } 104 | if (i == N - 1 && n == NULL) 105 | { 106 | return true; 107 | } 108 | } 109 | return false; 110 | } 111 | -------------------------------------------------------------------------------- /Week5/readme.md: -------------------------------------------------------------------------------- 1 | ## Achievement 2 | 3 | - [x] Lab 5: Inheritance 4 | - [x] Speller 5 | 6 | ## Description 7 | 8 | 0. [Lab 5: Inheritance](https://cs50.harvard.edu/x/2022/labs/5/) 9 | 1. Submit [Speller](https://cs50.harvard.edu/x/2022/psets/5/speller/) 10 | -------------------------------------------------------------------------------- /Week6/0-world-cup.py: -------------------------------------------------------------------------------- 1 | # Simulate a sports tournament 2 | 3 | import csv 4 | import sys 5 | import random 6 | 7 | # Number of simulation to run 8 | N = 1000 9 | 10 | 11 | def main(): 12 | # Ensure correct usage 13 | if len(sys.argv) != 2: 14 | sys.exit("Usage: python tournament.py FILENAME") 15 | 16 | teams = [] 17 | # TODO: Read teams into memory from file 18 | with open(sys.argv[1], "r") as file: 19 | reader = csv.DictReader(file) 20 | for row in reader: 21 | row["rating"] = int(row["rating"]) 22 | teams.append(row) 23 | 24 | counts = {} 25 | # TODO: Simulate N tournaments and keep track of win counts 26 | for i in range(N): 27 | winner = simulate_tournament(teams) 28 | if winner in counts: 29 | counts[winner] += 1 30 | else: 31 | counts[winner] = 1 32 | 33 | # Print each team's chances of winning, according to simulation 34 | for team in sorted(counts, key=lambda team: counts[team], reverse=True): 35 | print(f"{team}: {counts[team] * 100 / N:.1f}% chance of winning") 36 | 37 | 38 | def simulate_game(team1, team2): 39 | """Simulate a game. Return True if team1 wins, False otherwise.""" 40 | rating1 = team1["rating"] 41 | rating2 = team2["rating"] 42 | probability = 1 / (1 + 10 ** ((rating2 - rating1) / 600)) 43 | return random.random() < probability 44 | 45 | 46 | def simulate_round(teams): 47 | """Simulate a round. Return a list of winning teams.""" 48 | winners = [] 49 | 50 | # Simulate games for all pairs of teams 51 | for i in range(0, len(teams), 2): 52 | if simulate_game(teams[i], teams[i + 1]): 53 | winners.append(teams[i]) 54 | else: 55 | winners.append(teams[i + 1]) 56 | 57 | return winners 58 | 59 | 60 | def simulate_tournament(teams): 61 | """Simulate a tournament. Return name of winning team.""" 62 | # TODO 63 | while len(teams) > 1: 64 | teams = simulate_round(teams) 65 | return teams[0]["team"] 66 | 67 | 68 | if __name__ == "__main__": 69 | main() 70 | -------------------------------------------------------------------------------- /Week6/1-hello.py: -------------------------------------------------------------------------------- 1 | # TODO 2 | def main(): 3 | name = input("What is your name? ") 4 | print(f"hello, {name}") 5 | 6 | 7 | if __name__ == "__main__": 8 | main() 9 | -------------------------------------------------------------------------------- /Week6/2-mario-more.py: -------------------------------------------------------------------------------- 1 | # TODO 2 | def main(): 3 | height = get_height() 4 | for row in range(height): 5 | for i in range(height - row - 1, 0, -1): 6 | print(" ", end="") 7 | for i in range(row + 1): 8 | print("#", end="") 9 | print(" ", end="") 10 | for i in range(row + 1): 11 | print("#", end="") 12 | print() 13 | 14 | 15 | def get_height(): 16 | while True: 17 | try: 18 | n = int(input("Height: ")) 19 | if 1 <= n <= 8: 20 | break 21 | except ValueError: 22 | print("That's not an integer!") 23 | return n 24 | 25 | 26 | if __name__ == "__main__": 27 | main() 28 | -------------------------------------------------------------------------------- /Week6/3-credit.py: -------------------------------------------------------------------------------- 1 | # TODO 2 | import sys 3 | 4 | 5 | def main(): 6 | num = input("Number: ") 7 | length = len(str(num)) 8 | 9 | if length != 13 and length != 15 and length != 16: 10 | print("INVALID") 11 | sys.exit() 12 | 13 | if length % 2 == 0: 14 | flag = True 15 | else: 16 | flag = False 17 | 18 | checksum = 0 19 | for i in range(length): 20 | if flag: 21 | tmp = int(num[i]) * 2 22 | 23 | if tmp >= 10: 24 | checksum += tmp - 9 25 | else: 26 | checksum += tmp 27 | flag = False 28 | else: 29 | checksum += int(num[i]) 30 | flag = True 31 | 32 | check = int(num[0]) * 10 + int(num[1]) 33 | if checksum % 10 == 0: 34 | if check == 34 or check == 37: 35 | print("AMEX") 36 | elif 51 <= check <= 55: 37 | print("MASTERCARD") 38 | elif int(num[0]) == 4: 39 | print("VISA") 40 | else: 41 | print("INVALID") 42 | else: 43 | print("INVALID") 44 | 45 | 46 | if __name__ == "__main__": 47 | main() 48 | -------------------------------------------------------------------------------- /Week6/4-readability-easy.py: -------------------------------------------------------------------------------- 1 | def main(): 2 | text = input("Text: ") 3 | 4 | cnt = w_cnt = s_cnt = 0 5 | for i in range(len(text)): 6 | if text[i].isalnum(): 7 | cnt += 1 8 | if text[i].isspace(): 9 | w_cnt += 1 10 | if text[i] == '.' or text[i] == '!' or text[i] == '?': 11 | s_cnt += 1 12 | 13 | w_cnt += 1 14 | l = cnt * 100 / w_cnt 15 | s = s_cnt * 100 / w_cnt 16 | grade = round(0.0588 * l - 0.296 * s - 15.8) 17 | 18 | if grade < 1: 19 | print("Before Grade 1") 20 | elif grade > 16: 21 | print("Grade 16+") 22 | else: 23 | print(f"Grade {grade}") 24 | 25 | 26 | if __name__ == "__main__": 27 | main() 28 | -------------------------------------------------------------------------------- /Week6/4-readability.py: -------------------------------------------------------------------------------- 1 | # TODO 2 | def main(): 3 | text = input("Text: ") 4 | l = count_letters(text) * 100 / count_words(text) 5 | s = count_sentences(text) * 100 / count_words(text) 6 | grade = round(0.0588 * l - 0.296 * s - 15.8) 7 | 8 | if grade < 1: 9 | print("Before Grade 1") 10 | elif grade > 16: 11 | print("Grade 16+") 12 | else: 13 | print(f"Grade {grade}") 14 | 15 | 16 | def count_letters(text): 17 | cnt = 0 18 | for i in range(len(text)): 19 | if text[i].isalnum(): 20 | cnt += 1 21 | return cnt 22 | 23 | 24 | def count_words(text): 25 | cnt = 0 26 | for i in range(len(text)): 27 | if text[i].isspace(): 28 | cnt += 1 29 | return cnt + 1 30 | 31 | 32 | def count_sentences(text): 33 | cnt = 0 34 | for i in range(len(text)): 35 | if text[i] == '.' or text[i] == '!' or text[i] == '?': 36 | cnt += 1 37 | return cnt 38 | 39 | 40 | if __name__ == "__main__": 41 | main() 42 | -------------------------------------------------------------------------------- /Week6/5-dna.py: -------------------------------------------------------------------------------- 1 | import csv 2 | import sys 3 | 4 | 5 | def main(): 6 | # TODO: Check for command-line usage 7 | if len(sys.argv) != 3: 8 | sys.exit() 9 | 10 | # TODO: Read database file into a variable 11 | with open(sys.argv[1], "r") as file: 12 | reader = csv.DictReader(file) 13 | data = list(reader) 14 | 15 | # TODO: Read DNA sequence file into a variable 16 | with open(sys.argv[2], "r") as file: 17 | seq = file.read() 18 | 19 | # TODO: Find longest match of each STR in DNA sequence 20 | STR = [] 21 | for i in range(1, len(reader.fieldnames)): 22 | STR.append(longest_match(seq, reader.fieldnames[i])) 23 | 24 | # TODO: Check database for matching profiles 25 | for i in range(len(data)): 26 | matches = 0 27 | for j in range(1, len(reader.fieldnames)): 28 | if int(data[i][reader.fieldnames[j]]) == STR[j - 1]: 29 | matches += 1 30 | if matches == len(reader.fieldnames) - 1: 31 | print(data[i]['name']) 32 | return 33 | print("No match") 34 | 35 | 36 | def longest_match(sequence, subsequence): 37 | """Returns length of the longest run of subsequence in sequence.""" 38 | 39 | # Initialize variables 40 | longest_run = 0 41 | subsequence_length = len(subsequence) 42 | sequence_length = len(sequence) 43 | 44 | # Check each character in sequence for most consecutive runs of subsequence 45 | for i in range(sequence_length): 46 | 47 | # Initialize count of consecutive runs 48 | count = 0 49 | 50 | # Check for a subsequence match in a "substring" (a subset of characters) within sequence 51 | # If a match, move substring to next potential match in sequence 52 | # Continue moving substring and checking for matches until out of consecutive matches 53 | while True: 54 | 55 | # Adjust substring start and end 56 | start = i + count * subsequence_length 57 | end = start + subsequence_length 58 | 59 | # If there is a match in the substring 60 | if sequence[start:end] == subsequence: 61 | count += 1 62 | 63 | # If there is no match in the substring 64 | else: 65 | break 66 | 67 | # Update most consecutive matches found 68 | longest_run = max(longest_run, count) 69 | 70 | # After checking for runs at each character in sequence, return longest run found 71 | return longest_run 72 | 73 | 74 | main() 75 | -------------------------------------------------------------------------------- /Week6/readme.md: -------------------------------------------------------------------------------- 1 | ## Achievement 2 | 3 | - [x] Lab 6: World Cup 4 | - [x] Sentimental / Hello 5 | - [ ] Sentimental / Mario (Less) 6 | - [x] Sentimental / Mario (More) 7 | - [ ] Sentimental / Cash 8 | - [x] Sentimental / Credit 9 | - [x] Sentimental / Readability 10 | - [x] DNA 11 | 12 | ## Description 13 | 14 | 0. [Lab 6: World Cup](https://cs50.harvard.edu/x/2022/labs/6/) 15 | 1. Submit [Hello](https://cs50.harvard.edu/x/2022/psets/6/hello/) in Python 16 | 2. Submit one of: 17 | - [this version of Mario](https://cs50.harvard.edu/x/2022/psets/6/mario/less/) in Python, if feeling less comfortable 18 | - [this version of Mario](https://cs50.harvard.edu/x/2022/psets/6/mario/more/) in Python, if feeling more comfortable 19 | 3. Submit one of: 20 | - [Cash](https://cs50.harvard.edu/x/2022/psets/6/cash/) in Python, if feeling less comfortable 21 | - [Credit](https://cs50.harvard.edu/x/2022/psets/6/credit/) in Python, if feeling more comfortable 22 | 4. Submit [Readability](https://cs50.harvard.edu/x/2022/psets/6/readability/) in Python 23 | 5. Submit [DNA](https://cs50.harvard.edu/x/2022/psets/6/dna/) in Pythonhttps://cs50.harvard.edu/x/2022/psets/5/speller/) 24 | -------------------------------------------------------------------------------- /Week7/0-songs.sql: -------------------------------------------------------------------------------- 1 | -- 1 2 | SELECT name 3 | FROM songs; 4 | 5 | -- 2 6 | SELECT name 7 | FROM songs 8 | ORDER BY tempo; 9 | 10 | -- 3 11 | SELECT name 12 | FROM songs 13 | ORDER BY duration_ms DESC 14 | LIMIT 5; 15 | 16 | -- 4 17 | SELECT name 18 | FROM songs 19 | WHERE danceability > 0.75 20 | AND energy > 0.75 21 | AND valence > 0.75; 22 | 23 | -- 5 24 | SELECT avg(energy) 25 | FROM songs; 26 | 27 | -- 6 28 | SELECT name 29 | FROM songs 30 | WHERE artist_id IN 31 | (SELECT id 32 | FROM artists 33 | WHERE name = "Post Malone"); 34 | 35 | -- 7 36 | SELECT avg(energy) 37 | FROM songs 38 | WHERE artist_id IN 39 | (SELECT id 40 | FROM artists 41 | WHERE name = "Drake"); 42 | 43 | -- 8 44 | SELECT name 45 | FROM songs 46 | WHERE name 47 | LIKE "%feat.%"; 48 | -------------------------------------------------------------------------------- /Week7/1-movies.sql: -------------------------------------------------------------------------------- 1 | -- 1 2 | SELECT title 3 | FROM movies 4 | WHERE year = 2008; 5 | 6 | -- 2 7 | SELECT birth 8 | FROM people 9 | WHERE name = "Emma Stone"; 10 | 11 | -- 3 12 | SELECT title 13 | FROM movies 14 | WHERE year >= 2018 15 | ORDER BY title; 16 | 17 | -- 4 18 | SELECT count(rating) 19 | FROM ratings 20 | WHERE rating = 10.0; 21 | 22 | -- 5 23 | SELECT title, year 24 | FROM movies 25 | WHERE title 26 | LIKE "Harry Potter%" 27 | ORDER BY year; 28 | 29 | -- 6 30 | SELECT avg(rating) 31 | FROM movies 32 | JOIN ratings 33 | ON movies.id = ratings.movie_id 34 | WHERE year = 2012; 35 | 36 | -- 7 37 | SELECT title, rating 38 | FROM movies 39 | JOIN ratings 40 | ON movies.id = ratings.movie_id 41 | WHERE year = 2010 42 | ORDER BY rating DESC, title 43 | LIMIT 10; 44 | 45 | -- 8 46 | SELECT name 47 | FROM movies, stars, people 48 | WHERE movies.id = stars.movie_id 49 | AND people.id = stars.person_id 50 | AND title = "Toy Story"; 51 | 52 | -- 9 53 | SELECT distinct(name) 54 | FROM movies, stars, people 55 | WHERE movies.id = stars.movie_id 56 | AND people.id = stars.person_id 57 | AND year = 2004 58 | ORDER BY birth; 59 | 60 | -- 10 61 | SELECT distinct(name) 62 | FROM ratings, directors, people 63 | WHERE directors.movie_id = ratings.movie_id 64 | AND people.id = directors.person_id 65 | AND rating >= 9.0; 66 | 67 | -- 11 68 | SELECT title 69 | FROM movies, ratings, stars, people 70 | WHERE movies.id = ratings.movie_id 71 | AND movies.id = stars.movie_id 72 | AND people.id = stars.person_id 73 | AND name = "Chadwick Boseman" 74 | ORDER BY rating DESC 75 | LIMIT 5; 76 | 77 | -- 12 78 | SELECT title 79 | FROM movies, stars, people 80 | WHERE movies.id = stars.movie_id 81 | AND people.id = stars.person_id 82 | AND name = "Johnny Depp" 83 | AND title IN 84 | (SELECT title 85 | FROM movies, stars, people 86 | WHERE movies.id = stars.movie_id 87 | AND people.id = stars.person_id 88 | AND name = "Helena Bonham Carter"); 89 | 90 | -- 13 91 | SELECT distinct(name) 92 | FROM stars, people 93 | WHERE people.id = stars.person_id 94 | AND name != "Kevin Bacon" 95 | AND movie_id IN 96 | (SELECT movie_id 97 | FROM stars, people 98 | WHERE stars.person_id = people.id 99 | AND name = "Kevin Bacon" 100 | AND birth = 1958); 101 | -------------------------------------------------------------------------------- /Week7/2-answers.txt: -------------------------------------------------------------------------------- 1 | The THIEF is: Bruce 2 | The city the thief ESCAPED TO: New York City 3 | The ACCOMPLICE is: Robin 4 | -------------------------------------------------------------------------------- /Week7/2-fiftyville.sql: -------------------------------------------------------------------------------- 1 | -- Keep a log of any SQL queries you execute as you solve the mystery. 2 | 3 | -- 查看所有表 4 | .tables 5 | .schema 6 | 7 | -- 查看当天犯罪记录 8 | SELECT * 9 | FROM crime_scene_reports 10 | WHERE year = 2021 11 | AND month = 7 12 | AND day = 28 13 | AND street = "Humphrey Street"; 14 | 15 | -- 查看当天三位目击者关于小偷的采访记录 16 | SELECT * 17 | FROM interviews 18 | WHERE year = 2021 19 | AND month = 7 20 | AND day = 28 21 | AND transcript LIKE "%thief%"; 22 | 23 | -- 线索1. Sometime within ten minutes of the theft, I saw the thief get into a car in the bakery parking lot and drive away. 24 | -- If you have security footage from the bakery parking lot, you might want to look for cars that left the parking lot in that time frame. 25 | -- 停车场出去的人 26 | -- | Barry | 27 | -- | Bruce | 28 | -- | Diana | 29 | -- | Iman | 30 | -- | Kelsey | 31 | -- | Luca | 32 | -- | Sofia | 33 | -- | Vanessa | 34 | SELECT name 35 | FROM people 36 | WHERE license_plate IN 37 | (SELECT license_plate 38 | FROM bakery_security_logs 39 | WHERE year = 2021 40 | AND month = 7 41 | AND day = 28 42 | AND hour = 10 43 | AND minute > 15 44 | AND minute <= 25 45 | AND activity = "exit") 46 | ORDER BY name; 47 | 48 | -- 线索2. I don't know the thief's name, but it was someone I recognized. Earlier this morning, before I arrived at Emma's bakery, 49 | -- I was walking by the ATM on Leggett Street and saw the thief there withdrawing some money. 50 | -- 当天在Leggett Street取钱的人 51 | -- | Bruce | 52 | -- | Diana | 53 | -- | Iman | 54 | -- | Luca | 55 | SELECT name 56 | FROM people, bank_accounts 57 | WHERE people.id = bank_accounts.person_id 58 | AND account_number IN 59 | (SELECT account_number 60 | FROM atm_transactions 61 | WHERE year = 2021 62 | AND month = 7 63 | AND day = 28 64 | AND atm_location = "Leggett Street" 65 | AND transaction_type = "withdraw") 66 | ORDER BY name; 67 | 68 | 69 | -- 线索3. As the thief was leaving the bakery, they called someone who talked to them for less than a minute. In the call, I heard the thief 70 | -- say that they were planning to take the earliest flight out of Fiftyville tomorrow. The thief then asked the person on the other end of the phone to purchase the flight ticket. 71 | -- 买明天最早的机票的人 72 | -- | Bruce | 73 | -- | Luca | 74 | SELECT name 75 | FROM people 76 | WHERE passport_number IN 77 | (SELECT passport_number 78 | FROM passengers 79 | WHERE flight_id IN 80 | (SELECT id 81 | FROM flights 82 | WHERE year = 2021 83 | AND month = 7 84 | AND day = 29 85 | AND origin_airport_id IN 86 | (SELECT id 87 | FROM airports 88 | WHERE city = "Fiftyville") 89 | ORDER BY hour 90 | LIMIT 1)) 91 | ORDER BY name; 92 | 93 | -- 当天打了不到一分钟的电话的人 94 | -- | Bruce | 95 | SELECT name 96 | FROM people 97 | WHERE phone_number IN 98 | (SELECT caller 99 | FROM phone_calls 100 | WHERE year = 2021 101 | AND month = 7 102 | AND day = 28 103 | AND duration < 60) 104 | ORDER BY name; 105 | 106 | -- | 686048 | Bruce | (367) 555-5533 | 5773159633 | 94KL13X | 107 | -- 当天打给了 (375) 555-8161 108 | -- | 864400 | Robin | (375) 555-8161 | | 4V16VO0 | 109 | -- 飞往 New York City 110 | -------------------------------------------------------------------------------- /Week7/readme.md: -------------------------------------------------------------------------------- 1 | ## Achievement 2 | 3 | - [x] Lab 7: Songs 4 | - [x] Movies 5 | - [x] Fiftyville 6 | 7 | ## Description 8 | 9 | 0. [Lab 7: Songs](https://cs50.harvard.edu/x/2022/labs/7/) 10 | 1. Submit [Movies](https://cs50.harvard.edu/x/2022/psets/7/movies/) 11 | 2. Submit [Fiftyville](https://cs50.harvard.edu/x/2022/psets/7/fiftyville/) 12 | -------------------------------------------------------------------------------- /Week8/0-trivia/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Trivia! 9 | 45 | 46 | 47 | 48 |
49 |

Trivia!

50 |
51 | 52 |
53 |
54 |

Part 1: Multiple Choice

55 |
56 | 57 |

Which country invented tea?

58 |

59 | 60 | 61 | 62 | 63 |
64 | 65 |
66 |

Part 2: Free Response

67 |
68 | 69 |

Who starts first in chess?

70 |

71 | 72 | 73 |
74 |
75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /Week8/0-trivia/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #fff; 3 | color: #212529; 4 | font-size: 1rem; 5 | font-weight: 400; 6 | line-height: 1.5; 7 | margin: 0; 8 | text-align: left; 9 | } 10 | 11 | .container { 12 | margin-left: auto; 13 | margin-right: auto; 14 | padding-left: 15px; 15 | padding-right: 15px; 16 | } 17 | 18 | .header { 19 | background-color: #477bff; 20 | color: #fff; 21 | margin-bottom: 2rem; 22 | padding: 2rem 1rem; 23 | text-align: center; 24 | } 25 | 26 | .section { 27 | padding: 0.5rem 2rem 1rem 2rem; 28 | } 29 | 30 | .section:hover { 31 | background-color: #f5f5f5; 32 | transition: color 2s ease-in-out, background-color 0.15s ease-in-out; 33 | } 34 | 35 | h1 { 36 | font-family: 'Montserrat', sans-serif; 37 | font-size: 48px; 38 | } 39 | 40 | button, input[type="submit"] { 41 | background-color: #d9edff; 42 | border: 1px solid transparent; 43 | border-radius: 0.25rem; 44 | font-size: 0.95rem; 45 | font-weight: 400; 46 | line-height: 1.5; 47 | padding: 0.375rem 0.75rem; 48 | text-align: center; 49 | transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; 50 | vertical-align: middle; 51 | 52 | cursor: pointer; 53 | } 54 | 55 | button:hover { 56 | background-color: #93cafb; 57 | } 58 | 59 | 60 | input[type="text"] { 61 | line-height: 1.8; 62 | width: 25%; 63 | } 64 | 65 | input[type="text"]:hover { 66 | background-color: #f5f5f5; 67 | transition: color 2s ease-in-out, background-color 0.15s ease-in-out; 68 | } 69 | -------------------------------------------------------------------------------- /Week8/1-homepage/css/styles.css: -------------------------------------------------------------------------------- 1 | /* google fonts */ 2 | @import url('https://fonts.googleapis.com/css2?family=Arima:wght@700&display=swap'); 3 | @import url('https://fonts.googleapis.com/css2?family=Poppins&display=swap'); 4 | 5 | #nav { 6 | font-family: 'Arima', cursive; 7 | max-width: 80vw; 8 | margin: 0 auto; 9 | } 10 | 11 | #title { 12 | font-size: 5rem; 13 | font-weight: bold; 14 | background: linear-gradient(45deg, red, blue); 15 | background-clip: text; 16 | -webkit-background-clip: text; 17 | color: transparent; 18 | } 19 | 20 | a { 21 | text-decoration: none; 22 | } 23 | 24 | .carousel-item img { 25 | object-fit: contain; 26 | } 27 | 28 | main { 29 | font-family: 'Poppins', sans-serif; 30 | max-width: 75vw; 31 | margin: 50px auto; 32 | } 33 | 34 | section { 35 | margin: 30px auto; 36 | max-width: 60vw; 37 | } 38 | 39 | section h1 { 40 | text-align: center; 41 | font-weight: bold; 42 | margin: 2rem 0; 43 | color: #e34b59; 44 | } 45 | 46 | section h4 { 47 | font-weight: bold; 48 | } 49 | 50 | section p { 51 | font-size: x-large; 52 | } 53 | 54 | section blockquote { 55 | font-size: x-large; 56 | font-style: italic; 57 | padding-left: 10px; 58 | color: gray; 59 | border-left: gray 4px solid; 60 | margin: 1rem 0; 61 | } 62 | 63 | .card { 64 | border-radius: 15px; 65 | } 66 | 67 | .card-title { 68 | padding: 15px; 69 | margin: 10px 0; 70 | } 71 | 72 | .card-body { 73 | font-size: x-large; 74 | } 75 | 76 | .btn { 77 | font-size: x-large; 78 | margin: 8px 8px; 79 | padding: 8px 15px; 80 | border-radius: 0.7rem; 81 | } 82 | 83 | @media (max-width: 992px) { 84 | main { 85 | max-width: 85vw; 86 | } 87 | section { 88 | max-width: 75vw; 89 | } 90 | } -------------------------------------------------------------------------------- /Week8/1-homepage/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | Home 17 | 18 | 19 | 20 |
21 | 42 |
43 | 44 |
45 |
46 |

47 | This is CS50x 48 |

49 |

50 | Created for problem set 8 by Mancuoj 51 |

52 |
53 | Get Started 54 | Github 55 |
56 |
57 | 58 |
59 |
60 |
61 |
62 |
63 |

64 | Introduction to the intellectual enterprises of computer science and the art of programming. 65 |

66 |
67 |
68 |
69 |
70 |
71 |
72 |

73 | Topics include abstraction, algorithms, data structures, encapsulation, security, software engineering, and so on. 74 |

75 |
76 |
77 |
78 |
79 |
80 |
81 |

82 | Languages include C, Python, and SQL plus HTML, CSS, and JavaScript. 83 | 84 |

85 |
86 |
87 |
88 |
89 |
90 |
91 |

92 | Problem sets inspired by the arts, humanities, social sciences, and sciences. Course culminates in a final 93 | project. 94 |

95 |
96 |
97 |
98 |
99 |
100 | 101 |
102 | 123 |
124 |
125 | 126 | -------------------------------------------------------------------------------- /Week8/1-homepage/pages/about.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | About 17 | 18 | 19 | 20 |
21 | 42 |
43 | 44 |
45 |
46 |

FAQs

47 |
48 |
49 |

50 | 55 |

56 |
57 |
58 |

59 | Nope! CS50 at Harvard does have a test and quiz, but CS50x does not. 60 |

61 |
62 |
63 |
64 |
65 |

66 | 71 |

72 |
73 |
74 |

75 | Yes! You may resubmit; we will only count your most recent submission towards your progress. 76 |

77 |
78 |
79 |
80 |
81 |

82 | 89 |

90 |
91 |
92 |

93 | Nope! If you would like a verified certificate from edX, you can pay for verification at any point, even after completing all of the coursework. 94 | Though we do recommend, to avoid any logistical issues that can delay certificate issuance, that you verify before finishing the course. Otherwise, the 30-day wait we 95 | reference below only starts once you have had your identity verified by edX. 96 |

97 |
98 |
99 |
100 | 101 |
102 |

103 | 109 |

110 |
111 |
112 |

113 | Once you have completed the course and met all of the requirements, you’ll see a link on your CS50x Gradebook page allowing you to request a free CS50 Certificate, much 114 | like the one shown here. This link will be available within approximately four hours, and you should then proceed to log in using your GitHub credentials. If you have 115 | trouble accessing it, try logging out of GitHub and back in, then revisit the link to download your certificate. Be sure to request your certificate before 1 January 116 | 2023. 117 |

118 |
119 |
120 |
121 |
122 |
123 | 124 |
125 |

How to learn?

126 |
Week2 for example
127 |

Just click the sidebar to get the corresponding learning content for each week

128 | sidebar 129 |

Shift your eyes to the right, the video content

130 | video 131 |

Scroll down to see additional information

132 | other 133 |
134 | 135 |
136 |

How to submit homework?

137 |
Problem Set 1 for example
138 |

Enter the description page of Problem Set 1, and you can see the part of What to Do

139 | what to do 140 | 141 |
Submit Hello for example
142 |

Create and edit the file as required, and get the expected output after compiling

143 | expected output 144 |

You can see the test and submission method at the bottom

145 | test 146 |

Use check50 to make sure the test is all green

147 | test 148 |

Use style50 to test the coding style

149 | test 150 |

If you have passed both, you can submit using submit50

151 | test 152 |
153 |
154 | 155 | 156 | -------------------------------------------------------------------------------- /Week8/1-homepage/pages/works.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | Works 17 | 18 | 19 | 20 |
21 | 42 |
43 | 44 |
45 |
46 | 47 |
48 |
49 |
50 |

51 | Week 0 52 |

53 | 54 |
    55 |
  1. 56 | Submit this form 57 |
  2. 58 |
  3. 59 | Go to there 60 |
  4. 61 |
  5. 62 | Click “Choose File” and submit your .sb3 file 63 |
  6. 64 |
65 | 66 |
67 | Problem Set 68 | Solution 69 |
70 |
71 |
72 |
73 | 74 | 75 |
76 |
77 |
78 |

79 | Week 1 80 |

81 | 82 |
    83 |
  1. 84 | Submit Hello 85 |
  2. 86 |
  3. 87 | Submit one of: 88 |
    Mario-less, if feeling less comfortable 89 |
    Mario-more, if feeling more comfortable 90 |
  4. 91 |
  5. 92 | Submit one of: 93 |
    Cash, if feeling less comfortable 94 |
    Credit, if feeling more comfortable 95 |
  6. 96 |
97 | 98 |
99 | Problem Set 100 | Solution 101 |
102 |
103 |
104 |
105 | 106 | 107 |
108 |
109 |
110 |

111 | Week 2 112 |

113 | 114 |
    115 |
  1. 116 | Lab 2: Scrabble 117 |
  2. 118 |
  3. 119 | Submit Readability 120 |
  4. 121 |
  5. 122 | Submit one of: 123 |
    Caesar, if feeling less comfortable 124 |
    Substitution, if feeling more comfortable 125 |
  6. 126 |
127 | 128 |
129 | Lab 130 | Problem Set 131 | Solution 132 |
133 |
134 |
135 |
136 | 137 | 138 |
139 |
140 |
141 |

142 | Week 3 143 |

144 | 145 |
    146 |
  1. 147 | Lab 3: Sort 148 |
  2. 149 |
  3. 150 | Submit Plurality 151 |
  4. 152 |
  5. 153 | Submit one of: 154 |
    Runoff, if feeling less comfortable 155 |
    Tideman, if feeling more comfortable 156 |
  6. 157 |
158 | 159 |
160 | Lab 161 | Problem Set 162 | Solution 163 |
164 |
165 |
166 |
167 | 168 | 169 |
170 |
171 |
172 |

173 | To Be Continue ... 174 |

175 | 176 |
177 | to be continue 178 |
179 |
180 |
181 |
182 |
183 |
184 | 185 | -------------------------------------------------------------------------------- /Week8/1-homepage/public/GG.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csfive/CS50x/80afc24a783855523cd3ff96ee50ca8793d0616d/Week8/1-homepage/public/GG.jpg -------------------------------------------------------------------------------- /Week8/1-homepage/public/cs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csfive/CS50x/80afc24a783855523cd3ff96ee50ca8793d0616d/Week8/1-homepage/public/cs.png -------------------------------------------------------------------------------- /Week8/1-homepage/public/cs_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csfive/CS50x/80afc24a783855523cd3ff96ee50ca8793d0616d/Week8/1-homepage/public/cs_1.png -------------------------------------------------------------------------------- /Week8/1-homepage/public/cs_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csfive/CS50x/80afc24a783855523cd3ff96ee50ca8793d0616d/Week8/1-homepage/public/cs_2.png -------------------------------------------------------------------------------- /Week8/1-homepage/public/electronics.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csfive/CS50x/80afc24a783855523cd3ff96ee50ca8793d0616d/Week8/1-homepage/public/electronics.png -------------------------------------------------------------------------------- /Week8/1-homepage/public/img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csfive/CS50x/80afc24a783855523cd3ff96ee50ca8793d0616d/Week8/1-homepage/public/img.png -------------------------------------------------------------------------------- /Week8/1-homepage/public/img_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csfive/CS50x/80afc24a783855523cd3ff96ee50ca8793d0616d/Week8/1-homepage/public/img_1.png -------------------------------------------------------------------------------- /Week8/1-homepage/public/img_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csfive/CS50x/80afc24a783855523cd3ff96ee50ca8793d0616d/Week8/1-homepage/public/img_2.png -------------------------------------------------------------------------------- /Week8/1-homepage/public/img_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csfive/CS50x/80afc24a783855523cd3ff96ee50ca8793d0616d/Week8/1-homepage/public/img_3.png -------------------------------------------------------------------------------- /Week8/1-homepage/public/img_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csfive/CS50x/80afc24a783855523cd3ff96ee50ca8793d0616d/Week8/1-homepage/public/img_4.png -------------------------------------------------------------------------------- /Week8/1-homepage/public/img_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csfive/CS50x/80afc24a783855523cd3ff96ee50ca8793d0616d/Week8/1-homepage/public/img_5.png -------------------------------------------------------------------------------- /Week8/1-homepage/public/img_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csfive/CS50x/80afc24a783855523cd3ff96ee50ca8793d0616d/Week8/1-homepage/public/img_6.png -------------------------------------------------------------------------------- /Week8/1-homepage/public/img_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csfive/CS50x/80afc24a783855523cd3ff96ee50ca8793d0616d/Week8/1-homepage/public/img_7.png -------------------------------------------------------------------------------- /Week8/1-homepage/public/img_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csfive/CS50x/80afc24a783855523cd3ff96ee50ca8793d0616d/Week8/1-homepage/public/img_8.png -------------------------------------------------------------------------------- /Week8/readme.md: -------------------------------------------------------------------------------- 1 | ## Achievement 2 | 3 | - [x] Lab 8: Trivia 4 | - [x] Homepage 5 | 6 | ## Description 7 | 8 | 0. [Lab 8: Trivia](https://cs50.harvard.edu/x/2022/labs/8/) 9 | 1. Submit [Homepage](https://cs50.harvard.edu/x/2022/psets/8/homepage/) 10 | -------------------------------------------------------------------------------- /Week9/0-birthday/app.py: -------------------------------------------------------------------------------- 1 | from cs50 import SQL 2 | from flask import Flask, redirect, render_template, request 3 | 4 | # Configure application 5 | app = Flask(__name__) 6 | 7 | # Ensure templates are auto-reloaded 8 | app.config["TEMPLATES_AUTO_RELOAD"] = True 9 | 10 | # Configure CS50 Library to use SQLite database 11 | db = SQL("sqlite:///birthdays.db") 12 | 13 | 14 | @app.after_request 15 | def after_request(response): 16 | """Ensure responses aren't cached""" 17 | response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate" 18 | response.headers["Expires"] = 0 19 | response.headers["Pragma"] = "no-cache" 20 | return response 21 | 22 | 23 | @app.route("/", methods=["GET", "POST"]) 24 | def index(): 25 | if request.method == "POST": 26 | name = request.form.get("name") 27 | month = request.form.get("month") 28 | day = request.form.get("day") 29 | 30 | # TODO: Add the user's entry into the database 31 | db.execute("insert into birthdays (name, month, day) values(?, ?, ?)", name, month, day) 32 | return redirect("/") 33 | 34 | else: 35 | birthdays = db.execute("select * from birthdays") 36 | # TODO: Display the entries in the database on index.html 37 | return render_template("index.html", birthdays=birthdays) 38 | -------------------------------------------------------------------------------- /Week9/0-birthday/birthdays.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csfive/CS50x/80afc24a783855523cd3ff96ee50ca8793d0616d/Week9/0-birthday/birthdays.db -------------------------------------------------------------------------------- /Week9/0-birthday/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask 2 | cs50 -------------------------------------------------------------------------------- /Week9/0-birthday/static/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #fff; 3 | color: #212529; 4 | font-size: 1rem; 5 | font-weight: 400; 6 | line-height: 1.5; 7 | margin: 0; 8 | text-align: left; 9 | } 10 | 11 | .container { 12 | margin-left: auto; 13 | margin-right: auto; 14 | padding-left: 15px; 15 | padding-right: 15px; 16 | text-align: center; 17 | width: 90%; 18 | } 19 | 20 | .header { 21 | background-color: #477bff; 22 | color: #fff; 23 | margin-bottom: 2rem; 24 | padding: 2rem 1rem; 25 | text-align: center; 26 | } 27 | 28 | .section { 29 | padding-bottom: 1rem; 30 | padding-left: 2rem; 31 | padding-right: 2rem; 32 | padding-top: 0.5rem; 33 | } 34 | 35 | .section:hover { 36 | background-color: #f5f5f5; 37 | transition: color 2s ease-in-out, background-color 0.15s ease-in-out; 38 | } 39 | 40 | h1 { 41 | font-family: 'Montserrat', sans-serif; 42 | font-size: 48px; 43 | } 44 | 45 | button, 46 | input[type="submit"] { 47 | background-color: #d9edff; 48 | border: 1px solid transparent; 49 | border-radius: 0.25rem; 50 | font-size: 0.95rem; 51 | font-weight: 400; 52 | line-height: 1.5; 53 | padding: 0.375rem 0.75rem; 54 | text-align: center; 55 | transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; 56 | vertical-align: middle; 57 | } 58 | 59 | input[type="text"], 60 | input[type="number"] { 61 | line-height: 1.8; 62 | width: 25%; 63 | } 64 | 65 | input[type="text"]:hover, 66 | input[type="number"]:hover { 67 | background-color: #f5f5f5; 68 | transition: color 2s ease-in-out, background-color 0.15s ease-in-out; 69 | } 70 | 71 | table { 72 | background-color: transparent; 73 | margin-bottom: 1rem; 74 | width: 100%; 75 | } 76 | 77 | table th, 78 | table td { 79 | padding: 0.75rem; 80 | vertical-align: middle; 81 | } 82 | 83 | tbody tr:nth-of-type(odd) { 84 | background-color: rgb(179, 208, 255, 0.3) 85 | } -------------------------------------------------------------------------------- /Week9/0-birthday/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Birthdays 9 | 10 | 11 | 12 |
13 |

Birthdays

14 |
15 |
16 |
17 | 18 |

Add a Birthday

19 | 20 |
21 | 22 | 23 | 24 | 25 |
26 |
27 | 28 |
29 | 30 |

All Birthdays

31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | {% for birth in birthdays %} 41 | 42 | 43 | 44 | 45 | {% endfor %} 46 | 47 |
NameBirthday
{{birth.name}} {{birth.month}}/{{birth.day}}
48 |
49 |
50 | 51 | 52 | -------------------------------------------------------------------------------- /Week9/1-finance/app.py: -------------------------------------------------------------------------------- 1 | import os 2 | from datetime import datetime 3 | 4 | from cs50 import SQL 5 | from flask import Flask, redirect, render_template, request, session 6 | from flask_session import Session 7 | from werkzeug.security import check_password_hash, generate_password_hash 8 | 9 | from helpers import apology, login_required, lookup, usd 10 | 11 | # Configure application 12 | app = Flask(__name__) 13 | 14 | # Ensure templates are auto-reloaded 15 | app.config["TEMPLATES_AUTO_RELOAD"] = True 16 | 17 | # Custom filter 18 | app.jinja_env.filters["usd"] = usd 19 | 20 | # Configure session to use filesystem (instead of signed cookies) 21 | app.config["SESSION_PERMANENT"] = False 22 | app.config["SESSION_TYPE"] = "filesystem" 23 | Session(app) 24 | 25 | # Configure CS50 Library to use SQLite database 26 | db = SQL("sqlite:///finance.db") 27 | 28 | # Make sure API key is set 29 | if not os.environ.get("API_KEY"): 30 | raise RuntimeError("API_KEY not set") 31 | 32 | 33 | @app.after_request 34 | def after_request(response): 35 | """Ensure responses aren't cached""" 36 | response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate" 37 | response.headers["Expires"] = 0 38 | response.headers["Pragma"] = "no-cache" 39 | return response 40 | 41 | 42 | @app.route("/") 43 | @login_required 44 | def index(): 45 | """Show portfolio of stocks""" 46 | cash = db.execute("SELECT cash FROM users WHERE id = ?", session["user_id"]) 47 | orders = db.execute( 48 | "SELECT symbol, name, sum(shares) as sumshares, price FROM orders WHERE user_id = ? GROUP BY symbol", 49 | session["user_id"], 50 | ) 51 | account = cash[0]["cash"] 52 | for order in orders: 53 | name = order["name"] 54 | total = order["sumshares"] * order["price"] 55 | order["name"] = name 56 | order["total"] = total 57 | order["price"] = order["price"] 58 | account += total 59 | return render_template( 60 | "index.html", orders=orders, cash=cash[0]["cash"], account=account 61 | ) 62 | 63 | 64 | @app.route("/buy", methods=["GET", "POST"]) 65 | @login_required 66 | def buy(): 67 | """Buy shares of stock""" 68 | if request.method == "GET": 69 | return render_template("buy.html") 70 | else: 71 | symbol = request.form.get("symbol") 72 | if not symbol: 73 | return apology("Missing Symbol") 74 | 75 | quote = lookup(symbol) 76 | if not quote: 77 | return apology("Invalid Symbol") 78 | 79 | try: 80 | shares = float(request.form.get("shares")) 81 | if not shares or not float.is_integer(shares) or shares <= 0: 82 | raise ValueError 83 | except ValueError: 84 | return apology("Invalid number") 85 | 86 | row = db.execute("SELECT cash FROM users where id = ?", session["user_id"]) 87 | cash = row[0]["cash"] 88 | balance = cash - shares * quote["price"] 89 | if balance < 0: 90 | return apology("insufficient balance") 91 | 92 | db.execute( 93 | "UPDATE users SET cash = ? WHERE id = ?", balance, session["user_id"] 94 | ) 95 | db.execute( 96 | "INSERT INTO orders (user_id, symbol, shares, name, price, timestamp) VALUES (?, ?, ?, ?, ?, ?)", 97 | session["user_id"], 98 | symbol.upper(), 99 | shares, 100 | quote["name"], 101 | quote["price"], 102 | datetime.now(), 103 | ) 104 | return redirect("/") 105 | 106 | 107 | @app.route("/history") 108 | @login_required 109 | def history(): 110 | """Show history of transactions""" 111 | orders = db.execute( 112 | "SELECT symbol, name, shares, price, timestamp FROM orders WHERE user_id = ?", 113 | session["user_id"], 114 | ) 115 | if not orders: 116 | return apology("No history", 403) 117 | else: 118 | for order in orders: 119 | if order["shares"] > 0: 120 | order["status"] = "Bought" 121 | else: 122 | order["status"] = "Sold" 123 | return render_template("history.html", orders=orders) 124 | 125 | 126 | @app.route("/login", methods=["GET", "POST"]) 127 | def login(): 128 | """Log user in""" 129 | 130 | # Forget any user_id 131 | session.clear() 132 | 133 | # User reached route via POST (as by submitting a form via POST) 134 | if request.method == "POST": 135 | 136 | # Ensure username was submitted 137 | if not request.form.get("username"): 138 | return apology("must provide username", 403) 139 | 140 | # Ensure password was submitted 141 | elif not request.form.get("password"): 142 | return apology("must provide password", 403) 143 | 144 | # Query database for username 145 | rows = db.execute( 146 | "SELECT * FROM users WHERE username = ?", request.form.get("username") 147 | ) 148 | 149 | # Ensure username exists and password is correct 150 | if len(rows) != 1 or not check_password_hash( 151 | rows[0]["hash"], request.form.get("password") 152 | ): 153 | return apology("invalid username and/or password", 403) 154 | 155 | # Remember which user has logged in 156 | session["user_id"] = rows[0]["id"] 157 | 158 | # Redirect user to home page 159 | return redirect("/") 160 | 161 | # User reached route via GET (as by clicking a link or via redirect) 162 | else: 163 | return render_template("login.html") 164 | 165 | 166 | @app.route("/logout") 167 | def logout(): 168 | """Log user out""" 169 | 170 | # Forget any user_id 171 | session.clear() 172 | 173 | # Redirect user to login form 174 | return redirect("/") 175 | 176 | 177 | @app.route("/quote", methods=["GET", "POST"]) 178 | @login_required 179 | def quote(): 180 | """Get stock quote.""" 181 | if request.method == "GET": 182 | return render_template("quote.html") 183 | else: 184 | symbol = request.form.get("symbol") 185 | quote = lookup(symbol) 186 | if not symbol: 187 | return apology("missing symbol") 188 | if not quote: 189 | return apology("invalid symbol") 190 | return render_template("quoted.html", quote=quote) 191 | 192 | 193 | @app.route("/register", methods=["GET", "POST"]) 194 | def register(): 195 | """Register user""" 196 | if request.method == "GET": 197 | return render_template("register.html") 198 | else: 199 | name = request.form.get("username") 200 | ps1 = request.form.get("password") 201 | ps2 = request.form.get("confirmation") 202 | if not name or not ps1 or not ps1: 203 | return apology("please provide username and password!") 204 | if ps1 != ps2: 205 | return apology("password and confirmation don't match") 206 | if db.execute("SELECT * FROM users WHERE username = ?", name): 207 | return apology("user already exist!") 208 | 209 | db.execute( 210 | "INSERT INTO users (username, hash) VALUES (?, ?)", 211 | name, 212 | generate_password_hash(ps1), 213 | ) 214 | return redirect("/") 215 | 216 | 217 | @app.route("/sell", methods=["GET", "POST"]) 218 | @login_required 219 | def sell(): 220 | """Sell shares of stock""" 221 | if request.method == "GET": 222 | symbols = db.execute( 223 | "SELECT symbol FROM orders WHERE user_id = ? GROUP BY symbol", 224 | session["user_id"], 225 | ) 226 | return render_template("sell.html", symbol=symbols) 227 | else: 228 | symbol = request.form.get("symbol") 229 | shares = request.form.get("shares") 230 | 231 | if not shares: 232 | return apology("Invalid shares") 233 | shares = int(shares) 234 | if shares <= 0: 235 | return apology("Invalid symbol or shares") 236 | 237 | sumshares = db.execute( 238 | "SELECT symbol, price, name, SUM(shares) as sumshares FROM orders WHERE user_id = ? AND symbol = ?", 239 | session["user_id"], 240 | symbol, 241 | ) 242 | 243 | if shares > sumshares[0]["sumshares"]: 244 | return apology("You don't have so many shares") 245 | 246 | db.execute( 247 | "INSERT INTO orders (user_id, symbol, shares, name, price, timestamp) VALUES (?, ?, ?, ?, ?, ?)", 248 | session["user_id"], 249 | symbol, 250 | -shares, 251 | sumshares[0]["name"], 252 | sumshares[0]["price"], 253 | datetime.now(), 254 | ) 255 | sold = shares * sumshares[0]["price"] 256 | 257 | cash = db.execute("select cash FROM users WHERE id = ?", session["user_id"])[0]["cash"] 258 | db.execute( 259 | "UPDATE users SET cash = ? WHERE id = ?", cash + sold, session["user_id"] 260 | ) 261 | return redirect("/") 262 | -------------------------------------------------------------------------------- /Week9/1-finance/finance.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csfive/CS50x/80afc24a783855523cd3ff96ee50ca8793d0616d/Week9/1-finance/finance.db -------------------------------------------------------------------------------- /Week9/1-finance/helpers.py: -------------------------------------------------------------------------------- 1 | import os 2 | import requests 3 | import urllib.parse 4 | 5 | from flask import redirect, render_template, session 6 | from functools import wraps 7 | 8 | 9 | def apology(message, code=400): 10 | """Render message as an apology to user.""" 11 | 12 | def escape(s): 13 | """ 14 | Escape special characters. 15 | 16 | https://github.com/jacebrowning/memegen#special-characters 17 | """ 18 | for old, new in [ 19 | ("-", "--"), 20 | (" ", "-"), 21 | ("_", "__"), 22 | ("?", "~q"), 23 | ("%", "~p"), 24 | ("#", "~h"), 25 | ("/", "~s"), 26 | ('"', "''"), 27 | ]: 28 | s = s.replace(old, new) 29 | return s 30 | 31 | return render_template("apology.html", top=code, bottom=escape(message)), code 32 | 33 | 34 | def login_required(f): 35 | """ 36 | Decorate routes to require login. 37 | 38 | https://flask.palletsprojects.com/en/1.1.x/patterns/viewdecorators/ 39 | """ 40 | 41 | @wraps(f) 42 | def decorated_function(*args, **kwargs): 43 | if session.get("user_id") is None: 44 | return redirect("/login") 45 | return f(*args, **kwargs) 46 | 47 | return decorated_function 48 | 49 | 50 | def lookup(symbol): 51 | """Look up quote for symbol.""" 52 | 53 | # Contact API 54 | try: 55 | api_key = os.environ.get("API_KEY") 56 | url = f"https://cloud.iexapis.com/stable/stock/{urllib.parse.quote_plus(symbol)}/quote?token={api_key}" 57 | response = requests.get(url) 58 | response.raise_for_status() 59 | except requests.RequestException: 60 | return None 61 | 62 | # Parse response 63 | try: 64 | quote = response.json() 65 | return { 66 | "name": quote["companyName"], 67 | "price": float(quote["latestPrice"]), 68 | "symbol": quote["symbol"], 69 | } 70 | except (KeyError, TypeError, ValueError): 71 | return None 72 | 73 | 74 | def usd(value): 75 | """Format value as USD.""" 76 | return f"${value:,.2f}" 77 | -------------------------------------------------------------------------------- /Week9/1-finance/requirements.txt: -------------------------------------------------------------------------------- 1 | cs50 2 | Flask 3 | Flask-Session 4 | requests -------------------------------------------------------------------------------- /Week9/1-finance/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csfive/CS50x/80afc24a783855523cd3ff96ee50ca8793d0616d/Week9/1-finance/static/favicon.ico -------------------------------------------------------------------------------- /Week9/1-finance/static/styles.css: -------------------------------------------------------------------------------- 1 | /* Size for brand */ 2 | nav .navbar-brand 3 | { 4 | font-size: xx-large; 5 | } 6 | 7 | /* Colors for brand */ 8 | nav .navbar-brand .blue 9 | { 10 | color: #537fbe; 11 | } 12 | nav .navbar-brand .red 13 | { 14 | color: #ea433b; 15 | } 16 | nav .navbar-brand .yellow 17 | { 18 | color: #f5b82e; 19 | } 20 | nav .navbar-brand .green 21 | { 22 | color: #2e944b; 23 | } 24 | -------------------------------------------------------------------------------- /Week9/1-finance/templates/apology.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | 3 | {% block title %} 4 | Apology 5 | {% endblock %} 6 | 7 | {% block main %} 8 | 9 | {{ top }} 12 | {% endblock %} -------------------------------------------------------------------------------- /Week9/1-finance/templates/buy.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | 3 | {% block title %} 4 | Buy 5 | {% endblock %} 6 | 7 | {% block main %} 8 |
9 |
10 | 12 |
13 |
14 | 15 |
16 | 17 |
18 | {% endblock %} -------------------------------------------------------------------------------- /Week9/1-finance/templates/history.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | 3 | {% block title %} 4 | History 5 | {% endblock %} 6 | 7 | {% block main %} 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | {% for order in orders %} 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | {% endfor %} 30 | 31 |
SymbolNameStatusSharesPriceTime
{{ order["symbol"] }}{{ order["name"] }}{{ order["status"] }}{{ order["shares"] }}{{ order["price"] | usd }}{{ order["timestamp"] }}
32 | {% endblock %} -------------------------------------------------------------------------------- /Week9/1-finance/templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | 3 | {% block title %} 4 | Index 5 | {% endblock %} 6 | 7 | {% block main %} 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | {% for order in orders %} 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | {% endfor %} 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
SymbolNameSharesPriceTotal
{{ order["symbol"] }}{{ order["name"] }}{{ order["sumshares"] }}{{ order["price"] | usd}}{{ order["total"] | usd }}
Cash{{ cash | usd }}
Total{{ account | usd }}
40 | {% endblock %} -------------------------------------------------------------------------------- /Week9/1-finance/templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 13 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | C$50 Finance: {% block title %}{% endblock %} 22 | 23 | 24 | 25 | 26 | 27 | 55 | 56 | {% if get_flashed_messages() %} 57 |
58 | 61 |
62 | {% endif %} 63 | 64 |
65 | {% block main %}{% endblock %} 66 |
67 | 68 |
69 | Data provided by IEX 70 |
71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /Week9/1-finance/templates/login.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | 3 | {% block title %} 4 | Log In 5 | {% endblock %} 6 | 7 | {% block main %} 8 |
9 |
10 | 12 |
13 |
14 | 15 |
16 | 17 |
18 | {% endblock %} -------------------------------------------------------------------------------- /Week9/1-finance/templates/quote.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | 3 | {% block title %} 4 | Quote 5 | {% endblock %} 6 | 7 | {% block main %} 8 |
9 |
10 | 12 |
13 | 14 |
15 | {% endblock %} -------------------------------------------------------------------------------- /Week9/1-finance/templates/quoted.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | 3 | {% block title %} 4 | Quoted 5 | {% endblock %} 6 | 7 | {% block main %} 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
Company Name{{ quote.name }}
Symbol{{ quote.symbol }}
Latest Price{{ quote.price | usd }}
24 | 25 | {% endblock %} -------------------------------------------------------------------------------- /Week9/1-finance/templates/register.html: -------------------------------------------------------------------------------- 1 | {% extends 'layout.html' %} 2 | 3 | {% block title %} 4 | Register 5 | {% endblock %} 6 | 7 | {% block main %} 8 |
9 |
10 | 12 |
13 |
14 | 16 |
17 |
18 | 20 |
21 | 22 |
23 | {% endblock %} -------------------------------------------------------------------------------- /Week9/1-finance/templates/sell.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | 3 | {% block title %} 4 | Sell 5 | {% endblock %} 6 | 7 | {% block main %} 8 |
9 |
10 | 16 |
17 | 18 |
19 | 20 |
21 | 22 |
23 | {% endblock %} -------------------------------------------------------------------------------- /Week9/readme.md: -------------------------------------------------------------------------------- 1 | ## Achievement 2 | 3 | - [x] Lab 9: Birthdays 4 | - [x] Finance 5 | 6 | ## Description 7 | 8 | 0. [Lab 9: Birthdays](https://cs50.harvard.edu/x/2022/labs/9/) 9 | 1. Submit [Finance](https://cs50.harvard.edu/x/2022/psets/9/finance/) 10 | --------------------------------------------------------------------------------