├── .gitignore ├── Notes ├── 01. Computer Science.md ├── 02. Algorithms & Big O Notation.md ├── 03. Pseudocode.md ├── 04. Compiled & Interpreted.md ├── 05. Variables.md ├── 06. Floating Point Imprecision.md ├── 07. Integer Overflow.md ├── 08. Debugging.md ├── 09. Arrays.md ├── 10. Strings.md ├── 11. Command-Line Arguments.md ├── 12. Searching Algorithms.md ├── 13. Sorting Algorithms.md ├── 14. Recursion.md ├── 15. Structures.md ├── 16. Memory.md ├── 17. Data Structures.md ├── 18. Flat-file Databases.md ├── 19. Relational Databases.md ├── 20. Non-Relational Databases.md ├── 21. Internet.md ├── 22. HTML.md ├── 23. CSS.md └── 24. JavaScript.md ├── README.md ├── Week 1 - C ├── Lab1 │ └── Population │ │ └── population.c └── ProblemSet1 │ ├── Cash │ └── cash.c │ ├── MarioLess │ └── mario.c │ └── MarioMore │ └── mario.c ├── Week 2 - Arrays ├── Lab2 │ └── Scrabble │ │ └── scrabble.c └── ProblemSet2 │ ├── Caesar │ └── caesar.c │ └── Readability │ └── readability.c ├── Week 3 - Algorithms ├── Lab3 │ └── Sort │ │ └── answers.txt └── ProblemSet3 │ ├── Plurality │ └── plurality.c │ └── Runoff │ └── runoff.c ├── Week 4 - Memory ├── Lab4 │ └── Volume │ │ └── volume.c └── ProblemSet4 │ ├── FilterLess │ ├── Makefile │ ├── bmp.h │ ├── filter.c │ ├── helpers.c │ └── helpers.h │ └── Recover │ └── recover.c ├── Week 5 - Data Structures ├── Lab5 │ └── Inheritance │ │ └── inheritance.c └── ProblemSet5 │ └── Speller │ ├── Makefile │ ├── dictionary.c │ ├── dictionary.h │ └── speller.c ├── Week 6 - Python ├── Lab6 │ └── WorldCup │ │ ├── 2018m.csv │ │ ├── 2019w.csv │ │ ├── answers.txt │ │ └── tournament.py └── ProblemSet6 │ ├── DNA │ └── dna.py │ ├── SentimentalCash │ └── cash.py │ ├── SentimentalCredit │ └── credit.py │ ├── SentimentalMarioLess │ └── mario.py │ ├── SentimentalMarioMore │ └── mario.py │ └── SentimentalReadability │ └── readability.py ├── Week 7 - SQL ├── Lab7 │ └── Songs │ │ ├── 1.sql │ │ ├── 2.sql │ │ ├── 3.sql │ │ ├── 4.sql │ │ ├── 5.sql │ │ ├── 6.sql │ │ ├── 7.sql │ │ ├── 8.sql │ │ └── answers.txt └── ProblemSet7 │ ├── Fiftyville │ ├── answers.txt │ └── log.sql │ └── Movies │ ├── 1.sql │ ├── 10.sql │ ├── 11.sql │ ├── 12.sql │ ├── 13.sql │ ├── 2.sql │ ├── 3.sql │ ├── 4.sql │ ├── 5.sql │ ├── 6.sql │ ├── 7.sql │ ├── 8.sql │ ├── 9.sql │ └── info.txt ├── Week 8 - HTML, CSS, JavaScript ├── Lab8 │ └── Trivia │ │ ├── index.html │ │ ├── script.js │ │ └── styles.css └── ProblemSet8 │ └── Homepage │ ├── about.html │ ├── contact.html │ ├── index.html │ ├── portfolio.html │ ├── skills.html │ └── styles.css └── Week 9 - Flask ├── Lab9 └── Birthdays │ ├── app.py │ ├── static │ └── styles.css │ └── templates │ └── index.html └── ProblemSet9 └── Finance ├── app.py ├── helpers.py ├── requirements.txt ├── static ├── favicon.ico └── styles.css └── templates ├── apology.html ├── buy.html ├── deposit.html ├── history.html ├── index.html ├── layout.html ├── login.html ├── quote.html ├── quoted.html ├── register.html ├── sell.html └── withdraw.html /.gitignore: -------------------------------------------------------------------------------- 1 | *.exe 2 | *.db 3 | .vscode -------------------------------------------------------------------------------- /Notes/01. Computer Science.md: -------------------------------------------------------------------------------- 1 | # 1. Computer Science 2 | 3 | _**'Computer Science'**_ is fundamentally **problem solving**. 4 | 5 | **Problem solving** can be thought as the process of taking some _input_ (a problem we want to solve) and generate some _output_ (the solution to our problem). 6 | 7 | To begin doing that, we'll need a way to represent inputs and outputs, so we can store and work with information in a standardized way. 8 | 9 | --- 10 | 11 | ## 1.1. Representing - Numbers 12 | 13 | **Unary** - the system where each digit represents a single value. 14 | 15 | **Decimal** - the system which uses ten digits (0 to 9) to count to higher numbers. 16 | 17 | **Binary** - the system computers use. It has only two digits (0 & 1). 18 | 19 | ### For example: 20 | 21 | - to represent 0 in binary: 22 | 23 | `0 0 0` 24 | 25 | - to represent 1 in binary: 26 | 27 | `0 0 1 ` 28 | 29 | - to represent 2 in binary, we'll need to change another digit: 30 | 31 | `0 1 0` 32 | 33 | - to represent 3, we'll add 1: 34 | 35 | `0 1 1` 36 | 37 | - to represent 4: 38 | 39 | `1 0 0` 40 | 41 | - to represent 5: 42 | 43 | `1 0 1` 44 | 45 | - to represent 6: 46 | 47 | `1 1 0` 48 | 49 | - to represent 7: 50 | 51 | `1 1 1` 52 | 53 | Each binary digit is also called a **bit**. Since computers run on electricity, which can be turned on or off, we can simply represent a bit by turning some switch on or off to represent a 0 or a 1. 54 | 55 | Inside modern computers, there a billions of tiny switches called **transistors** that can be turned on and off to represent different values. 56 | 57 | The pattern to count in binary with multiple bits is the same as the pattern in decimal with multiple digits. For example, we know the following number in decimal represents one hundred and twenty-three. 58 | 59 | `1 2 3` 60 | 61 | The `3` is in the ones place, the `2` is in the tens place, and the `1` is in the hundreds place. 62 | So `123` is `100×1 + 10×2 + 1×3 = 100 + 20 + 3 = 123`. 63 | 64 | To count higher than 7, we would need another bit to the left to represent the number 8. Most computers use 8 bits at a time, like `00000011` for the number 3. 65 | 66 | --- 67 | 68 | ## 1.2. Representing - Text 69 | 70 | There's a standard mapping of numbers to letters called **ASCII** (_American Standard Code for Information Interchange_), which also includes lowercase letters and punctuations. 71 | 72 | Expanded map of **ASCII** values: 73 | 74 | ![](https://cs50.harvard.edu/extension/2022/fall/notes/0/cs50Week0Slide93.png) 75 | 76 | ### For example: 77 | 78 | - to represent "**A**", the number is 65, and in binary: 79 | 80 | `0 1 0 0 0 0 0 1` 81 | 82 | - to represent "**B**", the number is 66, and in binary: 83 | 84 | `0 1 0 0 0 0 1 0` 85 | 86 | - and so on. 87 | 88 | Other characters, such as letters with accent marks, symbols, are part of a standard called **Unicode**, which uses more than **8 bits** for each character, that **ASCII** uses. 89 | 90 | When we receive an _emoji_, our computer is actually reveiving a number in binary that it then maps to the image of the emoji based on the Unicode standard. Also worth noting, companies that create software for their devices will have slightly different images that represent each emoji, because only the descriptions were standardized. 91 | 92 | --- 93 | 94 | ## 1.3. Representing - Images, Video & Sounds 95 | 96 | With bits, we can map numbers to colors as well. There are many different systems to represent colors, but a common one is **RGB**, which represents colors by indicating the amount of _red_, _green_ and _blue_ within each color. 97 | 98 | - The little squares on screens are called **pixels**, which combined make **images**. 99 | 100 | - **Videos** are sequences of images, changing multiple times a second to give us the appearance of motion. 101 | 102 | - **Music** can be represented by bits too. **MIDI** is one such format which represents music with numbers for each of the notes and their duration & volume. 103 | 104 | All of these _ideas_ are just zeroes and ones, interpreted and used by software we've written to interpret them in the ways that we want. 105 | -------------------------------------------------------------------------------- /Notes/02. Algorithms & Big O Notation.md: -------------------------------------------------------------------------------- 1 | # 1. Algorithms 2 | 3 | Now that we can represent _inputs_ and _outputs_, we can work on **problem solving**. 4 | 5 | What stands between inputs(the problem) and outputs(the solution) are **algorithms**, which basically means _step-by-step instructions for solving our problems_. 6 | 7 | --- 8 | 9 | Let's say we have an old-school phone book which contains names and phone numbers. 10 | 11 | - We might open the book and start from the first page, looking for a name one page at a time. This algorithm is correct, since eventually we'll find the name if it's in the book. 12 | 13 | - We might flip through the book two pages at a time, but this algorithm would be incorrect since we might skip the page that contains the name. 14 | 15 | - Another algorithm would be opening the phone book in the middle, decide wether our name will be in the left half or right half of the book and reduce the size of our problem by half. We can repeat this until we find our name. 16 | 17 | We can visualize the efficiency of each algorithms with this chart: 18 | 19 | ![](https://cs50.harvard.edu/x/2022/notes/0/time_to_solve.png) 20 | 21 | - The first algorithm is represented by the red line. The '_time to solve_' increases linearly as the size of the problem increases. 22 | 23 | - The second algorithm is represented by the yellow line. 24 | 25 | - The third algoritm is represented by the green line. It has a different relationship between the _size of the problem_ and the _time to solve it_. 26 | 27 | --- 28 | 29 | # 2. Big O Notation 30 | 31 | When looking at **algorithms** in general, to compare their **efficiency** we must consider two aspects: the _running time_ and the _space complexity_. 32 | 33 | In **CS**, the _running time_ is oftenly described as the **big O notation**, which we can think of as _"on the order of"_ something, as though we want to convey the idea of running time and not an exact number of milliseconds or steps. 34 | 35 | Another definition of **Big O** - defines the **runtime** required to execute an **algorithm** by identifying how the performance of your **algorithm** will change as the input size grows. 36 | 37 | Reusing the chart from above where the **red line** is searching linearly (one page at a time), **yellow line** searching two pages at a time, and the **green line**, starting in the middle and dividing the problem in half each time. 38 | 39 | If we'd zoom out and change the units on our axes, the **red** and **yellow** lines would end up very close together. 40 | 41 | ![](https://cs50.harvard.edu/x/2022/notes/3/time_to_solve_zoomed_out.png) 42 | 43 | So we use **big O notation** to describe both the **red** and **yellow** lines, since they end up being very similar as _n_ becomes larger and larger. We would describe them as both having _"**big O of n**"_ or _"on the order of n"_ running time. 44 | 45 | The **green line** is different in shape even as _n_ becomes very large, so it takes _"**big O** of log n"_ steps. The base of the logarithm (2) is also removed since it's a constant factor. 46 | 47 | --- 48 | 49 | ## 2.1. Time & Space Complexity 50 | 51 | As stated previously, the **efficiency** and **performance** of an **algorithm** is measured using _time_ and _space complexity_. 52 | 53 | A factor that affects program's **efficiency** and **performance** is the _hardware_ (OS, CPU). These are not taken in consideration when analyzing an agorithm's **performance**. Instead, the _time_ and _space complexity_ as a function of the input's size are what matters. 54 | 55 | **Time complexity** of an **algorithm** quantifies the amount of time taken by an **algorithm** to run as a _function of the length of the input_. The **runtime** is a _function of the length of the input_, not the actual execution time. 56 | 57 | **Space complexity** specifies the total amount of **space** or **memory** required to execute an **algorithm** as a _function of the size of the input_ 58 | 59 | --- 60 | 61 | ### 2.1.1. Major Types of Complexities (Time & Space) 62 | 63 | - Constant: **_O_(1)** -> Best 64 | - Linear Time: **_O_(n)** -> Fair 65 | - Logarithmic Time: **_O_(n log n)** -> Bad 66 | - Quadratic Time: **_O_($n^2$)** -> Worst 67 | - Exponential Time: **_O_($2^n$)** -> Worst 68 | - Factorial Time: **_O_(n!)** -> worst 69 | 70 | The following chart illustrates **big O** complexity: 71 | 72 | ![](https://jarednielsen.com/static/9c24f10d0295ead7526e32d62fa2eac5/2ef06/big-o-cheatsheet.png) 73 | 74 | - **_O_(1)** -> Best 75 | - **_O_(log n)** -> Good 76 | - **_O_(n)** -> Fair 77 | - **_O_(n log n)** -> Bad 78 | - **_O_(n!)** **_O_($2^n$)** **_O_($n^2$)** -> Worst 79 | 80 | How to know which **algorithm** has which _time complexity_: 81 | 82 | - when calculation is not depended on the input size, it is a constant time complexity (**O(1)**). 83 | - when the input size is reduced by half, maybe when iterating, handling recursion, etc, it is a logarithmic time (**O(log n)**). 84 | - when you have a single loop within your algorithm, it is linear time complexity (**O(n)**). 85 | - when you have nested loops within your algorithm, it is quadratic time complexity (**O($n^2$)**). 86 | - when the growth rate doubles with each addition to the input, it is exponential time complexity (**O($2^n$)**). 87 | - when it grows in a factorial way based on tthe size of the input, it is factorial time complexity (**O(n!)**). 88 | 89 | --- 90 | 91 | ## 2.2. Big Omega Notation 92 | 93 | Similar to the **big O notation**, **big Omega notation** or **$\Omega$** is used to describe the _performance_ of an **algorithm**. 94 | 95 | The difference between the two, is that **big O** is used to describe the _worst case running time_, while **$\Omega$** is used to describe the best case running time of an **algorithm**. 96 | 97 | **Common 'Big $\Omega$' running times:** 98 | 99 | - **$\Omega$($n^2$)** 100 | - **$\Omega$(n log n)** 101 | - **$\Omega$(n)** 102 | - **$\Omega$(log n)** 103 | - **$\Omega$(1)** 104 | 105 | --- 106 | 107 | ## 2.3. Big Theta Notation 108 | 109 | The **big Theta notation**, or **$\Theta$** it is defined as the tightest bound which is the best of all the worst case times that an **algorithm** can take. In other words, it describes the running times of an **algorithm** if the upper bound (**big O**) and lower bound (**big $\Omega$**) are the same. 110 | 111 | There's also a notation which describes the running times of algorithms if the upper bound and lower bound are the same: **the Theta notation** or **$\Theta$**. 112 | 113 | **Common 'Big $\Theta$' running times:** 114 | 115 | - **$\Theta$($n^2$)** 116 | - **$\Theta$(n log n)** 117 | - **$\Theta$(n)** 118 | - **$\Theta$(log n)** 119 | - **$\Theta$(1)** 120 | -------------------------------------------------------------------------------- /Notes/03. Pseudocode.md: -------------------------------------------------------------------------------- 1 | # 1. Pseudocode 2 | 3 | **Pseudocode** is a human-readable version of the code. 4 | 5 | It's an important skill for many reasons. 6 | 7 | - First, when you _pseudocode_ before creating the former code, it allows to thing through the logic of your problem in advance. 8 | - Secondly, you can later provide this information to others that are seeking to understand the decisions and how your code works. 9 | 10 | The language within the pseudocode has some unique features. 11 | 12 | - some of the lines could begin with **verbs** such as: _pick up_, _open_, _close_, etc. 13 | - some lines include **conditional statements**, like _if_, or _else if_. 14 | - there are expressions that can be stated as _true_ or _false_, called **boolean expressions**. 15 | - some lines have statements such as _go back to_, called **loops**. 16 | -------------------------------------------------------------------------------- /Notes/04. Compiled & Interpreted.md: -------------------------------------------------------------------------------- 1 | # 1. Source Code & Machine Code 2 | 3 | **Machines** understand only **binary**. When human write **source code**, a list of instructions for the computer that is _human-readable_, machines only understand what is called **machine code**. 4 | 5 | **Source code** is converted to **machine code** using **compilers** and **interpreters**. 6 | 7 | --- 8 | 9 | ## 2. Compiled Languages 10 | 11 | - Compiled languages are converted directly into machine code that the processor can execute. 12 | - They tend to be faster and more efficient. 13 | - They give the developer more control over hardware aspects like memory management and CPU usage. 14 | - They need a _build_ step, meaning they need to be manually compiled first. 15 | - You need to _rebuild_ the program every time there's a change. 16 | 17 | ### 2.1. Examples of Compiled Languages: 18 | 19 | - C 20 | - C++ 21 | - Erlang 22 | - Haskell 23 | - Rust 24 | - Go 25 | 26 | ## 3. Interpreted Languages 27 | 28 | - Are run through a program _line by line_ and execute each command. 29 | - They were once significantly slower than compiled languages, but with development of **just-in-time compilation**, that gap is shrinking. 30 | 31 | ### 3.1. Examples of Interpreted Languages: 32 | 33 | - Python 34 | - PHP 35 | - Ruby 36 | - JavaScript 37 | 38 | Most programming languages can have both **compiled** and **interpreted** implementations. The _language_ itself is not necessarily **compiled** or **interpreted**, but for simplicity, they are referred to as such. 39 | 40 | --- 41 | 42 | ## 4. Compiling 43 | 44 | The `make` command used to compile **C** programs in the **CS50** version of **VSCode**, actually calls a program named `clang`, which is a _compiler_ named for the _C Language_. 45 | 46 | **Compiling** _source code_ into _machine code_ is made up of four steps: 47 | 48 | ### 4.1. Preprocessing: 49 | 50 | - involves replacing the lines that start with `#`, like `#include `, which tells the _compiler_ to look for that header file since it prototypes of functions that we want to include in our program. 51 | 52 | ### 4.2. Compiling: 53 | 54 | - takes the _source code_ in **C** and converts it into _assembly language_, which includes instructions for basic operations on memory and values, closer to the binary instructions that a **CPU** can directly understand. 55 | 56 | ### 4.3. Assembling: 57 | 58 | - the step that takes the code in _assembly_ and translates it into _binary_. 59 | - the instructions in binary are _machine code_, which a **CPU** can run directly. 60 | 61 | ### 4.4. Linking: 62 | 63 | - takes previously compiled versions of **libraries** that we included earlier, and combines them with our program. 64 | - in other words, **linking** is the process of combining all the _machine code_ for `hello.c`, `cs50.c`, etc. into our one binary file. 65 | 66 | These steps are abstracted by the `make` command, so we can think of the entire process as **compiling**. 67 | -------------------------------------------------------------------------------- /Notes/05. Variables.md: -------------------------------------------------------------------------------- 1 | # 1. Variables in C 2 | 3 | In **C**, **variables** must be a specified **data type** and they need **format specifiers** to be printed. 4 | 5 | --- 6 | 7 | ## 1.1. Basic Data Types 8 | 9 | | Data Type | Size | Description | 10 | | --------- | ------------ | -------------------------------------------------- | 11 | | int | 2 or 4 bytes | stores whole numbers | 12 | | float | 4 bytes | stores fractional numbers up to 7 decimal digits | 13 | | double | 8 bytes | stores fractional numbers up to 15 decimal digits | 14 | | char | 1 byte | a single character / letter / number / ASCII value | 15 | | long | 8 bytes | stores whole numbers, can go higher than int | 16 | | bool | 2 bytes | stores 'true' or 'false' values | 17 | 18 | --- 19 | 20 | ## 1.2. Basic Format Specifiers 21 | 22 | | Format Specifier | Data Type | 23 | | ---------------- | --------- | 24 | | %d or %i | int | 25 | | %f | float | 26 | | %1f | double | 27 | | %c | char | 28 | | %s | strings | 29 | 30 | --- 31 | 32 | ## 1.3. Operators 33 | 34 | - **'+'** for addition 35 | - **'-'** for substraction 36 | - **'\*'** for multiplication 37 | - **'/'** for division 38 | - **'%'** for remainder 39 | 40 | --- 41 | 42 | ## 1.4. Syntactic Sugar 43 | 44 | **C** also supports _syntactic sugar_, or shorthand expressions for the same functionality. We could equivalently say `counter += 1;` to add one to _counter_ before storing it again. We could also just write `counter++` or `counter--`. 45 | 46 | --- 47 | 48 | # 2. Variables in Python 49 | 50 | In **Python**, **variables** don't need a specified **data type** or a **format specifier** to pe printed. A **variable** is created when first assigning a value to it. 51 | 52 | --- 53 | 54 | ## 2.1. Basic Data Types 55 | 56 | | Data Type | Size | Description | 57 | |-----------|----------|---------------------------------| 58 | | int | 28 bytes | stores whole numbers | 59 | | float | 24 bytes | stores fractional numbers | 60 | | bool | 28 bytes | stores 'True' or 'False' values | 61 | | string | 49 bytes | +1 byte for each character | 62 | 63 | ## 2.2. Other Data Types 64 | 65 | Besides the previously mentioned **data types**, Python also has as built-in types: 66 | 67 | - _**complex**_ - numeric type that returns a complex number by specifing a real number and an imaginary number. 68 | - _**list**_ - sequence type that stores ordered, changeable, and duplicate items. 69 | - _**tuple**_ - sequence type that stores multiple items that are ordered, unchangeable and duplicate. 70 | - _**set**_ - set type that stores unordered, unchangeable and don't allow duplicates. 71 | - _**dict**_ - mapping type that stores ordered, changeable, and don't allow duplicates. Stores data in key - value pairs. 72 | - _**range**_ - sequence type returns a sequence of numbers. 73 | 74 | --- 75 | 76 | ## 2.3. Syntactic Sugar 77 | 78 | Similar to **C**, **Python** also supports _syntactic sugar_, although only the expression `counter += 1`. 79 | -------------------------------------------------------------------------------- /Notes/06. Floating Point Imprecision.md: -------------------------------------------------------------------------------- 1 | # 1. Floating Point Imprecision 2 | 3 | **Floating Point Imprecision** is the inability for computers to represent all possible real numbers with a finite number of bits, like 32 bits for a float. So, computers have to store the closest value it can, leading to imprecision. This problem is present even in a higher level language such as **Python**. 4 | 5 | To see this, we'll change the number of decimals displayed by specifing the number in the _print_ statement. 6 | 7 | ## 1.1. Example 8 | 9 | ```c 10 | #include 11 | #include 12 | 13 | int main(void) 14 | { 15 | float x = get_float("x: "); 16 | float y = get_float("y: "); 17 | 18 | float z = x / y; 19 | 20 | printf("%.50f\n", z); 21 | } 22 | ``` 23 | 24 | **Result:** 25 | 26 | ```c 27 | x: 2 28 | 29 | y: 3 30 | 31 | 0.66666668653488159179687500000000000000000000000000 32 | ``` 33 | -------------------------------------------------------------------------------- /Notes/07. Integer Overflow.md: -------------------------------------------------------------------------------- 1 | # 1. Integer Overflow 2 | 3 | **Integer overflow** happens when an integer can only be so large given a finite number of bits. 4 | 5 | The **Y2K** problem arose because many programs stored the calendar year with just two digits, like `98` for _1998_, and `99` for _1999_. When the year _2000_ approached, the programs had to store only `00`, leading to confusion betwenn the years _1900_ and _2000_. 6 | 7 | In **2038**, we'll also run out of bits to track time, since the standard number of bits to count the number of seconds since `January 1st 1970` is **32**. A **32** bit integer can only count up to about two billion, so in **2038** we'll reach that limit. 8 | 9 | - the 32 bit of an integer representing **2147483647** looks like: 10 | 11 | ```c 12 | 01111111111111111111111111111111 13 | ``` 14 | 15 | - when we increase that by _1_, the bits will look like: 16 | 17 | ```c 18 | 10000000000000000000000000000000 19 | ``` 20 | 21 | - but the first bit in an integer represent whether or not it's a negative value, so the decimal value will actually be **-2147483647**, the lowest possible _negative_ value of an _int_. So computers might actually think it's sometime in **1901**. 22 | 23 | In **Python**, integers have _arbitrary precision_, meaning that arbitrarily large numbers can be represented, the only limitation being **memory**. **Integer overflow** don't normally occur if the operations are purely performed in **Python**. -------------------------------------------------------------------------------- /Notes/08. Debugging.md: -------------------------------------------------------------------------------- 1 | # 1. Debugging 2 | 3 | **Bugs** are mistakes in programs that cause them to behave differently than intended. 4 | 5 | **Debugging** is the process of finding and fixing those **bugs**. 6 | 7 | ## 1.1. Print Statement Debugging 8 | 9 | - the process in which we tell our application with `printf` or any other similar statements in other languages, to generate output while the program is executing. 10 | - the output generated helps diagnose issues within the program. 11 | 12 | ## 1.2. Debugger 13 | 14 | - is a tool built into **VS Code**, which will walk through the program _step-by-step_. 15 | 16 | ## 1.3. Rubber Duck Debugging 17 | 18 | - the technique where we explain the code to a _rubber duck_ or any other _inanimate_ object. 19 | - by talking through the code out loud, we might realize the mistake. 20 | -------------------------------------------------------------------------------- /Notes/09. Arrays.md: -------------------------------------------------------------------------------- 1 | # 1. Arrays 2 | 3 | **Arrays** are used to store multiple values of the _same type_, _back-to-back_, _contiguously_. 4 | 5 | When declaring an array, the square brackets after the name indicates how many values we want to store. 6 | 7 | ## 1.1. Declare an Array 8 | 9 | ```c 10 | int scores[3]; 11 | 12 | scores[0] = 72; 13 | scores[1] = 73; 14 | scores[2] = 33; 15 | ``` 16 | 17 | ```c 18 | int scores[3] = {25, 50, 75, 100}; 19 | ``` 20 | -------------------------------------------------------------------------------- /Notes/10. Strings.md: -------------------------------------------------------------------------------- 1 | # 1. Strings 2 | 3 | **String** are _arrays of characters_, which are not defined in **C**, but by the **CS50 Library**. 4 | 5 | ## 1.1. Declare a String in C 6 | 7 | ```c 8 | char s[] = "Hi!"; 9 | ``` 10 | 11 | ```c 12 | char *s = "Hi!"; 13 | ``` 14 | 15 | ## 1.2. Declare a String in C using the CS50 Library 16 | 17 | ```c 18 | #include 19 | 20 | string s = "Hi!"; 21 | ``` 22 | 23 | Each charater in the **string** is stored in a **byte of memory**. Also **string** end with a _special character_, `\n`, or a byte with all eight bits set to **0**, so the program knows when to string ends. So, for a **string** with **3** characters, we need **4 bytes**. 24 | 25 | ![](https://cs50.harvard.edu/x/2022/notes/2/string.png) 26 | -------------------------------------------------------------------------------- /Notes/11. Command-Line Arguments.md: -------------------------------------------------------------------------------- 1 | # 1. Command-Line Arguments 2 | 3 | Programs can also take **arguments** or **inputs** given in the command we use to run it. 4 | 5 | The `main` function has to be changed from `void` so it can take arguments as: 6 | 7 | ```c 8 | #include 9 | #include 10 | 11 | int main(int argc, string argv[]) 12 | { 13 | printf("Hello, %s\n", argv[1]); 14 | } 15 | ``` 16 | 17 | Now when running the program, we need to pass an argument: `./argv David`. 18 | 19 | The `main` function also returns an integer value called an **exit status**. By default the `main` function returns 0 to indicate nothing went wrong, but we can write a program to return a different value. 20 | 21 | ```c 22 | #include 23 | #include 24 | 25 | int main(int argc, string argv[]) 26 | { 27 | if (argc != 2) 28 | { 29 | printf("Missing command-line argument!\n"); 30 | return 1; 31 | } 32 | 33 | printf("Helo, %s\n", argv[1]); 34 | return 0; 35 | } 36 | ``` 37 | 38 | - A _non-zero_ **exit status** indicates some error to the system that runs our program. Once we run `return 1;`, our program will exit early with an exit status of `1`. 39 | - **C** will automatically return `0` if the program ran as expected so we don't really need to write it in the code. 40 | -------------------------------------------------------------------------------- /Notes/12. Searching Algorithms.md: -------------------------------------------------------------------------------- 1 | # 1. Searching 2 | 3 | **Searching** represents how we solve the problem of finding information. 4 | 5 | A simple problem has an input of some values, and an output of a `bool`, whether or not a particular value is in the array. 6 | 7 | To define **searching algorithms**, they are designed to check for an element or retrieve it from any data structured it is stored in. 8 | 9 | These **algorithms** are generally classified into two categories: 10 | 11 | - **sequential search**: the array is traversed sequentially and every element is checked (**linear search**). 12 | - **interval search**: designed for searching sorted data structures (**binary search**). 13 | 14 | --- 15 | 16 | ## 1.1. Linear Search 17 | 18 | **Linear Search** is defined as a sequential search algorithm that starts at one end and goes through each elements of a list until the desired element is found, otherwise the search continues until the end of the set. 19 | 20 | - Worst-case performance - **_O_(n)** 21 | - Best-case performance - **_O_(1)** 22 | - Average performance - **_O_($n^2)** 23 | - Worst-case space complexity - **_O_(1)** 24 | 25 | --- 26 | 27 | - **Representing 'Linear Search' in _pseudocode_:** 28 | 29 | ```c 30 | for each door from left to right 31 | if number is behind door 32 | return True 33 | 34 | return False 35 | ``` 36 | 37 | **NOTE:** the `return False` is outside the loop, since we only want to do that after we've looked behind all doors. 38 | 39 | --- 40 | 41 | ## 1.2. Binary Search 42 | 43 | **Binary Search** find the position of a target value within a sorted list. It compares the target value to the middle element of the array, if they are not equal the half in which the target cannot be is eliminated and the search continues in the remaining half, continuing until the target value is found. If the search ends with the remaining half being empty, the target is not in the list. 44 | 45 | - Worst-case performance - **_O_(log n)** 46 | - Best-case performance - **_O_(1)** 47 | - Average performance - **_O_(log n)** 48 | - Worst-case space complexity - **_O_(1)** 49 | 50 | --- 51 | 52 | - **Representing 'Binary Search' in _pseudocode_:** 53 | 54 | ```c 55 | if no doors 56 | return False 57 | if number behind middle door 58 | return True 59 | else if number < middle door 60 | search left half 61 | else if number > middle door 62 | search right half 63 | ``` 64 | 65 | **NOTE:** remember to check whether there are no doors left, since that means our number isn't behind any of them. 66 | -------------------------------------------------------------------------------- /Notes/13. Sorting Algorithms.md: -------------------------------------------------------------------------------- 1 | # 1. Sorting 2 | 3 | **Sorting** is used to rearrange a given array of list of elements according to a comparison operator on the elements. The comparison operator is used to decide the new order of elements in the structure. 4 | 5 | --- 6 | 7 | ## 1.1. Selection Sort 8 | 9 | The **selection sort** algorithm sorts an array by repeatedly finding the mininum element (considering ascending order) from the unsorted part and putting it at the beginning. 10 | 11 | The algorithm maintains two subarrays in a given array: 12 | 13 | - the subarray which already sorted. 14 | - the remaining unsorted array. 15 | 16 | --- 17 | 18 | ## 1.2. Bubble Sort 19 | 20 | The **bubble sort** algorithm is the simplest sorting algorithm. It works by repeatedly swapping the adjacent elements if they are in the wrong order. 21 | 22 | This algorithm is not suitable for large arrays because its average and worst-case time complexity are quite high. 23 | 24 | --- 25 | 26 | ## 1.3. Merge Sort 27 | 28 | The **merge sort** algorithm is based on the _divide and conquer_ paradigm. The initial array is split into two equal halves and then combined in a sorted manner. 29 | 30 | Think of it as a **recursive** algorithm that continuously splits the array in half until it cannot be further divided, meaning if the array becomes empty or has one element left in it, the dividing will stop and it is the base case to stop the **recursion**. If the array has multiple elements, split the array into halves and **recursively** invoke the merge to sort on each of the halves. Finally when both halves are sorted, the merge operation is applied. Merge operation is the process of taking two smaller sorted arrays and combining them to eventually make a larger one. 31 | 32 | --- 33 | 34 | ## [1.4. Comparison of Sorting Algorithms](https://www.cs.usfca.edu/~galles/visualization/ComparisonSort.html) 35 | -------------------------------------------------------------------------------- /Notes/14. Recursion.md: -------------------------------------------------------------------------------- 1 | # 1. Recursion 2 | 3 | **Recursion** is the ability for a function _to call itself_ directly or indirectly. A **recursive** function solves a particular problem by calling a copy of itself and solving smaller subproblems of the original problems. 4 | 5 | An important aspect of **recursion** is that we should provide a certain case in order to terminate the recursion process. 6 | 7 | **Recursion in pseudocode as seen in the _binary search_ pseudocode:** 8 | 9 | ```c 10 | if no doors 11 | return false 12 | if number behind middle door 13 | return true 14 | else if number < middle door 15 | search left half 16 | else if number > middle door 17 | search right half 18 | ``` 19 | 20 | We're using the same _search algorithm_ for each half. This seems like a cyclical process that will never end, but we're actually changing the input to the function and dividing the problem in half each time, stopping once there are no doors left. 21 | -------------------------------------------------------------------------------- /Notes/15. Structures.md: -------------------------------------------------------------------------------- 1 | # 1. Structures 2 | 3 | **Structures** also called **structs** are a way to group several related variables into one place, each variable being known as a _member_ of the **structure**. 4 | 5 | Unlike arrays, **structures** can contain different data types(int, float, char, etc). 6 | 7 | **Creating a Structure in C using the CS50 Library:** 8 | 9 | ```c 10 | typedef struct 11 | { 12 | string name; 13 | string number; 14 | } 15 | person; 16 | ``` 17 | 18 | **Assigning and accessing values:** 19 | 20 | ```c 21 | person phonebook[1] = {"David", "+1-949-468-2750"}; 22 | 23 | printf("%s\n", phonebook[0].name) 24 | printf("%s\n", phonebook[0].number) 25 | ``` 26 | -------------------------------------------------------------------------------- /Notes/16. Memory.md: -------------------------------------------------------------------------------- 1 | # 1. Addresses 2 | 3 | When a variable is created in **C**, a **memory address** is assigned to that variable. The address is the location of where the variable is stored on the computer. 4 | 5 | To access the address of the variable, the **reference operator (&)** is used. 6 | 7 | ```c 8 | #include 9 | 10 | int main(void) 11 | { 12 | int age = 30; 13 | 14 | printf("%p\n", &age); 15 | } 16 | ``` 17 | 18 | It will return the **address** in hexadecimal form (0x...) which is just a numbering system with base 16. 19 | 20 | ![](https://cs50.harvard.edu/x/2022/notes/4/addresses.png) 21 | 22 | --- 23 | 24 | # 2. Pointers 25 | 26 | **Pointers** store the **memory address** of a variable as its value. To print it, use the `%p` format specifier. **Pointers** give you the ability to manipulate data in the computer's memory which can reduce the code and improve the performance. 27 | 28 | They point to a _data type_ of the same type, and is created with the `*` operator. 29 | 30 | ```c 31 | #include 32 | 33 | int main(void) 34 | { 35 | int age = 30; 36 | int *pointer = &age; 37 | 38 | // prints out the value of age 39 | printf("%i\n", age); 40 | 41 | // prints out the memory address of age 42 | printf("%p\n", &age); 43 | 44 | // prints out the memory address of age with the pointer 45 | printf("%p\n", pointer); 46 | } 47 | ``` 48 | 49 | In the example above, the pointer variable was used to get the memory address of a variable (used together with the `&` **reference operator**). 50 | 51 | There's also the possibility to get the value of the variable the pointer points to with the `*` operator, also known as the **dereference operator**. 52 | 53 | ```c 54 | #include 55 | 56 | int main(void) 57 | { 58 | int age = 30; 59 | int *pointer = &age; 60 | 61 | // prints out the memory address of age with the pointer 62 | printf("%p\n", pointer); 63 | 64 | // prints out the value of age with the pointer 65 | printf("%p\n", *pointer); 66 | } 67 | ``` 68 | 69 | - When the `*` sign is used in declaration `int* pointer`, it creates a **pointer variable**. 70 | - When not used in declaration, it acts as a **dereference operator**. 71 | 72 | --- 73 | 74 | ## 2.1. Pointer Arithmetic 75 | 76 | **Pointer arithmetic** is the process of applying mathematical operation to pointers, using them just like numbers. 77 | 78 | ```c 79 | #include 80 | 81 | int main(void) 82 | { 83 | int numbers[] = {4, 6, 8, 2, 7, 5, 0}; 84 | 85 | printf("%i\n", *numbers); 86 | printf("%i\n", *(numbers + 1)); 87 | printf("%i\n", *(numbers + 2)); 88 | printf("%i\n", *(numbers + 3)); 89 | printf("%i\n", *(numbers + 4)); 90 | printf("%i\n", *(numbers + 5)); 91 | printf("%i\n", *(numbers + 6)); 92 | } 93 | ``` 94 | 95 | We add only **1** to the address of `numbers` instead of **4** (**int**s are 4 bytes in size), since the compiler already knows that the type of each value in `numbers` is 4 bytes. With **+1** we're telling the compiler to move the next value in the array, not the next byte. 96 | 97 | Also, `numbers` is an array, but we can use it as a pointers with **\*numbers**. 98 | 99 | --- 100 | 101 | ## 2.2. Compare & Copy 102 | 103 | When comparing two integers with the same values, the program works as expected. 104 | 105 | ```c 106 | #include 107 | 108 | int main(void) 109 | { 110 | int n = 50; 111 | int m = 50; 112 | 113 | if (n == m) 114 | { 115 | printf("Same!\n"); 116 | } 117 | else 118 | { 119 | printf("Different!\n"); 120 | } 121 | } 122 | ``` 123 | 124 | When comparing two strings with the same inputs, the program will print '_Different!_'. 125 | 126 | ```c 127 | #include 128 | #include 129 | 130 | int main(void) 131 | { 132 | char *s = get_string("s: "); 133 | char *t = get_string("t: "); 134 | 135 | if (s == t) 136 | { 137 | printf("Same!\n"); 138 | } 139 | else 140 | { 141 | printf("Different!\n"); 142 | } 143 | } 144 | ``` 145 | 146 | This happens because each **string** is a pointer (char \*) to a different location in memory, where the first character of each string is stored. So even if the characters in the string are the same, this will always print '_Different!_'. 147 | 148 | The `get_string()` function has been returning just a **char \***, or a pointer to the first character of a string from the used. Since we called `get string()` twice, we got two different pointers back. 149 | 150 | This problem can be solved by using the `strcmp()` function from the `string.h` library, which wll to to each string and compare them character by character. 151 | 152 | When trying to copy a string, then capitalize the first letter in the copied one, we see that in both strings the first letter is capitalized. 153 | 154 | ```c 155 | #include 156 | #include 157 | #include 158 | #include 159 | 160 | int main(void) 161 | { 162 | string s = get_string("s: "); 163 | 164 | string t = s; 165 | 166 | t[0] = toupper(t[0]); 167 | 168 | printf("s: %s\n", s); 169 | printf("t: %s\n", t); 170 | } 171 | ``` 172 | 173 | Since we set **s** and **t** to the same value, or the same address, they're both pointing to the same character, and so we capitalized the same character in memory. 174 | 175 | ![](https://cs50.harvard.edu/x/2022/notes/4/s_t_pointing.png) 176 | 177 | --- 178 | 179 | ## 2.3. Arrow Operator 180 | 181 | In **C**, the **arrow operator (->)** allows the access to elements inside **Structures** and **Unions**. It is used with a _pointer variable pointing to a structure or union_. 182 | 183 | ```c 184 | #include 185 | #include 186 | 187 | // create the structure 188 | struct car { 189 | char brand[]; 190 | char color[]; 191 | int year; 192 | }; 193 | 194 | // create the structure object 195 | struct car* firstCar = NULL; 196 | 197 | int main(void) 198 | { 199 | // assign memory to struct variable 200 | firstCar = (struct car*) 201 | malloc(sizeof(struct car)); 202 | 203 | // assign value to age variable using the arrow operator 204 | firstCar->year = 2012; 205 | 206 | // print the assigned value 207 | printf("%i\n", firstCar->year); 208 | } 209 | 210 | ``` 211 | 212 | --- 213 | 214 | # 3. Memory Allocation 215 | 216 | To actually make a copy of a string, and solve the problem above, we have to copy each character in `s` to somewhere else in memory. For that, the function `malloc()` is used to allocate some number of bytes in memory. After we're done with it, we'll use `free()` to mark the memory as usable for something else. 217 | Also, we'll use the `strcpy()` from `string.h` library to copy the string. 218 | 219 | ```c 220 | #include 221 | #include 222 | #include 223 | #include 224 | #include 225 | 226 | int main(void) 227 | { 228 | char *s = get_string("s: "); 229 | 230 | char *t = malloc(strlen(s) + 1); 231 | 232 | // exit if 't' is equal to NULL, meaning the computer is out of memory and there is not an address to point to 233 | if (t == NULL) 234 | { 235 | return 1; 236 | } 237 | 238 | strcpy(t, s); 239 | 240 | // check that 't' has a length before capitalizing 241 | if (strlen(t) > 0) 242 | { 243 | t[0] = toupper(t[0]); 244 | } 245 | 246 | printf("s: %s\n", s); 247 | printf("t: %s\n", t); 248 | 249 | free(t); 250 | } 251 | ``` 252 | 253 | --- 254 | 255 | # 4. Memory Layout 256 | 257 | The **data types** that need to be stored for our program are organized into different sections. 258 | 259 | ![](https://cs50.harvard.edu/x/2022/notes/4/memory_layout.png) 260 | 261 | - the **machine code** section is the compiled program's binary code. When running the program, the code is loaded into memory. 262 | - the **global variables** declare within the program occupy the next section of memory. 263 | - the **heap** section is an empty area where `malloc()` can get free memory for our program to use. 264 | - the **stack** section is used by **functions** and **local variables** as they are called. 265 | 266 | If we call `malloc()` for too much memory, we will have a **heap overflow** since we end up going past our heap. 267 | If we call too many functions without returning from them, we will have a **stack overflow**, where our stack has too much memory allocated as well. 268 | 269 | --- 270 | 271 | # 5. Garbage Values 272 | 273 | A **garbage value** occurs when allocating a memory for your variable, but you don't assign a value to it. The memory of the variable may still have a value from the previous program. 274 | 275 | ```c 276 | #include 277 | #include 278 | 279 | int main(void) 280 | { 281 | int scores[3]; 282 | 283 | for (int i = 0; i < 3; i++) 284 | { 285 | printf("%i\n", scores[i]); 286 | } 287 | } 288 | ``` 289 | 290 | In the example above, we declared an array named **scores**, but didn't initialize it with any values. The values in the array are **garbage values**, whatever unknown values that were in memory from whatever program was running on the computer before. 291 | 292 | If we try to go to an address that's a **garbage value**, our program is likely to crash from a **segmentation fault**. 293 | -------------------------------------------------------------------------------- /Notes/17. Data Structures.md: -------------------------------------------------------------------------------- 1 | # 1. Data Structures 2 | 3 | **Data Structures** are forms of organization of data in **memory** so that it can be accessed and updated efficiently. It is also used for processing, retrieving, and storing data. 4 | 5 | There are different **basic** and **advanced** types of **data structures** that are used in almost every program or software system that has been developed. 6 | 7 | --- 8 | 9 | ## 1.1. Classification of Data Structures 10 | 11 | **Linear Data Strucutres** are structures where **data elements** are arranged _sequentially_ or _linearly_, and where each **element** is attached to its previous and next adjacent **element**. 12 | 13 | **Examples**: arrays, stacks, queues, linked lists, etc. 14 | 15 | **Non-linear Data Structures** are structures where **data elements** are not placed _sequentially_ or _linearly_. In this type of structure we can't traverse all the elements in a single run only. 16 | 17 | **Examples**: trees, graphs. 18 | 19 | --- 20 | 21 | ### 1.1.1. Queues 22 | 23 | **Queues** are specific properties, namely **FIFO** or _first in, first out_. You can imagine yourself in a line for a ride at an amusement park. The first person in the line gets to go on the ride first. The last person get to go on the ride last. 24 | 25 | **Queues** have specific actions associated with them. An item can be **enqueued**, meaning that item can join the line or queue, or an item can be **dequeued**, meaning it can leave once it reaches the front of the line. 26 | 27 | --- 28 | 29 | ### 1.1.2. Stacks 30 | 31 | **Stacks** have properties that are different than a **queue**: **LIFO** or _last in, first out_. Just like stacking trays in a cafeteria, a tray that is placed in a stack last is the first to be picked. 32 | 33 | --- 34 | 35 | ### 1.1.3. Linked Lists 36 | 37 | **Linked Lists** can store a list of values in **different parts of memory**. 38 | 39 | ![](https://cs50.harvard.edu/x/2022/notes/5/linked_list.png) 40 | 41 | - we have the values `1`, `2` and `3`, each stored in some address memory, like `0x123`, `0x456` and `0x789`. 42 | - this is different than an array since our values are no longer next to one another in memory. 43 | - we can use whatever locations in memory that are free. 44 | 45 | When **inserting** a new value to a **linked list**, we allocate enough memory for both the value we want to store and the address next to the value. 46 | 47 | ![](https://cs50.harvard.edu/x/2022/notes/5/linked_list_with_addresses.png) 48 | 49 | - next to value `1`, for example, we also store a pointer, `0x456` to the next value and pointer. 50 | - for the last group, we have the null pointer, `0x0`, since there's no next group. 51 | 52 | We can also visualize these addresses as just pointers, since we don't need to know what the addresses actually are. 53 | 54 | ![](https://cs50.harvard.edu/x/2022/notes/5/linked_list_with_pointers.png) 55 | 56 | With a **linked list**, we have the tradeoff of needing to allocate more memory for each value and pointer, in order to spend less time adding values. 57 | 58 | The next group of boxes with a value and a pointer are called a **node**, a component of a data structure that encapsulates some information. **Nodes** can be implemented with a struct. 59 | 60 | --- 61 | 62 | ### 1.1.4. Binary Search Tree 63 | 64 | **Binary Search Trees** are another **data structure** that can be used to store data more efficiently such that it can be searched and retrieved. 65 | 66 | ![](https://cs50.harvard.edu/x/2023/notes/5/cs50Week5Slide120.png) 67 | 68 | - the value that's in the center becomes the top of the tree. Values that are less than the center are placed to the left and values that are more are placed to the right. 69 | - pointers can be used to point to the correct location of each area of memory such that each of these nodes can be connected. 70 | 71 | --- 72 | 73 | ### 1.1.5. Dictionaries 74 | 75 | **Dictionaries** are actual book-form dictionaries that have a word and a definition - a _key_ and a _value_. 76 | 77 | --- 78 | 79 | ### 1.1.6. Hash Tables 80 | 81 | **Hash Tables** are a combination of both arrays and linked lists. When implemented in code, a **hash table** is an _array of pointers to nodes_. 82 | 83 | **Hashing** is the idea of taking a value and being able to output another value that becomes a shortcut to it later. For example, the name _Aaron_ can be hashed as value 1, _Ben_, as 2, and so on for the whole alphabet. While not ideal in terms of design, ultimately, putting all _a_'s in one bucket, illustrates how you can use this concept. 84 | 85 | **Hash function** is an algorithm that reduces a larger value to something small and predictable. Generally, this function takes in an item you with to add to your hash table and returns an integer representing the array index in which the item should be placed. 86 | 87 | --- 88 | 89 | ### 1.1.7. Tries 90 | 91 | **Tries** are always searchable in _constant time_. One downside of **tries** is that they tent to take up a large amount of **memory**. 92 | -------------------------------------------------------------------------------- /Notes/18. Flat-file Databases.md: -------------------------------------------------------------------------------- 1 | # 1. Flat-file Databases 2 | 3 | A **flat-file database** is a **database** stored in a file called a _flat file_. Records follow a uniform format, and there are no structures for indexing or recognizing relationship between records. Relationships can be inferred from the data in the **database**, but the format of the **database** doesn't make those relationships explicit. 4 | 5 | A flat file can be a **plain text file** (csv, tsv, txt) or a **binary file**. 6 | 7 | The **records** in the **database** are separated by delimiters such as _tabs_ or _commas_ and each line holds only one record. 8 | 9 | --- 10 | 11 | ## 1.1. Advantages of Flat-file Databases 12 | 13 | - all records are stored in one place; 14 | - easy to understand and configure; 15 | - an excellent option for small databases; 16 | - requires less hardware and software components; 17 | 18 | --- 19 | 20 | ## 1.2. Disadvantages of Flat-file Databases 21 | 22 | - they are harder to update; 23 | - harder to change data format; 24 | - poor in terms of complex queries; 25 | - increased redundancy and inconsistency; 26 | -------------------------------------------------------------------------------- /Notes/19. Relational Databases.md: -------------------------------------------------------------------------------- 1 | # 1. Relational Databases 2 | 3 | A **relational database** is a type of **database** that stores and provides access to data points that are _related to one another_. **Relational databases** are based on the _relational model_, which is a way of representing data in **tables**. Each row in the **table** is a record with a unique ID called **key**. The columns of the **table** hold attributes of the data, and each record usually has a value of each attribute, making it easy to establish relationships among data points. 4 | 5 | **SQL** or **Structured Query Language** is used to write and query data in the **database**. **SQL** allows for four types of commands: _create_, _read_, _update_, and _delete_, also known as _CRUD_. 6 | 7 | Although **SQL** is the standard _ANSI_/_ISO_, there are different versions of the language. Most of the **SQL** **database** programs have their own proprietary extensions in addition to the SQL standard. 8 | 9 | A **relational database management system** or **RDBMS** is a program used to create, update and manage such **databases**. 10 | 11 | --- 12 | 13 | ## 1.1. Database Schema 14 | 15 | The **database schema** is the skeleton structure of the **database** described in a _formal language_ supported by the **database management system**. The term _schema_ refers to the organization of data as a blueprint of how the database is constructed (divided into database tables). 16 | 17 | --- 18 | 19 | ## 1.2. Relational Model 20 | 21 | The **relational database model** allows any table to be related to another table using a common attribute. Instead of using hierarchical structures to organize data, the data is stored, accessed and related in tables without reorganizing the tables that contain them. 22 | 23 | --- 24 | 25 | ### 1.2.1. Types of Relational Models 26 | 27 | There are three types of relational models in **DBMS**. 28 | 29 | 1. **One-to-Many Model** 30 | 31 | In this type of relationship, one entity is related to multiple other entities. The key feature of the model is that the relationship between two entities is not reciprocal. For example, a customer can have multiple orders on a website, but that order cannot have multiple customers. 32 | 33 | 2. **One-to-One Model** 34 | 35 | The **one-to-one model** states that there is a direct and unique relationship between two specific objects. In other words, each object can only be related to one other object and vice versa. This type of relationship is often used to represent relations between physical things, such as people and their driver's license number. 36 | 37 | 3. **Many-to-Many Model** 38 | 39 | In a **many-to-many model**, each record in the primary table can be linked to multiple records in the foreign table and vice versa. This type of relationship is less common. One such example migh be between students and courses. A student can take multiple courses and a course can have multiple students enrolled. 40 | 41 | --- 42 | 43 | ## 1.3. Primary Key & Foreign Key 44 | 45 | The **primary key** constraint uniquely identifies each record in a table. **Primary keys** must be _unique_ and cannot contain _null values_. A table can only have one **primary key** and the **key** can consist of single or multiple columns (fields). 46 | 47 | The **foreign key** constraint is used to prevent actions that would destroy links between tables, so it's a field or a collection of fields in one table, that refers to the **primary key** in another table. 48 | 49 | The table with the **foreign key** is called the _child_ table, and the table with the **primary key** is the _referenced_ or _parent_ table. 50 | 51 | --- 52 | 53 | ## 1.4. Example 54 | 55 | ### **Employees Table** 56 | 57 | | PersonID | LastName | FirstName | Age | 58 | |----------|----------|-----------|-----| 59 | | 1 | Halpert | Jim | 28 | 60 | | 2 | Scott | Michael | 42 | 61 | | 3 | Beesly | Pam | 26 | 62 | | 4 | Schrute | Dwight | 34 | 63 | | 5 | Malone | Kevin | 39 | 64 | 65 | ### **Sales Table** 66 | 67 | | SaleID | SaleNumber | PersonID | 68 | |--------|------------|----------| 69 | | 1 | 4985 | 1 | 70 | | 2 | 3455 | 4 | 71 | | 3 | 2321 | 2 | 72 | | 4 | 6752 | 1 | 73 | | 5 | 8795 | 3 | 74 | 75 | - the _PersonID_ column in the **Sales Table** points to the _PersonID_ in the **Employees Table**; 76 | - the _PersonID_ in the **Employees Table** is the **Primary Key** in the **Employees Table**; 77 | - the _PersonID_ in the **Sales Table** is the **Foreign Key** in the **Sales Table**; 78 | - the relationship between the two is **one-to-many**, an employee can have multiple sales, but that sale cannot have multiple employees, in this case. 79 | -------------------------------------------------------------------------------- /Notes/20. Non-Relational Databases.md: -------------------------------------------------------------------------------- 1 | # 1. Non-Relational Databases 2 | 3 | A **non-relational database** is a **database** that does not use the tabular schema of rows and columns found in most traditional database systems. Instead, they use a storage model that is optimized for the specific requirements of the type of data being stored. 4 | 5 | These type of **databases** don't use the _relational model_. Also, they tend to be more specific in the type of data they support and how data can be queried. 6 | 7 | The term **NoSQL** refers to data stores that do not use **SQL** for queries. Instead, the data stores use other programming languages and constructs to query the data. Although **NoSQL** stands for _non-relational database_, many of these **databases** support **SQL** compatible queries. However, the query execution is usually very different from how a traditional **RDBMS** would execute the same query. 8 | 9 | --- 10 | 11 | ## 1.1. Types of Non-Relational Databases 12 | 13 | ### **1. Document Data Stores** 14 | 15 | A document data store manages a set of named string fields and object data values in an entity that's referred to as a _document_. They tend to store data in the form of JSON documents. 16 | 17 | ### **2. Columnar Data Stores** 18 | 19 | A columnar or column-family data store organizes data into columns and rows. They can appear very similar to relational databases, conceptually. The real power of this type of databases lies in its denormalized approach to structuring sparse data, which stems from the column-oriented approach to storing data. 20 | 21 | ### **3. Key-Value Data Stores** 22 | 23 | It's essentially a large hash table/dictionary. You associate each value with a unique key, and the key/value store uses this key to store the data by using an appropiate hashing function. The hashing function is selected to provide an even distribution of hashed keys across the data storage. 24 | 25 | ### **4. Graph Data Stores** 26 | 27 | A graph data store manages two types of information, nodes and edges. Nodes represent entities, and edges specify the relationships between these entities. Both nodes and edges can have properties that provide information about that node or edge, similar to columns in a table. Edges can also have a direction indicating the nature of the relationship. 28 | 29 | ### **5. Time Series Data Stores** 30 | 31 | Time series data is a set of values organized by time, and a time series data store is optimized for this type of data. Time series data stores must support a very high number of writes, as they typically collect large amounts of data in real time from a large number of sources. Time series data stores are optimized for storing telemetry data. Scenarios include IoT sensors or application/system counters. 32 | 33 | ### **6. Object Data Stores** 34 | 35 | Object data stores are optimized for storing and retrieving large binary objects or blobs such as images, text files, video and audio streams, large application data objects and documents, and virtual machine disk images. An object consists of the stored data, some metadata, and a unique ID for accessing the object. Object stores are designed to support files that are individually very large, as well provide large amounts of total storage to manage all files. 36 | 37 | ### **7. External Index Data Stores** 38 | 39 | External index data stores provide the ability to search for information held in other data stores and services. An external index acts as a secondary index for any data store, and can be used to index massive volumes of data and provide near real-time access to these indexes. 40 | -------------------------------------------------------------------------------- /Notes/21. Internet.md: -------------------------------------------------------------------------------- 1 | # 1. Internet 2 | 3 | The **internet** is a worldwide system of computer networks that uses the **protocol suite** (_TCP/IP_) to communicate between networks and devices. 4 | 5 | To transfer **data** from one network to another, we need to make _routing decisions_. The **data** could take multiple paths, such that when a router is congested, **data** can flow through another path. 6 | 7 | _TCP/IP_ are two protocols that allow computers to transfer **data** between them over the internet. 8 | 9 | --- 10 | 11 | ## 1.1. IP 12 | 13 | **IP** or **Internet Protocol** is a way by which computers can identify one another across the internet. Every computer has a unique address in the world, by this form `#.#.#.#`. Instead of the hashes, there are numbers that range from 0 to 255. **IP** addresses are 32-bits, meaning that these addresses could accomodate over 4 billion addresses. Newer versions of **IP** addresses can accomodate even more computers. 14 | 15 | --- 16 | 17 | ## 1.2. TCP 18 | 19 | **TCP** or **Transmission Control Protocol** is used to distinguish web services from one another. For example, `80` is used to denote _HTTP_ and `443` is used to denote _HTTPS_. These numbers are **port numbers**. When information is sent from one location to another, an **IP** address and **TCP** port number are sent. 20 | 21 | These protocols are also used to fragment large files into multiple parts called _packets_. For example, a large photo can be sent in multiple packets. When a packet is lost, **TCP/IP** can request missing packets again from the origin server. **TCP** will acknowledge when all the **data** has been transmitted and received. 22 | 23 | --- 24 | 25 | ## 1.3. DNS 26 | 27 | **DNS** or **Domain Name System** is a collection of servers on the internet that are used to route website addresses to a specific **IP** address, instead of needing the address for visiting the website. 28 | 29 | **DNS** simply hold a table or database that links specific, fully qualified domain names to specific **IP** addresses. 30 | 31 | --- 32 | 33 | ## 1.4. HTTP 34 | 35 | **HTTP** or **Hypertext Transfer Protocol** is an application-level protocol that developers use to build things. When you see an address such as `https://www.example.com` you are actually implicitly visiting that address with a `/` at the end of it. 36 | 37 | The **path** is what exists after that `/`. For example, `https://www.example.com/folder/file.html` visits `example.com` and browses for the `folder` and then visits the file named `file.html`. 38 | 39 | ### 1.4.1. HTTP Methods 40 | 41 | The **https** in the address is the protocol used to connect to that web address. **HTTP** utilizes _GET_ or _POST_ requests to ask for information from a server. 42 | 43 | - _GET_ is used to request **data** from a specified source. _GET_ requests can be cached, remain in the browser history, can be bookmarked, should never be used when dealing with sensitive **data**, are only used to request **data**, not modify it. 44 | - _POST_ is used to send **data** to a server to create/update a resource. _POST_ requests are never cached, do not remain in the browser history and cannot be bookmarked. 45 | 46 | ### 1.4.2. HTTP Messages 47 | 48 | When requesting a service from a web server, an error might occur, and the server might return an error code like `404 Not Found`. The server always returns a message for every request. The most coomon message is `200 OK`, which means that the request was successful. 49 | 50 | List of all the HTTP status messages can be found here: https://www.w3schools.com/tags/ref_httpmessages.asp. 51 | -------------------------------------------------------------------------------- /Notes/22. HTML.md: -------------------------------------------------------------------------------- 1 | # 1. HTML 2 | 3 | **HTML** or **Hypertext Markup Language** is the standard markup language for web pages. 4 | 5 | ```html 6 | 7 | 8 | 9 | 10 | 11 | 12 | Webpage - Title 13 | 14 | 15 | Hello World! 16 | 17 | ``` 18 | 19 | **HTML** is made up of _tags_, which may have some _attributes_ that describe that _tag_. 20 | 21 | - _tags_ start end end with `<>`. Example: ``. 22 | - _attributes_ provide additional information about _tags_. Example: `Visit Example`. -------------------------------------------------------------------------------- /Notes/23. CSS.md: -------------------------------------------------------------------------------- 1 | # 1. CSS 2 | 3 | **CSS** or **Cascading Style Sheet** is another markup language that allows you to fine-tune the aesthetics of the **HTML** files. 4 | 5 | ```html 6 | 7 | 8 | 9 | 10 | 11 | 12 | Webpage - Title 13 | 14 | 15 |
16 | Hello World! 17 |
18 |
19 | Homepage 20 |
21 |
22 | Copyright © all rights reserved. 23 |
24 | 25 | ``` 26 | 27 | ```html 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | css 36 | 37 | 38 |
39 | Hello World! 40 |
41 |
42 | Homepage 43 |
44 |
45 | Copyright © all rights reserved. 46 |
47 | 48 | 49 | ``` 50 | -------------------------------------------------------------------------------- /Notes/24. JavaScript.md: -------------------------------------------------------------------------------- 1 | # 1. JavaScript 2 | 3 | **JavaScript** is the programming language of the web. It allows to dynamically read and modify the **HTML** document loaded into memory without the need to reload to see the changes. Similar to **CSS**, **JavaScript** can be used inside the **HTML** or in an external file. 4 | 5 | ```html 6 | 7 | 8 | 9 | 10 | 11 | 12 | background 13 | 14 | 15 | 16 | 17 | 18 | 32 | 33 | 34 | ``` 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## :label: **About CS50** 2 | 3 | **[CS50](https://pll.harvard.edu/course/cs50-introduction-computer-science?delta=0)** is an online introductory course on computer science and programming. It teaches the languages C, Python, SQL, HTML, CSS & JavaScript, as well as fundamental computer science concepts such as algorithms & data structures, abstraction, encapsulation, resource management, security, and the Flask web framework. 4 | 5 | --- 6 | 7 |
8 | 9 | ## :computer: **About the Repository** 10 | 11 | An important part of the course, it's submitting the labs and problem sets, as well as the final project for feedback. This repository contains the solutions I've come up with for the problem sets and labs. The final project is in a separate repository, the link is below. 12 | 13 | Also down below are links and short descriptions for each of the projects. If you'd like to read more about the implementation requirements, there's a link in each folder that will lead to them. 14 | 15 | --- 16 | 17 |
18 | 19 | ## :closed_book: **Academic Honesty** 20 | 21 | Keep in mind the course's [academic honesty](https://cs50.harvard.edu/x/2023/honesty/). You should try figuring out a solution yourself before looking at other implementations. Also, bear in mind that I am a beginner, I've taken the course to learn, so the solutions might not be the best implementations. 22 | 23 | --- 24 | 25 |
26 | 27 | ## :book: **Content** 28 | 29 | --- 30 | 31 | ### :arrow_forward: **Notes** 32 | 33 |
34 | 35 | ![Markdown](https://img.shields.io/badge/markdown-%23000000.svg?style=for-the-badge&logo=markdown&logoColor=white) 36 | 37 | - **[Notes](Notes)** - _contains notes I took from various sources, mostly from each week's notes section._ 38 | 39 | --- 40 | 41 | ### :arrow_forward: **Week 1 - C** 42 | 43 |
44 | 45 | ![C](https://img.shields.io/badge/c-%2300599C.svg?style=for-the-badge&logo=c&logoColor=white) 46 | 47 | - **[L-1 - Population Growth](Week%201%20-%20C/Lab1/Population/population.c)** - _determine how long it takes for a population to reach a particular size._ 48 | 49 | - **[PS-1 - Mario Less](Week%201%20-%20C/ProblemSet1/MarioLess/mario.c)** - _create a right-aligned pyramid of blocks._ 50 | 51 | - **[PS-1 - Mario More](Week%201%20-%20C/ProblemSet1/MarioMore/mario.c)** - _create an adjacent pyramid of blocks._ 52 | 53 | - **[PS-1 - Cash](Week%201%20-%20C/ProblemSet1/Cash/cash.c)** - _minimize the number of coins given to a customer when making a change using greedy algorithms._ 54 | 55 | --- 56 | 57 | ### :arrow_forward: **Week 2 - Arrays** 58 | 59 |
60 | 61 | ![C](https://img.shields.io/badge/c-%2300599C.svg?style=for-the-badge&logo=c&logoColor=white) 62 | 63 | - **[L-2 Scrabble](Week%202%20-%20Arrays/Lab2/Scrabble/scrabble.c)** - _determine which of two scrabble words is worth more._ 64 | 65 | - **[PS-2 Caesar](Week%202%20-%20Arrays/ProblemSet2/Caesar/caesar.c)** - _program that encrypts messages using Caesar's cipher._ 66 | 67 | - **[PS-2 Readability](Week%202%20-%20Arrays/ProblemSet2/Readability/readability.c)** - _computes the approximate grade level needed to comprehend some text._ 68 | 69 | --- 70 | 71 | ### :arrow_forward: **Week 3 - Algorithms** 72 | 73 |
74 | 75 | ![C](https://img.shields.io/badge/c-%2300599C.svg?style=for-the-badge&logo=c&logoColor=white) 76 | 77 | - **[L-3 Sort](Week%203%20-%20Algorithms/Lab3/Sort/answers.txt)** - _analyze three sorting programs to determine which algorithms they use._ 78 | 79 | - **[PS-3 Plurality](Week%203%20-%20Algorithms/ProblemSet3/Plurality/plurality.c)** - _program that runs a plurality election._ 80 | 81 | - **[PS-3 Runoff](Week%203%20-%20Algorithms/ProblemSet3/Runoff/runoff.c)** - _program that runs a runoff election._ 82 | 83 | --- 84 | 85 | ### :arrow_forward: **Week 4 - Memory** 86 | 87 |
88 | 89 | ![C](https://img.shields.io/badge/c-%2300599C.svg?style=for-the-badge&logo=c&logoColor=white) 90 | 91 | - **[L-4 Volume](Week%204%20-%20Memory/Lab4/Volume/volume.c)** - _modify the volume of an audio file._ 92 | 93 | - **[PS-4 Filter Less](Week%204%20-%20Memory/ProblemSet4/FilterLess/filter.c)** - _program that applies filters to BMPs._ 94 | 95 | - **[PS-4 Recover](Week%204%20-%20Memory/ProblemSet4/Recover/recover.c)** - _program that recovers JPEGs from a forensic image._ 96 | 97 | --- 98 | 99 | ### :arrow_forward: **Week 5 - Data Structures** 100 | 101 |
102 | 103 | ![C](https://img.shields.io/badge/c-%2300599C.svg?style=for-the-badge&logo=c&logoColor=white) 104 | 105 | - **[L-5 Inheritance](Week%205%20-%20Data%20Structures/Lab5/Inheritance/inheritance.c)** - _simulates the inheritance of blood types for each member of a family._ 106 | 107 | - **[PS-5 Speller](Week%205%20-%20Data%20Structures/ProblemSet5/Speller/speller.c)** - _program that spell-checks a file using a hash table._ 108 | 109 | --- 110 | 111 | ### :arrow_forward: **Week 6 - Python** 112 | 113 |
114 | 115 | ![Python](https://img.shields.io/badge/python-3670A0?style=for-the-badge&logo=python&logoColor=ffdd54) 116 | 117 | - **[L-6 World Cup](Week%206%20-%20Python/Lab6/WorldCup/tournament.py)** - _program to run simulations of the FIFA World Cup._ 118 | 119 | - **[PS-6 Mario Less](Week%206%20-%20Python/ProblemSet6/SentimentalMarioLess/mario.py)** - _create a right-aligned pyramid of blocks._ 120 | 121 | - **[PS-6 Mario More](Week%206%20-%20Python/ProblemSet6/SentimentalMarioMore/mario.py)** - _create an adjacent pyramid of blocks._ 122 | 123 | - **[PS-6 Cash](Week%206%20-%20Python/ProblemSet6/SentimentalCash/cash.py)** - _minimize the number of coins given to a customer when making a change using greedy algorithms._ 124 | 125 | - **[PS-6 Credit](Week%206%20-%20Python/ProblemSet6/SentimentalCredit/credit.py)** - _program that determines whether a provided credit card number is valid according to Luhn's algorithm._ 126 | 127 | - **[PS-6 Readability](Week%206%20-%20Python/ProblemSet6/SentimentalReadability/readability.py)** - _computes the approximate grade level needed to comprehend some text._ 128 | 129 | - **[PS-6 DNA](Week%206%20-%20Python/ProblemSet6/DNA/dna.py)** - _program that identifies a person based on their DNA._ 130 | 131 | --- 132 | 133 | ### :arrow_forward: **Week 7 - SQL** 134 | 135 |
136 | 137 | ![SQLite](https://img.shields.io/badge/sqlite-%2307405e.svg?style=for-the-badge&logo=sqlite&logoColor=white) 138 | 139 | - **[L-7 Songs](Week%207%20-%20SQL/Lab7/Songs/)** - _SQL queries that answer questions about a database of songs._ 140 | 141 | - **[PS-7 Movies](Week%207%20-%20SQL/ProblemSet7/Movies/)** - _SQL queries that answer questions about a database of movies._ 142 | 143 | - **[PS-8 Fiftyville](Week%207%20-%20SQL/ProblemSet7/Fiftyville/log.sql)** - _write SQL queries to solve a mystery._ 144 | 145 | --- 146 | 147 | ### :arrow_forward: **Week 8 - HTML, CSS, JavaScript** 148 | 149 |
150 | 151 | ![HTML5](https://img.shields.io/badge/html5-%23E34F26.svg?style=for-the-badge&logo=html5&logoColor=white) ![CSS3](https://img.shields.io/badge/css3-%231572B6.svg?style=for-the-badge&logo=css3&logoColor=white) ![JavaScript](https://img.shields.io/badge/javascript-%23323330.svg?style=for-the-badge&logo=javascript&logoColor=%23F7DF1E) ![Bootstrap](https://img.shields.io/badge/bootstrap-%23563D7C.svg?style=for-the-badge&logo=bootstrap&logoColor=white) 152 | 153 | - **[L-8 Trivia](Week%208%20-%20HTML,%20CSS,%20JavaScript/Lab8/Trivia/index.html)** - _simple webpage that lets users answer trivia questions._ 154 | 155 | - **[PS-8 Homepage](Week%208%20-%20HTML,%20CSS,%20JavaScript/ProblemSet8/Homepage/index.html)** - _simple web application with multiple pages._ 156 | 157 | --- 158 | 159 | ### :arrow_forward: **Week 9 - Flask** 160 | 161 |
162 | 163 | ![Python](https://img.shields.io/badge/python-3670A0?style=for-the-badge&logo=python&logoColor=ffdd54) ![Flask](https://img.shields.io/badge/flask-%23000.svg?style=for-the-badge&logo=flask&logoColor=white) ![SQLite](https://img.shields.io/badge/sqlite-%2307405e.svg?style=for-the-badge&logo=sqlite&logoColor=white) ![HTML5](https://img.shields.io/badge/html5-%23E34F26.svg?style=for-the-badge&logo=html5&logoColor=white) ![CSS3](https://img.shields.io/badge/css3-%231572B6.svg?style=for-the-badge&logo=css3&logoColor=white) ![JavaScript](https://img.shields.io/badge/javascript-%23323330.svg?style=for-the-badge&logo=javascript&logoColor=%23F7DF1E) ![Bootstrap](https://img.shields.io/badge/bootstrap-%23563D7C.svg?style=for-the-badge&logo=bootstrap&logoColor=white) 164 | 165 | - **[L-9 Birthdays](Week%209%20-%20Flask/Lab9/Birthdays/app.py)** - _web application that keeps track of birthdays._ 166 | 167 | - **[PS-9 Finance](Week%209%20-%20Flask/ProblemSet9/Finance/app.py)** - _website via which users can 'buy' and 'sell' stocks._ 168 | 169 | --- 170 | 171 | ### :arrow_forward: **Final Project** 172 | 173 |
174 | 175 | - **[Portfolio Website](https://github.com/BogdanOtava/Portfolio-Website)** - _full-stack portfolio website_. 176 | 177 | --- 178 | 179 | ### :arrow_forward: **Scratch** 180 | 181 |
182 | 183 | - **[Whack-a-Mouse](https://scratch.mit.edu/projects/819729030)** - _a simple Scratch game which is a combination of Space Invaders and Whack-a-Mole._ 184 | 185 | --- 186 | 187 |
188 | 189 | ## :books: **Credits** 190 | 191 | First of all, a huge thank you to Prof. David J. Malan and the rest of the CS50 staff for giving us this free learning opportunity. I thoroughly recommend the CS50 course for anyone who wants to get into or improve their skills in the Computer Science field. 192 | 193 |
194 | 195 | If you'd like to know more about CS50, I'll leave a few link down below. 196 | 197 | - **[Official Website](https://cs50.harvard.edu/x/2023/)** 198 | - **[CS50 Introduction on YouTube](https://www.youtube.com/watch?v=3oFAJtFE8YU)** 199 | - **[CS50 on edX](https://www.edx.org/course/introduction-computer-science-harvardx-cs50x)** 200 | - **[CS50 on Wikipedia](https://en.wikipedia.org/wiki/CS50)** 201 | -------------------------------------------------------------------------------- /Week 1 - C/Lab1/Population/population.c: -------------------------------------------------------------------------------- 1 | /* 2 | https://cs50.harvard.edu/x/2023/labs/1/ 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | int main(void) 9 | { 10 | // Prompt for start size 11 | int start; 12 | int end; 13 | int years; 14 | 15 | do 16 | { 17 | start = get_int("Start size: "); 18 | } 19 | while (start < 9); 20 | 21 | // Prompt for end size 22 | do 23 | { 24 | end = get_int("End size: "); 25 | } 26 | while (end < start); 27 | 28 | // Calculate number of years until we reach threshold 29 | for (years = 0; start < end; years++) 30 | { 31 | start = start + (start / 3) - (start / 4); 32 | } 33 | 34 | // Print number of years 35 | printf("Years: %i\n", years); 36 | } 37 | -------------------------------------------------------------------------------- /Week 1 - C/ProblemSet1/Cash/cash.c: -------------------------------------------------------------------------------- 1 | /* 2 | https://cs50.harvard.edu/x/2022/psets/1/cash/ 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | int get_cents(void); 9 | int calculate_quarters(int cents); 10 | int calculate_dimes(int cents); 11 | int calculate_nickels(int cents); 12 | int calculate_pennies(int cents); 13 | 14 | int main(void) 15 | { 16 | // Ask how many cents the customer is owed 17 | int cents = get_cents(); 18 | 19 | // Calculate the number of quarters to give the customer 20 | int quarters = calculate_quarters(cents); 21 | cents = cents - quarters * 25; 22 | 23 | // Calculate the number of dimes to give the customer 24 | int dimes = calculate_dimes(cents); 25 | cents = cents - dimes * 10; 26 | 27 | // Calculate the number of nickels to give the customer 28 | int nickels = calculate_nickels(cents); 29 | cents = cents - nickels * 5; 30 | 31 | // Calculate the number of pennies to give the customer 32 | int pennies = calculate_pennies(cents); 33 | cents = cents - pennies * 1; 34 | 35 | // Sum coins 36 | int coins = quarters + dimes + nickels + pennies; 37 | 38 | // Print total number of coins to give the customer 39 | printf("%i\n", coins); 40 | } 41 | 42 | int get_cents(void) 43 | { 44 | int cents; 45 | 46 | // Prompt user for a number of cents 47 | do 48 | { 49 | cents = get_int("Cents: "); 50 | } while (cents < 0); 51 | 52 | return cents; 53 | } 54 | 55 | int calculate_quarters(int cents) 56 | { 57 | // Get number of quarters 58 | int quarters = cents / 25; 59 | 60 | return quarters; 61 | } 62 | 63 | int calculate_dimes(int cents) 64 | { 65 | // Get number of dimes 66 | int dimes = cents / 10; 67 | 68 | return dimes; 69 | } 70 | 71 | int calculate_nickels(int cents) 72 | { 73 | // Get number of nickels 74 | int nickels = cents / 5; 75 | 76 | return nickels; 77 | } 78 | 79 | int calculate_pennies(int cents) 80 | { 81 | // Get number of pennies 82 | int pennies = cents / 1; 83 | 84 | return pennies; 85 | } 86 | -------------------------------------------------------------------------------- /Week 1 - C/ProblemSet1/MarioLess/mario.c: -------------------------------------------------------------------------------- 1 | /* 2 | https://cs50.harvard.edu/x/2022/psets/1/mario/less/ 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | int main(void) 9 | { 10 | // Declare height variable 11 | int height; 12 | 13 | // Get user input 14 | do 15 | { 16 | height = get_int("Height: "); 17 | } 18 | while (height < 1 || height > 8); 19 | 20 | // Outer loop / Switch to next line of the pyramid after printing the spaces and blocks: 21 | for (int line = 0; line < height; line++) 22 | { 23 | // Print the spaces 24 | for (int space = height - 1; space > line; space--) 25 | { 26 | printf(" "); 27 | } 28 | 29 | // Print the blocks 30 | for (int block = 0; block <= line; block++) 31 | { 32 | printf("#"); 33 | } 34 | 35 | // Go to the next line 36 | printf("\n"); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Week 1 - C/ProblemSet1/MarioMore/mario.c: -------------------------------------------------------------------------------- 1 | /* 2 | https://cs50.harvard.edu/x/2023/psets/1/mario/more/ 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | int main(void) 9 | { 10 | // Declare height variable 11 | int height; 12 | 13 | // Get user input 14 | do 15 | { 16 | height = get_int("Height: "); 17 | } 18 | while (height < 1 || height > 8); 19 | 20 | // Outer loop / Switch to the next line of the pyramid after printing the spaces and blocks 21 | for (int line = 0; line < height; line++) 22 | { 23 | // Print the spaces 24 | for (int space = height - 1; space > line; space--) 25 | { 26 | printf(" "); 27 | } 28 | 29 | // Print the left blocks 30 | for (int left_blocks = 0; left_blocks <= line; left_blocks++) 31 | { 32 | printf("#"); 33 | } 34 | 35 | // Print the two spaces between the blocks 36 | printf(" "); 37 | 38 | // Print the right blocks 39 | for (int right_blocks = 0; right_blocks <= line; right_blocks++) 40 | { 41 | printf("#"); 42 | } 43 | 44 | // Go to the next line 45 | printf("\n"); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Week 2 - Arrays/Lab2/Scrabble/scrabble.c: -------------------------------------------------------------------------------- 1 | /* 2 | https://cs50.harvard.edu/x/2022/labs/2/ 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | // Points assigned to each letter of the alphabet 11 | 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}; 12 | 13 | int compute_score(string word); 14 | 15 | int main(void) 16 | { 17 | // Get input words from both players 18 | string word1 = get_string("Player 1: "); 19 | string word2 = get_string("Player 2: "); 20 | 21 | // Score both words 22 | int score1 = compute_score(word1); 23 | int score2 = compute_score(word2); 24 | 25 | // Print the winner 26 | if (score1 > score2) 27 | { 28 | printf("Player 1 wins!\n"); 29 | } 30 | else if (score1 < score2) 31 | { 32 | printf("Player 2 wins!\n"); 33 | } 34 | else 35 | { 36 | printf("Tie!"); 37 | } 38 | } 39 | 40 | int compute_score(string word) 41 | { 42 | // Score 43 | int score = 0; 44 | 45 | // Compute and return score for string 46 | for (int i = 0, len = strlen(word); i < len; i++) 47 | { 48 | if (isupper(word[i])) 49 | { 50 | score += POINTS[word[i] - 'A']; 51 | } 52 | 53 | else if (islower(word[i])) 54 | { 55 | score += POINTS[word[i] - 'a']; 56 | } 57 | } 58 | 59 | return score; 60 | } 61 | -------------------------------------------------------------------------------- /Week 2 - Arrays/ProblemSet2/Caesar/caesar.c: -------------------------------------------------------------------------------- 1 | /* 2 | https://cs50.harvard.edu/x/2022/psets/2/caesar/ 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | bool only_digits(string arg); 12 | char rotate(char chr, int key); 13 | 14 | int main(int argc, string argv[]) 15 | { 16 | // Check for the argument count to be exactly 2 17 | if (!(argc == 2)) 18 | { 19 | printf("Usage: ./caesar key\n"); 20 | return 1; 21 | } 22 | 23 | // Check for the second argument to be a digit 24 | if (!(only_digits(argv[1]))) 25 | { 26 | printf("Usage: ./caesar key\n"); 27 | return 1; 28 | } 29 | 30 | // Get user input 31 | string plaintext = get_string("plaintext: "); 32 | 33 | // Print output 34 | printf("ciphertext: "); 35 | for (int i = 0, len = strlen(plaintext); i < len; i++) 36 | { 37 | printf("%c", rotate(plaintext[i], atoi(argv[1]))); 38 | } 39 | printf("\n"); 40 | } 41 | 42 | // Checks that the argument is only digits from 0 to 9 43 | bool only_digits(string arg) 44 | { 45 | if (isdigit(arg[0])) 46 | { 47 | return true; 48 | } 49 | else 50 | { 51 | return false; 52 | } 53 | } 54 | 55 | // Shifts 'char' by the 'key' value 56 | char rotate(char chr, int key) 57 | { 58 | // if 'char' is a letter, shift it by 'key' value 59 | if (isalpha(chr)) 60 | { 61 | if (isupper(chr)) 62 | { 63 | return (chr - 'A' + key) % 26 + 'A'; 64 | } 65 | if (islower(chr)) 66 | { 67 | return (chr - 'a' + key) % 26 + 'a'; 68 | } 69 | 70 | return 0; 71 | } 72 | // if 'char' is anything else, return 'char' as is 73 | else 74 | { 75 | return chr; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /Week 2 - Arrays/ProblemSet2/Readability/readability.c: -------------------------------------------------------------------------------- 1 | /* 2 | https://cs50.harvard.edu/x/2022/psets/2/readability/ 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | int count_letters(string text); 12 | int count_words(string text); 13 | int count_sentences(string text); 14 | 15 | int main(void) 16 | { 17 | // Get user input 18 | string text = get_string("Text: "); 19 | 20 | // Variables for letters, words, sentences 21 | int letters = count_letters(text); 22 | int words = count_words(text); 23 | int sentences = count_sentences(text); 24 | 25 | // Calculate average number of letters & average number of sentences 26 | float avgLetters = (100 / (float)words) * (float)letters; 27 | float avgSentences = (100 / (float)words) * (float)sentences; 28 | 29 | // Calculate Coleman-Liau index 30 | int index = round(0.0588 * avgLetters - 0.296 * avgSentences - 15.8); 31 | 32 | // Print out index based on result 33 | if (index < 1) 34 | { 35 | printf("Before Grade 1\n"); 36 | } 37 | else if (index >= 16) 38 | { 39 | printf("Grade 16+\n"); 40 | } 41 | else 42 | { 43 | printf("Grade %i\n", index); 44 | } 45 | } 46 | 47 | // Determine the number of letters in a string 48 | int count_letters(string text) 49 | { 50 | int letters = 0; 51 | 52 | for (int i = 0, len = strlen(text); i < len; i++) 53 | { 54 | if (isalpha(text[i])) 55 | { 56 | letters++; 57 | } 58 | } 59 | 60 | return letters; 61 | } 62 | 63 | // Determine the number of words in a string 64 | int count_words(string text) 65 | { 66 | int words = 1; 67 | 68 | for (int i = 0; text[i] != '\0'; i++) 69 | { 70 | if (text[i] == ' ') 71 | { 72 | words++; 73 | } 74 | } 75 | 76 | return words; 77 | } 78 | 79 | // Determine the number of sentences in a string 80 | int count_sentences(string text) 81 | { 82 | int sentences = 0; 83 | 84 | for (int i = 0; text[i] != '\0'; i++) 85 | { 86 | if (text[i] == '.' || text[i] == '!' || text[i] == '?') 87 | { 88 | sentences++; 89 | } 90 | } 91 | 92 | return sentences; 93 | } 94 | -------------------------------------------------------------------------------- /Week 3 - Algorithms/Lab3/Sort/answers.txt: -------------------------------------------------------------------------------- 1 | https://cs50.harvard.edu/x/2022/labs/3/#walkthrough 2 | 3 | sort1 uses: Bubble Sort 4 | 5 | How do you know?: Has a fast runtime for the sorted datasets, but it performes poorer on bigger datasets of reversed and random numbers. 6 | 7 | sort2 uses: Merge Sort 8 | 9 | How do you know?: It's efficient in all the datasets. 10 | 11 | sort3 uses: Selection Sort 12 | 13 | How do you know?: It performs poorly on all three .txt files which contains larger datasets(50000) and it's faster while going through the smaller datasets(5000). 14 | -------------------------------------------------------------------------------- /Week 3 - Algorithms/ProblemSet3/Plurality/plurality.c: -------------------------------------------------------------------------------- 1 | /* 2 | https://cs50.harvard.edu/x/2022/psets/3/plurality/ 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | // Max number of candidates 10 | #define MAX 9 11 | 12 | // Candidates have name and vote count 13 | typedef struct 14 | { 15 | string name; 16 | int votes; 17 | } candidate; 18 | 19 | // Array of candidates 20 | candidate candidates[MAX]; 21 | 22 | // Number of candidates 23 | int candidate_count; 24 | 25 | // Function prototypes 26 | bool vote(string name); 27 | void print_winner(void); 28 | 29 | int main(int argc, string argv[]) 30 | { 31 | // Check for invalid usage 32 | if (argc < 2) 33 | { 34 | printf("Usage: plurality [candidate ...]\n"); 35 | return 1; 36 | } 37 | 38 | // Populate array of candidates 39 | candidate_count = argc - 1; 40 | if (candidate_count > MAX) 41 | { 42 | printf("Maximum number of candidates is %i\n", MAX); 43 | return 2; 44 | } 45 | for (int i = 0; i < candidate_count; i++) 46 | { 47 | candidates[i].name = argv[i + 1]; 48 | candidates[i].votes = 0; 49 | } 50 | 51 | int voter_count = get_int("Number of voters: "); 52 | 53 | // Loop over all voters 54 | for (int i = 0; i < voter_count; i++) 55 | { 56 | string name = get_string("Vote: "); 57 | 58 | // Check for invalid vote 59 | if (!vote(name)) 60 | { 61 | printf("Invalid vote.\n"); 62 | } 63 | } 64 | 65 | // Display winner of election 66 | print_winner(); 67 | } 68 | 69 | // Update vote totals given a new vote 70 | bool vote(string name) 71 | { 72 | for (int i = 0; i < candidate_count; i++) 73 | { 74 | if (strcmp(name, candidates[i].name) == 0) 75 | { 76 | candidates[i].votes++; 77 | return true; 78 | } 79 | } 80 | 81 | return false; 82 | } 83 | 84 | // Print the winner (or winners) of the election 85 | void print_winner(void) 86 | { 87 | int totalVotes = 0; 88 | 89 | // Check to see who has the highest number of votes 90 | for (int i = 0; i < candidate_count; i++) 91 | { 92 | if (candidates[i].votes > totalVotes) 93 | { 94 | totalVotes = candidates[i].votes; 95 | } 96 | } 97 | 98 | // Prints the names of who has the highest number of votes 99 | for (int i = 0; i < candidate_count; i++) 100 | { 101 | if (candidates[i].votes == totalVotes) 102 | { 103 | printf("%s\n", candidates[i].name); 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /Week 3 - Algorithms/ProblemSet3/Runoff/runoff.c: -------------------------------------------------------------------------------- 1 | /* 2 | https://cs50.harvard.edu/x/2022/psets/3/runoff/ 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | // Max voters and candidates 10 | #define MAX_VOTERS 100 11 | #define MAX_CANDIDATES 9 12 | 13 | // preferences[i][j] is jth preference for voter i 14 | int preferences[MAX_VOTERS][MAX_CANDIDATES]; 15 | 16 | // Candidates have name, vote count, eliminated status 17 | typedef struct 18 | { 19 | string name; 20 | int votes; 21 | bool eliminated; 22 | } 23 | candidate; 24 | 25 | // Array of candidates 26 | candidate candidates[MAX_CANDIDATES]; 27 | 28 | // Numbers of voters and candidates 29 | int voter_count; 30 | int candidate_count; 31 | 32 | // Function prototypes 33 | bool vote(int voter, int rank, string name); 34 | void tabulate(void); 35 | bool print_winner(void); 36 | int find_min(void); 37 | bool is_tie(int min); 38 | void eliminate(int min); 39 | 40 | int main(int argc, string argv[]) 41 | { 42 | // Check for invalid usage 43 | if (argc < 2) 44 | { 45 | printf("Usage: runoff [candidate ...]\n"); 46 | return 1; 47 | } 48 | 49 | // Populate array of candidates 50 | candidate_count = argc - 1; 51 | if (candidate_count > MAX_CANDIDATES) 52 | { 53 | printf("Maximum number of candidates is %i\n", MAX_CANDIDATES); 54 | return 2; 55 | } 56 | for (int i = 0; i < candidate_count; i++) 57 | { 58 | candidates[i].name = argv[i + 1]; 59 | candidates[i].votes = 0; 60 | candidates[i].eliminated = false; 61 | } 62 | 63 | voter_count = get_int("Number of voters: "); 64 | if (voter_count > MAX_VOTERS) 65 | { 66 | printf("Maximum number of voters is %i\n", MAX_VOTERS); 67 | return 3; 68 | } 69 | 70 | // Keep querying for votes 71 | for (int i = 0; i < voter_count; i++) 72 | { 73 | 74 | // Query for each rank 75 | for (int j = 0; j < candidate_count; j++) 76 | { 77 | string name = get_string("Rank %i: ", j + 1); 78 | 79 | // Record vote, unless it's invalid 80 | if (!vote(i, j, name)) 81 | { 82 | printf("Invalid vote.\n"); 83 | return 4; 84 | } 85 | } 86 | 87 | printf("\n"); 88 | } 89 | 90 | // Keep holding runoffs until winner exists 91 | while (true) 92 | { 93 | // Calculate votes given remaining candidates 94 | tabulate(); 95 | 96 | // Check if election has been won 97 | bool won = print_winner(); 98 | if (won) 99 | { 100 | break; 101 | } 102 | 103 | // Eliminate last-place candidates 104 | int min = find_min(); 105 | bool tie = is_tie(min); 106 | 107 | // If tie, everyone wins 108 | if (tie) 109 | { 110 | for (int i = 0; i < candidate_count; i++) 111 | { 112 | if (!candidates[i].eliminated) 113 | { 114 | printf("%s\n", candidates[i].name); 115 | } 116 | } 117 | break; 118 | } 119 | 120 | // Eliminate anyone with minimum number of votes 121 | eliminate(min); 122 | 123 | // Reset vote counts back to zero 124 | for (int i = 0; i < candidate_count; i++) 125 | { 126 | candidates[i].votes = 0; 127 | } 128 | } 129 | return 0; 130 | } 131 | 132 | // Record preference if vote is valid 133 | bool vote(int voter, int rank, string name) 134 | { 135 | // Loop over candidates 136 | for (int i = 0; i < candidate_count; i++) 137 | { 138 | // Check whether the name is a valid candidate and update the preferences based on voter rank 139 | if (strcmp(candidates[i].name, name) == 0) 140 | { 141 | preferences[voter][rank] = i; 142 | return true; 143 | } 144 | } 145 | 146 | return false; 147 | } 148 | 149 | // Tabulate votes for non-eliminated candidates 150 | void tabulate(void) 151 | { 152 | // Loop over voters 153 | for (int i = 0; i < voter_count; i++) 154 | { 155 | // Loop over candidates 156 | for (int j = 0; j < candidate_count; j++) 157 | { 158 | // Check if candidate is not eliminated and update their votes based on voter preference 159 | if (!candidates[j].eliminated) 160 | { 161 | candidates[preferences[i][j]].votes++; 162 | break; 163 | } 164 | } 165 | } 166 | } 167 | 168 | // Print the winner of the election, if there is one 169 | bool print_winner(void) 170 | { 171 | // Majority of the votes 172 | int majority = voter_count / 2; 173 | 174 | // Loop over candidates 175 | for (int i = 0; i < candidate_count; i++) 176 | { 177 | // Check who has the highest number of votes and print out their name 178 | if (candidates[i].votes > majority) 179 | { 180 | printf("%s\n", candidates[i].name); 181 | return true; 182 | } 183 | } 184 | // Return 'false' is there isn't a winner yet 185 | return false; 186 | } 187 | 188 | // Return the minimum number of votes any remaining candidate has 189 | int find_min(void) 190 | { 191 | // Keep track of lowest number of votes 192 | int lowest_votes = candidates[0].votes; 193 | 194 | // Loop over candidates 195 | for (int i = 0; i < candidate_count; i++) 196 | { 197 | // Check if the candidate is not eliminated and if he has the lowest number of votes 198 | if (!candidates[i].eliminated && candidates[i].votes < lowest_votes) 199 | { 200 | // If the condition is true, update lowest_votes to that candidate votes 201 | lowest_votes = candidates[i].votes; 202 | } 203 | } 204 | return lowest_votes; 205 | } 206 | 207 | // Return true if the election is tied between all candidates, false otherwise 208 | bool is_tie(int min) 209 | { 210 | // Loop over candidates 211 | for (int i = 0; i < candidate_count; i++) 212 | { 213 | // Check if the candidate is not eliminated and if their numbers of votes is not equal to min 214 | if (!candidates[i].eliminated && candidates[i].votes != min) 215 | { 216 | return false; 217 | } 218 | } 219 | return true; 220 | } 221 | 222 | // Eliminate the candidate (or candidates) in last place 223 | void eliminate(int min) 224 | { 225 | // Loop over candidates 226 | for (int i = 0; i < candidate_count; i++) 227 | { 228 | // Check if candidate has the lowest number of votes and eliminate that candidate 229 | if (candidates[i].votes == min) 230 | { 231 | candidates[i].eliminated = true; 232 | } 233 | } 234 | } 235 | -------------------------------------------------------------------------------- /Week 4 - Memory/Lab4/Volume/volume.c: -------------------------------------------------------------------------------- 1 | /* 2 | https://cs50.harvard.edu/x/2022/labs/4/ 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | // Number of bytes in .wav header 10 | const int HEADER_SIZE = 44; 11 | 12 | int main(int argc, char *argv[]) 13 | { 14 | // Check command-line arguments 15 | if (argc != 4) 16 | { 17 | printf("Usage: ./volume input.wav output.wav factor\n"); 18 | return 1; 19 | } 20 | 21 | // Open files and determine scaling factor 22 | FILE *input = fopen(argv[1], "r"); 23 | if (input == NULL) 24 | { 25 | printf("Could not open file.\n"); 26 | return 1; 27 | } 28 | 29 | FILE *output = fopen(argv[2], "w"); 30 | if (output == NULL) 31 | { 32 | printf("Could not open file.\n"); 33 | return 1; 34 | } 35 | 36 | float factor = atof(argv[3]); 37 | 38 | // Copy header from input file to output file 39 | uint8_t header[HEADER_SIZE]; 40 | 41 | fread(header, HEADER_SIZE, 1, input); 42 | fwrite(header, HEADER_SIZE, 1, output); 43 | 44 | // Read samples from input file and write updated data to output file 45 | int16_t buffer; 46 | 47 | while (fread(&buffer, sizeof(int16_t), 1, input)) 48 | { 49 | // Update volume 50 | buffer *= factor; 51 | fwrite(&buffer, sizeof(int16_t), 1, output); 52 | } 53 | 54 | // Close files 55 | fclose(input); 56 | fclose(output); 57 | } 58 | -------------------------------------------------------------------------------- /Week 4 - Memory/ProblemSet4/FilterLess/Makefile: -------------------------------------------------------------------------------- 1 | filter: 2 | clang -ggdb3 -gdwarf-4 -O0 -Qunused-arguments -std=c11 -Wall -Werror -Wextra -Wno-gnu-folding-constant -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow -lm -o filter filter.c helpers.c 3 | -------------------------------------------------------------------------------- /Week 4 - Memory/ProblemSet4/FilterLess/bmp.h: -------------------------------------------------------------------------------- 1 | // BMP-related data types based on Microsoft's own 2 | 3 | #include 4 | 5 | // These data types are essentially aliases for C/C++ primitive data types. 6 | // Adapted from http://msdn.microsoft.com/en-us/library/cc230309.aspx. 7 | // See https://en.wikipedia.org/wiki/C_data_types#stdint.h for more on stdint.h. 8 | 9 | typedef uint8_t BYTE; 10 | typedef uint32_t DWORD; 11 | typedef int32_t LONG; 12 | typedef uint16_t WORD; 13 | 14 | // The BITMAPFILEHEADER structure contains information about the type, size, 15 | // and layout of a file that contains a DIB [device-independent bitmap]. 16 | // Adapted from http://msdn.microsoft.com/en-us/library/dd183374(VS.85).aspx. 17 | 18 | typedef struct 19 | { 20 | WORD bfType; 21 | DWORD bfSize; 22 | WORD bfReserved1; 23 | WORD bfReserved2; 24 | DWORD bfOffBits; 25 | } __attribute__((__packed__)) 26 | BITMAPFILEHEADER; 27 | 28 | // The BITMAPINFOHEADER structure contains information about the 29 | // dimensions and color format of a DIB [device-independent bitmap]. 30 | // Adapted from http://msdn.microsoft.com/en-us/library/dd183376(VS.85).aspx. 31 | 32 | typedef struct 33 | { 34 | DWORD biSize; 35 | LONG biWidth; 36 | LONG biHeight; 37 | WORD biPlanes; 38 | WORD biBitCount; 39 | DWORD biCompression; 40 | DWORD biSizeImage; 41 | LONG biXPelsPerMeter; 42 | LONG biYPelsPerMeter; 43 | DWORD biClrUsed; 44 | DWORD biClrImportant; 45 | } __attribute__((__packed__)) 46 | BITMAPINFOHEADER; 47 | 48 | // The RGBTRIPLE structure describes a color consisting of relative intensities of 49 | // red, green, and blue. Adapted from http://msdn.microsoft.com/en-us/library/aa922590.aspx. 50 | 51 | typedef struct 52 | { 53 | BYTE rgbtBlue; 54 | BYTE rgbtGreen; 55 | BYTE rgbtRed; 56 | } __attribute__((__packed__)) 57 | RGBTRIPLE; 58 | -------------------------------------------------------------------------------- /Week 4 - Memory/ProblemSet4/FilterLess/filter.c: -------------------------------------------------------------------------------- 1 | /* 2 | https://cs50.harvard.edu/x/2022/psets/4/filter/less/ 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "helpers.h" 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | // Define allowable filters 14 | char *filters = "bgrs"; 15 | 16 | // Get filter flag and check validity 17 | char filter = getopt(argc, argv, filters); 18 | if (filter == '?') 19 | { 20 | printf("Invalid filter.\n"); 21 | return 1; 22 | } 23 | 24 | // Ensure only one filter 25 | if (getopt(argc, argv, filters) != -1) 26 | { 27 | printf("Only one filter allowed.\n"); 28 | return 2; 29 | } 30 | 31 | // Ensure proper usage 32 | if (argc != optind + 2) 33 | { 34 | printf("Usage: ./filter [flag] infile outfile\n"); 35 | return 3; 36 | } 37 | 38 | // Remember filenames 39 | char *infile = argv[optind]; 40 | char *outfile = argv[optind + 1]; 41 | 42 | // Open input file 43 | FILE *inptr = fopen(infile, "r"); 44 | if (inptr == NULL) 45 | { 46 | printf("Could not open %s.\n", infile); 47 | return 4; 48 | } 49 | 50 | // Open output file 51 | FILE *outptr = fopen(outfile, "w"); 52 | if (outptr == NULL) 53 | { 54 | fclose(inptr); 55 | printf("Could not create %s.\n", outfile); 56 | return 5; 57 | } 58 | 59 | // Read infile's BITMAPFILEHEADER 60 | BITMAPFILEHEADER bf; 61 | fread(&bf, sizeof(BITMAPFILEHEADER), 1, inptr); 62 | 63 | // Read infile's BITMAPINFOHEADER 64 | BITMAPINFOHEADER bi; 65 | fread(&bi, sizeof(BITMAPINFOHEADER), 1, inptr); 66 | 67 | // Ensure infile is (likely) a 24-bit uncompressed BMP 4.0 68 | if (bf.bfType != 0x4d42 || bf.bfOffBits != 54 || bi.biSize != 40 || 69 | bi.biBitCount != 24 || bi.biCompression != 0) 70 | { 71 | fclose(outptr); 72 | fclose(inptr); 73 | printf("Unsupported file format.\n"); 74 | return 6; 75 | } 76 | 77 | // Get image's dimensions 78 | int height = abs(bi.biHeight); 79 | int width = bi.biWidth; 80 | 81 | // Allocate memory for image 82 | RGBTRIPLE(*image)[width] = calloc(height, width * sizeof(RGBTRIPLE)); 83 | if (image == NULL) 84 | { 85 | printf("Not enough memory to store image.\n"); 86 | fclose(outptr); 87 | fclose(inptr); 88 | return 7; 89 | } 90 | 91 | // Determine padding for scanlines 92 | int padding = (4 - (width * sizeof(RGBTRIPLE)) % 4) % 4; 93 | 94 | // Iterate over infile's scanlines 95 | for (int i = 0; i < height; i++) 96 | { 97 | // Read row into pixel array 98 | fread(image[i], sizeof(RGBTRIPLE), width, inptr); 99 | 100 | // Skip over padding 101 | fseek(inptr, padding, SEEK_CUR); 102 | } 103 | 104 | // Filter image 105 | switch (filter) 106 | { 107 | // Blur 108 | case 'b': 109 | blur(height, width, image); 110 | break; 111 | 112 | // Grayscale 113 | case 'g': 114 | grayscale(height, width, image); 115 | break; 116 | 117 | // Reflection 118 | case 'r': 119 | reflect(height, width, image); 120 | break; 121 | 122 | // Sepia 123 | case 's': 124 | sepia(height, width, image); 125 | break; 126 | } 127 | 128 | // Write outfile's BITMAPFILEHEADER 129 | fwrite(&bf, sizeof(BITMAPFILEHEADER), 1, outptr); 130 | 131 | // Write outfile's BITMAPINFOHEADER 132 | fwrite(&bi, sizeof(BITMAPINFOHEADER), 1, outptr); 133 | 134 | // Write new pixels to outfile 135 | for (int i = 0; i < height; i++) 136 | { 137 | // Write row to outfile 138 | fwrite(image[i], sizeof(RGBTRIPLE), width, outptr); 139 | 140 | // Write padding at end of row 141 | for (int k = 0; k < padding; k++) 142 | { 143 | fputc(0x00, outptr); 144 | } 145 | } 146 | 147 | // Free memory for image 148 | free(image); 149 | 150 | // Close files 151 | fclose(inptr); 152 | fclose(outptr); 153 | return 0; 154 | } 155 | -------------------------------------------------------------------------------- /Week 4 - Memory/ProblemSet4/FilterLess/helpers.c: -------------------------------------------------------------------------------- 1 | #include "helpers.h" 2 | #include 3 | 4 | // Convert image to grayscale 5 | void grayscale(int height, int width, RGBTRIPLE image[height][width]) 6 | { 7 | // Loop through rows 8 | for (int row = 0; row < height; row++) 9 | { 10 | // Loop through columns 11 | for (int column = 0; column < width; column++) 12 | { 13 | // Round out the values of each pixel 14 | int avgGray = round((image[row][column].rgbtBlue + image[row][column].rgbtGreen + image[row][column].rgbtRed) / 3.0); 15 | 16 | // Change pixel color to new color 17 | image[row][column].rgbtRed = avgGray; 18 | image[row][column].rgbtGreen = avgGray; 19 | image[row][column].rgbtBlue = avgGray; 20 | } 21 | } 22 | } 23 | 24 | // Convert image to sepia 25 | void sepia(int height, int width, RGBTRIPLE image[height][width]) 26 | { 27 | // Loop through rows 28 | for (int row = 0; row < height; row++) 29 | { 30 | // Loop through columns 31 | for (int column = 0; column < width; column++) 32 | { 33 | // Make the sepia color for each pixel 34 | int sepiaRed = round(.393 * image[row][column].rgbtRed + .769 * image[row][column].rgbtGreen + .189 * image[row][column].rgbtBlue); 35 | int sepiaGreen = round(.349 * image[row][column].rgbtRed + .686 * image[row][column].rgbtGreen + .168 * image[row][column].rgbtBlue); 36 | int sepiaBlue = round(.272 * image[row][column].rgbtRed + .534 * image[row][column].rgbtGreen + .131 * image[row][column].rgbtBlue); 37 | 38 | // Change value to 255 if bigger than that 39 | if (sepiaRed > 255) 40 | { 41 | sepiaRed = 255; 42 | } 43 | if (sepiaGreen > 255) 44 | { 45 | sepiaGreen = 255; 46 | } 47 | if (sepiaBlue > 255) 48 | { 49 | sepiaBlue = 255; 50 | } 51 | 52 | // Change pixel color to sepia color 53 | image[row][column].rgbtRed = sepiaRed; 54 | image[row][column].rgbtGreen = sepiaGreen; 55 | image[row][column].rgbtBlue = sepiaBlue; 56 | } 57 | } 58 | } 59 | 60 | // Reflect image horizontally 61 | void reflect(int height, int width, RGBTRIPLE image[height][width]) 62 | { 63 | // Loop through rows 64 | for (int row = 0; row < height; row++) 65 | { 66 | // Loop through the first half of columns in each row 67 | for (int column = 0; column < width / 2; column++) 68 | { 69 | // Store the left column in a temporary variable; 70 | RGBTRIPLE temp = image[row][column]; 71 | // Move the right column in the left spot 72 | image[row][column] = image[row][width - column - 1]; 73 | // Move the left column in the right spot 74 | image[row][width - column - 1] = temp; 75 | } 76 | } 77 | } 78 | 79 | // Blur image 80 | void blur(int height, int width, RGBTRIPLE image[height][width]) 81 | { 82 | // Declare image variable 83 | RGBTRIPLE temp[height][width]; 84 | 85 | // Loop through rows 86 | for (int row = 0; row < height; row++) 87 | { 88 | // Loop through columns 89 | for (int column = 0; column < width; column++) 90 | { 91 | // Duplicate the original image 92 | temp[row][column] = image[row][column]; 93 | } 94 | } 95 | 96 | // Loop through rows 97 | for (int row = 0; row < height; row++) 98 | { 99 | for (int column = 0; column < width; column++) 100 | { 101 | // // Initialize the variables 102 | int sumRed = 0; 103 | int sumGreen = 0; 104 | int sumBlue = 0; 105 | 106 | float counter = 0; 107 | 108 | // Loop through the surrounding pixels for each pixel (3x3 grid) 109 | for (int i = -1; i < 2; i++) 110 | { 111 | for (int j = -1; j < 2; j++) 112 | { 113 | // Check for the pixel to be in the grid and skip if it isn't 114 | if (row + i < 0 || row + i >= height) 115 | { 116 | continue; 117 | } 118 | if (column + j < 0 || column + j >= width) 119 | { 120 | continue; 121 | } 122 | // Add to sum 123 | sumRed += temp[row + i][column + j].rgbtRed; 124 | sumGreen += temp[row + i][column + j].rgbtGreen; 125 | sumBlue += temp[row + i][column +j].rgbtBlue; 126 | 127 | counter++; 128 | } 129 | } 130 | 131 | // Add the blur effect to the original image 132 | image[row][column].rgbtRed = round(sumRed / counter); 133 | image[row][column].rgbtGreen = round(sumGreen / counter); 134 | image[row][column].rgbtBlue = round(sumBlue / counter); 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /Week 4 - Memory/ProblemSet4/FilterLess/helpers.h: -------------------------------------------------------------------------------- 1 | #include "bmp.h" 2 | 3 | // Convert image to grayscale 4 | void grayscale(int height, int width, RGBTRIPLE image[height][width]); 5 | 6 | // Convert image to sepia 7 | void sepia(int height, int width, RGBTRIPLE image[height][width]); 8 | 9 | // Reflect image horizontally 10 | void reflect(int height, int width, RGBTRIPLE image[height][width]); 11 | 12 | // Blur image 13 | void blur(int height, int width, RGBTRIPLE image[height][width]); 14 | -------------------------------------------------------------------------------- /Week 4 - Memory/ProblemSet4/Recover/recover.c: -------------------------------------------------------------------------------- 1 | /* 2 | https://cs50.harvard.edu/x/2023/psets/4/recover/ 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | const int BLOCK_SIZE = 512; 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | // Check for proper usage 14 | if (argc != 2) 15 | { 16 | printf("Usage: ./recover filename.raw\n"); 17 | return 1; 18 | } 19 | 20 | // Open memory card 21 | FILE *file = fopen(argv[1], "r"); 22 | 23 | if (file == NULL) 24 | { 25 | printf("Could not open %s.\n", argv[1]); 26 | return 1; 27 | } 28 | 29 | // Create buffer - pointer to where to store the read data 30 | typedef uint8_t BYTE; 31 | BYTE buffer[BLOCK_SIZE]; 32 | 33 | // Counter for number of JPEGs found on the memory card 34 | int counter = 0; 35 | 36 | // Allocate enough bytes for the name of the file 37 | char *filename = malloc(8 * sizeof(char)); 38 | 39 | // Output file 40 | FILE *output = NULL; 41 | 42 | // Loop through the data on the card and read every block of 512 bytes into a buffer 43 | while (fread(buffer, 1, BLOCK_SIZE, file) == BLOCK_SIZE) 44 | { 45 | // Check if it's the start of a new JPEG 46 | if (buffer[0] == 0xFF && buffer[1] == 0xD8 && buffer[2] == 0xFF && (buffer[3] & 0xF0) == 0xE0) 47 | { 48 | // If it's the first JPEG 49 | if (counter == 0) 50 | { 51 | // Start writing the first file - 000.jpg 52 | sprintf(filename, "%03i.jpg", counter); 53 | output = fopen(filename, "w"); 54 | fwrite(buffer, 1, BLOCK_SIZE, output); 55 | 56 | counter++; 57 | } 58 | 59 | // If already found a JPEG 60 | else if (counter > 0) 61 | { 62 | // Close the current file and open up a new file to continue writing to 63 | fclose(output); 64 | sprintf(filename, "%03i.jpg", counter); 65 | output = fopen(filename, "w"); 66 | fwrite(buffer, 1, BLOCK_SIZE, output); 67 | counter++; 68 | } 69 | } 70 | 71 | // If it's not the start of a new JPEG 72 | else if (counter > 0) 73 | { 74 | // Keep writing to it because it's the next 512 bytes block of the current JPEG 75 | fwrite(buffer, 1, BLOCK_SIZE, output); 76 | } 77 | } 78 | 79 | // Close remaining files 80 | free(filename); 81 | fclose(file); 82 | fclose(output); 83 | } 84 | -------------------------------------------------------------------------------- /Week 5 - Data Structures/Lab5/Inheritance/inheritance.c: -------------------------------------------------------------------------------- 1 | /* 2 | https://cs50.harvard.edu/x/2023/labs/5/ 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | // Each person has two parents and two alleles 11 | typedef struct person 12 | { 13 | struct person *parents[2]; 14 | char alleles[2]; 15 | } 16 | person; 17 | 18 | const int GENERATIONS = 3; 19 | const int INDENT_LENGTH = 4; 20 | 21 | person *create_family(int generations); 22 | void print_family(person *p, int generation); 23 | void free_family(person *p); 24 | char random_allele(); 25 | 26 | int main(void) 27 | { 28 | // Seed random number generator 29 | srand(time(0)); 30 | 31 | // Create a new family with three generations 32 | person *p = create_family(GENERATIONS); 33 | 34 | // Print family tree of blood types 35 | print_family(p, 0); 36 | 37 | // Free memory 38 | free_family(p); 39 | } 40 | 41 | // Create a new individual with `generations` 42 | person *create_family(int generations) 43 | { 44 | // Allocate memory for new person 45 | person *p = malloc(sizeof(person)); 46 | 47 | // If there are still generations left to create 48 | if (generations > 1) 49 | { 50 | // Create two new parents for current person by recursively calling create_family 51 | person *parent0 = create_family(generations - 1); 52 | person *parent1 = create_family(generations - 1); 53 | 54 | // Set parent pointers for current person 55 | p->parents[0] = parent0; 56 | p->parents[1] = parent1; 57 | 58 | // Randomly assign current person's alleles based on the alleles of their parents 59 | p->alleles[0] = p->parents[0]->alleles[rand() % 2]; 60 | p->alleles[1] = p->parents[1]->alleles[rand() % 2]; 61 | } 62 | 63 | // If there are no generations left to create 64 | else 65 | { 66 | // Set parent pointers to NULL 67 | p->parents[0] = NULL; 68 | p->parents[1] = NULL; 69 | 70 | // Randomly assign alleles 71 | p->alleles[0] = random_allele(); 72 | p->alleles[1] = random_allele(); 73 | 74 | } 75 | 76 | // TODO: Return newly created person 77 | return p; 78 | } 79 | 80 | // Free `p` and all ancestors of `p`. 81 | void free_family(person *p) 82 | { 83 | // Handle base case 84 | if (p == NULL) 85 | { 86 | return; 87 | } 88 | 89 | // Free parents recursively 90 | free_family(p->parents[0]); 91 | free_family(p->parents[1]); 92 | 93 | // Free child 94 | free(p); 95 | 96 | } 97 | 98 | // Print each family member and their alleles. 99 | void print_family(person *p, int generation) 100 | { 101 | // Handle base case 102 | if (p == NULL) 103 | { 104 | return; 105 | } 106 | 107 | // Print indentation 108 | for (int i = 0; i < generation * INDENT_LENGTH; i++) 109 | { 110 | printf(" "); 111 | } 112 | 113 | // Print person 114 | if (generation == 0) 115 | { 116 | printf("Child (Generation %i): blood type %c%c\n", generation, p->alleles[0], p->alleles[1]); 117 | } 118 | else if (generation == 1) 119 | { 120 | printf("Parent (Generation %i): blood type %c%c\n", generation, p->alleles[0], p->alleles[1]); 121 | } 122 | else 123 | { 124 | for (int i = 0; i < generation - 2; i++) 125 | { 126 | printf("Great-"); 127 | } 128 | printf("Grandparent (Generation %i): blood type %c%c\n", generation, p->alleles[0], p->alleles[1]); 129 | } 130 | 131 | // Print parents of current generation 132 | print_family(p->parents[0], generation + 1); 133 | print_family(p->parents[1], generation + 1); 134 | } 135 | 136 | // Randomly chooses a blood type allele. 137 | char random_allele() 138 | { 139 | int r = rand() % 3; 140 | if (r == 0) 141 | { 142 | return 'A'; 143 | } 144 | else if (r == 1) 145 | { 146 | return 'B'; 147 | } 148 | else 149 | { 150 | return 'O'; 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /Week 5 - Data Structures/ProblemSet5/Speller/Makefile: -------------------------------------------------------------------------------- 1 | speller: 2 | clang -ggdb3 -gdwarf-4 -O0 -Qunused-arguments -std=c11 -Wall -Werror -Wextra -Wno-gnu-folding-constant -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow -c -o speller.o speller.c 3 | clang -ggdb3 -gdwarf-4 -O0 -Qunused-arguments -std=c11 -Wall -Werror -Wextra -Wno-gnu-folding-constant -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow -c -o dictionary.o dictionary.c 4 | clang -ggdb3 -gdwarf-4 -O0 -Qunused-arguments -std=c11 -Wall -Werror -Wextra -Wno-gnu-folding-constant -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow -o speller speller.o dictionary.o -lm 5 | -------------------------------------------------------------------------------- /Week 5 - Data Structures/ProblemSet5/Speller/dictionary.c: -------------------------------------------------------------------------------- 1 | /* 2 | https://cs50.harvard.edu/x/2023/psets/5/speller/ 3 | */ 4 | 5 | // Implements a dictionary's functionality 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "dictionary.h" 15 | 16 | // Represents a node in a hash table 17 | typedef struct node 18 | { 19 | char word[LENGTH + 1]; 20 | struct node *next; 21 | } 22 | node; 23 | 24 | // Choose number of buckets in hash table 25 | const unsigned int N = 1000; 26 | 27 | // Counter for the number of words in the dictionary 28 | int counter = 0; 29 | 30 | // Hash table 31 | node *table[N]; 32 | 33 | // Returns true if word is in dictionary, else false 34 | bool check(const char *word) 35 | { 36 | // Hash the word to obtain a hash value 37 | int index = hash(word); 38 | 39 | // Cursor to move through the linked lists 40 | node *cursor = table[index]; 41 | 42 | // Access linked list at that index in the hash table and traverse it 43 | while (cursor != NULL) 44 | { 45 | // If the word is found return true, else move cursor to the next node 46 | if (strcasecmp(cursor->word, word) != 0) 47 | { 48 | cursor = cursor->next; 49 | } 50 | else 51 | { 52 | return true; 53 | } 54 | } 55 | 56 | return false; 57 | } 58 | 59 | // Hashes word to a number 60 | unsigned int hash(const char *word) 61 | { 62 | // This is the function I came up with, it's not as fast as the staff's implementation but significantly faster than the one from the distribution code 63 | int points = 0; 64 | 65 | for (int i = 0, len = strlen(word); i < len; i++) 66 | { 67 | points += toupper(word[i]) - 'A'; 68 | } 69 | 70 | return points % N; 71 | } 72 | 73 | // Loads dictionary into memory, returning true if successful, else false 74 | bool load(const char *dictionary) 75 | { 76 | // Open dictionary file 77 | FILE *file = fopen(dictionary, "r"); 78 | 79 | if (file == NULL) 80 | { 81 | return false; 82 | } 83 | 84 | char word[LENGTH + 1]; 85 | 86 | // Read strings from file one at a time 87 | while (fscanf(file, "%s", word) != EOF) 88 | { 89 | // Create a new node for each word 90 | node *n = malloc(sizeof(node)); 91 | 92 | if (n == NULL) 93 | { 94 | return false; 95 | } 96 | 97 | // Copy word into node and set the next node to NULL 98 | strcpy(n->word, word); 99 | n->next = NULL; 100 | 101 | // Hash word to obtain a hash value 102 | int index = hash(word); 103 | 104 | // Insert node into hash table in the corresponding bucket 105 | n->next = table[index]; 106 | table[index] = n; 107 | counter++; 108 | } 109 | 110 | fclose(file); 111 | 112 | return true; 113 | } 114 | 115 | // Returns number of words in dictionary if loaded, else 0 if not yet loaded 116 | unsigned int size(void) 117 | { 118 | return counter; 119 | } 120 | 121 | // Unloads dictionary from memory, returning true if successful, else false 122 | bool unload(void) 123 | { 124 | // Cursor to move through the linked lists 125 | node *cursor = NULL; 126 | 127 | // Iterating through the buckets of the hash table 128 | for (int i = 0; i < N; i++) 129 | { 130 | cursor = table[i]; 131 | 132 | // Iterate through the linked lists and free the allocated memory for it's nodes 133 | while (cursor != NULL) 134 | { 135 | node *temp = cursor; 136 | cursor = cursor->next; 137 | 138 | free(temp); 139 | } 140 | } 141 | 142 | return true; 143 | } 144 | -------------------------------------------------------------------------------- /Week 5 - Data Structures/ProblemSet5/Speller/dictionary.h: -------------------------------------------------------------------------------- 1 | // Declares a dictionary's functionality 2 | 3 | #ifndef DICTIONARY_H 4 | #define DICTIONARY_H 5 | 6 | #include 7 | 8 | // Maximum length for a word 9 | // (e.g., pneumonoultramicroscopicsilicovolcanoconiosis) 10 | #define LENGTH 45 11 | 12 | // Prototypes 13 | bool check(const char *word); 14 | unsigned int hash(const char *word); 15 | bool load(const char *dictionary); 16 | unsigned int size(void); 17 | bool unload(void); 18 | 19 | #endif // DICTIONARY_H 20 | -------------------------------------------------------------------------------- /Week 5 - Data Structures/ProblemSet5/Speller/speller.c: -------------------------------------------------------------------------------- 1 | // Implements a spell-checker 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "dictionary.h" 9 | 10 | // Undefine any definitions 11 | #undef calculate 12 | #undef getrusage 13 | 14 | // Default dictionary 15 | #define DICTIONARY "dictionaries/large" 16 | 17 | // Prototype 18 | double calculate(const struct rusage *b, const struct rusage *a); 19 | 20 | int main(int argc, char *argv[]) 21 | { 22 | // Check for correct number of args 23 | if (argc != 2 && argc != 3) 24 | { 25 | printf("Usage: ./speller [DICTIONARY] text\n"); 26 | return 1; 27 | } 28 | 29 | // Structures for timing data 30 | struct rusage before, after; 31 | 32 | // Benchmarks 33 | double time_load = 0.0, time_check = 0.0, time_size = 0.0, time_unload = 0.0; 34 | 35 | // Determine dictionary to use 36 | char *dictionary = (argc == 3) ? argv[1] : DICTIONARY; 37 | 38 | // Load dictionary 39 | getrusage(RUSAGE_SELF, &before); 40 | bool loaded = load(dictionary); 41 | getrusage(RUSAGE_SELF, &after); 42 | 43 | // Exit if dictionary not loaded 44 | if (!loaded) 45 | { 46 | printf("Could not load %s.\n", dictionary); 47 | return 1; 48 | } 49 | 50 | // Calculate time to load dictionary 51 | time_load = calculate(&before, &after); 52 | 53 | // Try to open text 54 | char *text = (argc == 3) ? argv[2] : argv[1]; 55 | FILE *file = fopen(text, "r"); 56 | if (file == NULL) 57 | { 58 | printf("Could not open %s.\n", text); 59 | unload(); 60 | return 1; 61 | } 62 | 63 | // Prepare to report misspellings 64 | printf("\nMISSPELLED WORDS\n\n"); 65 | 66 | // Prepare to spell-check 67 | int index = 0, misspellings = 0, words = 0; 68 | char word[LENGTH + 1]; 69 | 70 | // Spell-check each word in text 71 | char c; 72 | while (fread(&c, sizeof(char), 1, file)) 73 | { 74 | // Allow only alphabetical characters and apostrophes 75 | if (isalpha(c) || (c == '\'' && index > 0)) 76 | { 77 | // Append character to word 78 | word[index] = c; 79 | index++; 80 | 81 | // Ignore alphabetical strings too long to be words 82 | if (index > LENGTH) 83 | { 84 | // Consume remainder of alphabetical string 85 | while (fread(&c, sizeof(char), 1, file) && isalpha(c)); 86 | 87 | // Prepare for new word 88 | index = 0; 89 | } 90 | } 91 | 92 | // Ignore words with numbers (like MS Word can) 93 | else if (isdigit(c)) 94 | { 95 | // Consume remainder of alphanumeric string 96 | while (fread(&c, sizeof(char), 1, file) && isalnum(c)); 97 | 98 | // Prepare for new word 99 | index = 0; 100 | } 101 | 102 | // We must have found a whole word 103 | else if (index > 0) 104 | { 105 | // Terminate current word 106 | word[index] = '\0'; 107 | 108 | // Update counter 109 | words++; 110 | 111 | // Check word's spelling 112 | getrusage(RUSAGE_SELF, &before); 113 | bool misspelled = !check(word); 114 | getrusage(RUSAGE_SELF, &after); 115 | 116 | // Update benchmark 117 | time_check += calculate(&before, &after); 118 | 119 | // Print word if misspelled 120 | if (misspelled) 121 | { 122 | printf("%s\n", word); 123 | misspellings++; 124 | } 125 | 126 | // Prepare for next word 127 | index = 0; 128 | } 129 | } 130 | 131 | // Check whether there was an error 132 | if (ferror(file)) 133 | { 134 | fclose(file); 135 | printf("Error reading %s.\n", text); 136 | unload(); 137 | return 1; 138 | } 139 | 140 | // Close text 141 | fclose(file); 142 | 143 | // Determine dictionary's size 144 | getrusage(RUSAGE_SELF, &before); 145 | unsigned int n = size(); 146 | getrusage(RUSAGE_SELF, &after); 147 | 148 | // Calculate time to determine dictionary's size 149 | time_size = calculate(&before, &after); 150 | 151 | // Unload dictionary 152 | getrusage(RUSAGE_SELF, &before); 153 | bool unloaded = unload(); 154 | getrusage(RUSAGE_SELF, &after); 155 | 156 | // Abort if dictionary not unloaded 157 | if (!unloaded) 158 | { 159 | printf("Could not unload %s.\n", dictionary); 160 | return 1; 161 | } 162 | 163 | // Calculate time to unload dictionary 164 | time_unload = calculate(&before, &after); 165 | 166 | // Report benchmarks 167 | printf("\nWORDS MISSPELLED: %d\n", misspellings); 168 | printf("WORDS IN DICTIONARY: %d\n", n); 169 | printf("WORDS IN TEXT: %d\n", words); 170 | printf("TIME IN load: %.2f\n", time_load); 171 | printf("TIME IN check: %.2f\n", time_check); 172 | printf("TIME IN size: %.2f\n", time_size); 173 | printf("TIME IN unload: %.2f\n", time_unload); 174 | printf("TIME IN TOTAL: %.2f\n\n", 175 | time_load + time_check + time_size + time_unload); 176 | 177 | // Success 178 | return 0; 179 | } 180 | 181 | // Returns number of seconds between b and a 182 | double calculate(const struct rusage *b, const struct rusage *a) 183 | { 184 | if (b == NULL || a == NULL) 185 | { 186 | return 0.0; 187 | } 188 | else 189 | { 190 | return ((((a->ru_utime.tv_sec * 1000000 + a->ru_utime.tv_usec) - 191 | (b->ru_utime.tv_sec * 1000000 + b->ru_utime.tv_usec)) + 192 | ((a->ru_stime.tv_sec * 1000000 + a->ru_stime.tv_usec) - 193 | (b->ru_stime.tv_sec * 1000000 + b->ru_stime.tv_usec))) 194 | / 1000000.0); 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /Week 6 - Python/Lab6/WorldCup/2018m.csv: -------------------------------------------------------------------------------- 1 | team,rating 2 | Uruguay,976 3 | Portugal,1306 4 | France,1166 5 | Argentina,1254 6 | Brazil,1384 7 | Mexico,1008 8 | Belgium,1346 9 | Japan,528 10 | Spain,1162 11 | Russia,493 12 | Croatia,975 13 | Denmark,1054 14 | Sweden,889 15 | Switzerland,1179 16 | Colombia,989 17 | England,1040 18 | -------------------------------------------------------------------------------- /Week 6 - Python/Lab6/WorldCup/2019w.csv: -------------------------------------------------------------------------------- 1 | team,rating 2 | Norway,1915 3 | Australia,2003 4 | England,2049 5 | Cameroon,1499 6 | France,2043 7 | Brazil,1944 8 | Spain,1913 9 | United States,2101 10 | Italy,1868 11 | China PR,1866 12 | Netherlands,1967 13 | Japan,1991 14 | Germany,2072 15 | Nigeria,1599 16 | Sweden,1962 17 | Canada,2006 18 | -------------------------------------------------------------------------------- /Week 6 - Python/Lab6/WorldCup/answers.txt: -------------------------------------------------------------------------------- 1 | Times: 2 | 3 | 10 simulations: 0m0.026s 4 | 100 simulations: 0m0.028s 5 | 1000 simulations: 0m0.034s 6 | 10000 simulations: 0m0.097s 7 | 100000 simulations: 0m0.856s 8 | 1000000 simulations: 0m7.705s 9 | 10 | Questions: 11 | 12 | Which predictions, if any, proved incorrect as you increased the number of simulations?: 13 | 14 | When running a small number of simulations the output can be random, 15 | for example a team like Brazil can have one time a chance of 60%, next time 10%. 16 | 17 | Suppose you're charged a fee for each second of compute time your program uses. 18 | After how many simulations would you call the predictions "good enough"?: 19 | 20 | When running 10000 simulations the output stabilized, showing Belgium as the favourite, 21 | followed up by Brazil. After 10000 simulations, the results usually show the same, 22 | so I'd consider 10000 to be good enough. 23 | -------------------------------------------------------------------------------- /Week 6 - Python/Lab6/WorldCup/tournament.py: -------------------------------------------------------------------------------- 1 | """ 2 | https://cs50.harvard.edu/x/2023/labs/6/ 3 | """ 4 | 5 | import csv 6 | import sys 7 | import random 8 | 9 | # Number of simluations to run. 10 | N = 100 11 | 12 | 13 | def main(): 14 | 15 | # Ensure correct usage. 16 | if len(sys.argv) != 2: 17 | sys.exit("Usage: python tournament.py FILENAME") 18 | 19 | # Read teams into memory. 20 | teams = [] 21 | 22 | with open(sys.argv[1]) as file: 23 | reader = csv.DictReader(file) 24 | 25 | for team in reader: 26 | team["rating"] = int(team["rating"]) 27 | teams.append(team) 28 | 29 | # Keep track of number of wins for each team. 30 | counts = {} 31 | 32 | for _ in range(N): 33 | winner = simulate_tournament(teams) 34 | 35 | if winner in counts: 36 | counts[winner] += 1 37 | else: 38 | counts[winner] = 1 39 | 40 | # Print each team's chances of winning, according to simulation. 41 | for team in sorted(counts, key=lambda team: counts[team], reverse=True): 42 | print(f"{team}: {counts[team] * 100 / N:.1f}% chance of winning") 43 | 44 | 45 | def simulate_game(team1, team2): 46 | """Simulate a game. Return True if team1 wins, False otherwise.""" 47 | 48 | rating1 = team1["rating"] 49 | rating2 = team2["rating"] 50 | probability = 1 / (1 + 10 ** ((rating2 - rating1) / 600)) 51 | 52 | return random.random() < probability 53 | 54 | 55 | def simulate_round(teams): 56 | """Simulate a round. Return a list of winning teams.""" 57 | 58 | winners = [] 59 | 60 | # Simulate games for all pairs of teams. 61 | for i in range(0, len(teams), 2): 62 | if simulate_game(teams[i], teams[i + 1]): 63 | winners.append(teams[i]) 64 | else: 65 | winners.append(teams[i + 1]) 66 | 67 | return winners 68 | 69 | 70 | def simulate_tournament(teams): 71 | """Simulate a tournament. Return name of winning team.""" 72 | 73 | while len(teams) != 1: 74 | teams = simulate_round(teams) 75 | 76 | return teams[0]["team"] 77 | 78 | 79 | if __name__ == "__main__": 80 | main() 81 | -------------------------------------------------------------------------------- /Week 6 - Python/ProblemSet6/DNA/dna.py: -------------------------------------------------------------------------------- 1 | """ 2 | https://cs50.harvard.edu/x/2023/psets/6/dna/ 3 | """ 4 | 5 | import csv 6 | import sys 7 | 8 | def main(): 9 | 10 | database = [] 11 | results = {} 12 | 13 | # Check for command-line usage. 14 | if len(sys.argv) != 3: 15 | print("Usage: python dna.py DATABASE SEQUENCE") 16 | 17 | # Read database file into a variable. 18 | with open(sys.argv[1]) as file: 19 | reader = csv.reader(file) 20 | 21 | for row in reader: 22 | database.append(row) 23 | 24 | # Read DNA sequence file into a variable. 25 | with open(sys.argv[2]) as file: 26 | sequence = file.read() 27 | 28 | # Find longest match of each STR in DNA sequence. 29 | # Get the STRs from the CSV file by iterating through the row starting from 1 so we omit 'name'. 30 | for i in range(1, len(database[0])): 31 | # Each iteration save the STR in a variable. 32 | subsequence = "".join(x for x in database[0][i]) 33 | 34 | # In the 'results' dictionary, save each STR along with the length of the longest run. 35 | results[subsequence] = longest_match(sequence, subsequence) 36 | 37 | # Convert the results of the STRs to a list containing only the values. 38 | sequence_dna = list(results.values()) 39 | 40 | # Check database for matching profiles by iterating through the CSV file and getting the STRs for each person. 41 | for person in database[1:][0:]: 42 | # Save the STR values to a list. 43 | person_dna = [int(i) for i in person[1:]] 44 | 45 | # Compare the two lists and print the name of the person if there's a match. 46 | if person_dna == sequence_dna: 47 | sys.exit(person[0]) 48 | 49 | # Print 'No match' if there wasn't a match. 50 | print("No match") 51 | 52 | 53 | def longest_match(sequence, subsequence): 54 | """Returns length of longest run of subsequence in sequence.""" 55 | 56 | # Initialize variables 57 | longest_run = 0 58 | subsequence_length = len(subsequence) 59 | sequence_length = len(sequence) 60 | 61 | # Check each character in sequence for most consecutive runs of subsequence. 62 | for i in range(sequence_length): 63 | 64 | # Initialize count of consecutive runs. 65 | count = 0 66 | 67 | # Check for a subsequence match in a "substring" (a subset of characters) within sequence. 68 | # If a match, move substring to next potential match in sequence. 69 | # Continue moving substring and checking for matches until out of consecutive matches. 70 | while True: 71 | 72 | # Adjust substring start and end 73 | start = i + count * subsequence_length 74 | end = start + subsequence_length 75 | 76 | # If there is a match in the substring. 77 | if sequence[start:end] == subsequence: 78 | count += 1 79 | 80 | # If there is no match in the substring. 81 | else: 82 | break 83 | 84 | # Update most consecutive matches found. 85 | longest_run = max(longest_run, count) 86 | 87 | # After checking for runs at each character in seqeuence, return longest run found. 88 | return longest_run 89 | 90 | 91 | if __name__ == "__main__": 92 | main() 93 | -------------------------------------------------------------------------------- /Week 6 - Python/ProblemSet6/SentimentalCash/cash.py: -------------------------------------------------------------------------------- 1 | """ 2 | https://cs50.harvard.edu/x/2023/psets/6/cash/ 3 | """ 4 | 5 | def main(): 6 | dollars = get_input() 7 | amount = get_coins(dollars) 8 | 9 | print(amount) 10 | 11 | 12 | def get_input(): 13 | """Prompts user for a positive float. Returns that amount times 100 as an integer.""" 14 | 15 | while True: 16 | try: 17 | dollars = float(input("Change owed: ")) 18 | 19 | if dollars > 0: 20 | return int(dollars * 100) 21 | 22 | except ValueError as error: 23 | print(error) 24 | 25 | 26 | def get_coins(dollars): 27 | """Returns the smallest number of coins that can be given for the change owed.""" 28 | 29 | counter = 0 30 | 31 | # Loop through a list that contains all coins available. 32 | for coin in [25, 10, 5, 1]: 33 | # Divide the dollars by each coin and store integer result in a temporary variable. 34 | amount = int(dollars / coin) 35 | # Substract from dollars that result multiplied by the coin. 36 | dollars -= amount * coin 37 | # Add to counter the result of the division. 38 | counter += amount 39 | 40 | # Break out of the loop when dollars reach 0. 41 | if dollars == 0: 42 | break 43 | 44 | return counter 45 | 46 | 47 | if __name__ == "__main__": 48 | main() 49 | -------------------------------------------------------------------------------- /Week 6 - Python/ProblemSet6/SentimentalCredit/credit.py: -------------------------------------------------------------------------------- 1 | """ 2 | https://cs50.harvard.edu/x/2023/psets/6/credit/ 3 | """ 4 | 5 | def main(): 6 | 7 | number = input("Number: ") 8 | 9 | calculate_checksum(number) 10 | check_card_length(number) 11 | 12 | print_issuing_company(number) 13 | 14 | 15 | def calculate_checksum(card): 16 | """Calculates whether a card number is valid or not based on Luhn's Algorithm. Returns 'True' if valid, 'False' if not.""" 17 | 18 | card_sum = 0 19 | 20 | # Get all the digits starting with the last to first jumping every 2 digits. 21 | for digit in reversed(range(0, len(card), 2)): 22 | # Convert to integers and multiply by 2 23 | multiplied_digit = int(card[digit]) * 2 24 | 25 | # If the result of the multiplication is lower than 10, add result to sum. 26 | if len(str(multiplied_digit)) != 2: 27 | card_sum += multiplied_digit 28 | # If the result of the multiplication is higher than 10, separate the result in two and add each number to sum. 29 | else: 30 | multiplied_digit = str(multiplied_digit) 31 | first, second = multiplied_digit[0], multiplied_digit[1] 32 | 33 | card_sum += int(first) + int(second) 34 | 35 | # Get the remaining digits in the card number from last to first and add to sum. 36 | for digit in reversed(range(1, len(card), 2)): 37 | card_sum += int(card[digit]) 38 | 39 | # If the sum last digit is 0 then the card is valid, else it's invalid. 40 | if card_sum % 10 == 0: 41 | return True 42 | else: 43 | return False 44 | 45 | 46 | def check_card_length(card): 47 | """Checks for the length of the card number to be either 13, 15 or 16. Prints out 'INVALID' if it's not.""" 48 | 49 | if len(card) != [13, 15, 16]: 50 | print("INVALID") 51 | 52 | 53 | def print_issuing_company(card): 54 | """Prints out the name of the company that issued the card based on the first digit/digits. Prints out 'INVALID' if none matches.""" 55 | 56 | if card.startswith("4"): 57 | print("VISA") 58 | elif card.startswith(("51", "52", "53", "54", "55")): 59 | print("MASTERCARD") 60 | elif card.startswith(("34", "37")): 61 | print("AMEX") 62 | else: 63 | print("INVALID") 64 | 65 | 66 | if __name__ == "__main__": 67 | main() 68 | -------------------------------------------------------------------------------- /Week 6 - Python/ProblemSet6/SentimentalMarioLess/mario.py: -------------------------------------------------------------------------------- 1 | """ 2 | https://cs50.harvard.edu/x/2023/psets/6/mario/less/ 3 | """ 4 | 5 | def get_height(): 6 | """Returns the height that was given by the user.""" 7 | 8 | while True: 9 | try: 10 | height = int(input("Height: ")) 11 | 12 | if height > 0 and height < 9: 13 | return height 14 | 15 | except ValueError as error: 16 | print(error) 17 | 18 | 19 | def print_pyramid(height): 20 | """Prints out the pyramid.""" 21 | 22 | for line in range(height): 23 | print(" " * (height - line - 1), end="") 24 | print("#" * (line + 1)) 25 | 26 | 27 | # Call the function that prints the pyramid which takes as argument the function that returns the height. 28 | print_pyramid(get_height()) 29 | -------------------------------------------------------------------------------- /Week 6 - Python/ProblemSet6/SentimentalMarioMore/mario.py: -------------------------------------------------------------------------------- 1 | """ 2 | https://cs50.harvard.edu/x/2023/psets/6/mario/more/ 3 | """ 4 | 5 | def get_height(): 6 | """Returns the height that was given by the user.""" 7 | 8 | while True: 9 | try: 10 | height = int(input("Height: ")) 11 | 12 | if height > 0 and height < 9: 13 | return height 14 | 15 | except ValueError as error: 16 | print(error) 17 | 18 | 19 | def print_pyramid(height): 20 | """Prints out the pyramid.""" 21 | 22 | for line in range(height): 23 | print(" " * (height - line - 1), end="") 24 | print("#" * (line + 1), end="") 25 | print(" ", end="") 26 | print("#" * (line + 1)) 27 | 28 | 29 | # Call the function that prints the pyramid which takes as argument the function that returns the height. 30 | print_pyramid(get_height()) 31 | -------------------------------------------------------------------------------- /Week 6 - Python/ProblemSet6/SentimentalReadability/readability.py: -------------------------------------------------------------------------------- 1 | """ 2 | https://cs50.harvard.edu/x/2023/psets/6/readability/ 3 | """ 4 | 5 | def main(): 6 | 7 | sentence = input("Text: ") 8 | 9 | # Number of letters, words and sentences in the string. 10 | letters = count_letters(sentence) 11 | words = count_words(sentence) 12 | sentences = count_sentences(sentence) 13 | 14 | # Average number of letters and stentences per 100 words in text. 15 | avg_letters = (100 / float(words)) * float(letters) 16 | avg_sentences = (100 / float(words)) * float(sentences) 17 | 18 | # Coleman-Liau index. 19 | index = calculate_index(avg_letters, avg_sentences) 20 | 21 | if index < 1: 22 | print("Before Grade 1") 23 | elif index >= 16: 24 | print("Grade 16+") 25 | else: 26 | print(f"Grade {index}") 27 | 28 | 29 | def count_letters(sentence): 30 | """Counts and returns the number of letters in a string.""" 31 | 32 | letters = 0 33 | 34 | for character in sentence: 35 | if character.isalpha(): 36 | letters += 1 37 | 38 | return letters 39 | 40 | 41 | def count_words(sentence): 42 | """Counts and returns the number of words in a string.""" 43 | 44 | return len(sentence.split()) 45 | 46 | 47 | def count_sentences(sentence): 48 | """Counts and returns the number of sentences in a string.""" 49 | 50 | sentences = 0 51 | 52 | for character in sentence: 53 | if character in [".", "!", "?"]: 54 | sentences += 1 55 | 56 | return sentences 57 | 58 | 59 | def calculate_index(avg_letters, avg_sentences): 60 | """Calculates the approximate grade level needed to comprehend some text according to the Coleman-Liau formula. Returns the result of the formula.""" 61 | 62 | return round(0.0588 * avg_letters - 0.296 * avg_sentences - 15.8) 63 | 64 | 65 | if __name__ == "__main__": 66 | main() 67 | -------------------------------------------------------------------------------- /Week 7 - SQL/Lab7/Songs/1.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Write a SQL query to list the names of all songs in the database. 3 | Your query should output a table with a single column for the name of each song. 4 | */ 5 | 6 | SELECT name 7 | FROM songs; 8 | -------------------------------------------------------------------------------- /Week 7 - SQL/Lab7/Songs/2.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Write a SQL query to list the names of all songs in increasing order of tempo. 3 | Your query should output a table with a single column for the name of each song. 4 | */ 5 | 6 | SELECT name 7 | FROM songs 8 | ORDER BY tempo; 9 | -------------------------------------------------------------------------------- /Week 7 - SQL/Lab7/Songs/3.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Write a SQL query to list the names of the top 5 longest songs, in descending order of length. 3 | Your query should output a table with a single column for the name of each song. 4 | */ 5 | 6 | SELECT name 7 | FROM songs 8 | ORDER BY duration_ms DESC 9 | LIMIT 5; 10 | -------------------------------------------------------------------------------- /Week 7 - SQL/Lab7/Songs/4.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Write a SQL query that lists the names of any songs that have danceability, energy, and valence greater than 0.75. 3 | Your query should output a table with a single column for the name of each song. 4 | */ 5 | 6 | SELECT name 7 | FROM songs 8 | WHERE (danceability > 0.75 AND energy > 0.75 AND valence > 0.75); 9 | -------------------------------------------------------------------------------- /Week 7 - SQL/Lab7/Songs/5.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Write a SQL query that returns the average energy of all the songs. 3 | Your query should output a table with a single column and a single row containing the average energy. 4 | */ 5 | 6 | SELECT AVG(energy) 7 | FROM songs; 8 | -------------------------------------------------------------------------------- /Week 7 - SQL/Lab7/Songs/6.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Write a SQL query that lists the names of songs that are by Post Malone. 3 | Your query should output a table with a single column for the name of each song. 4 | You should not make any assumptions about what Post Malone’s artist_id is. 5 | */ 6 | 7 | SELECT name 8 | FROM songs 9 | WHERE artist_id = ( 10 | SELECT id 11 | FROM artists 12 | WHERE name = "Post Malone"); 13 | -------------------------------------------------------------------------------- /Week 7 - SQL/Lab7/Songs/7.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Write a SQL query that returns the average energy of songs that are by Drake. 3 | Your query should output a table with a single column and a single row containing the average energy. 4 | You should not make any assumptions about what Drake’s artist_id is. 5 | */ 6 | 7 | SELECT AVG(energy) 8 | FROM songs 9 | WHERE artist_id = ( 10 | SELECT id 11 | FROM artists 12 | WHERE name = "Drake"); 13 | -------------------------------------------------------------------------------- /Week 7 - SQL/Lab7/Songs/8.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Write a SQL query that lists the names of the songs that feature other artists. 3 | Songs that feature other artists will include “feat.” in the name of the song. 4 | Your query should output a table with a single column for the name of each song. 5 | */ 6 | 7 | SELECT name 8 | FROM songs 9 | WHERE name LIKE "%feat.%"; 10 | -------------------------------------------------------------------------------- /Week 7 - SQL/Lab7/Songs/answers.txt: -------------------------------------------------------------------------------- 1 | https://cs50.harvard.edu/x/2023/labs/7/ 2 | 3 | Seems like a lot of the songs this person listened to are some of the most streamed songs in the last few years. 4 | 5 | From what I could gather, the auras that match this Wrapped are: 6 | Orange - seems like there are quite a few songs that could increase your energy levels and boost your confidence. 7 | Blue - most songs are giving a message to the listener, and this Wrapper could reflect what this person is feeling inside. 8 | -------------------------------------------------------------------------------- /Week 7 - SQL/ProblemSet7/Fiftyville/answers.txt: -------------------------------------------------------------------------------- 1 | The THIEF is: Bruce. 2 | The city the thief ESCAPED TO: New York City. 3 | The ACCOMPLICE is: Robin. 4 | -------------------------------------------------------------------------------- /Week 7 - SQL/ProblemSet7/Fiftyville/log.sql: -------------------------------------------------------------------------------- 1 | /* 2 | https://cs50.harvard.edu/x/2023/psets/7/fiftyville/ 3 | */ 4 | 5 | -- We know the theft took place on Humphrey St., on July 28 2021. 6 | 7 | SELECT * 8 | FROM crime_scene_reports 9 | WHERE street = "Humphrey Street" AND year = 2021 AND month = 7 AND day = 28; 10 | 11 | -- By checking the crime scene reports we found out that it took place at 10:15 AM at the bakery. 12 | -- Three witnesses were present each mentioning the bakery. 13 | 14 | SELECT * 15 | FROM interviews 16 | WHERE year = 2021 AND month = 7 AND day = 28; 17 | 18 | -- By checking the interviews that took place on that day, we found out after 10 minutes of the theft, 19 | -- the thief got into a car in the bakery parking lot and drove away. 20 | -- Also someone mentioned that he recognized the thief because earlier that morning he saw the thief withdrawing some money on Leggett Street. 21 | -- The thief called someone after leaving the bakery and talked to them for less than a minute. 22 | -- The thief said on the phone that they were planning to take the earliest flight out of Fiftyville tomorrow and asked the person he was talking to to buy the tickets. 23 | 24 | SELECT * 25 | FROM people 26 | WHERE license_plate IN ( 27 | SELECT license_plate 28 | FROM bakery_security_logs 29 | WHERE activity = "exit" AND year = 2021 AND month = 7 AND day = 28 AND hour = 10 AND minute BETWEEN 15 AND 40 30 | ) 31 | AND phone_number IN ( 32 | SELECT caller 33 | FROM phone_calls 34 | WHERE year = 2021 AND month = 7 AND day = 28 AND duration < 60 35 | ) 36 | AND people.id IN ( 37 | SELECT person_id 38 | FROM bank_accounts 39 | WHERE bank_accounts.account_number IN ( 40 | SELECT account_number 41 | FROM atm_transactions 42 | WHERE year = 2021 AND month = 7 AND day = 28 AND atm_location = "Leggett Street" AND transaction_type = "withdraw" 43 | ) 44 | ); 45 | 46 | -- Following the leads about the bakery parking and the ATM withdrawal and the call, we get back 3 suspects. 47 | -- Taylor, Diana and Bruce. 48 | 49 | SELECT * 50 | FROM people 51 | WHERE phone_number IN ( 52 | SELECT receiver 53 | FROM phone_calls 54 | WHERE year = 2021 AND month = 7 AND day = 28 AND duration < 60 AND caller IN ("(286) 555-6063", "(770) 555-1861", "(367) 555-5533") 55 | ); 56 | 57 | -- If we check the receivers of those phone calls against the 3 suspects phone numbers, we get 3 names that might be the accomplices. 58 | -- James, Philip and Robin. 59 | 60 | SELECT * 61 | FROM phone_calls 62 | WHERE year = 2021 AND month = 7 AND day = 28 AND duration < 60 63 | AND caller IN ("(286) 555-6063", "(770) 555-1861", "(367) 555-5533") 64 | AND receiver IN ("(676) 555-6554", "(725) 555-3243", "(375) 555-8161"); 65 | 66 | -- Knowing the names of the possible suspects and accomplices we can check who called who. 67 | -- Taylor called James, Diana called Philip and Bruce called Robin. 68 | 69 | SELECT * 70 | FROM flights 71 | JOIN airports 72 | ON airports.id = flights.origin_airport_id 73 | WHERE flights.year = 2021 AND flights.month = 7 AND flights.day = 29 AND flights.hour BETWEEN 00 AND 12 AND airports.city = "Fiftyville" 74 | ORDER BY flights.hour, flights.minute; 75 | 76 | SELECT full_name, city 77 | FROM airports 78 | WHERE id IN (1, 4, 11); 79 | 80 | -- The thief said he wants to leave as early as possible tomorrow. 81 | -- Checking the earliest flights we get back 3 flights: to New York at 8:20 AM, to Chicago at 9:30 AM and to San Francisco at 12:15 PM. 82 | 83 | SELECT name, passport_number 84 | FROM people 85 | WHERE people.name IN ("Bruce", "Taylor", "Diana", "James", "Philip", "Robin") 86 | AND passport_number IN ( 87 | SELECT passport_number 88 | FROM passengers 89 | JOIN flights 90 | ON flights.id = passengers.flight_id 91 | JOIN airports 92 | ON airports.id = flights.origin_airport_id 93 | WHERE flights.year = 2021 AND flights.month = 7 AND flights.day = 29 AND flights.hour BETWEEN 00 AND 12 94 | AND flights.origin_airport_id IN ( 95 | SELECT airports.id 96 | FROM airports 97 | WHERE airports.city = "Fiftyville" 98 | ) 99 | AND flights.destination_airport_id IN ( 100 | SELECT airports.id 101 | FROM airports 102 | WHERE airports.city IN ("New York City", "Chicago", "San Francisco") 103 | ) 104 | ); 105 | 106 | -- From the three suspects, Bruce and Taylor flew on the 29th on one of the three aforementioned flights. 107 | 108 | SELECT full_name, city, passport_number, flights.destination_airport_id, flights.hour, flights.minute 109 | FROM airports 110 | JOIN flights 111 | ON flights.origin_airport_id = airports.id 112 | JOIN passengers 113 | ON passengers.flight_id = flights.id 114 | WHERE flights.year = 2021 AND flights.month = 7 AND flights.day = 29 AND hour BETWEEN 00 AND 12 115 | AND passengers.passport_number IN ( 116 | SELECT passport_number 117 | FROM people 118 | WHERE people.name IN ("Bruce", "Taylor", "Diana", "James", "Philip", "Robin") 119 | ); 120 | 121 | -- Both of them flew to New York without the accomplices. 122 | 123 | -- From the information gathered so far there are two options: 124 | -- Thief: Taylor | Accomplice: James | Flew to: New York. 125 | -- Thief: Bruce | Accomplice: Robin | Flew to: New York. 126 | -------------------------------------------------------------------------------- /Week 7 - SQL/ProblemSet7/Movies/1.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Write a SQL query to list the titles of all movies released in 2008. 3 | Your query should output a table with a single column for the title of each movie. 4 | */ 5 | 6 | SELECT title 7 | FROM movies 8 | WHERE year = 2008; 9 | -------------------------------------------------------------------------------- /Week 7 - SQL/ProblemSet7/Movies/10.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Write a SQL query to list the names of all people who have directed a movie that received a rating of at least 9.0. 3 | Your query should output a table with a single column for the name of each person. 4 | If a person directed more than one movie that received a rating of at least 9.0, they should only appear in your results once. 5 | */ 6 | 7 | SELECT DISTINCT people.name 8 | FROM people 9 | JOIN directors 10 | ON directors.person_id = people.id 11 | 12 | JOIN movies 13 | ON movies.id = directors.movie_id 14 | 15 | JOIN ratings 16 | ON ratings.movie_id = movies.id 17 | WHERE rating >= 9.0; 18 | -------------------------------------------------------------------------------- /Week 7 - SQL/ProblemSet7/Movies/11.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Write a SQL query to list the titles of the five highest rated movies (in order) that Chadwick Boseman starred in, starting with the highest rated. 3 | Your query should output a table with a single column for the title of each movie. 4 | You may assume that there is only one person in the database with the name Chadwick Boseman. 5 | */ 6 | 7 | SELECT movies.title 8 | FROM movies 9 | JOIN stars 10 | ON stars.movie_id = movies.id 11 | 12 | JOIN people 13 | ON people.id = stars.person_id 14 | 15 | JOIN ratings 16 | ON ratings.movie_id = movies.id 17 | WHERE people.name = "Chadwick Boseman" 18 | ORDER BY rating DESC 19 | LIMIT 5; 20 | -------------------------------------------------------------------------------- /Week 7 - SQL/ProblemSet7/Movies/12.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Write a SQL query to list the titles of all movies in which both Johnny Depp and Helena Bonham Carter starred. 3 | Your query should output a table with a single column for the title of each movie. 4 | You may assume that there is only one person in the database with the name Johnny Depp. 5 | You may assume that there is only one person in the database with the name Helena Bonham Carter. 6 | */ 7 | 8 | SELECT movies.title 9 | FROM movies 10 | JOIN stars 11 | ON stars.movie_id = movies.id 12 | 13 | JOIN people 14 | ON people.id = stars.person_id 15 | WHERE people.name = "Johnny Depp" 16 | 17 | INTERSECT 18 | 19 | SELECT movies.title 20 | FROM movies 21 | JOIN stars 22 | ON stars.movie_id = movies.id 23 | 24 | JOIN people 25 | ON people.id = stars.person_id 26 | WHERE people.name = "Helena Bonham Carter"; 27 | -------------------------------------------------------------------------------- /Week 7 - SQL/ProblemSet7/Movies/13.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Write a SQL query to list the names of all people who starred in a movie in which Kevin Bacon also starred. 3 | Your query should output a table with a single column for the name of each person. 4 | There may be multiple people named Kevin Bacon in the database. Be sure to only select the Kevin Bacon born in 1958. 5 | Kevin Bacon himself should not be included in the resulting list. 6 | */ 7 | 8 | SELECT DISTINCT people.name 9 | FROM people 10 | JOIN stars 11 | ON stars.person_id = people.id 12 | WHERE stars.movie_id IN ( 13 | SELECT stars.movie_id 14 | FROM stars 15 | JOIN people 16 | ON people.id = stars.person_id 17 | WHERE people.name = "Kevin Bacon" AND people.birth = 1958) 18 | AND people.id NOT IN ( 19 | SELECT people.id 20 | FROM people 21 | WHERE people.name = "Kevin Bacon" AND people.birth = 1958); 22 | -------------------------------------------------------------------------------- /Week 7 - SQL/ProblemSet7/Movies/2.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Write a SQL query to determine the birth year of Emma Stone. 3 | Your query should output a table with a single column and a single row (not counting the header) containing Emma Stone’s birth year. 4 | You may assume that there is only one person in the database with the name Emma Stone. 5 | */ 6 | 7 | SELECT birth 8 | FROM people 9 | WHERE name = "Emma Stone"; 10 | -------------------------------------------------------------------------------- /Week 7 - SQL/ProblemSet7/Movies/3.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Write a SQL query to list the titles of all movies with a release date on or after 2018, in alphabetical order. 3 | Your query should output a table with a single column for the title of each movie. 4 | Movies released in 2018 should be included, as should movies with release dates in the future. 5 | */ 6 | 7 | SELECT title 8 | FROM movies 9 | WHERE year >= 2018 10 | ORDER BY title; 11 | -------------------------------------------------------------------------------- /Week 7 - SQL/ProblemSet7/Movies/4.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Write a SQL query to determine the number of movies with an IMDb rating of 10.0. 3 | Your query should output a table with a single column and a single row (not counting the header) containing the number of movies with a 10.0 rating. 4 | */ 5 | 6 | SELECT COUNT(title) 7 | FROM movies 8 | JOIN ratings 9 | ON ratings.movie_id = movies.id 10 | WHERE rating = 10.0; 11 | -------------------------------------------------------------------------------- /Week 7 - SQL/ProblemSet7/Movies/5.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Write a SQL query to list the titles and release years of all Harry Potter movies, in chronological order. 3 | Your query should output a table with two columns, one for the title of each movie and one for the release year of each movie. 4 | You may assume that the title of all Harry Potter movies will begin with the words “Harry Potter”, and that if a movie title begins with the words “Harry Potter”, it is a Harry Potter movie. 5 | */ 6 | 7 | SELECT title, year 8 | FROM movies 9 | WHERE title LIKE "Harry Potter%" 10 | ORDER BY year; 11 | -------------------------------------------------------------------------------- /Week 7 - SQL/ProblemSet7/Movies/6.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Write a SQL query to determine the average rating of all movies released in 2012. 3 | Your query should output a table with a single column and a single row (not counting the header) containing the average rating. 4 | */ 5 | 6 | SELECT AVG(rating) 7 | FROM ratings 8 | JOIN movies 9 | ON ratings.movie_id = movies.id 10 | WHERE year = 2012; 11 | -------------------------------------------------------------------------------- /Week 7 - SQL/ProblemSet7/Movies/7.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Write a SQL query to list all movies released in 2010 and their ratings, in descending order by rating. 3 | For movies with the same rating, order them alphabetically by title. 4 | Your query should output a table with two columns, one for the title of each movie and one for the rating of each movie. 5 | Movies that do not have ratings should not be included in the result. 6 | */ 7 | 8 | SELECT movies.title, ratings.rating 9 | FROM movies 10 | JOIN ratings 11 | ON ratings.movie_id = movies.id 12 | WHERE ratings.rating IS NOT NULL 13 | AND year = 2010 14 | ORDER BY ratings.rating DESC, movies.title ASC; 15 | -------------------------------------------------------------------------------- /Week 7 - SQL/ProblemSet7/Movies/8.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Write a SQL query to list the names of all people who starred in Toy Story. 3 | Your query should output a table with a single column for the name of each person. 4 | You may assume that there is only one movie in the database with the title Toy Story. 5 | */ 6 | 7 | SELECT people.name 8 | FROM people 9 | JOIN stars 10 | ON stars.person_id = people.id 11 | 12 | JOIN movies 13 | ON movies.id = stars.movie_id 14 | WHERE title = "Toy Story"; 15 | -------------------------------------------------------------------------------- /Week 7 - SQL/ProblemSet7/Movies/9.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Write a SQL query to list the names of all people who starred in a movie released in 2004, ordered by birth year. 3 | Your query should output a table with a single column for the name of each person. 4 | People with the same birth year may be listed in any order. 5 | No need to worry about people who have no birth year listed, so long as those who do have a birth year are listed in order. 6 | If a person appeared in more than one movie in 2004, they should only appear in your results once. 7 | */ 8 | 9 | SELECT DISTINCT people.name 10 | FROM people 11 | JOIN stars 12 | ON stars.person_id = people.id 13 | 14 | JOIN movies 15 | ON movies.id = stars.movie_id 16 | WHERE movies.year = 2004 17 | ORDER BY people.birth; 18 | -------------------------------------------------------------------------------- /Week 7 - SQL/ProblemSet7/Movies/info.txt: -------------------------------------------------------------------------------- 1 | https://cs50.harvard.edu/x/2023/psets/7/movies/ -------------------------------------------------------------------------------- /Week 8 - HTML, CSS, JavaScript/Lab8/Trivia/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Trivia! 10 | 11 | 12 | 13 |
14 |

Trivia!

15 |
16 | 17 |
18 |
19 |

Part 1: Multiple Choice

20 |
21 | 22 |

Which city is the state capital of California?

23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |

31 | 32 |
33 | 34 |
35 |

Part 2: Free Response

36 |
37 | 38 |

Which mountain peak is the highest in North America?

39 | 40 | 41 | 42 | 43 |

44 | 45 |
46 |
47 | 48 | 49 | -------------------------------------------------------------------------------- /Week 8 - HTML, CSS, JavaScript/Lab8/Trivia/script.js: -------------------------------------------------------------------------------- 1 | // Run the script when DOM content is loaded 2 | document.addEventListener("DOMContentLoaded", function() { 3 | // Check response for first question. 4 | 5 | // Change color to green if option is correct. 6 | let correctOption = document.querySelector(".correct"); 7 | 8 | correctOption.addEventListener("click", function() { 9 | correctOption.style.backgroundColor = "green"; 10 | document.querySelector("#feedback1").innerHTML = "Correct!"; 11 | }); 12 | 13 | // Change color to red if option is incorrect. 14 | let incorrectOption = document.querySelectorAll(".incorrect"); 15 | 16 | for (let i = 0; i < incorrectOption.length; i++) { 17 | incorrectOption[i].addEventListener("click", function() { 18 | incorrectOption[i].style.backgroundColor = "red"; 19 | document.querySelector("#feedback1").innerHTML = "Incorrect!"; 20 | }); 21 | } 22 | 23 | // Check response for second question. 24 | document.querySelector("#check").addEventListener("click", function() { 25 | 26 | let input = document.querySelector("input"); 27 | 28 | // Change color to green if input is correct. 29 | if (input.value.toLowerCase() == "denali") { 30 | input.style.backgroundColor = "green"; 31 | document.querySelector("#feedback2").innerHTML = "Correct!"; 32 | } 33 | // Change color to red if input is incorrect. 34 | else { 35 | input.style.backgroundColor = "red"; 36 | document.querySelector("#feedback2").innerHTML = "Incorrect!"; 37 | } 38 | }); 39 | }); 40 | -------------------------------------------------------------------------------- /Week 8 - HTML, CSS, JavaScript/Lab8/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 | 53 | 54 | input[type="text"] { 55 | line-height: 1.8; 56 | width: 25%; 57 | } 58 | 59 | input[type="text"]:hover { 60 | background-color: #f5f5f5; 61 | transition: color 2s ease-in-out, background-color 0.15s ease-in-out; 62 | } 63 | -------------------------------------------------------------------------------- /Week 8 - HTML, CSS, JavaScript/ProblemSet8/Homepage/about.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | About 19 | 20 | 21 | 22 |
23 | 24 |
25 | 26 | 53 | 54 |
55 | 56 | 57 | 58 | 59 | 60 | 71 | 72 |
73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /Week 8 - HTML, CSS, JavaScript/ProblemSet8/Homepage/contact.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | Contact 19 | 20 | 21 | 22 |
23 | 24 |
25 | 26 | 53 | 54 |
55 | 56 | 57 |
58 |
59 |

Leave a Message

60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 | 69 |
70 | 71 |
72 |
73 | 74 | 75 |
76 |
77 | 78 |
79 |
80 | 81 | 82 |
83 |
84 |
85 | 86 |
87 | 88 |
89 |
90 | 91 | 92 |
93 |
94 | 95 |
96 |
97 | 98 | 105 |
106 |
107 |
108 | 109 |
110 | 111 |
112 |
113 | 114 | 115 |
116 |
117 |
118 | 119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 | 130 | 131 | 142 |
143 | 144 | 145 | 146 | 147 | 148 | -------------------------------------------------------------------------------- /Week 8 - HTML, CSS, JavaScript/ProblemSet8/Homepage/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | Homepage 21 | 22 | 23 | 24 |
25 | 26 |
27 | 28 | 55 | 56 |
57 | 58 | 59 |
60 |
61 |
62 |
63 | 64 |

65 | Hello there,
my name is John Doe. 66 |

67 | 68 |

69 | I am a Full-Stack Developer. 70 |

71 | 72 | Read More → 73 |
74 |
75 |
76 |
77 | 78 | 79 | 90 | 91 |
92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /Week 8 - HTML, CSS, JavaScript/ProblemSet8/Homepage/portfolio.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | Portfolio 19 | 20 | 21 | 22 |
23 | 24 |
25 | 26 | 53 | 54 |
55 | 56 | 57 |
58 |

Projects

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

Space Invaders

66 | 67 |
Developed in Python using PyGame.
68 |

69 | A simple game of Space Invaders developed using the PyGame module. 70 |

71 | GitHub 72 |
73 |
74 | 75 |
76 |
77 |

Advanced Password Generator

78 | 79 |
Developed in JavaScript.
80 |

81 | Program that can generate different types of passwords. 82 |

83 | GitHub 84 |
85 |
86 | 87 |
88 |
89 |

IMDb Scraper

90 | 91 |
Developed in Python using BeautifulSoup.
92 |

93 | Scraper for retrieving data from the popular database. 94 |

95 | GitHub 96 |
97 |
98 | 99 |
100 |
101 |

Furniture Shop Website

102 | 103 |
A website developed for a client.
104 |

105 | Uses a few popular frameworks such as Bootstrap, Vue.js and Angular. 106 |

107 | GitHub 108 |
109 |
110 |
111 |
112 |
113 |
114 | 115 |
116 |
117 |

ETL Pipeline

118 | 119 |
Simple ETL pipeline design in Python.
120 |

121 | Uses data scraped in a previous project from IMDb. 122 |

123 | GitHub 124 |
125 |
126 | 127 |
128 |
129 |

CV Builder/Generator

130 | 131 |
Java project.
132 |

133 | Generates a custom CV from data given by the user. Has multiple templates to choose from and to customize. 134 |

135 | GitHub 136 |
137 |
138 | 139 |
140 |
141 |

Dashboard of Real Estate Properties

142 | 143 |
Developed in Python.
144 |

145 | Tool that can be used to optimize your choice of house/rental properties. 146 |

147 | GitHub 148 |
149 |
150 | 151 |
152 |
153 |

Ad Tracker

154 | 155 |
Developed in C#.
156 |

157 | Software used to track and manage ads in a browser. 158 |

159 | GitHub 160 |
161 |
162 |
163 |
164 | 165 | 166 | 177 | 178 |
179 | 180 | 181 | 182 | -------------------------------------------------------------------------------- /Week 8 - HTML, CSS, JavaScript/ProblemSet8/Homepage/styles.css: -------------------------------------------------------------------------------- 1 | /* General CSS */ 2 | 3 | body, html { 4 | background: radial-gradient(circle, rgba(255,255,255,1) 0%, rgba(181,181,181,1) 100%) !important; 5 | margin: 0 auto; 6 | padding: 0; 7 | height: 100%; 8 | box-sizing: border-box; 9 | font-family: "Lora", sans-serif; 10 | background: #fff; 11 | color: #000; 12 | overflow-x: hidden; /* hide overflow on the sides */ 13 | } 14 | 15 | ul { 16 | list-style: none; 17 | } 18 | 19 | img { 20 | max-width: 100%; 21 | } 22 | 23 | /* Links */ 24 | 25 | a { 26 | text-decoration: none; 27 | transition: all 0.5s ease-in-out; 28 | color: #fff !important; 29 | } 30 | 31 | /* Buttons */ 32 | 33 | a:hover { 34 | color: #bbb !important; 35 | } 36 | 37 | .button { 38 | border-radius: 1rem; 39 | border: none; 40 | background: radial-gradient(circle, rgba(120,167,97,1) 0%, rgba(67,112,63,1) 100%); 41 | transition: 0.3s; 42 | } 43 | 44 | .button:hover { 45 | color: #fff !important; 46 | box-shadow: 0px 0px 15px 5px rgba(0,0,0,0.5); 47 | transform: scale(1.05); 48 | } 49 | 50 | /* Titles */ 51 | 52 | .main-title { 53 | position: relative; 54 | margin-top: 2rem; 55 | margin-bottom: 2rem; 56 | text-align: center; 57 | } 58 | 59 | .main-title h1 { 60 | font-size: 40px; 61 | } 62 | 63 | /* Navigation Menu */ 64 | 65 | .navbar { 66 | position: relative; 67 | background: rgba(0,0,0,0.8); 68 | } 69 | 70 | .navbar-brand { 71 | font-family: "Ubuntu", sans-serif; 72 | font-size: 60px; 73 | } 74 | 75 | .first-letter { 76 | font-weight: 700; 77 | color: #78a761 !important; 78 | } 79 | 80 | .navbar-brand:hover { 81 | color: #fff !important; 82 | } 83 | 84 | .navbar-toggler { 85 | background-color: #fff; 86 | } 87 | 88 | .navbar-toggler:hover { 89 | background-color: #bbb; 90 | } 91 | 92 | .navbar-collapse { 93 | text-align: center; /* centers the navigation menu when collapsed */ 94 | } 95 | 96 | .navbar ul li { 97 | position: relative; 98 | margin-top: 2rem; 99 | margin-left: 2.5rem; 100 | margin-right: 0rem; 101 | margin-bottom: 2rem; 102 | } 103 | 104 | .navbar ul li a { 105 | position: relative; 106 | display: block; 107 | font-size: 20px; 108 | font-weight: 600; 109 | line-height: 14px; 110 | letter-spacing: 1.6px; 111 | } 112 | 113 | .is-active { 114 | border-bottom: 2px solid #78a761; 115 | } 116 | 117 | .is-active:hover { 118 | border-bottom: 2px solid #a3d18c; 119 | } 120 | 121 | /* Content */ 122 | 123 | .content { 124 | position: relative; 125 | padding-top: 5rem; 126 | padding-bottom: 3rem; 127 | font-weight: 500; 128 | } 129 | 130 | .content .content-title { 131 | position: relative; 132 | margin: 0; 133 | padding-top: 10rem; 134 | padding-bottom: 2rem; 135 | font-family: "Ubuntu", serif; 136 | font-size: 50px; 137 | font-weight: 600; 138 | letter-spacing: 1px; 139 | color: #000; 140 | } 141 | 142 | .content .content-description { 143 | position: relative; 144 | font-size: 25px; 145 | color: #000; 146 | } 147 | 148 | .content .content-button { 149 | text-transform: uppercase; 150 | } 151 | 152 | /* Footer */ 153 | 154 | .footer { 155 | position: fixed; /* using fixed position to make the footer stay at the bottom */ 156 | background: rgba(0,0,0,0.8); 157 | bottom: 0; 158 | width: 100%; 159 | padding-top: 20px; 160 | } 161 | 162 | .footer .socials .footer-list { 163 | position: relative; 164 | margin: 0 0 20px 0; 165 | display: inline-block; 166 | } 167 | 168 | .footer .socials .footer-list li { 169 | float: left; 170 | margin-right: 10px; 171 | } 172 | 173 | .footer .socials .footer-list li a { 174 | position: relative; 175 | font-size: 40px; 176 | font-weight: 500; 177 | letter-spacing: 0.5rem; 178 | color: #78a761 !important; 179 | } 180 | 181 | .footer .socials .footer-list li a:hover { 182 | color: #a3d18c !important; 183 | } 184 | 185 | /* About */ 186 | 187 | /* Skills */ 188 | 189 | .skills-page .card { 190 | background-color: rgba(104,104,104, 0.3); 191 | margin-bottom: 1rem; 192 | } 193 | 194 | .skills-page .card-title { 195 | text-align: center; 196 | font-size: 20px; 197 | font-weight: 700; 198 | } 199 | 200 | .skills-page .card-img-top { 201 | padding: 1rem; 202 | border-radius: 10%; 203 | } 204 | 205 | /* Portfolio */ 206 | 207 | .img-portfolio { 208 | height: 150px; 209 | width: 100%; 210 | } 211 | 212 | .card { 213 | background-color: rgba(104,104,104, 0.3); 214 | transition: 0.3s; 215 | border-radius: 1rem; 216 | } 217 | 218 | .card:hover { 219 | transform: scale(1.05); 220 | box-shadow: 10px 10px 15px rgba(0,0,0,0.3); 221 | } 222 | 223 | .card-title { 224 | font-size: 15px; 225 | } 226 | 227 | .card-text { 228 | height: 80px; 229 | } 230 | 231 | /* Contact */ 232 | 233 | .contact-container { 234 | padding-left: 5rem; 235 | padding-right: 5rem; 236 | margin-top: 10rem; 237 | } 238 | 239 | .contact-container .contact { 240 | transition: 0.3s; 241 | border-radius: 1rem; 242 | box-shadow: 0px 0px 50px 0px rgba(0,0,0,1); 243 | background-color: rgba(104,104,104, 0.3); 244 | } 245 | 246 | .contact-container .contact:hover { 247 | transform: scale(1.05); 248 | } 249 | 250 | .contact-container .button { 251 | width: 100%; 252 | margin-top: 0.5rem; 253 | } 254 | -------------------------------------------------------------------------------- /Week 9 - Flask/Lab9/Birthdays/app.py: -------------------------------------------------------------------------------- 1 | """ 2 | https://cs50.harvard.edu/x/2023/labs/9/ 3 | """ 4 | 5 | from cs50 import SQL 6 | from flask import Flask, flash, jsonify, redirect, render_template, request, session 7 | 8 | # Configure application 9 | app = Flask(__name__) 10 | 11 | # Ensure templates are auto-reloaded 12 | app.config["TEMPLATES_AUTO_RELOAD"] = True 13 | 14 | # Configure CS50 Library to use SQLite database 15 | db = SQL("sqlite:///birthdays.db") 16 | 17 | 18 | @app.after_request 19 | def after_request(response): 20 | """Ensure responses aren't cached""" 21 | response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate" 22 | response.headers["Expires"] = 0 23 | response.headers["Pragma"] = "no-cache" 24 | return response 25 | 26 | 27 | @app.route("/", methods=["GET", "POST"]) 28 | def index(): 29 | if request.method == "POST": 30 | 31 | # Add the user's entry into the database 32 | first_name = request.form.get("first_name") 33 | last_name = request.form.get("last_name") 34 | day = request.form.get("day") 35 | month = request.form.get("month") 36 | year = request.form.get("year") 37 | 38 | db.execute("INSERT INTO birthdays (first_name, last_name, day, month, year) VALUES (?, ?, ?, ?, ?)", first_name, last_name, day, month, year) 39 | 40 | return redirect("/") 41 | 42 | else: 43 | # Display the entries in the database on index.html 44 | birthdays = db.execute("SELECT * FROM birthdays") 45 | 46 | return render_template("index.html", birthdays=birthdays) 47 | -------------------------------------------------------------------------------- /Week 9 - Flask/Lab9/Birthdays/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, input[type="submit"] { 46 | background-color: #d9edff; 47 | border: 1px solid transparent; 48 | border-radius: 0.25rem; 49 | font-size: 0.95rem; 50 | font-weight: 400; 51 | line-height: 1.5; 52 | padding: 0.375rem 0.75rem; 53 | text-align: center; 54 | 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; 55 | vertical-align: middle; 56 | } 57 | 58 | input[type="text"], input[type="number"] { 59 | line-height: 1.8; 60 | width: 15%; 61 | } 62 | 63 | input[type="text"]:hover, input[type="number"]:hover { 64 | background-color: #f5f5f5; 65 | transition: color 2s ease-in-out, background-color 0.15s ease-in-out; 66 | } 67 | 68 | table { 69 | background-color: transparent; 70 | margin-bottom: 1rem; 71 | width: 100%; 72 | } 73 | 74 | table th, 75 | table td { 76 | padding: 0.75rem; 77 | vertical-align: middle; 78 | } 79 | 80 | tbody tr:nth-of-type(odd) { 81 | background-color: rgb(179, 208, 255, 0.3) 82 | } 83 | -------------------------------------------------------------------------------- /Week 9 - Flask/Lab9/Birthdays/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Birthdays 8 | 9 | 10 |
11 |

Birthdays

12 |
13 |
14 |
15 | 16 |

Add a Birthday

17 | 18 |
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 birthday in birthdays %} 41 | 42 | 43 | 44 | 45 | {% endfor %} 46 | 47 |
NameBirthday
{{ birthday["first_name"] }} {{ birthday["last_name"] }}{{ birthday["day"] }}/{{ birthday["month"] }}/{{ birthday["year"] }}
48 |
49 |
50 | 51 | 52 | -------------------------------------------------------------------------------- /Week 9 - Flask/ProblemSet9/Finance/helpers.py: -------------------------------------------------------------------------------- 1 | import os 2 | import urllib.parse 3 | import requests 4 | 5 | from flask import redirect, render_template, session 6 | from werkzeug.security import check_password_hash 7 | from datetime import datetime 8 | from functools import wraps 9 | 10 | 11 | def apology(message, code=400): 12 | """Render message as an apology to user.""" 13 | 14 | def escape(s): 15 | """ 16 | Escape special characters. 17 | 18 | https://github.com/jacebrowning/memegen#special-characters 19 | """ 20 | 21 | for old, new in [ 22 | ("-", "--"), 23 | (" ", "-"), 24 | ("_", "__"), 25 | ("?", "~q"), 26 | ("%", "~p"), 27 | ("#", "~h"), 28 | ("/", "~s"), 29 | ('"', "''"), 30 | ]: 31 | s = s.replace(old, new) 32 | return s 33 | 34 | if isinstance(message, str): 35 | message = escape(message) 36 | else: 37 | message = "Error occured!" 38 | 39 | return render_template("apology.html", top=code, bottom=message), code 40 | 41 | 42 | def login_required(f): 43 | """ 44 | Decorate routes to require login. 45 | 46 | https://flask.palletsprojects.com/en/1.1.x/patterns/viewdecorators/ 47 | """ 48 | 49 | @wraps(f) 50 | def decorated_function(*args, **kwargs): 51 | if session.get("user_id") is None: 52 | return redirect("/login") 53 | 54 | return f(*args, **kwargs) 55 | 56 | return decorated_function 57 | 58 | 59 | def lookup(symbol): 60 | """Look up quote for symbol.""" 61 | 62 | # Contact API 63 | try: 64 | api_key = os.environ.get("API_KEY") 65 | url = f"https://cloud.iexapis.com/stable/stock/{urllib.parse.quote_plus(symbol)}/quote?token={api_key}" 66 | response = requests.get(url) 67 | response.raise_for_status() 68 | except requests.RequestException: 69 | return None 70 | 71 | # Parse response 72 | try: 73 | quote = response.json() 74 | return { 75 | "name": quote["companyName"], 76 | "price": float(quote["latestPrice"]), 77 | "symbol": quote["symbol"], 78 | } 79 | except (KeyError, TypeError, ValueError): 80 | return None 81 | 82 | 83 | def usd(value): 84 | """Format value as USD.""" 85 | 86 | return f"${value:,.2f}" 87 | 88 | 89 | def get_time(): 90 | """Returns formatted local time.""" 91 | 92 | return datetime.now().strftime("%d-%m-%Y %H:%M:%S") 93 | 94 | 95 | def check_password(first_password, second_password): 96 | """Checks the passwords to be a match. Returns a message error if they do not match.""" 97 | 98 | if not check_password_hash(first_password, second_password): 99 | return apology("Passwords do not match!", code=401) 100 | -------------------------------------------------------------------------------- /Week 9 - Flask/ProblemSet9/Finance/requirements.txt: -------------------------------------------------------------------------------- 1 | cs50 2 | Flask 3 | Flask-Session 4 | requests 5 | -------------------------------------------------------------------------------- /Week 9 - Flask/ProblemSet9/Finance/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BogdanOtava/CS50x/91015c56adf89e719cd1b212f1a93784d900c6f2/Week 9 - Flask/ProblemSet9/Finance/static/favicon.ico -------------------------------------------------------------------------------- /Week 9 - Flask/ProblemSet9/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 | -------------------------------------------------------------------------------- /Week 9 - Flask/ProblemSet9/Finance/templates/apology.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% extends "layout.html" %} 4 | 5 | {% block title %} 6 | Apology 7 | {% endblock %} 8 | 9 | {% block main %} 10 | 11 | {{ top }} 12 | {% endblock %} 13 | -------------------------------------------------------------------------------- /Week 9 - Flask/ProblemSet9/Finance/templates/buy.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% extends "layout.html" %} 4 | 5 | {% block title %} 6 | Buy Shares 7 | {% endblock %} 8 | 9 | {% block main %} 10 |
11 |
12 | 13 | 14 | 15 | 16 |
17 |
18 | {% endblock %} 19 | -------------------------------------------------------------------------------- /Week 9 - Flask/ProblemSet9/Finance/templates/deposit.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% extends "layout.html" %} 4 | 5 | {% block title %} 6 | Deposit Funds 7 | {% endblock %} 8 | 9 | {% block main %} 10 |
11 |
12 | 13 | 14 | 15 | 16 |
17 |
18 | {% endblock %} 19 | -------------------------------------------------------------------------------- /Week 9 - Flask/ProblemSet9/Finance/templates/history.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% extends "layout.html" %} 4 | 5 | {% block title %} 6 | History 7 | {% endblock %} 8 | 9 | {% block main %} 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | {% for stock in portfolio %} 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | {% endfor %} 33 | 34 |
Company NameSymbolSharesActionBalanceTransacted
{{ stock["name"] }}{{ stock["symbol"] }}{{ stock["shares"] }}{{ stock["action"] }}{{ stock["balance"] }}{{ stock["date"] }}
35 |
36 | {% endblock %} 37 | -------------------------------------------------------------------------------- /Week 9 - Flask/ProblemSet9/Finance/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% extends "layout.html" %} 4 | 5 | {% block title %} 6 | Homepage 7 | {% endblock %} 8 | 9 | {% block main %} 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | {% for stock in portfolio %} 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | {% endfor %} 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 |
Company NameSymbolNo. of SharesBuying PriceCurrent PriceSTOCK VALUE
{{ stock["name"] }}{{ stock["symbol"] }}{{ stock["shares"] }}{{ stock["paid_price"] | usd }}{{ stock["current_price"] | usd }}{{ stock["stock_value"] | usd }}
CASH LEFT{{ cash_left | usd }}
TOTAL{{ total_amount | usd }}
45 |
46 | {% endblock %} 47 | -------------------------------------------------------------------------------- /Week 9 - Flask/ProblemSet9/Finance/templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | C$50 Finance: {% block title %}{% endblock %} 19 | 20 | 21 | 22 | 23 | 51 | 52 | {% if get_flashed_messages() %} 53 |
54 | 57 |
58 | {% endif %} 59 |
60 | {% block main %}{% endblock %} 61 |
62 | 63 |
64 | Data provided by IEX 65 |
66 | 67 | 68 | -------------------------------------------------------------------------------- /Week 9 - Flask/ProblemSet9/Finance/templates/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% extends "layout.html" %} 4 | 5 | {% block title %} 6 | Log In 7 | {% endblock %} 8 | 9 | {% block main %} 10 |
11 |
12 | 13 |
14 |
15 | 16 |
17 | 18 |
19 | {% endblock %} 20 | -------------------------------------------------------------------------------- /Week 9 - Flask/ProblemSet9/Finance/templates/quote.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% extends "layout.html" %} 4 | 5 | {% block title %} 6 | Quote 7 | {% endblock %} 8 | 9 | {% block main %} 10 |
11 |
12 | 13 | 14 | 15 |
16 |
17 | {% endblock %} 18 | -------------------------------------------------------------------------------- /Week 9 - Flask/ProblemSet9/Finance/templates/quoted.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% extends "layout.html" %} 4 | 5 | {% block title %} 6 | Search Results 7 | {% endblock %} 8 | 9 | {% block main %} 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
NameSymbolValue
{{ stock.name }}{{ stock.symbol }}{{ stock.price }}
26 | {% endblock %} 27 | -------------------------------------------------------------------------------- /Week 9 - Flask/ProblemSet9/Finance/templates/register.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% extends "layout.html" %} 4 | 5 | {% block title %} 6 | Register 7 | {% endblock %} 8 | 9 | {% block main %} 10 |
11 |
12 | 13 |
a 14 |
15 | 16 |
17 |
18 | 19 |
20 | 21 |
22 | {% endblock %} 23 | -------------------------------------------------------------------------------- /Week 9 - Flask/ProblemSet9/Finance/templates/sell.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% extends "layout.html" %} 4 | 5 | {% block title %} 6 | Sell Shares 7 | {% endblock %} 8 | 9 | {% block main %} 10 |
11 | 12 | 18 | 19 | 20 |
21 | {% endblock %} 22 | -------------------------------------------------------------------------------- /Week 9 - Flask/ProblemSet9/Finance/templates/withdraw.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% extends "layout.html" %} 4 | 5 | {% block title %} 6 | Deposit Funds 7 | {% endblock %} 8 | 9 | {% block main %} 10 |
11 |
12 | 13 | 14 | 15 | 16 |
17 |
18 | {% endblock %} 19 | --------------------------------------------------------------------------------