├── .gitignore
├── .nojekyll
├── Assessments
├── Quiz-1-Study-Guide.md
├── Quiz-2-Study-Guide.md
├── Quiz-3-Study-Guide.md
└── Quiz-Study-Guide.md
├── Assignments
├── 01-Graph-ADT.md
├── 02-Graph-Traversals.md
├── 03-Graph-Applications.md
├── 04-Weighted-Graphs.md
├── 05-Dynamic-Programming.md
├── 06-Graph-Applications.md
├── Assets
│ ├── 2-colorable-graphs.png
│ ├── 3-colorable-graph.png
│ ├── connected-components-graph.png
│ └── directed-acyclic-graph.png
├── Challenges.md
└── Graph-Tutorial.md
├── Challenges
└── Solutions
│ └── challenge_1
│ ├── challenge_1.py
│ ├── src
│ ├── __init__.py
│ ├── graph.py
│ ├── graph_file_reader.py
│ └── vertex.py
│ ├── test_inputs
│ ├── edge_incorrect.txt
│ ├── empty.txt
│ ├── extra_vertex.txt
│ ├── simple.txt
│ ├── type_incorrect.txt
│ ├── unused_vertex.txt
│ └── weighted.txt
│ ├── testing.py
│ └── tests
│ ├── __init__.py
│ ├── test_graph.py
│ ├── test_graph_file_reader.py
│ └── test_vertex.py
├── LICENSE
├── Lessons-T6-2019
├── 1.Intro-Graph-Theory.md
├── 2.Graph-Properties.md
├── 3.Graph-Traversals.md
├── 4.Weighted-Graph-Algorithms.md
├── 5.Advanced-Recursion-Dynamic-Programming.md
├── 6.Advanced-Recursion-Dynamic-Programming-2.md
├── 7.Traveling-Salesman.md
├── 8.Algorithm-Classification.md
└── More-Topics.md
├── Lessons
├── 01-Intro-to-Graph-Theory.md
├── 02-Graph-Traversals-BFS.md
├── 03-Graph-Traversals-DFS.md
├── 04-Topological-Sort.md
├── 05-Weighted-Graphs.md
├── 06-More-Weighted-Graphs.md
├── 07-Dynamic-Programming.md
├── 08-More-Dynamic-Programming.md
├── 09-Max-Flow.md
├── 10-More-Max-Flow.md
├── 11-Graph-Applications.md
├── 12-Graph-Applications-Lab.md
├── 13-NP-Complete.md
└── assets
│ └── graph.png
├── Projects
├── Final-Project.md
└── Graph-Project.md
├── README.md
├── Resources
├── graph-algorithms.md
├── graph-problems.md
└── graph-properties.md
├── Web
├── .nojekyll
├── logo-icononly.svg
├── style.css
└── sw.js
├── _navbar.md
├── _sidebar.md
└── index.html
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled source #
2 | ###################
3 | *.com
4 | *.class
5 | *.dll
6 | *.exe
7 | *.o
8 | *.so
9 | *.pyc
10 |
11 | # Packages #
12 | ############
13 | # it's better to unpack these files and commit the raw source
14 | # git has its own built in compression methods
15 | *.7z
16 | *.dmg
17 | *.gz
18 | *.iso
19 | *.jar
20 | *.rar
21 | *.tar
22 | *.zip
23 |
24 | # Logs and databases #
25 | ######################
26 | *.log
27 | *.sql
28 | *.sqlite
29 |
30 | # OS generated files #
31 | ######################
32 | .DS_Store
33 | .DS_Store?
34 | ._*
35 | .Spotlight-V100
36 | .Trashes
37 | ehthumbs.db
38 | Thumbs.db
--------------------------------------------------------------------------------
/.nojekyll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/CS-2.2-Graphs-Recursion/f4ed85d10b4c471fb2b12a81cb6bfa9ce6a2360b/.nojekyll
--------------------------------------------------------------------------------
/Assessments/Quiz-1-Study-Guide.md:
--------------------------------------------------------------------------------
1 | # Quiz 1: Graph Properties and Traversals
2 |
3 | Graph properties:
4 |
5 | - Given a problem (e.g. find a path from place A to place B), identify the vertices and edges and describe the problem in terms of a graph.
6 | - Compare and contrast directed & undirected graphs
7 | - Compare and contrast connected & disconnected graphs
8 |
9 | Graph traversals:
10 |
11 | - Implement Breadth-first Search / Traversal on a graph or digraph.
12 | - Implement Recursive Depth-first Search on a graph or digraph.
13 | - Write pseudocode for BFS, Iterative DFS or Recursive DFS.
14 | - Model solutions to applications using BFS or DFS, such as:
15 | - How should I get home? (Shortest path with BFS)
16 | - Is there a way to send data to all the computers on the network? (Connected graph with DFS)
17 |
18 |
--------------------------------------------------------------------------------
/Assessments/Quiz-2-Study-Guide.md:
--------------------------------------------------------------------------------
1 | # Quiz 2: Greedy Algorithms & Weighted Graphs
2 |
3 | You should be able to...
4 |
5 | - Describe a greedy algorithm to solve a real-world problem.
6 | - Describe a real-world use case for Minimum Spanning Tree.
7 | - Write pseudocode for Prim's Algorithm, Kruskal's Algorithm, and Dijkstra's Algorithm.
8 | - Explain how Union/Find is used in Kruskal's Algorithm.
9 | - Explain how a heap (or priority queue) is used in Prim's Algorithm & Dijkstra's Algorithm.
10 | - Analyze the runtime of various greedy algorithms.
11 | - Debug code for greedy algorithms covered in class.
12 | - Compare and contrast Dijkstra & Floyd-Warshall algorithms and give a use case for each.
--------------------------------------------------------------------------------
/Assessments/Quiz-3-Study-Guide.md:
--------------------------------------------------------------------------------
1 | # Quiz 3: Dynamic Programming & NP-Hard Problems
2 |
3 | ## Dynamic Programming
4 |
5 | - Given a recurrence relation, draw a graph of the recursive call stack.
6 | - Fill in a DP table for any of the 3 problems we've seen in class: 1) Longest Common Substring, 2) Knapsack, 3) Edit Distance.
7 | - Describe the recurrence relation for any of the above problems.
8 | - Describe the purpose of memoization; explain the differences between memoization & DP table
9 |
10 | ## NP-Hard Problems
11 |
12 | - Describe what it means for a problem to be NP-Hard
13 | - Describe what is a heuristic and how are they useful
14 | - Describe the "naive solution" for a given NP-Hard problem
--------------------------------------------------------------------------------
/Assessments/Quiz-Study-Guide.md:
--------------------------------------------------------------------------------
1 | # Quiz Study Guide
2 |
3 | ## Quiz Format
4 | Quizzes will be given in class either using on online format, paper format, or on interview / code interaction.
5 |
6 |
7 | 1. [General Instructions](#general-instructions)
8 | 1. [Quiz 1](#quiz-1)
9 | 1. [Quiz 2](#quiz-2)
10 | 1. [Quiz 3](#quiz-3)
11 | 1. [Quiz 4](#quiz-4)
12 |
13 |
14 | ## Quiz 1
15 | ### Graph Properties
16 | - Model problems with graphs and graph properties
17 | - Define several graph properties and identify them on a sample graph.
18 |
19 |
20 | ## Quiz 2
21 | ### Graph Traversal
22 | - Implement Breadth-first search/ traversal on an unweighted graph or digraph.
23 | - Implement Recursive Depth-first search on an unweighted graph or digraph.
24 | - Generate a spanning tree from DFS or BFS.
25 | - Write pseudocode for BFS, Iterative DFS or Recursive DFS
26 | - Model solutions to applications using BFS or DFS such as:
27 | - How should I get home? (Shortest path with BFS)
28 | - Is there a way to send data to all the computers on the network? (Connected graph with DFS))
29 |
30 |
31 | ## Quiz 3
32 | ### Greedy Algorithms on Weighted Graphs: Prim's Algorithm, Dijkstra's Algorithm
33 | - Describe greedy algorithms.
34 | - Give an example of a greedy algorithm (existing or one you make up) that doesn't give the optimal result.
35 | - Debug code that implements Dijkstra's algorithm.
36 | - Explain how Prim's algorithm works, implement by hand, debug code.
37 | - Discuss how a priority queue speeds up Dijkstra's algorithm.
38 |
39 |
40 | ## Quiz 4
41 | ### Dynamic Programming
42 | - Explain the 5 steps of Dynamic Programming.
43 | - Find a recurrence relation from a sub problem definition.
44 | - Draw a recursion tree from a recursive implementation of a dynamic programming problem.
45 | - Define memoization and how it speeds up a Dynamic Programming solution.
46 |
--------------------------------------------------------------------------------
/Assignments/01-Graph-ADT.md:
--------------------------------------------------------------------------------
1 | # Homework 1: Graph Abstract Data Type (ADT)
2 |
3 | In this assignment, you'll build out the **Graph** and **Vertex** classes, which we'll use throughout the course to model many different scenarios and build out algorithms to analyze those scenarios in various ways. You'll also get a bit of practice with using **Breadth-first Search** to solve various problems.
4 |
5 | ## Purpose (Why should I do this?)
6 |
7 | There are many ways to represent a graph in code. We'll be getting up close and friendly with the **Adjacency List** implementation. Building out the code will give you a better understanding of how the **Graph** class works, which will build up a foundation for tackling more complex graph algorithms.
8 |
9 | Scoring is as follows:
10 |
11 | | Criteria | Possible |
12 | | :------: | :------: |
13 | | Graph class | 20 |
14 | | File Reader | 20 |
15 | | Breadth-first Search & Find Neighbors | 20 |
16 | | Discussion Questions | 10 |
17 | | **TOTAL** | **70** |
18 |
19 | ## Instructions
20 |
21 | ### Getting Started
22 |
23 | Create a fork of the [Homework 1 starter code](https://classroom.github.com/a/_sde3eAN) by clicking on "Accept", then clone the repository to your local machine. When you make changes to your code, you will use `git add`, `git commit`, and `git push` as normal. When you are ready to submit, you will use the Gradescope GitHub integration to submit.
24 |
25 | If you have trouble with this, check out [this guide](https://hmc-cs-131-spring2020.github.io/howtos/assignments.html) on how to use GitHub Classroom and Gradescope. (Keep in mind there are some differences, e.g. our assignments are individual and not partnered, but it should answer most questions.)
26 |
27 | ## Graph Class _(20 Points)_
28 |
29 | Open the `graphs/graph.py` file and take a look at the code. The `Graph` class contains a _dictionary_ of its edges, with each vertex mapped to a list of edges.
30 |
31 | **Complete the code for** the missing `Graph` methods.
32 |
33 | After you are done, _manually test_ your code by running the `main.py` file in your terminal. Modify the `main.py` code to test many types of graphs!
34 |
35 | Then, run the built-in tests by running the following from your repository's root directory. The first two test cases should pass.
36 |
37 | ```bash
38 | $ python3 -m unittest discover
39 | ```
40 |
41 | ## File Reader _(20 Points)_
42 |
43 | Open the `util/file_reader.py` file. Your goal is to write a function that takes in the name of a text file, and returns a `Graph` object with vertices and edges as specified by the file.
44 |
45 | The files you read in will have the following format:
46 |
47 | - The first line is either `G` (for undirected graph) or `D` (for digraph)
48 | - The second line is a list of vertices separated by commas
49 | - The remaining lines are one vertex pair per line representing the edges (x, y).
50 |
51 | Here is an example of a graph file:
52 |
53 | ```
54 | G
55 | A,B,C,D
56 | (A,B)
57 | (A,D)
58 | (B,C)
59 | (B,D)
60 | ```
61 |
62 | If you need a refresher on File I/O in Python, check out [this guide](https://www.programiz.com/python-programming/file-operation).
63 |
64 | After you are done, _manually test_ your code by running the `main.py` file in your terminal. Modify the `main.py` code to test many types of graphs!
65 |
66 | Then, run the built-in tests by running the following from your repository's root directory. The first two test cases should pass.
67 |
68 | ```bash
69 | $ python3 -m unittest discover
70 | ```
71 |
72 | ## Breadth-first Search Traversal
73 |
74 | Take a look at the `bfs_traversal` method in the `Graph` class. This method "visits" every vertex in the graph, one at a time, in breadth-first-search order. This means that vertices that are closest to the start node (in terms of number of edges away) will be visited first, and the vertices that are furthest away from the start node will be visited last.
75 |
76 | The pseudocode of the function is roughly as follows:
77 |
78 | - Create a 'seen' set to hold the vertices we visit along the way. This step is necessary in order to avoid entering an infinite loop! If we've already 'seen' a vertex, we don't want to visit it again.
79 | - Create a queue to hold the vertices we'll be visiting next. Using a queue ensures that the vertices closest to the start (which are added to the queue first) are visited first.
80 | - While the queue is not empty, do the following:
81 | - Pop a vertex `v` from the queue (that is, remove it)
82 | - Process vertex `v` by printing it to the console (In some cases, "processing" a vertex could mean something different; in this case, we're just printing it.)
83 | - Put each of `v`'s unvisited neighbors into the queue.
84 |
85 | Run the method on a graph by running `main.py` and make sure it works as intended. If it doesn't, you may need to go back and fix your code for the `Vertex` and/or `Graph` classes.
86 |
87 | ### Find Shortest Path _(10 Points)_
88 |
89 | Complete the `find_shortest_path` method in the `Graph` class. This method uses a similar methodology to the `bfs_traversal` method, but now there's more that we need to keep track of! Instead of merely "visiting" each vertex, we need to know each vertex's shortest path from the start vertex. So, we can utilize the "seen" data structure to serve a dual purpose: It can keep track of what we've seen so far (so that we don't enter any infinite loops!), _and_ it can store each vertex's shortest path from the start.
90 |
91 | The pseudocode of the function is roughly as follows:
92 |
93 | - Create a `vertex_id_to_path` dictionary. This keeps track of the vertices we've seen so far, _and_ stores their shortest paths.
94 | - Create a queue to hold the vertices we'll be visiting next.
95 | - While the queue is not empty, do the following:
96 | - Pop a vertex `v` from the queue
97 | - If `v` is the target, quit early (this saves us some runtime, since we no longer care about the rest of the graph!)
98 | - Do the following for each of `v`'s unvisited neighbors `n`:
99 | - Extend `v`'s path by one vertex to form `n`'s path (that is, if the old path was `A -> B -> V`, it will now be `A -> B -> V -> N`)
100 | - Put `n` into the queue
101 | - After the queue is empty, return the path for the target vertex, or `None` if it was not found.
102 |
103 | Run the method on a graph by running `main.py` and make sure it works as intended. You can then run the provided unit tests with `python3 -m unittest discover`.
104 |
105 | ### Find All Connections of a Given Distance _(10 Points)_
106 |
107 | Complete the `find_vertices_n_away` method in the `Graph` class. This method should use breadth-first search to find all vertices that are `n` away from the start vertex, for some `n`.
108 |
109 |
110 |
111 | For example, using the graph above:
112 |
113 | - `find_vertices_n_away('A', 0)` should return `['A']`
114 | - `find_vertices_n_away('A', 1)` should return `['B', 'C']`
115 | - `find_vertices_n_away('A', 2)` should return `['D', 'E']`
116 | - `find_vertices_n_away('A', 3)` should return `['F']`
117 |
118 | Your solution should be similar to the `find_shortest_path` method. You may want to start by writing pseudocode, then writing real code.
119 |
120 | To test your code, make sure you run `main.py` to test manually, and run the provided unit tests with `python3 -m unittest discover`.
121 |
122 | ## Discussion Questions _(10 Points)_
123 |
124 | In your repository's `README.txt`, answer the following discussion questions:
125 |
126 | 1. How is Breadth-first Search different in graphs than in trees? Describe the differences in your own words.
127 |
128 | 2. What is one application of Breadth-first Search (besides social networks)? Describe how BFS is used for that application. If you need some ideas, check out [this article](https://www.geeksforgeeks.org/applications-of-breadth-first-traversal/?ref=rp).
129 |
130 | ## Submission
131 |
132 | Submit your code for Assignment 1 using [Gradescope](https://gradescope.com) using the GitHub integration feature. If you are unable to submit for any reason, please reach out to your instructor.
133 |
134 | ## Resources
135 |
136 | 1. [A Gentle Introduction to Graph Theory](https://medium.com/basecs/a-gentle-introduction-to-graph-theory-77969829ead8)
137 | 1. [Breadth-First Search for a Graph](https://www.geeksforgeeks.org/breadth-first-search-or-bfs-for-a-graph/)
138 | 1. [Shortest Path in an Unweighted Graph](https://www.geeksforgeeks.org/shortest-path-unweighted-graph/)
139 | 1. [File I/O in Python](https://www.programiz.com/python-programming/file-operation)
140 |
--------------------------------------------------------------------------------
/Assignments/02-Graph-Traversals.md:
--------------------------------------------------------------------------------
1 | # Homework 2: Graph Traversals
2 |
3 | In this assignment, you'll practice writing **Graph Traversal** functions using **Breadth-first Search** and **Depth-first Search** techniques.
4 |
5 | ## Purpose (Why should I do this?)
6 |
7 | Using graph traversal algorithms to solve problems is a helpful technique that has many applications, including in social networks, search engine web crawlers, peer-to-peer networks, and more. These techniques will also be helpful in solving programming interview questions.
8 |
9 | Scoring is as follows:
10 |
11 | | Criteria | Possible |
12 | | :------: | :------: |
13 | | Breadth-first Search Algorithms | 20 |
14 | | Depth-first Search Algorithms | 20 |
15 | | Topological Sort | 10 |
16 | | Discussion Questions | 10 |
17 | | **TOTAL** | **60** |
18 |
19 | ## Instructions
20 |
21 | You will continue working with your homework repository created for [Homework 1](Assignments/01-Graph-ADT). Take a look at the starter code [here](https://github.com/Make-School-Labs/Graph-ADT-Starter-Code) if you'd like a refresher.
22 |
23 | ## Breadth-first Search Algorithms _(20 Points)_
24 |
25 | ### Bipartite Graphs _(10 Points)_
26 |
27 | A **coloring** of a graph is an assignment of labels, often called _colors_, to each of its vertices. A graph coloring is a **proper coloring** if no two vertices in the graph which share an edge are assigned the same color.
28 |
29 | We say that a graph is **n-colorable** if we can assign it a proper coloring using **n** colors.
30 |
31 | For example, the following graph is **3-colorable** but **not** 2-colorable:
32 |
33 |
34 |
35 | Whereas the following 2 graphs are **2-colorable**:
36 |
37 |
38 |
39 | An undirected graph is **bipartite** if and only if it is 2-colorable; that is, if we can separate the vertices into 2 distinct sets (e.g. **Red** and **Blue**), such that no two vertices in the same set share an edge.
40 |
41 | **Write a method in the Graph class called** `is_bipartite()` which returns `True` if the graph is bipartite, and `False` otherwise. Your method should utilize the **Breadth-first Search** algorithm to assign colors to each of the vertices. If you find a vertex that has already been colored with the opposite color, then the method should return False.
42 |
43 | ```py
44 | class Graph:
45 | # ...
46 |
47 | def is_bipartite(self):
48 | """
49 | Return True if the graph is bipartite, and False otherwise.
50 | """
51 | pass
52 | ```
53 |
54 | ### Connected Components _(10 Points)_
55 |
56 | A **connected component** of an undirected graph is a set of vertices such that any two vertices are connected by a path (i.e. set of edges), and no other vertices in the graph are connected to the vertices in the set.
57 |
58 | For example, the following graph contains three connected components:
59 |
60 |
61 |
62 | We can represent the connected components in the above graph as a list of lists (with each connected component being a separate list), as follows:
63 |
64 | ```
65 | [
66 | ['A', 'B', 'C'],
67 | ['D', 'E', 'F'],
68 | ['G', 'H']
69 | ]
70 | ```
71 |
72 | **Write a method in the Graph class called** `get_connected_components()` that returns a list of connected components, as described above. Your method should loop over each vertex in the graph, and execute a **Breadth-first Search** from each unvisited vertex to find its connected component.
73 |
74 | ```py
75 | class Graph:
76 | # ...
77 |
78 | def get_connected_components(self):
79 | """
80 | Return a list of all connected components, with each connected component
81 | represented as a list of vertex ids.
82 | """
83 | pass
84 | ```
85 |
86 | ## Depth-first Search Algorithms _(20 Points)_
87 |
88 | ### Iterative Depth-first Search _(10 Points)_
89 |
90 | One way to implement a depth-first algorithm is to re-write the breadth-first algorithm, using a stack instead of a queue.
91 |
92 | **Write an iterative depth-first algorithm** to find _a_ path (not necessarily the _shortest_ path) from a start vertex to an end vertex.
93 |
94 | ```py
95 | def find_path_dfs_iter(self, start_id, target_id):
96 | """
97 | Use DFS with a stack to find a path from start_id to target_id.
98 | """
99 | pass
100 | ```
101 |
102 | ### Recursive Depth-first Search
103 |
104 | An example of a recursive depth-first function, to visit each node in DFS order, is as follows:
105 |
106 | ```py
107 | def dfs_traversal(self, start_id):
108 | """Visit each vertex, starting with start_id, in DFS order."""
109 |
110 | visited = set() # set of vertices we've visited so far
111 |
112 | def dfs_traversal_recursive(start_vertex):
113 | print(f'Visiting vertex {start_vertex.get_id()}')
114 |
115 | # recurse for each vertex in neighbors
116 | for neighbor in start_vertex.get_neighbors():
117 | if neighbor.get_id() not in visited:
118 | visited.add(neighbor.get_id())
119 | dfs_traversal_recursive(neighbor)
120 | return
121 |
122 | visited.add(start_id)
123 | start_vertex = self.get_vertex(start_id)
124 | dfs_traversal_recursive(start_vertex)
125 | ```
126 |
127 | You'll notice that this method contains an **inner function**, `dfs_traversal_recursive`, that executes the recursive part of the algorithm. Another way to structure the code would be to write `dfs_traversal_recursive` as a helper method that takes in a start vertex and the `visited` set.
128 |
129 | ### Cycle Detection _(10 Points)_
130 |
131 | A **cycle** in a graph is a path that has the same start and end vertex - that is, it loops back around to a vertex that was already in the path. Cycle detection is important in graph theory because it tells us a lot about the graph. For example, if a graph does _not_ contain a cycle, we can perform topological sort on the graph.
132 |
133 | **Write a method** `contains_cycle()` that returns `True` if the directed graph contains a cycle, and `False` otherwise. (All undirected graphs with at least one edge contain a cycle.)
134 |
135 | Make sure your method still works on graphs containing multiple connected components! You can do this by iterating over all the vertices in the graph, and executing a DFS traversal starting from each unvisited vertex.
136 |
137 | **HINT**: As you perform a DFS traversal, keep a `current_path` set containing all of the vertices in the current DFS path. If in the traversal you encounter a neighbor that is already in the `current_path`, you have found a cycle and can return True. Make sure to remove vertices from the `current_path` when going back up the traversal tree.
138 |
139 | ```py
140 | def contains_cycle(self):
141 | """
142 | Return True if the directed graph contains a cycle, False otherwise.
143 | """
144 | pass
145 | ```
146 |
147 | ## Topological Sort _(10 Points)_
148 |
149 | Topological Sort imposes an ordering on the vertices of a Directed Acyclic Graph (or DAG).
150 |
151 | Here is an example of a Directed Acyclic Graph:
152 |
153 |
154 |
155 | The vertices in this graph have two valid orderings: `['A', 'B', 'C', 'D', 'E', 'F']`, or `['A', 'C', 'B', 'D', 'E', 'F']`.
156 |
157 | Write a method `topological_sort()` that returns a valid ordering of vertices in a DAG. If the graph contains a cycle, the method should throw a `ValueError`.
158 |
159 | ```py
160 | def topological_sort(self):
161 | """
162 | Return a valid ordering of vertices in a directed acyclic graph.
163 | If the graph contains a cycle, throw a ValueError.
164 | """
165 | # TODO: Create a stack to hold the vertex ordering.
166 | # TODO: For each unvisited vertex, execute a DFS from that vertex.
167 | # TODO: On the way back up the recursion tree (that is, after visiting a
168 | # vertex's neighbors), add the vertex to the stack.
169 | # TODO: Reverse the contents of the stack and return it as a valid ordering.
170 | pass
171 | ```
172 |
173 | ## Discussion Questions _(10 Points)_
174 |
175 | Answer the following questions, using your own words, in the project's `README.md` file.
176 |
177 | 1. Compare and contrast Breadth-first Search and Depth-first Search by providing one similarity and one difference.
178 |
179 | 1. Explain why a Depth-first Search traversal does not necessarily find the shortest path between two vertices. What is one such example of a graph where a DFS search would _not_ find the shortest path?
180 |
181 | 1. Explain why we cannot perform a topological sort on a graph containing a cycle.
182 |
183 | ## Submission
184 |
185 | Submit your code for Assignment 2 using [Gradescope](https://gradescope.com) using the GitHub integration feature. If you are unable to submit for any reason, please reach out to your instructor.
186 |
187 | ## Resources
188 |
189 | 1. [Breadth First Search or BFS for a Graph](https://www.geeksforgeeks.org/breadth-first-search-or-bfs-for-a-graph/)
190 | 1. [Depth First Search or DFS for a Graph](https://www.geeksforgeeks.org/depth-first-search-or-dfs-for-a-graph/)
191 | 1. [Check whether a given graph is Bipartite or not](https://www.geeksforgeeks.org/bipartite-graph/)
192 | 1. [Detect Cycle in a Directed Graph
193 | ](https://www.geeksforgeeks.org/detect-cycle-in-a-graph/)
194 | 1. [Topological Sorting](https://www.geeksforgeeks.org/topological-sorting/)
195 |
196 |
--------------------------------------------------------------------------------
/Assignments/03-Graph-Applications.md:
--------------------------------------------------------------------------------
1 | # Homework 3: Graph Applications
2 |
3 | In this assignment, you'll continue to practice graph traversals using the algorithms we've studied so far.
4 |
5 | You will need to complete **3 out of 4** of the problems in order to earn full credit. Scoring for this assignment is as follows:
6 |
7 | | Criteria | Possible |
8 | | :------: | :------: |
9 | | Problem #1 | `15` |
10 | | Problem #2 | `15` |
11 | | Problem #3 | `15` |
12 | | **TOTAL** | **`45`** |
13 |
14 | ## Instructions
15 |
16 | Create a **new** folder for this assignment - you will be submitting it separately from your code for Homework 1 and 2.
17 |
18 | Initialize a Git repository in your project folder, create a repository on [GitHub](https://github.com), and commit and push your work.
19 |
20 | Create a file called `challenges.py` which will store your solution code.
21 |
22 | ## Problem 1: Number of Islands
23 |
24 | Write a function, `numIslands`, which takes in a 2D grid map of `1`s (land) and `0`s (water). Your function should return the number of distinct islands in the grid. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.
25 |
26 | **Example 1:**
27 |
28 | ```
29 | Input:
30 | 11110
31 | 11010
32 | 11000
33 | 00000
34 |
35 | Output: 1
36 | ```
37 |
38 | **Example 2:**
39 |
40 | ```
41 | Input:
42 | 11000
43 | 11000
44 | 00100
45 | 00011
46 |
47 | Output: 3
48 | ```
49 |
50 | Your algorithm should utilize a Breadth-first Search or Depth-first Search approach. You may utilize a helper `Graph` class if you wish.
51 |
52 | ```py
53 | def numIslands(grid):
54 | """Take in a grid of 1s (land) and 0s (water) and return the number of islands."""
55 | pass
56 |
57 | # Test Cases
58 | map1 = [
59 | [1, 1, 1, 1, 0],
60 | [1, 1, 0, 1, 0],
61 | [1, 1, 0, 0, 0],
62 | [0, 0, 0, 0, 0]
63 | ]
64 | assert numIslands(map1) == 1
65 |
66 | map2 = [
67 | [1, 1, 0, 0, 0],
68 | [1, 1, 0, 0, 0],
69 | [0, 0, 1, 0, 0],
70 | [0, 0, 0, 1, 1]
71 | ]
72 | assert numIslands(map2) == 3
73 | ```
74 |
75 | Text and examples from: LeetCode [Number of Islands](https://leetcode.com/problems/number-of-islands/)
76 |
77 |
78 | ## Problem 2: Rotting Oranges
79 |
80 | Write a function, `timeToRot`, which takes in a grid of numbers, each of which is one of the following three values:
81 |
82 | - A `0` represents an empty spot;
83 | - A `1` represents a fresh orange;
84 | - A `2` represents a rotten orange.
85 |
86 | Every minute, any fresh orange that is adjacent (up, down, left, right) to a rotten orange becomes rotten.
87 |
88 | Your function should return the minimum number of minutes that must elapse until no cell has a fresh orange. If this is impossible, return -1 instead.
89 |
90 | **Example 1:**
91 |
92 | ```
93 | Input:
94 | 2 1 1
95 | 1 1 0
96 | 0 1 1
97 | Output: 4
98 | ```
99 |
100 | **Example 2:**
101 |
102 | ```
103 | Input:
104 | 2 1 1
105 | 0 1 1
106 | 1 0 1
107 | Output: -1
108 | Explanation: The orange in the bottom left corner (row 2, column 0) is never rotten, because rotting only happens 4-directionally.
109 | ```
110 |
111 | **Example 3:**
112 |
113 | ```
114 | Input:
115 | 0 2
116 | Output: 0
117 | Explanation: Since there are already no fresh oranges at minute 0, the answer is just 0.
118 | ```
119 |
120 | Your algorithm should utilize a Breadth-first Search approach. You may utilize a helper `Graph` class if you wish.
121 |
122 | ```py
123 | def timeToRot(grid):
124 | """
125 | Take in a grid of numbers, where 0 is an empty space, 1 is a fresh orange, and 2 is a rotten
126 | orange. Each minute, a rotten orange contaminates its 4-directional neighbors. Return the number
127 | of minutes until all oranges rot.
128 | """
129 | pass
130 |
131 | # Test Cases
132 | oranges1 = [
133 | [2,1,1],
134 | [1,1,0],
135 | [0,1,1]
136 | ]
137 | assert timeToRot(oranges1) == 4
138 |
139 | oranges2 = [
140 | [2,1,1],
141 | [0,1,1],
142 | [1,0,1]
143 | ]
144 | assert timeToRot(oranges2) == -1
145 |
146 | oranges3 = [
147 | [0,2]
148 | ]
149 | assert timeToRot(oranges3) == 0
150 | ```
151 |
152 | Text and examples from: LeetCode [Rotten Oranges](https://leetcode.com/problems/rotting-oranges/)
153 |
154 | ## Problem 3: Class Scheduling
155 |
156 | There are a total of `n` courses you have to take, labeled from `0` to `n-1`.
157 |
158 | Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: `[0,1]`
159 |
160 | Given the total number of courses and a list of prerequisite pairs, return the ordering of courses you should take to finish all courses.
161 |
162 | There may be multiple correct orders, you just need to return one of them. If it is impossible to finish all courses, return an empty array.
163 |
164 | **Example 1:**
165 |
166 | ```
167 | Input: 2, [[1,0]]
168 | Output: [0,1]
169 | Explanation: There are a total of 2 courses to take. To take course 1 you should have finished
170 | course 0. So the correct course order is [0,1].
171 | ```
172 |
173 | **Example 2:**
174 |
175 | ```
176 | Input: 4, [ [1,0], [2,0], [3,1], [3,2] ]
177 | Output: [0,1,2,3] or [0,2,1,3]
178 | Explanation: There are a total of 4 courses to take. To take course 3 you should have finished both
179 | courses 1 and 2. Both courses 1 and 2 should be taken after you finished course 0.
180 | So one correct course order is [0,1,2,3]. Another correct ordering is [0,2,1,3].
181 | ```
182 |
183 | Your code should utilize a Topological Sort algorithm. You may utilize a helper `Graph` class if you wish.
184 |
185 | ```py
186 | def courseOrder(numCourses, prerequisites):
187 | """Return a course schedule according to the prerequisites provided."""
188 | pass
189 |
190 | # Test Cases
191 | courses1 = [ [1,0] ]
192 | assert courseOrder(2, courses1) == [0, 1]
193 |
194 | courses2 = [ [1,0], [2,0], [3,1], [3,2] ]
195 | possibleSchedules = [ [0, 1, 2, 3], [0, 2, 1, 3] ]
196 | assert courseOrder(4, courses2) in possibleSchedules
197 | ```
198 |
199 | Text and examples from: LeetCode [Course Schedule II](https://leetcode.com/problems/course-schedule-ii/)
200 |
201 | ## Problem 4: Word Ladder
202 |
203 | Write a function that takes in two words (`beginWord` and `endWord`), and a dictionary's word list. A word can be _transformed_ into another word if 1), they differ by only one letter, and 2) the new word exists in the dictionary.
204 |
205 | Return the length of shortest transformation sequence from `beginWord` to `endWord`.
206 |
207 | **Example 1:**
208 |
209 | ```
210 | Input:
211 | beginWord = "hit",
212 | endWord = "cog",
213 | wordList = ["hot","dot","dog","lot","log","cog"]
214 |
215 | Output: 5
216 |
217 | Explanation: As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog",
218 | return its length 5.
219 | ```
220 |
221 | Your code should utilize a Breadth-first Search approach. You may utilize a helper `Graph` class if you wish.
222 |
223 | ```py
224 | def wordLadderLength(beginWord, endWord, wordList):
225 | """Return the length of the shortest word chain from beginWord to endWord, using words from wordList."""
226 | pass
227 |
228 | # Test Cases
229 | beginWord = "hit"
230 | endWord = "cog"
231 | wordList = ["hot","dot","dog","lot","log","cog"]
232 |
233 | assert wordLadderLength(beginWord, endWord, wordList) == 5
234 | ```
235 |
236 | ## Submission
237 |
238 | Submit your code repository using [Gradescope](https://gradescope.com).
239 |
240 | ## Resources
241 |
242 | 1. [Breadth-first Search](https://www.geeksforgeeks.org/breadth-first-search-or-bfs-for-a-graph/)
243 | 1. [Depth-first Search](https://www.geeksforgeeks.org/depth-first-search-or-dfs-for-a-graph/)
244 | 1. [Topological Sorting](https://www.geeksforgeeks.org/topological-sorting/)
--------------------------------------------------------------------------------
/Assignments/04-Weighted-Graphs.md:
--------------------------------------------------------------------------------
1 | # Homework 4: Weighted Graphs
2 |
3 | In this assignment, you'll practice implementing **weighted graph algorithms**, including **Prim's**, **Kruskal's**, and **Dijkstra's**.
4 |
5 | | Criteria | Possible |
6 | | :------: | :------: |
7 | | WeightedVertex & WeightedGraph Classes | `15` |
8 | | Kruskal's Algorithm | `15` |
9 | | Prim's Algorithm | `15` |
10 | | Dijkstra's Algorithm | `15` |
11 | | **TOTAL** | **`60`** |
12 |
13 | ## Instructions
14 |
15 | Continue to use your **Homework 1 and 2** starter code for this assignment. Alternatively, you may make a copy of your existing code and submit it instead.
16 |
17 | ## WeightedVertex & WeightedGraph Classes
18 |
19 | In the `graphs` folder, take a look at the `weighted_graph.py` file. It contains two classes, `WeightedVertex` and `WeightedGraph`. Note that we are now storing vertices as objects, instead of strings. This is so that each vertex can keep track of the edge weights of each of their neighbors.
20 |
21 | Implement the `WeightedVertex` class methods `add_neighbor()`, `get_neighbors()`,
22 | and `get_neighbors_with_weights()`, as described.
23 |
24 | Implement the `WeightedGraph` class methods `add_vertex()` and `add_edge()`, as described.
25 |
26 | ## Kruskal's Algorithm - Find Edges of MST
27 |
28 | In the `WeightedGraph` class, add the following method signatures for finding a **Minimum Spanning Tree** using **Kruskal's Algorithm**:
29 |
30 | ```py
31 | class WeightedGraph:
32 | # ...
33 |
34 | def union(self, parent_map, vertex_id1, vertex_id2):
35 | """Combine vertex_id1 and vertex_id2 into the same group."""
36 | vertex1_root = self.find(parent_map, vertex_id1)
37 | vertex2_root = self.find(parent_map, vertex_id2)
38 | parent_map[vertex1_root] = vertex2_root
39 |
40 |
41 | def find(self, parent_map, vertex_id):
42 | """Get the root (or, group label) for vertex_id."""
43 | if(parent_map[vertex_id] == vertex_id):
44 | return vertex_id
45 | return self.find(parent_map, parent_map[vertex_id])
46 |
47 | def minimum_spanning_tree_kruskal(self):
48 | """
49 | Use Kruskal's Algorithm to return a list of edges, as tuples of
50 | (start_id, dest_id, weight) in the graph's minimum spanning tree.
51 | """
52 | # TODO: Create a list of all edges in the graph, sort them by weight
53 | # from smallest to largest
54 |
55 | # TODO: Create a dictionary `parent_map` to map vertex -> its "parent".
56 | # Initialize it so that each vertex is its own parent.
57 |
58 | # TODO: Create an empty list to hold the solution (i.e. all edges in the
59 | # final spanning tree)
60 |
61 | # TODO: While the spanning tree holds < V-1 edges, get the smallest
62 | # edge. If the two vertices connected by the edge are in different sets
63 | # (i.e. calling `find()` gets two different roots), then it will not
64 | # create a cycle, so add it to the solution set and call `union()` on
65 | # the two vertices.
66 |
67 | # TODO: Return the solution list.
68 | ```
69 |
70 | Fill in the TODOs to complete `minimum_spanning_tree_kruskal`. Make sure to test your code thoroughly to ensure its correctness.
71 |
72 | ## Prim's Algorithm - Find Weight of MST
73 |
74 | In the `WeightedGraph` class, add the following method signature for finding a **Minimum Spanning Tree** using **Prim's Algorithm**:
75 |
76 | ```py
77 | class WeightedGraph(Graph):
78 | # ...
79 |
80 | def minimum_spanning_tree_prim(self):
81 | """
82 | Use Prim's Algorithm to return the total weight of all edges in the
83 | graph's spanning tree.
84 |
85 | Assume that the graph is connected.
86 | """
87 | # TODO: Create a dictionary `vertex_to_weight` and initialize all
88 | # vertices to INFINITY - hint: use `float('inf')`
89 |
90 | # TODO: Choose one vertex and set its weight to 0
91 |
92 | # TODO: While `vertex_to_weight` is not empty:
93 | # 1. Get the minimum-weighted remaining vertex, remove it from the
94 | # dictionary, & add its weight to the total MST weight
95 | # 2. Update that vertex's neighbors, if edge weights are smaller than
96 | # previous weights
97 |
98 | # TODO: Return total weight of MST
99 | ```
100 |
101 | Fill in the TODOs to complete `minimum_spanning_tree_prim`. Make sure to test your code thoroughly to ensure its correctness.
102 |
103 | **Stretch Challenge**: Modify the algorithm to use a [heap](https://www.geeksforgeeks.org/heap-data-structure/) to find and retrieve the minimum weight vertex.
104 |
105 | ## Dijkstra's Algorithm - Shortest Path
106 |
107 | In the `WeightedGraph` class, add the following method signature for finding the **shortest path** between two vertices using **Dijkstra's Algorithm**:
108 |
109 | ```py
110 | class WeightedGraph(Graph):
111 | # ...
112 |
113 | def find_shortest_path(self, start_id, target_id):
114 | """
115 | Use Dijkstra's Algorithm to return the total weight of the shortest path
116 | from a start vertex to a destination.
117 | """
118 | # TODO: Create a dictionary `vertex_to_distance` and initialize all
119 | # vertices to INFINITY - hint: use `float('inf')`
120 |
121 | # TODO: While `vertex_to_distance` is not empty:
122 | # 1. Get the minimum-distance remaining vertex, remove it from the
123 | # dictionary. If it is the target vertex, return its distance.
124 | # 2. Update that vertex's neighbors by adding the edge weight to the
125 | # vertex's distance, if it is lower than previous.
126 |
127 | # TODO: Return None if target vertex not found.
128 | ```
129 |
130 | Fill in the TODOs to complete `find_shortest_path`. Make sure to test your code thoroughly to ensure its correctness.
131 |
132 | **Stretch Challenge**: Modify the algorithm to use a [heap](https://www.geeksforgeeks.org/heap-data-structure/) to find and retrieve the minimum weight vertex.
133 |
134 | ## Submission
135 |
136 | Submit your code repository using [Gradescope](https://gradescope.com).
137 |
138 | ## Resources
139 |
140 | 1. [Kruskal’s Minimum Spanning Tree](https://www.geeksforgeeks.org/kruskals-minimum-spanning-tree-algorithm-greedy-algo-2/)
141 | 1. [Disjoint Set (Or Union-Find)](https://www.geeksforgeeks.org/union-find/)
142 | 1. [Prim’s Minimum Spanning Tree](https://www.geeksforgeeks.org/prims-minimum-spanning-tree-mst-greedy-algo-5/)
143 | 1. [Dijkstra’s shortest path algorithm](https://www.geeksforgeeks.org/dijkstras-shortest-path-algorithm-greedy-algo-7/)
144 |
145 |
--------------------------------------------------------------------------------
/Assignments/05-Dynamic-Programming.md:
--------------------------------------------------------------------------------
1 | # Homework 5: Dynamic Programming
2 |
3 | In this assignment, you'll practice implementing **dynamic programming algorithms**.
4 |
5 | | Criteria | Possible |
6 | | :------: | :------: |
7 | | Longest Common Subsequence: Iterative | `10` |
8 | | Knapsack: Recursive | `10` |
9 | | Knapsack: Iterative | `10` |
10 | | Edit Distance: Recursive | `10` |
11 | | Edit Distance: Iterative | `10` |
12 | | **TOTAL** | **`50`** |
13 |
14 | ## Instructions
15 |
16 | Clone the [starter code](https://github.com/Make-School-Labs/CS-2.2-Dynamic-Programming-Starter) and fill out the functions in `challenges.py`.
17 |
18 | ## Longest Common Subsequence _(10 Points)_
19 |
20 | Take a look at the code for the **recursive** version of the **LCS** problem:
21 |
22 | ```py
23 | class Memoize:
24 | """Memoize a function by caching its result for each input."""
25 | def __init__(self, fn):
26 | self.fn = fn
27 | self.memo = {}
28 |
29 | def __call__(self, *args):
30 | if args not in self.memo:
31 | self.memo[args] = self.fn(*args)
32 | return self.memo[args]
33 |
34 |
35 | @Memoize
36 | def lcs(strA, strB):
37 | """Determine the length of the Longest Common Subsequence of 2 strings."""
38 | if len(strA) == 0 or len(strB) == 0:
39 | return 0
40 | elif strA[-1] == strB[-1]: # if the last characters match
41 | return 1 + lcs(strA[:-1], strB[:-1])
42 | else: # if the last characters don't match
43 | return max(lcs(strA[:-1], strB), lcs(strA, strB[:-1]))
44 | ```
45 |
46 | **NOTE**: The `Memoize` class is optional here, but will **significantly** speed up the runtime of the `lcs` function, as described in class.
47 |
48 | Now, **write the iterative version of the LCS function** using a **Dynamic Programming (DP) table**. If you're having trouble, watch [this video](https://www.youtube.com/watch?v=ASoaQq66foQ) to refresh your memory on the algorithm & intuition.
49 |
50 | **TIP**: Make sure to pay careful attention to your array indices - off-by-one errors are common here! It may help to choose an example (as in the video), plot it out on paper, then use that to determine the array indices to use at each point in the algorithm.
51 |
52 | ```py
53 | def lcs_dp(strA, strB):
54 | """Determine the length of the Longest Common Subsequence of 2 strings."""
55 | rows = len(strA) + 1
56 | cols = len(strB) + 1
57 |
58 | dp_table = [[0 for j in range(cols)] for i in range(rows)]
59 |
60 | # TODO: Fill in the table using a nested for loop.
61 |
62 | return dp_table[rows-1][cols-1]
63 | ```
64 |
65 | After you finish, try testing your code to verify that it works:
66 |
67 | ```
68 | $ python3 test_challenges.py
69 | ```
70 |
71 | **STRETCH CHALLENGE**: Write another function to return the _contents_ of the Longest Common Subsequence, not just its length.
72 |
73 | ## Knapsack Problem _(20 Points)_
74 |
75 | Complete the code for the Knapsack Problem, both the recursive version & DP (iterative) version.
76 |
77 | **TIP**: Pay careful attention to the inputs here: Each item in `items` is a tuple of `(name, weight, value)`, e.g. the tuple `('elephant', 500, 2000)` would refer to an elephant which weighs 500 pounds and is worth $2000.
78 |
79 | ```py
80 | def knapsack(items, capacity):
81 | """Return the maximum value that can be stored in the knapsack using the
82 | items given."""
83 | pass
84 |
85 | def knapsack_dp(items, capacity):
86 | """Return the maximum value that can be stored in the knapsack using the
87 | items given."""
88 | rows = len(items) + 1
89 | cols = capacity + 1
90 | dp_table = [[0 for j in range(cols)] for i in range(rows)]
91 |
92 | # TODO: Fill in the table using a nested for loop.
93 |
94 | return dp_table[rows-1][cols-1]
95 | ```
96 |
97 | After you finish, try testing your code to verify that it works:
98 |
99 | ```
100 | $ python3 test_challenges.py
101 | ```
102 |
103 | **STRETCH CHALLENGE**: Write another function to return the _contents_ of the Knapsack solution (e.g. a list of all item names included), not just its total value.
104 |
105 | ## Edit Distance _(20 Points)_
106 |
107 | The **Edit Distance** between 2 strings is the number of **edits** it takes to get from one string to the other, where an **edit** is defined as either an **insertion** (add a character), a **deletion** (remove a character), or a **replacement** (replace one character with another).
108 |
109 | Watch [this video](https://www.youtube.com/watch?v=MiqoA-yF-0M) on the Edit Distance problem and its DP solution.
110 |
111 | Complete the code for the Edit Distance, both the recursive version & DP (iterative) version.
112 |
113 | ```py
114 | def edit_distance(str1, str2):
115 | """Compute the Edit Distance between 2 strings."""
116 | pass
117 |
118 | def edit_distance_dp(str1, str2):
119 | """Compute the Edit Distance between 2 strings."""
120 | rows = len(str1) + 1
121 | cols = len(str2) + 1
122 | dp_table = [[0 for j in range(cols)] for i in range(rows)]
123 |
124 | # TODO: Fill in the table using a nested for loop.
125 |
126 | return dp_table[rows-1][cols-1]
127 | ```
128 |
129 | After you finish, try testing your code to verify that it works:
130 |
131 | ```
132 | $ python3 test_challenges.py
133 | ```
134 |
135 | ## Submission
136 |
137 | Submit your code repository using [Gradescope](https://gradescope.com).
138 |
139 | ## Resources
140 |
141 | 1. [Dynamic Programming](https://www.geeksforgeeks.org/dynamic-programming/)
142 | 1. [Longest Common Subsequence](https://www.geeksforgeeks.org/longest-common-subsequence-dp-4/)
143 | 1. [Knapsack](https://www.geeksforgeeks.org/0-1-knapsack-problem-dp-10/)
144 | 1. [Edit Distance](https://www.geeksforgeeks.org/edit-distance-dp-5/)
--------------------------------------------------------------------------------
/Assignments/06-Graph-Applications.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/CS-2.2-Graphs-Recursion/f4ed85d10b4c471fb2b12a81cb6bfa9ce6a2360b/Assignments/06-Graph-Applications.md
--------------------------------------------------------------------------------
/Assignments/Assets/2-colorable-graphs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/CS-2.2-Graphs-Recursion/f4ed85d10b4c471fb2b12a81cb6bfa9ce6a2360b/Assignments/Assets/2-colorable-graphs.png
--------------------------------------------------------------------------------
/Assignments/Assets/3-colorable-graph.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/CS-2.2-Graphs-Recursion/f4ed85d10b4c471fb2b12a81cb6bfa9ce6a2360b/Assignments/Assets/3-colorable-graph.png
--------------------------------------------------------------------------------
/Assignments/Assets/connected-components-graph.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/CS-2.2-Graphs-Recursion/f4ed85d10b4c471fb2b12a81cb6bfa9ce6a2360b/Assignments/Assets/connected-components-graph.png
--------------------------------------------------------------------------------
/Assignments/Assets/directed-acyclic-graph.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/CS-2.2-Graphs-Recursion/f4ed85d10b4c471fb2b12a81cb6bfa9ce6a2360b/Assignments/Assets/directed-acyclic-graph.png
--------------------------------------------------------------------------------
/Assignments/Challenges.md:
--------------------------------------------------------------------------------
1 | # Challenges
2 |
3 | 1. [General Instructions](#general-instructions)
4 | 1. [Challenge 1](#challenge-1)
5 | 1. [Challenge 2](#challenge-2)
6 | 1. [Challenge 3](#challenge-3)
7 | 1. [Challenge 4](#challenge-4)
8 | 1. [Challenge 5](#challenge-5)
9 |
10 |
11 | ## General instructions
12 | - Your code should go in the Challenge Folder of your personal repo that you created for this class.
13 | - Create a separate folder for each challenge, and copy any code you are re-using from the previous challenge before modifying. The code in each folder should only solve that challenge.
14 | - Your code should meet the following minimum requirements
15 | - meets PEP8 style guidelines
16 | - is well tested
17 | - is well documented
18 | - cites any sources used for inspiration and clearly indicates what code is used / modified from these sources
19 |
20 | - Unless otherwise stated, use simple concrete data types in your implementations (lists, dictionaries). Stretch challenges will give you an opportunity to refactor with collections and more complex data types.
21 |
22 | - Each challenge will read in a graphs from a text file with
23 | - the first line being a G or D (for graph or digraph)
24 | - the second line being a list of vertices,
25 | - remaining lines are one vertex pair per line representing the edges `(x,y)` or a triplet if there are weights ``(x, y, w)``
26 |
27 | ```
28 | G
29 | 1,2,3,4
30 | (1,2)
31 | (1,4)
32 | (2,3)
33 | (2,4)
34 | ```
35 |
36 | - Each challenge should be run from the command line and provide output in the format requested.
37 |
38 | - Your code should be in at least two files. File 1 must be named challege_X.py where X is the challenge number. This file will be run from the command line with arguments of the graph text file and (possibly) additional arguments needed for the challenge. `python3 challenge_1.py graph_data.txt`
39 |
40 | - Other files should follow best practices for code architecture (classes in a file with the class name, etc) but the structure is up to you.
41 |
42 | - You will be graded on if your code works (produces the correct output), and code quality based on the rubrics linked in each challenge.
43 |
44 | ## Challenge 1
45 | - Implement the Graph ADT with an adjacency list
46 | - Implement code to read in a graph from a text file to create an instance of the Graph ADT and use its methods.
47 |
48 | **Input:** A graph file (can contain a directed or undirected graph with or without weights)
49 | `python3 challenge_1.py graph_data.txt`
50 | ```
51 | G
52 | 1,2,3,4
53 | (1,2,10)
54 | (1,4,5)
55 | (2,3,5)
56 | (2,4,7)
57 | ```
58 |
59 | **Output:**
60 | * The # vertices in the graph.
61 | * The # edges in the graph.
62 | * A list of the edges with their weights (if weighted)
63 |
64 | ```
65 | # Vertices: 4
66 | # Edges: 4
67 | Edge List:
68 | (1,2,10)
69 | (1,4,5)
70 | (2,3,5)
71 | (2,4,7)
72 |
73 | ```
74 |
75 |
76 |
77 | ### Stretch Challenge 1
78 | - Re-implement the Graph ADT using one of the [python collections](https://docs.python.org/3.6/library/collections.html#module-collections).
79 |
80 | ### Challenge 1 Rubrics
81 | [Challenge Rubric Online - Beta Testing](https://www.makeschool.com/rubrics/UnVicmljLTQ=)
82 | or [Challenge Rubric Document](https://docs.google.com/document/d/1mRnSLMeuHLODGGxVI1-0AsTS7lqjNiemZCO9fo1gUzg/edit?usp=sharing)
83 |
84 | ## Challenge 2
85 |
86 | **Create a Challenge_2 folder in your challenge repository. Copy any code you want to re-use from Challenge 1 to that folder before modifying**
87 |
88 | Update your Graph ADT code to use Breadth-first search to compute the shortest path between two provided vertices in your graph.
89 |
90 | **Input:** A graph file (containing an undirected, unweighted graph), a from_vertex and a to_vertex.
91 |
92 | `python3 challenge_2.py graph_data.txt 1 5`
93 |
94 | ```
95 | G
96 | 1,2,3,4,5
97 | (1,2)
98 | (1,4)
99 | (2,3)
100 | (2,4)
101 | (2,5)
102 | (3,5)
103 | ```
104 |
105 | **Output:**
106 | The vertices in a shortest path from `from_vertex` to `to_vertex` and the number of edges in that path.
107 | ```
108 | Vertices in shortest path: 1,2,5
109 | Number of edges in shortest path: 2
110 |
111 | ```
112 | ### [Challenge 2 Rubric](https://www.makeschool.com/rubrics/UnVicmljLTk=)
113 |
114 | ## Challenge 3
115 |
116 | Update your Graph ADT code to do the following
117 | 1. Implement Recursive Depth-first search to determine if there is a path between two vertices in a **directed** graph.
118 |
119 | **Input:** A file containing a directed graph, a from_vertex and a to_vertex.
120 |
121 | `python3 challenge_3.py graph_data.txt 1 5`
122 |
123 | ```
124 | D
125 | 1,2,3,4,5
126 | (1,2)
127 | (1,4)
128 | (2,3)
129 | (2,4)
130 | (3,5)
131 | (5,2)
132 | ```
133 |
134 | **Output:**
135 | If there is a path between the vertices (T/F) and the vertices in that path.
136 | ```
137 | There exists a path between vertex 1 and 5: TRUE
138 | Vertices in the path: 1,2,3,5
139 |
140 |
141 | ```
142 |
143 | ### Stretch Challenges 3 : Dijkstra's and Priority Queue
144 | **Stretch Challenge 3.1** Implement Dijkstra's Algorithm to find the minimum weight path between two vertices in a weighted undirected graph.
145 |
146 | **Input:** A file containing a weighted undirected graph, a from_vertex and a to_vertex.
147 |
148 | `python3 challenge_3.py graph_data.txt 1 5`
149 |
150 | ```
151 | G
152 | 1,2,3,4,5
153 | (1,2,4)
154 | (1,4,5)
155 | (2,3,6)
156 | (2,4,9)
157 | (2,5,6)
158 | (3,5,10)
159 | ```
160 |
161 | **Output:**
162 | The vertices in a minimum weight path between the vertices and the weight of that path.
163 | ```
164 |
165 | The weight of the minimum weight path between vertex 1 and 5 is: 10
166 | Vertices in the path: 1,2,5
167 | ```
168 |
169 | **Stretch Challenge 3.2** (From CS 2.1). Implement BinaryMinHeap using a dynamic array and then implement Priory Queue using BinaryMinHeap. See [binary heap starter code](https://github.com/Make-School-Courses/CS-2.1-Advanced-Trees-and-Sorting-Algorithms/blob/master/Code/binaryheap.py) and [priority queue starter code](https://github.com/Make-School-Courses/CS-2.1-Advanced-Trees-and-Sorting-Algorithms/blob/master/Code/priorityqueue.py) for outline.
170 |
171 |
172 | ### [Challenge 3 Rubric](https://docs.google.com/document/d/1VHCcs3rFtrIaJRT5GWL3P-m3oagptYXuA2T9O67eJQU/preview)
173 |
174 | ## Challenge 4
175 | For this challenge, you can choose to work in pairs (recommended) or solo. If you work in pairs, both partners should submit an answer and clearly note who you worked with in your solution.
176 | - Your solutions will be in your Challenge GitHub repo and have both a README markdown file and code file(s).
177 |
178 | ### Part 1: Solve the Knapsack Problem using Dynamic Programming.
179 | 1. In your README - Clearly define the problem. Give full credit to any references you use.
180 | 1. In your README - Define in words, the 5 steps of DP as applied to this problem.
181 | 1. Write a an **iterative or memoized recursive solution** to this problem with hardcoded sample input. You do not have to read sample data from a file. Write your code in `knapsack.py` and other files as needed.
182 | ```python
183 | def knapsack(C, items, n):
184 | ''' A method to determine the maximum value of the items included in the knapsack
185 | without exceeding the capacity C
186 |
187 | Parameters:
188 | C= 50
189 | items = (("boot", 10, 60),
190 | ("tent", 20, 100),
191 | ("water", 30, 120),
192 | ("first aid", 15, 70))
193 | Returns: max value
194 | '''
195 | ```
196 | 4. Print the sample input and optimal solution
197 |
198 | ```
199 | For this input:
200 | items = (("boot", 10, 60),
201 | ("tent", 20, 100),
202 | ("water", 30, 120),
203 | ("first aid", 15, 70))
204 | Capacity of knapsack: 50
205 |
206 | The value of the optimal solution to the knapsack problem is V=230
207 | ```
208 |
209 | 5. Print the values included in the optimal solution (if computed) similar to how it is shown below with actual data from your problem. (your structure for storing input may be different).
210 |
211 | ```
212 | The items included in the knapsack for this optimal solution are
213 | (("boot", 10, 60),("tent", 20, 100),("first aid", 15, 70))
214 | ```
215 |
216 |
217 | ### Part 2: Solve any other DP problem not discussed in class.
218 | Choose any other Dynamic Programming problem from this list []() or elsewhere.
219 | 1. In your README - Clearly define the problem. Give full credit to any references you use.
220 | 1. In your README - Define in words, the 5 steps of DP as applied to this problem.
221 | 1. Write an **iterative or memoized recursive solution** to this problem with hardcoded small sample input. You do not have to read sample data from a file. Write your code in `dynamic_program.py` and other files as needed.
222 | 1. Print the sample input and optimal solution.
223 |
224 | ```
225 | For this input:
226 | XXXX
227 |
228 | The optimal solution is:
229 | YYYY
230 | ```
231 |
232 | 5. Print the values included in the optimal solution (if computed) similar to how it is shown below with actual data from your problem. (your structure for storing input may be different).
233 |
234 | ```
235 | The [values] included for this optimal solution are:
236 | ZZZZ
237 | ```
238 |
239 |
240 | ### [Challenge 4 Rubric](https://docs.google.com/document/d/1mRnSLMeuHLODGGxVI1-0AsTS7lqjNiemZCO9fo1gUzg/edit?usp=sharing) (updated)
241 |
242 |
243 |
244 | ## Challenge 5
245 | Using your Graph ADT code, or in a completely separate program (without a graph class). Determine if a given undirected graph is Eulerian (has an Eulerian Cycle). Your code should be well documented, tested and organized.
246 |
247 | **Input:** A file containing a undirected graph.
248 |
249 | `python3 challenge_5.py graph_data.txt`
250 |
251 | ```
252 | G
253 | 1,2,3,4,5
254 | (1,2)
255 | (2,3)
256 | (3,4)
257 | (4,5)
258 | (1,5)
259 | ```
260 |
261 | **Output** TRUE or FALSE
262 |
263 | ```
264 | This graph is Eulerian: TRUE
265 |
266 | ```
267 | [Challenge 5 Rubric](https://docs.google.com/document/d/1R3Zf4ogpu9g3dWJNxKAnnvV3c_EZ2q66lDUOJpptkjs/edit?usp=sharing)
268 |
--------------------------------------------------------------------------------
/Assignments/Graph-Tutorial.md:
--------------------------------------------------------------------------------
1 | # Your Social Network - Graph Tutorial
2 | [Graph Tutorial Rubric](https://docs.google.com/document/d/1ICVRzuDMIapVhpqbG7oHpk7_yCWu2bET8EYv6o_J9io/edit?usp=sharing)
3 |
4 |
5 | ## Chapter 0: Set up
6 | How many social network platforms are you currently on? Each of those is an example of graph theory being applied to solve the problem of finding connections – and recommending appropriate ones.
7 |
8 | In this tutorial, you'll build a graph of your nine closest friends and use graph theory to figure out interesting data about them.
9 |
10 | ### Learning Outcomes
11 | By the end of this tutorial, you will be able to...
12 |
13 | 1. Implement a graph in code.
14 | 1. Use a variety of neighbor lookup algorithms for a given graph
15 | 1. Traverse a graph through various search methods
16 |
17 |
18 | ### Using Git/GitHub
19 | Much like we've done in earlier tutorials, make sure you're committing your code as you complete milestones. At a minimum, you should make a commit whenever the tutorial prompts you.
20 |
21 | Let's get your repo set up!
22 |
23 | 1. Go to the [Graph Tutorial](https://github.com/Make-School-Labs/CS-2.2-Labs) and clone the repo locally.
24 | 1. Now we need to change the remote so that you can commit/push/pull the changes you make to your own repo. **It is very important you do the below steps in order to get everything working properly.**
25 | 1. Go to GitHub and create an _empty_, public repository called Graph-Tutorial, and now associate it as a remote for your cloned starter code, and then push to it.
26 | 1. Go to your repo on GitHub and make sure your previously empty repo is now full with starter code! Now when you add/commit/push, it'll be to your repo!
27 |
28 | ## Chapter 1: Who do you know?
29 | This tutorial will focus on properties of a social network. To begin with, we'll need to define a network as a set of people (vertices) and the people they know. If person *A* knows person *B* then there is an edge between them. We will begin by assuming that if person *A* knows person *B* then the reverse is also true. (So the edge is undirected).
30 |
31 | 1. Draw a graph with you at the center connected by and edge to another 9 people you know. Do any of these 9 know each other? If so draw an edge between them. This will be your "Social Graph" to use as a sample in the rest of this tutorial. Your graph must have the following properties:
32 | - Every person knows at least 2 other people.
33 | - No person knows more than 5 people.
34 |
35 | **Challenge** Add a diagram (or hand drawn image) of your friend network to the readme of your tutorial code. Label the nodes with you and your 9 friends names. If you don't want to use your real friends, feel free to use [Faker](https://faker.readthedocs.io/en/master/) to give fake names.
36 |
37 | ### Implement in code
38 |
39 | Throughout this tutorial we will build up a *graph data structure* that will implement our graph and graph algorithms in python.
40 |
41 | We will be building onto the basic Graph Abstract Data Type (ADT) which is defined as follows:
42 |
43 | ```python
44 |
45 | Graph() #creates a new, empty graph.
46 | add_vertex(vert) #adds an instance of vertex to the graph.
47 | add_edge(from_vert, to_vert) #Adds a new, directed edge to the graph that connects two vertices.
48 | add_edge(from_vert, to_vert, weight) #Adds a new, weighted, directed edge to the graph that connects two vertices.
49 | get_vertex(vertKey) #finds the vertex in the graph named vertKey.
50 | get_vertices() #returns the list of all vertices in the graph.
51 |
52 | ```
53 |
54 | **Challenge:** Implement the `Graph` class in the file *graph.py* and input your personal Social Graph with vertices and edges matching the diagram you drew of your friends. Note: Initially we'll create a `Vertex` class as a helper class to the `Graph` class.
55 |
56 | **Stretch Challenge:** Write a method that reads in graph data from a file and returns an instance of the `Graph` class. The file format should look like this:
57 |
58 | ```
59 | G
60 | 1,2,3,4
61 | (1,2)
62 | (1,3)
63 | (2,4)
64 | ```
65 |
66 | Your method might look something like this:
67 |
68 | ```python
69 | def make_graph_from_file(filename):
70 | # Check if first line is 'G' or 'D' and store the value. If neither, raise an exception
71 | # For each vertex id in first line, add a vertex to the graph
72 | # For each of the following lines:
73 | # Extract the vertex ids and the (optional) weight, and add an edge to the graph
74 | # If it is a Graph and not a Digraph, add another edge in the opposite direction
75 | # Raise an exception if line contains too many (or too few) items
76 | ```
77 |
78 | If the file is not formatted correctly, you can raise an exception:
79 |
80 | ```python
81 | raise Exception(f"File must begin with G or D, found {firstline}")
82 | ```
83 |
84 | ## Chapter 2: Won't you Be My Neighbor?
85 | Have you ever had that moment where you find out a friend knows another one of your friends? Having one of those "worlds collide" moments can be exciting, scary, or a whole mixture of emotions. Instead of having that situation surprise us, what if we had a way to know this information in advance?
86 |
87 | ### Find Your Neighbors
88 | Turns out we do! We can utilize a **neighbor lookup** for a given node in our graph to see what other nodes it is connected with. If you and a friend are connected, you two share a friendship. How do we know if two nodes are connected? _They share an edge!_
89 |
90 | **Challenge:** Write a method `get_neighbors` in the `Vertex` class that outputs all nodes connected to the current node.
91 |
92 | ```python
93 | def get_neighbors(self):
94 | # Make sure the input node is actually in the graph
95 | # Find all edges for the input node
96 | # See what nodes are connected to the input node via the edge
97 | # return the connected nodes
98 | ```
99 |
100 | ### Down The Friend Chain We Go
101 | All right, no more surprise connections for us! But what if we want to go even _further_ than one connection? Onward!
102 |
103 |
104 | ## Chapter 3: Breadth of Fresh Neighbors
105 |
106 | How does Facebook or LinkedIn know what friends to recommend to you? They look at who your friends are friends with, and who their friends are friends with, and so on
107 |
108 | 
109 |
110 | _Source: [Giphy](https://giphy.com/gifs/saturday-night-live-waynes-world-r73emnWNwTWRq)_
111 |
112 | ### Friends of Friends
113 | The function you just wrote is great for finding your immediate friends, but what if we want to see their friend's friends?
114 |
115 | Think back to CS 1.3: what's an algorithm at your disposal we could use here?
116 |
117 | Since we want to find _all_ friends at a certain connection level away (friend's friend would be 2 connections from you), this sounds like a perfect application of **Breadth First Search (BFS)**. Check out the [Tree Traversals lesson](https://github.com/Make-School-Courses/CS-1.3-Core-Data-Structures/blob/master/Lessons/TreeTraversals.md) from CS 1.3 if you want a refresher.
118 |
119 | **Challenge:** Write a method `breadth_first_search(self, vertex, n)`in the `Graph()` class that takes in a node, and `n` (an integer) as input, and outputs all nodes that are exactly `n` connections away from the input node.
120 |
121 |
122 | ```python
123 | def breadth_first_search(self, vertex, n):
124 | # Make sure the input node is actually in the graph
125 | # Run breadth_first_search starting from the input node and going `n` levels deep
126 | # Return all nodes found at the `n`th level
127 | ```
128 |
129 | ### A More Granular Approach
130 | Great application of BFS! But as with anything related to BFS, specificity isn't a strong suite. Having _all_ of your 3rd, 4th, 5th degree connections is daunting. What if we just want to see how two _specific_ people are connected? We'll solve this in the next chapter!
131 |
132 | ## Chapter 4: Friends Along the Way
133 | There's this idea of [six degrees of separation](https://en.wikipedia.org/wiki/Six_degrees_of_separation): take two people in the world, and they are at most six social connections away from each other. You may be more familiar with the [Six Degrees of Kevin Bacon](https://en.wikipedia.org/wiki/Six_Degrees_of_Kevin_Bacon) as an example of this.
134 |
135 | 
136 |
137 | _Source: [MisterDressup](https://www.teepublic.com/t-shirt/4930303-kevin-bacon-bacon-lover-funny-t-shirt)_
138 |
139 | You may not know Kevin Bacon (or _do_ you?), but we can still apply this to our graph of friends to find the connections that create a chain between two people. This is an application of **path finding**
140 |
141 | ### Finding the Path
142 | Think of a graph as a neighborhood, each house as a node, and immediate neighbors as nodes that share an edge. If you wanted to figure out how to get from one house to another, you'd walk to that house, passing other houses along the way. _You'd be walking a path, walking from one node to another via edges!_
143 |
144 | **Challenge:** Write a method `find_path(self, from_vert, to_vert)` in the `Graph()` class that takes in two nodes (`from_vert` and `to_vert`) as input, and outputs the list of nodes that must be traversed to get from `from_vert` to `to_vert`. The output list of nodes _must be in order of nodes visited starting from `from_vert` and ending at `to_vert`._ Note: This path doesn't have to be the shortest path, just a path.
145 |
146 | **Hint:** BFS or it's familiar friend **Depth First Search (DFS)** could be useful here. Again if you need a refresher, here's that [Tree Traversals lesson](https://github.com/Make-School-Courses/CS-1.3-Core-Data-Structures/blob/master/Lessons/TreeTraversals.md) from CS 1.3
147 |
148 | ```python
149 | def find_path(self, from_vert, to_vert):
150 |
151 | # Make sure that both nodes from_vert and to_vert are actually in the graph
152 | # Run BFS or DFS starting from from_vert
153 | # Figure out a way to keep track of each path you take
154 | # Once you find to_vert, end the search.
155 | # Since you've been tracking the paths, find the path that goes from from_vert to to_vert
156 | # Return the path, in the order of nodes visited starting with from_vert and ending with to_vert
157 | ```
158 |
159 | ### Optimizing our Path
160 | This works, but what if there are multiple paths between two nodes? What if one of those paths is significantly longer than the other? Do you know Veronica from high school from your cousin Ricky, who went to college with Sarah, who dated Jane, who is friends with Billy, who was on the swim team with Veronica? Or do you know Veronica from your friend Tom who also is friends with Veronica? In the next chapter, we'll learn how to differentiate paths in order to optimize our route.
161 |
162 | ## Chapter 5: Closest of Friends
163 | If you were trying to show how two people are socially connected, you would want to do so in the least number of connections possible. Can you imagine if LinkedIn couldn't determine if someone was a 2nd or 20th degree connection?
164 |
165 | ### Shortest Path
166 |
167 | In order to solve this problem, we want to find the **shortest path** between two nodes in a graph.
168 |
169 | **Challenge 1:** Write a method `find_shortest_path(self, A, B)` that takes two nodes (A and B) as input, and outputs the list of nodes that make up the _shortest path_ from A to B. The output list of nodes _must be in order of nodes visited starting from A and ending at B._
170 |
171 | ```python
172 | def find_shortest_path(self, A, B):
173 | # Make sure that both nodes A and B are actually in the graph
174 | # Run BFS starting from A
175 | # Figure out a way to keep track of each path you take
176 | # Once you find B, end the search.
177 | # Since you've been tracking the paths, find the shortest path that goes from A to B
178 | # Return the shortest path, in the order of nodes visited starting with A and ending with B
179 | ```
180 |
181 |
182 | It's great to find the _shortest_ path, but sometimes we want to know more about a graph. There's a lot of properties around distance we can measure, and we'll dive into another one of them in the next chapter!
183 |
184 |
185 |
186 | ### Clique through
187 | As with any large group of people, smaller groups start to form within the larger ones. We can find these cliques through graph theory. On to the next chapter to discover how..
188 |
189 | ## Chapter 6: Find your friend group
190 | Find “cliques” of friends (small groups of tightly-connected users), etc…
191 |
192 | The [clique problem](https://en.wikipedia.org/wiki/Clique_problem) is a popular computational problem in computer science.
193 | ### Clique Discovery
194 |
195 | Among other applications, the clique problem can arise in a social network. With our social network, a clique will represent a subset of people (nodes) who all know each other (share edges), and we can use various algorithms to find these cliques.
196 |
197 | **Challenge:** Write a method `clique(self)` that finds a clique in a graph that cannot have any other vertices added to it (note this is called a *maximal* clique).
198 |
199 |
200 | ```python
201 | def clique(self):
202 | #
203 | Start with an arbitrary vertex u and add it to the clique
204 |
205 | For v in remaining vertices not in the clique
206 | If v is adjacent to every other vertex already in the clique.
207 | Add v to the clique
208 | Discard v otherwise
209 |
210 | ```
211 |
212 | # Stretch Challenges
213 | Now that you've gotten a taste of how you can use graphs to find out more about your friends, here's a couple more applications to explore. These are stretch challenges, so feel free to skip too.
214 |
215 | ## STRETCH : Chapter 7: Long-Distance Friendships
216 |
217 | We know you're six degrees away from Kevin Bacon, but who are you the _furthest_ away from? Not your pen pal in Bhutan (that would still be a neighbor!), but someone you _don't_ know, and who you in fact know the least!
218 |
219 | ### Graph Diameter
220 | One concept around graph distance that helps us solve this problem is finding the **diameter** of a graph. The diameter of a graph is the calculated by _finding the shortest path between every possible pair of nodes, and then selecting the longest of those paths._
221 |
222 | **Challenge:** Write a method `diameter(self)` that outputs the diameter of the graph
223 |
224 | ```python
225 | def diameter(self):
226 | # For every node, find the shortest path from it to every other node in the graph and track the paths and their length
227 | # From your list of path/length pairs, pick the one with the largest length and return the length.
228 | ```
229 |
230 | *Note:* The algorithm above will work for small graphs, but takes a lot of time. There are lots of quicker algorithms you can use.
231 |
232 | **Stretch Challenges:** Find other properties of a graph! See if you can calculate the center or radius of a weighted graph. Keep these notes in mind:
233 |
234 | - A radius of a graph _must_ also have a diameter.
235 | - Radius can be calculated by finding the minimum distance among all the maximum distances between a node to all other nodes
236 | - The center of a graph is the set of all nodes where the greatest distance to other nodes is the shortest.
237 | - Read up on [eccentricity](https://en.wikipedia.org/wiki/Distance_(graph_theory) to help with this!
238 |
239 | ## STRETCH : Chapter 8: How to Win Friends and Influence Users
240 | Google's [PageRank](https://en.wikipedia.org/wiki/PageRank) algorithm is what they use to show you the most relevant search results for your query. Through this and other factors, Google influences what you see on that first page every single time you search something (and how often are you going past the first page?)
241 |
242 |
243 | ### PageRank Your Friends
244 |
245 | PageRank is currently implemented using concepts from graph theory, assigning scores of "relevance" to links. We're going to model that by doing the same thing to our social networks (what, you've never ranked your friends before?). _This is how social media influence is calculated!_ Let's find out which of our friends have the most influence in the network.
246 |
247 | The algorithm for PageRank uses an iterative approach, where each iteration improves our _approximation_ of the true PageRank value. For determining the importance of web pages, the rankings become stable after around 30-40 iterations. But for our much smaller graphs, the rankings will likely become stable after just a few iterations.
248 |
249 | 1. Each vertex is assigned an initial PageRank value of 1/n for n vertices. So if our social network has 10 users, each user is assigned 1/10.
250 | 1. For each iteration:
251 | 1. Assign each vertex a new PageRank value of 0.
252 | 1. For each vertex v, take v's previous PageRank value and divide it amongst v's outgoing links. So if v had a PageRank value of 1/10 and has links to a, b, and c, then a, b, and c will each receive 1/30 to their new PageRank values.
253 |
254 | Here's a great [video explanation](https://www.youtube.com/watch?v=P8Kt6Abq_rM) if you'd like to learn more.
255 |
256 | **Note:** For the below challenge, you'll be using a _directed_ weighted graph.
257 |
258 | **Stretch Challenge:** Write a method `influencer(self)` that uses the PageRank algorithm to rank you and your friends according to influence.
259 |
260 | ```python
261 | def influencer(self):
262 | # Create a dictionary of vertex -> PageRank value and set initial values to 1/n
263 | # For each iteration:
264 | # Create a new dictionary of vertex -> PageRank value, set all to 0
265 | # For each vertex v:
266 | # Divide up v's previous PageRank value amongst v's neighbors.
267 | # For m neighbors, each neighbor receives value/m
268 | # Replace previous PageRanks with new PageRanks
269 | # Sort all vertices according to their PageRank value, return sorted list
270 | ```
271 |
272 |
273 | **Congrats on completing your journey through your Social Network!**
274 |
275 | ### Feedback and Review - 2 minutes
276 |
277 | **We promise this won't take longer than 2 minutes!**
278 |
279 | Please take a moment to rate your understanding of the learning outcomes from this tutorial, and how we can improve it via our [tutorial feedback form](https://forms.gle/Wva3u51vBiDQHBAw9)
280 |
281 | This allows us to get feedback on how well the students are grasping the learning outcomes, and tells us where we can improve the tutorial experience.
282 |
--------------------------------------------------------------------------------
/Challenges/Solutions/challenge_1/challenge_1.py:
--------------------------------------------------------------------------------
1 | import sys
2 | from src.graph_file_reader import read_from_file
3 |
4 | def main():
5 | # Create the graph
6 | filename = sys.argv[1]
7 | g = read_from_file(filename)
8 |
9 | # Print number of vertices, edges
10 | print(f"# vertices: {len(g.get_vertices())}")
11 | print(f"# edges: {len(g.get_edges())} \n")
12 |
13 | # Print vertices
14 | print(f"The vertices are: {g.get_vertices()}")
15 |
16 | # Print edges
17 | print("The edges are: ")
18 | for edge in g.get_edges():
19 | print(edge)
20 |
21 | print(g.dijkstra(sys.argv[2], sys.argv[3]))
22 |
23 |
24 | if __name__ == "__main__":
25 | main()
26 |
--------------------------------------------------------------------------------
/Challenges/Solutions/challenge_1/src/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/CS-2.2-Graphs-Recursion/f4ed85d10b4c471fb2b12a81cb6bfa9ce6a2360b/Challenges/Solutions/challenge_1/src/__init__.py
--------------------------------------------------------------------------------
/Challenges/Solutions/challenge_1/src/graph.py:
--------------------------------------------------------------------------------
1 | from src.vertex import Vertex
2 |
3 | class Graph:
4 | """ Graph Class
5 | A class demonstrating the essential facts and functionalities of graphs.
6 | """
7 | # Static variables
8 | DEFAULT_EDGE_WEIGHT = 0
9 |
10 | def __init__(self, is_directed):
11 | """Initialize a graph object with an empty dictionary."""
12 | self.is_directed = is_directed
13 | self.vert_list = {}
14 |
15 | def add_vertex(self, key):
16 | """Add a new vertex object to the graph with the given key and return the vertex."""
17 | if key in self.vert_list:
18 | raise Exception(f"Vertex {key} already in graph.")
19 | self.vert_list[key] = Vertex(key)
20 | return self.vert_list[key]
21 |
22 | def get_vertex(self, key):
23 | """Return the vertex if it exists."""
24 | return self.vert_list[key]
25 |
26 | def get_vertices(self):
27 | """Return all the vertices in the graph."""
28 | return list(self.vert_list.keys())
29 |
30 | def get_num_vertices(self):
31 | """Return the number of vertices in the graph."""
32 | return len(self.vert_list.keys())
33 |
34 | def add_edge(self, key1, key2, weight=None):
35 | """Add an edge from vertex with key `key1` to vertex with key `key2` with a weight."""
36 | if weight is None:
37 | weight = Graph.DEFAULT_EDGE_WEIGHT
38 |
39 | # Add edges if they are not already in the graph
40 | if key1 not in self.vert_list:
41 | self.add_vertex(key1)
42 | if key2 not in self.vert_list:
43 | self.add_vertex(key2)
44 |
45 | # Add neighbor(s) to vertex objects
46 | self.vert_list[key1].add_neighbor(self.vert_list[key2], weight)
47 | if not self.is_directed:
48 | self.vert_list[key2].add_neighbor(self.vert_list[key1], weight)
49 |
50 | def get_edge_as_tuple(self, v, w):
51 | """
52 | Return a tuple representing the edge from v to w. If graph is
53 | undirected, v and w should be in alphabetical order to deduplicate.
54 |
55 | Parameters:
56 | v (Vertex): The 'from' vertex
57 | w (Vertex): The 'to' vertex
58 | """
59 | edge_tuple = None
60 | if self.is_directed:
61 | edge_tuple = (v.id, w.id, v.get_edge_weight(w))
62 | else:
63 | # Alphabetize if graph is undirected
64 | if v.id < w.id:
65 | edge_tuple = (v.id, w.id, v.get_edge_weight(w))
66 | else:
67 | edge_tuple = (w.id, v.id, w.get_edge_weight(v))
68 | # If edge weight is 0, do not include it in tuple
69 | if edge_tuple[2] == 0:
70 | edge_tuple = edge_tuple[:2]
71 | return edge_tuple
72 |
73 | def get_edges(self):
74 | """Return the list of edges with weights, as tuples."""
75 | edges = set()
76 | for v in self.vert_list.values():
77 | for w in v.neighbors:
78 | edges.add(self.get_edge_as_tuple(v, w))
79 | return edges
80 |
81 | def get_num_edges(self):
82 | num_total_edges = 0
83 | for v in self.vert_list.values():
84 | num_total_edges += len(v.get_neighbors())
85 | if self.is_directed:
86 | return num_total_edges
87 | else:
88 | return num_total_edges / 2
89 |
90 | def __iter__(self):
91 | """Iterate over the vertex objects in the graph, to use sytax: for v in g"""
92 | return iter(self.vert_list.values())
93 |
94 | def dijkstra(self, a, b):
95 | distances = {}
96 | min_distances = {}
97 | for vert in self.vert_list:
98 | distances[vert] = 10000
99 | distances[a] = 0
100 |
101 | while distances:
102 | next_vertex = min(distances.keys(), key=lambda v: distances[v])
103 | next_vertex_obj = self.vert_list[next_vertex]
104 |
105 | # put in min distances
106 | min_distances[next_vertex] = distances[next_vertex]
107 |
108 | # update its neighbors
109 | for neighbor in next_vertex_obj.get_neighbors():
110 | alt = distances[next_vertex] + next_vertex_obj.get_edge_weight(neighbor)
111 | if neighbor.id in distances and alt < distances[neighbor.id]:
112 | distances[neighbor.id] = alt
113 |
114 | # remove from queue
115 | del distances[next_vertex]
116 |
117 | return min_distances[b]
118 |
119 |
--------------------------------------------------------------------------------
/Challenges/Solutions/challenge_1/src/graph_file_reader.py:
--------------------------------------------------------------------------------
1 | from src.graph import Graph
2 |
3 | def read_from_file(filename):
4 | """Read from a file located at `filename` and return the corresponding graph object."""
5 | file = open(filename, "r")
6 | lines = file.readlines()
7 | file.close()
8 |
9 | # Check if it is a graph or digraph
10 | graph_or_digraph_str = lines[0].strip() if len(lines) > 0 else None
11 | if graph_or_digraph_str != "G" and graph_or_digraph_str != "D":
12 | raise Exception("File must start with G or D.")
13 | is_directed = graph_or_digraph_str == "D"
14 |
15 | g = Graph(is_directed)
16 |
17 | # Add all vertices
18 | for vertex_key in lines[1].strip("() \n").split(","):
19 | g.add_vertex(vertex_key)
20 |
21 | # Add all edges
22 | for line in lines[2:]:
23 | # Split components of edge
24 | new_edge = line.strip("() \n").split(",")
25 | if len(new_edge) < 2 or len(new_edge) > 3:
26 | raise Exception("Lines adding edges must include 2 or 3 values")
27 |
28 | # Get vertices
29 | vertex1, vertex2 = new_edge[:2]
30 |
31 | # Get weight if it exists
32 | weight = int(new_edge[2]) if len(new_edge) == 3 else None
33 |
34 | # Add edge(s)
35 | g.add_edge(vertex1, vertex2, weight)
36 |
37 | return g
--------------------------------------------------------------------------------
/Challenges/Solutions/challenge_1/src/vertex.py:
--------------------------------------------------------------------------------
1 | class Vertex(object):
2 | """ Vertex Class
3 | A helper class for the Graph class that defines vertices and vertex neighbors.
4 | """
5 |
6 | def __init__(self, vertex_id):
7 | """Initialize a vertex and its neighbors.
8 |
9 | neighbors: set of vertices adjacent to self,
10 | stored in a dictionary with key = vertex,
11 | value = weight of edge between self and neighbor.
12 | """
13 | self.id = vertex_id
14 | self.neighbors = {}
15 |
16 | def add_neighbor(self, vertex, weight=1):
17 | """Add a neighbor along a weighted edge."""
18 | if vertex not in self.neighbors:
19 | self.neighbors[vertex] = weight
20 |
21 | def __str__(self):
22 | """Output the list of neighbors of this vertex."""
23 | return f"{self.id} adjacent to {[x.id for x in self.neighbors]}"
24 |
25 | def get_neighbors(self):
26 | """Return the neighbors of this vertex."""
27 | return self.neighbors.keys()
28 |
29 | def get_id(self):
30 | """Return the id of this vertex."""
31 | return self.id
32 |
33 | def get_edge_weight(self, vertex):
34 | """Return the weight of this edge."""
35 | return self.neighbors[vertex]
36 |
--------------------------------------------------------------------------------
/Challenges/Solutions/challenge_1/test_inputs/edge_incorrect.txt:
--------------------------------------------------------------------------------
1 | D
2 | 1,2,3,4
3 | (1)
4 | (2,4)
5 | (3,4)
--------------------------------------------------------------------------------
/Challenges/Solutions/challenge_1/test_inputs/empty.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/CS-2.2-Graphs-Recursion/f4ed85d10b4c471fb2b12a81cb6bfa9ce6a2360b/Challenges/Solutions/challenge_1/test_inputs/empty.txt
--------------------------------------------------------------------------------
/Challenges/Solutions/challenge_1/test_inputs/extra_vertex.txt:
--------------------------------------------------------------------------------
1 | D
2 | 1,2,3,4
3 | (1,2)
4 | (2,4)
5 | (1,3)
6 | (2,6)
--------------------------------------------------------------------------------
/Challenges/Solutions/challenge_1/test_inputs/simple.txt:
--------------------------------------------------------------------------------
1 | G
2 | 1,2,3,4
3 | (1,2)
4 | (2,4)
5 | (1,3)
6 |
--------------------------------------------------------------------------------
/Challenges/Solutions/challenge_1/test_inputs/type_incorrect.txt:
--------------------------------------------------------------------------------
1 | X
2 | 1,2,3,4
3 | (1,2)
4 | (2,4)
5 | (1,3)
6 |
--------------------------------------------------------------------------------
/Challenges/Solutions/challenge_1/test_inputs/unused_vertex.txt:
--------------------------------------------------------------------------------
1 | D
2 | 1,2,3,4,5
3 | (1,2)
4 | (1,4)
5 | (2,3)
6 | (3,1)
--------------------------------------------------------------------------------
/Challenges/Solutions/challenge_1/test_inputs/weighted.txt:
--------------------------------------------------------------------------------
1 | D
2 | 1,6,10,15,21
3 | (1,6,9)
4 | (6,10,4)
5 | (6,15,2)
6 | (21,10,3)
7 | (15,1,10)
8 | (1,21,5)
--------------------------------------------------------------------------------
/Challenges/Solutions/challenge_1/testing.py:
--------------------------------------------------------------------------------
1 | from src.graph import Graph
2 |
3 | g = Graph(True)
--------------------------------------------------------------------------------
/Challenges/Solutions/challenge_1/tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/CS-2.2-Graphs-Recursion/f4ed85d10b4c471fb2b12a81cb6bfa9ce6a2360b/Challenges/Solutions/challenge_1/tests/__init__.py
--------------------------------------------------------------------------------
/Challenges/Solutions/challenge_1/tests/test_graph.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | from src.graph import Graph
3 | from src.vertex import Vertex
4 |
5 | class GraphTest(unittest.TestCase):
6 | def test_add_vertex(self):
7 | graph = Graph(True)
8 | graph.add_vertex("apple")
9 | graph.add_vertex("banana")
10 |
11 | self.assertEqual(2, graph.get_num_vertices())
12 | self.assertIsInstance(graph.get_vertex("apple"), Vertex)
13 |
14 |
15 | def test_add_edge(self):
16 | graph = Graph(True)
17 | graph.add_vertex("apple")
18 | graph.add_vertex("banana")
19 | graph.add_vertex("coconut")
20 |
21 | graph.add_edge("apple", "banana")
22 | graph.add_edge("apple", "coconut", 3)
23 |
24 | self.assertEqual(3, graph.get_num_vertices())
25 | self.assertEqual(2, graph.get_num_edges())
26 |
27 | graph.add_edge("pineapple", "strawberry")
28 |
29 | self.assertEqual(5, graph.get_num_vertices())
30 | self.assertEqual(3, graph.get_num_edges())
31 | self.assertCountEqual(
32 | ["apple", "banana", "coconut", "pineapple", "strawberry"],
33 | graph.get_vertices())
34 |
35 | def test_get_edge_as_tuple(self):
36 | graph = Graph(True)
37 | v1 = graph.add_vertex("apple")
38 | v2 = graph.add_vertex("banana")
39 | v3 = graph.add_vertex("coconut")
40 |
41 | graph.add_edge("apple", "banana")
42 | graph.add_edge("apple", "coconut", 3)
43 |
44 | self.assertEqual(("apple", "banana"), graph.get_edge_as_tuple(v1, v2))
45 | self.assertEqual(
46 | ("apple", "coconut", 3), graph.get_edge_as_tuple(v1, v3))
47 |
48 | if __name__ == "__main__":
49 | unittest.main()
--------------------------------------------------------------------------------
/Challenges/Solutions/challenge_1/tests/test_graph_file_reader.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | from src.graph_file_reader import read_from_file
3 |
4 | class FileInputTest(unittest.TestCase):
5 | """Test the graph output of reading from a file."""
6 |
7 | def test_input_type_incorrect(self):
8 | self.assertRaisesRegex(
9 | Exception, "File must start with", read_from_file,
10 | "test_inputs/type_incorrect.txt")
11 |
12 | def test_empty_file(self):
13 | self.assertRaisesRegex(
14 | Exception, "File must start with", read_from_file,
15 | "test_inputs/empty.txt")
16 |
17 | def test_edge_incorrect(self):
18 | self.assertRaisesRegex(
19 | Exception, "Lines adding edges", read_from_file,
20 | "test_inputs/edge_incorrect.txt")
21 |
22 | def test_basic_input(self):
23 | result_graph = read_from_file("test_inputs/simple.txt")
24 | self.assertEqual(4, result_graph.get_num_vertices())
25 | self.assertCountEqual(
26 | result_graph.get_vertices(),
27 | ['1', '2', '3', '4'])
28 |
29 | self.assertEqual(3, result_graph.get_num_edges())
30 | self.assertCountEqual(
31 | [('1', '2'), ('1', '3'), ('2', '4')],
32 | result_graph.get_edges())
33 |
34 | def test_extra_vertex(self):
35 | result_graph = read_from_file("test_inputs/extra_vertex.txt")
36 | self.assertEqual(5, result_graph.get_num_vertices())
37 | self.assertCountEqual(
38 | result_graph.get_vertices(),
39 | ['1', '2', '3', '4', '6'])
40 |
41 | self.assertEqual(4, result_graph.get_num_edges())
42 | self.assertCountEqual(
43 | [('1', '2'), ('1', '3'),
44 | ('2', '4'), ('2', '6')],
45 | result_graph.get_edges())
46 |
47 | def test_unused_vertex(self):
48 | result_graph = read_from_file("test_inputs/unused_vertex.txt")
49 | self.assertEqual(5, result_graph.get_num_vertices())
50 | self.assertCountEqual(
51 | result_graph.get_vertices(),
52 | ['1', '2', '3', '4', '5'])
53 |
54 | self.assertEqual(4, result_graph.get_num_edges())
55 | self.assertCountEqual(
56 | [('1', '2'), ('1', '4'),
57 | ('2', '3'), ('3', '1')],
58 | result_graph.get_edges())
59 |
60 | def test_weighted(self):
61 | result_graph = read_from_file("test_inputs/weighted.txt")
62 | self.assertEqual(5, result_graph.get_num_vertices())
63 | self.assertCountEqual(
64 | result_graph.get_vertices(),
65 | ['1', '6', '10', '15', '21'])
66 |
67 | self.assertEqual(6, result_graph.get_num_edges())
68 | self.assertCountEqual(
69 | [
70 | ('1', '6', 9),
71 | ('6','10',4),
72 | ('6','15',2),
73 | ('21','10',3),
74 | ('15','1',10),
75 | ('1','21',5)
76 | ],
77 | result_graph.get_edges())
78 |
79 | if __name__ == "__main__":
80 | unittest.main()
--------------------------------------------------------------------------------
/Challenges/Solutions/challenge_1/tests/test_vertex.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | from src.vertex import Vertex
3 |
4 | class VertexTest(unittest.TestCase):
5 | def test_add_neighbor(self):
6 | vertex1 = Vertex("apple")
7 | vertex2 = Vertex("banana")
8 | vertex3 = Vertex("coconut")
9 |
10 | vertex1.add_neighbor(vertex2)
11 | vertex1.add_neighbor(vertex3, 3)
12 |
13 | self.assertEqual(2, len(vertex1.neighbors))
14 | self.assertEqual(1, vertex1.neighbors[vertex2])
15 | self.assertEqual(3, vertex1.neighbors[vertex3])
16 |
17 | if __name__ == "__main__":
18 | unittest.main()
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Make School
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Lessons-T6-2019/1.Intro-Graph-Theory.md:
--------------------------------------------------------------------------------
1 | # Introduction to Graph Theory
2 |
3 | # [Slides](https://docs.google.com/presentation/d/1eOGVRA2ziw9swgB1t0VXn2_gnIWl1sd-H5xglgSa3-E/edit?usp=sharing)
4 |
5 |
6 | ## Why you should know this...
7 | Graph theory is a powerful tool for developing algorithmic thinking and modeling real world problems. Today we will get a glimpse of how we can use this tool by exploring both algorithms and modeling and then merging these together.
8 |
9 |
10 | ## Learning Objectives (5 min)
11 |
12 | 1. Practice modeling real world problems with graph theory.
13 | 1. Implement algorithms from graph theory with diagrams and pseudocode.
14 | 1. Define the Graph ADT and implement in code.
15 |
16 | ## Activity 1: Model & Implement [40 min]
17 | - With your pair, choose a Model or Implement scenario from the list.
18 | - [15 min] Using pseudocode, diagrams, whiteboards, etc. complete your scenario.
19 | - [5 min] Find another pair whose scenario maps to yours.
20 | - [15 min] Swap scenarios with the other pair
21 | - [5 min] Discuss the solutions
22 |
23 | ## Course Overview [20 min]
24 | - Go over syllabus, learning outcomes, course policies, key deliverables.
25 | - Our course learning approach: Model, Implement Solution, Synthesize & Algorithmic Thinking
26 |
27 | ## BREAK [10 min]
28 |
29 | ## Overview 2: Graphs & Digraphs [10 min]
30 | - A **graph** is a collection of **vertices** (also called nodes) and a collection of **edges** which connect one vertex to another. An edge from vertex *u* to vertex *v* is represented by the unordered pair *(u,v)* and is the same as an edge from *v* to *u*.
31 | - Unless otherwise noted, the term **graph** will represent a **undirected simple graph** which has at most one edge between two vertices, and no **loops** or edges from a vertex to itself.
32 |
33 | - A **digraph** (directed graph) is a collection of **vertices** and a collection of **arcs** (also called directed edges) which connect one vertex to another with an ordering. An arc from vertex *u* to *v* can be represented by the ordered pair *(u,v)* and this is different than an arc from vertex *v* to *u* represented as *(v,u)* .
34 |
35 | - A **weighted graph (or digraph)** is a graph (digraph) with weights assigned to its edges (arcs). The weight of an edge is denoted *w(u,v)* and can represent a variety of properties like distance, time, or cost.
36 |
37 |
38 | ## Activity 2: Graph Implementation [10 min]
39 | In pairs, write pseudocode to store and process a graph.
40 | - What data structure(s) should you use?
41 | - Does your structure allow weights? Edge direction?
42 | - What things might you want to compute on a graph and how does this affect your data structure?
43 | - How well does your structure support finding a path from vertex *u* to vertex *v*?
44 |
45 | ## Overview 3: Graph Representation
46 | There are many ways to represent a graph, the decision of which method to use is based on what you want to do with the graph. Most programming languages (including python) don't have a **graph** data structure. So we'll use the **Graph Abstract Data Type (ADT)** as a basis to define our own.
47 |
48 | The Graph ADT is defined as follows:
49 | ```python
50 |
51 | Graph() #creates a new, empty graph.
52 | addVertex(vert) #adds an instance of Vertex to the graph.
53 | addEdge(fromVert, toVert) #Adds a new, directed edge to the graph that connects two vertices.
54 | addEdge(fromVert, toVert, weight) #Adds a new, weighted, directed edge to the graph that connects two vertices.
55 | getVertex(vertKey) #finds the vertex in the graph named vertKey.
56 | getVertices() #returns the list of all vertices in the graph.
57 | getNeighbors(x) # lists all vertices y such that there is an edge from the vertex x to the vertex y;
58 |
59 | ```
60 |
61 |
62 | The implementation of the Graph ADT includes making choices about how to store the vertices and edges. We'll explore three methods:
63 |
64 |
65 | - **Edge List:** A graph is defined by its vertices and edges, so the simplest way to represent it is a list of vertices and a list of edges.
66 | - Positive: Easy to build.
67 | - Negative: Time to look up (`O(E)`).
68 |
69 | - **Adjacency Matrix:** A graph is defined by a matrix with rows and columns representing vertices and entries of 1 if an edge exist and 0 if not.
70 | - Positive: Easy to find, add, delete vertices or edges (`O(1)`)
71 | - Negative: Space use is more than necessary (`O(V^2)`) especially as most graphs are sparse.
72 |
73 | - **Adjacency List:** A graph is defined by an array of linked lists indicating which vertices are adjacent to each other. Each vertex is an index with its adjacent vertices stored in a linked list.
74 | - Positives: Easy to solve graph traversal problems
75 | - Negatives: Time to find edges is slightly more than in adjacency matrix.
76 |
77 |
78 |
79 | ## Activity 3: Implement the Graph ADT [40 min]
80 | - Start on Challenge 1 with your pair.
81 |
82 |
83 |
84 | ## Wrap Up (5 min)
85 |
86 | - Review Learning Outcomes
87 | - Overview of homework and topics for next class
88 |
89 | ## Challenges
90 | - [Challenge 1](../Challenges/Challenges.md#challenge-1)) : Implement the Graph ADT
91 |
92 | ## Interview Questions
93 | - Given this graph, how would you represent it in code?
94 | - [Clone a graph](https://leetcode.com/problems/clone-graph/)
95 |
96 | ## Resources:
97 | - [A Gentle Introduction To Graph Theory](https://medium.com/basecs/a-gentle-introduction-to-graph-theory-77969829ead8)
98 | - [Graph Theory](https://en.wikipedia.org/wiki/Graph_theory#Route_problems)
99 | - [From Theory To Practice: Representing Graphs](https://medium.com/basecs/from-theory-to-practice-representing-graphs-cfd782c5be38)
100 | - [How to think in graphs](https://medium.com/free-code-camp/i-dont-understand-graph-theory-1c96572a1401)
101 | - [Visualgo Graphs](https://visualgo.net/en/graphds)
102 |
--------------------------------------------------------------------------------
/Lessons-T6-2019/2.Graph-Properties.md:
--------------------------------------------------------------------------------
1 | # Graph Properties
2 |
3 | ## [Slides](https://docs.google.com/presentation/d/1VXFHzViCROaTJRJerTudUWWMTcYjbHEIMxP46_mSYtk/edit?usp=sharing)
4 |
5 |
6 | ## Why you should know this...
7 | When modeling real world problems in graphs and implementing graph algorithms, we need a common vocabulary to both describe the problem and abstract out the details to allow comparison to similar problems. If representing countries on a map and determining the menu at your next potluck can both be stated as finding a coloring of a graph, then solving one means you can solve the other.
8 |
9 |
10 | ## Learning Objectives (5 min)
11 |
12 | 1. Define common graph properties.
13 | 1. Model real world problems in terms of graph properties.
14 | 1. Compute graph properties in small graphs by hand through mathematical formulas and/or algorithm implementation.
15 |
16 | ## Review (20 min)
17 | - Code review in pairs.
18 | - Did you test your code?
19 | - Did you consider edge cases?
20 |
21 | ## Overview 1: Thinking about properties [10 min]
22 | - A property or characteristic of a graph is defined in terms of its vertices, edges or both.
23 | - EX: A *path* in a graph is a subset of the vertices and edges of the graph where the edges connect the vertices in a sequence without revisiting any vertices.
24 | - Problems are often represented through existence, instance, enumeration, or optimization of a property.
25 | - **Existence:** Does the graph have this property?
26 | - EX: Is there a path in graph G? (Yes, by definition every graph has at least one path)
27 | - EX: Is there a path of length 5 in G?
28 | - **Instance:** Find an example of the property in the graph.
29 | - EX: Find a path from vertex *u* to vertex *v* in G. List the vertices in the path.
30 | - **Enumeration:** How many instances of the property exist in the graph?
31 | - EX: How many paths of length 5 exist in G?
32 | - **Optimization:** Find a minimum or maximum instance of the property
33 | - EX: What is the longest path in G?
34 | - Graph algorithms are used to find the existence, instance, enumeration or optimization of graph properties.
35 |
36 | ## Activity 1: Property Worksheet [20 min]
37 | - With a partner, draw a simple graph (and digraph) and explore the definition, existence, instance, enumeration and optimization of common graph properties.
38 |
39 | ## BREAK [10 min]
40 |
41 | ## Overview 2 : Modeling with graphs and graph properties. [20 min]
42 | Modeling with graphs consists of representing the problem and the solution with a graph. Once we have a model, we can use an existing algorithm or define a new algorithm to find the solution, but we don't need this algorithm to create the model. There are many problems that we can model with graphs but we cannot (yet) solve.
43 |
44 | - Reduce. Build a small example of your problem space. What information can you ignore?
45 | - Clearly state what you are trying to solve. Only try to solve one thing.
46 | - Build the graph. What are the vertices, what are the edges? *(Tip: sometimes it is reversed)*
47 | - Illustrate your solution on the graph. What property does it map to?
48 |
49 | Once you have built a simple model, try it on a different example with more vertices / edges. Does it still hold up?
50 |
51 |
52 | ## Activity 2: Build and test models [20 min]
53 | - Working in pairs, create a model of your problem scenario. With diagrams, clear statements and graph notation, define the mapping of your problem to a graph and the solution to a graph property.
54 | - Swap with another pair - can they use your model and get to the correct solution (from your definition only)? If not, what clarification / modification is needed?
55 |
56 | ## Wrap Up (5 min)
57 |
58 | - Review Learning Outcomes
59 | - Overview of homework and topics for next class
60 |
61 |
62 | ## Resources
63 | - [Graph Properties](https://en.wikipedia.org/wiki/Graph_property)
64 | - [Graph Glossary](https://en.wikipedia.org/wiki/Glossary_of_graph_theory_terms)
65 |
--------------------------------------------------------------------------------
/Lessons-T6-2019/3.Graph-Traversals.md:
--------------------------------------------------------------------------------
1 | # Graph Traversals
2 |
3 | ## [Slides](https://docs.google.com/presentation/d/1bfFSSSj4j9H5nefw1gJfwvViPXt1RzdiyQ6l6ET2wAA/edit?usp=sharing)
4 |
5 | ## Why you should know this...
6 | Graph traversals allow us to discover and visit all the vertices in a graph. Traversals are used both to find common graph properties and form the basis of many other algorithms. We will revisit them throughout the class.
7 |
8 |
9 | ## Learning Objectives (5 min)
10 |
11 | 1. Implement Iterative version of Breadth-first search (BFS).
12 | 1. Find the shortest path between two vertices using Breadth-first search.
13 | 1. Implement Iterative and Recursive version of Depth-first search (DFS).
14 | 1. Compare and Contrast Depth-first search and Breadth-first search to determine when to use each traversal method.
15 |
16 | ## Review [15 min]
17 | Recall that you've already learned how to traverse a tree (CS 1.3) using either
18 | **Breadth-first search (BFS)** or **Depth-first search (DFS)**.
19 |
20 | #### BFS in Trees
21 |
22 |
23 | In BFS we visit the nodes one level at a time, starting with the root, then all the nodes on the next level moving from left to right, then on to the next level until we reach the last level and all nodes have been visited.
24 | #### DFS in Trees
25 |
26 | In DFS there are three different ways to visit the nodes: in-order, pre-order, and post-order. To simplify we'll just focus on in-order traversal in which we visit all the nodes in the left sub-tree first before the parent, then visit the parent, then visit all the nodes in the right sub-tree.
27 |
28 |
29 |
30 | ## Activity 1 [20 min]
31 |
32 | - Complete the first part of the [Traversal Worksheet](https://docs.google.com/document/d/1GyyRmSq1fN6vMWsthUcJQNV0LHcP4lGrMilbaIkbL8M/edit?usp=sharing) in pairs.
33 |
34 | - Now that you've refreshed your memory of how traversals work in trees, let's review how they work in graphs.
35 |
36 | ## Overview 1: Breadth-first Search [20 min]
37 |
38 | Breadth-first search (BFS) is an algorithm for traversing or searching tree or graph data structures. It starts at the tree root (or some arbitrary node of a graph, sometimes referred to as a 'search key'[1]), and explores all of the neighbor nodes at the present depth prior to moving on to the nodes at the next depth level.
39 |
40 |
41 | ### Shortest Path
42 |
43 | A common graph routing problem is to find the shortest path between two vertices in a connected weighted graph.
44 |
45 | - We can find the shortest path between two vertices with a modification of the Breadth-first search algorithm.
46 |
47 |
48 | ## Activity 1: Implement Shortest Path Algorithm [20 min]
49 | - Draw diagrams and write pseudocode to use BFS to find the shortest path between two vertices.
50 |
51 | ## Break [10 min]
52 |
53 |
54 | ## Overview 2: Depth-first search [15 min]
55 |
56 | Depth-first search (DFS) is an algorithm for traversing or searching tree or graph data structures. The algorithm starts at the root node (selecting some arbitrary node as the root node in the case of a graph) and explores as far as possible along each branch before backtracking.
57 |
58 | ### Spanning trees
59 | The set of nodes visited in BFS or DFS and the edges traversed form a tree. If the algorithm is run to traverse all vertices, then the tree formed is a **spanning tree**. By keeping track of the parent vertex when we perform BFS or DFS, we can recreate the path that we took to traverse the graph and this path is a spanning tree.
60 |
61 | ## Overview 3: Graph Traversal in Directed Graphs [10 min]
62 |
63 | ### Directed Graphs.
64 | - In a [directed graph](https://en.wikipedia.org/wiki/Directed_graph), the edges are ordered so the edge (1, 2) goes from vertex 1 to vertex 2.
65 | - The set of vertices that are adjacent to *v* are classified as in-neighbors or out-neighbors based on the direction of the edge.
66 | - Likewise, the number of in-neighbors is the in-degree of *v* while the number of out-neighbors is the out-degree of *v*.
67 |
68 | - A directed graph that has no cycles is called a *[Directed Acyclic Graph (DAG)](https://en.wikipedia.org/wiki/Directed_acyclic_graph)*. Many algorithms rely on the underlying graph being a DAG.
69 |
70 | - Traversal algorithms in directed graphs must follow the direction of the edges so only the vertices that are adjacent along the directed edge (out-neighbors) are considered at each iteration.
71 |
72 | ## Activity 3 [20 min]
73 | Discuss in pairs the pseudocode for the iterative and recursive implementations of Depth-first search on a directed graph. How could you use DFS to find a cycle in a graph?
74 |
75 |
76 |
77 | ## Wrap Up (5 min)
78 |
79 | - Review Learning Outcomes
80 | - Overview of homework and topics for next class
81 |
82 | ## Challenges
83 | [Challenge 2](../Challenges/Challenges.md#challenge-2) : Find a shortest path using BFS Search
84 |
85 | ## Stretch Challenges
86 | - Use traversal to find the connected components in a graph.
87 |
88 |
89 | ## Resources
90 | - [Deep Dive Through A Graph: DFS Traversal](https://medium.com/basecs/deep-dive-through-a-graph-dfs-traversal-8177df5d0f13)
91 | - [Going Broad In A Graph: BFS Traversal](https://medium.com/basecs/going-broad-in-a-graph-bfs-traversal-959bd1a09255)
92 | - [Spinning Around In Cycles With Directed Acyclic Graphs](https://medium.com/basecs/spinning-around-in-cycles-with-directed-acyclic-graphs-a233496d4688)
93 |
--------------------------------------------------------------------------------
/Lessons-T6-2019/4.Weighted-Graph-Algorithms.md:
--------------------------------------------------------------------------------
1 | # Weighted Graph Algorithms
2 |
3 | ## [Slides](https://docs.google.com/presentation/d/1mvH1YpsiDTl8T_fB6xYF_gkwF_M11DDCme8Agd0EACc/edit?usp=sharing)
4 |
5 | ## Why you should know this...
6 | One of the most common applications of graph theory is to find and optimize a route between two vertices. When working with weighted graphs, this is often done using a greedy algorithm like Prims or Dijkstra's.
7 |
8 |
9 | ## Learning Objectives (5 min)
10 |
11 | 1. Implement common graph routing and path algorithms on weighted graphs.
12 | 1. Implement Dijkstra's Algorithm using a priority queue.
13 | 1. Compare and Contrast Dijkstra's algorithm to other shortest path algorithm.
14 |
15 | ## Review [15 min]
16 | - Code review of shortest path in unweighted graph using BFS
17 |
18 |
19 | ## Activity 1: Minimum Spanning Tree
20 |
21 | A [minimum spanning tree](https://en.wikipedia.org/wiki/Minimum_spanning_tree) is a spanning tree with the minimum possible total edge weight.
22 |
23 | Develop your own algorithm for finding a minimum spanning tree. Discuss.
24 |
25 | ## Overview 1: Minimum Spanning Trees - Prim's Algorithm.
26 |
27 | While BFS and DFS can be used to find a spanning tree in a graph, they are not useful for finding a minimum spanning tree. This is because the algorithms do not consider the weight of an edge, so while they generate a spanning tree it may not be the one of minimal weight.
28 |
29 | There are several greedy algorithms to find a minimum spanning tree including [Prim's Algorithm](https://en.wikipedia.org/wiki/Prim%27s_algorithm) which builds a tree from an arbitrary starting vertex by repeatedly adding the cheapest possible edge to a vertex not currently in the tree.
30 |
31 | ## BREAK
32 |
33 | ## Overview 2: Minimum Weight Path - Dijkstra's Algorithm [20 min]
34 |
35 | A *minimum weight path* from vertex *a* to vertex *b* in a weighted graph is the path from *a* to *b* with a minimum possible total weight.
36 |
37 | While BFS is an efficient algorithm for finding a shortest path (path with the least number of edges), it can't be used to find a minimum weight path in a weighted graph because the shortest path in number of edges may not be the path of minimum weight.
38 |
39 | - EX: Consider a cycle on 3 vertices (a-b-c-a). The shortest path from a to c is one edge, but if this edge weight is greater than the combined weight of the edge from a to b and b to c, then the shortest path is not the minimum weight path.
40 |
41 |
42 | Similar to Prim's Algorithm for finding a minimum spanning tree, we can use a greedy approach to iteratively build a shortest path in a weighted graph or digraph.
43 |
44 | ### Dijkstra's Algorithm
45 |
46 | **[Dijkstra's Algorithm](https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm)** is a shortest path algorithm that visits neighbors one by one and assigns them a distance value based on the cumulative weights of the shortest path to get to that neighbor. Distances are updated if a shorter path can be found, so that once the target node is reached the shortest path is also computed.
47 |
48 | Consider the following pseudocode:
49 |
50 | ```
51 | - Mark all vertices unvisited and store them.
52 | - Set the distance to zero for initial vertex and to infinity for other vertices.
53 | - Select the unvisited vertex with the smallest distance to the current vertex, and label the new vertex as the current vertex.
54 | - Find unvisited neighbors (out-neighbors) for the current vertex and calculate their distances through the current vertex.
55 | - Compare the newly calculated distance to the current assigned value and save the smaller one.
56 | - Mark the current vertex as visited and remove it from the unvisited set.
57 | - Stop, if the destination vertex has been visited or if the smallest distance among the unvisited vertices is infinity.
58 |
59 | ```
60 | Data structures are needed to
61 | - Record if a vertex has been visited
62 | - Store the unvisited out-neighbors of each vertex
63 | - Store the current minimum distance between two vertices
64 |
65 | For the last of these, we will will use a [priority queue](https://en.wikipedia.org/wiki/Priority_queue) to keep track of the current best distance.
66 |
67 | ### Priority Queues
68 | A priority queue is an abstract data type similar to a regular queue with the additional property that each element has a priority associated with it. Elements with high priority are dequeued before elements with low priority. For our application, the priority will be the minimum distance between two vertices.
69 |
70 | - See [CS 2.1 Priority Queues](https://github.com/Make-School-Courses/CS-2.1-Advanced-Trees-and-Sorting-Algorithms/blob/master/Lessons/Heaps.md) for more resources
71 |
72 |
73 | ## Activity 2: Implement Dijkstra's Algorithm [20 min]
74 | - Build a sample 7 vertex connected graph and implement Dijkstra's algorithm on it using pseudocode.
75 | - Start of the challenge homework of implementing Dijkstra's algorithm in code.
76 |
77 |
78 | ## Wrap Up (5 min)
79 |
80 | - Review Learning Outcomes
81 | - Overview of homework and topics for next class
82 |
83 |
84 |
85 | ## Resources
86 | - [Spinning Around In Cycles With Directed Acyclic Graphs](https://medium.com/basecs/spinning-around-in-cycles-with-directed-acyclic-graphs-a233496d4688)
87 | - [Dijkstra's Algorithm - Brilliant.org](https://brilliant.org/wiki/dijkstras-short-path-finder/)
88 | - [Finding The Shortest Path, With A Little Help From Dijkstra](https://medium.com/basecs/finding-the-shortest-path-with-a-little-help-from-dijkstra-613149fbdc8e)
89 | - [Priority Queue in Python](https://www.pythoncentral.io/priority-queue-beginners-guide/)
90 |
--------------------------------------------------------------------------------
/Lessons-T6-2019/5.Advanced-Recursion-Dynamic-Programming.md:
--------------------------------------------------------------------------------
1 | # Advanced Recursion and Dynamic Programming
2 |
3 | ## [Slides](https://docs.google.com/presentation/d/1l_PiwpgssIQpflZxSo9NHYObCaIpQeQAs6W6g4FgVVY/edit#slide=id.g5df7b93ad9_0_0)
4 |
5 | ## Why you should know this...
6 | Dynamic programming is a common technique that allows us to solve a problem by breaking it into subproblems and solving those. This makes problems that would take a long time to solve run much quicker!
7 |
8 |
9 | ## Learning Objectives (5 min)
10 |
11 | 1. Implement Dynamic Programming to improve algorithm speed.
12 | 1. Explore advanced recursion implementations.
13 | 1. Compare and contrast Brute Force and Dynamic Programming algorithms.
14 |
15 |
16 | ## Overview 1: Memoization in Fibonacci [ 20 min]
17 |
18 | [Memoization](https://en.wikipedia.org/wiki/Memoization) is a technique to speed up recursion by storing the results of recursive calls and returning the cached result when the same inputs are required.
19 |
20 | ## Activity 1: Faster Fibonacci [20 min]
21 | - Write code to implement Fibonacci with and without memoization. Benchmark and compare results.
22 |
23 |
24 | ## Overview 2: Dynamic Programming [30 min]
25 | - [Dynamic Programming](https://en.wikipedia.org/wiki/Dynamic_programming) is the process of simplifying a complicated problem by breaking it down into simpler sub-problems in a recursive manner. The 'programming' part of the name actually refers to the process of optimization, not coding. However, we will use this process to implement more effective algorithms in code by breaking problems into sub-problems and then recursively finding the optimal solutions to the sub-problems.
26 |
27 | The five steps of Dynamic Programming are:
28 | 1. Identify the subproblems
29 | 1. Guess first choice
30 | 1. Recursively define the value of an optimal solution
31 | 1. Compute the value of an optimal solution (recurse and memoize)
32 | 1. Solve original problem - reconstruct from the subproblems
33 |
34 | As we've already seen, the recurse and memoize step is a quick way to improve the speed of a recursive algorithm.
35 |
36 | The process of breaking the problem into smaller subproblems is the key step to dynamic programming. We'll start by looking at several non-graph theory problems and identifying subproblems there.
37 |
38 | ## Break [10 min]
39 |
40 | ## Overview: Dynamic Programming - Minimum Weight Path
41 | The minimum weight path we solved using Dijkstra's algorithm, can also be solved with dynamic programming.
42 |
43 |
44 |
45 | ## Wrap Up (5 min)
46 |
47 | - Review Learning Outcomes
48 | - Overview of homework and topics for next class
49 |
50 |
51 | ## Interview Questions
52 | - [Top 50 Dynamic Programming Problems](https://blog.usejournal.com/top-50-dynamic-programming-practice-problems-4208fed71aa3)
53 | - [7 steps to Solving A DP Problem](https://www.freecodecamp.org/news/follow-these-steps-to-solve-any-dynamic-programming-interview-problem-cc98e508cd0e/)
54 |
55 | ## Resources
56 |
57 | - [Memoization in Python](https://www.python-course.eu/python3_memoization.php)
58 | - [Cracking the Coding Interview: Memoization and Dynamic Programming](https://www.youtube.com/watch?v=P8Xa2BitN3I)
59 | - [Dynamic Programming](https://brilliant.org/wiki/problem-solving-dynamic-programming/)
60 | - [What is Dynamic Programming](https://skerritt.blog/dynamic-programming/#knapsack-problem)
61 | - [Memoization and Decorators in Python](https://medium.com/@nkhaja/memoization-and-decorators-with-python-32f607439f84)
62 | - [VisuAlgo - Recursion Trees](https://visualgo.net/en/recursion?slide=1)
63 |
64 |
--------------------------------------------------------------------------------
/Lessons-T6-2019/6.Advanced-Recursion-Dynamic-Programming-2.md:
--------------------------------------------------------------------------------
1 | # Advanced Recursion and Dynamic Programming - Part 2
2 |
3 | ## [Slides]( https://docs.google.com/presentation/d/1QoK6PMX0eiJ6XEQsKa5ZkU-_EJHZ-uG1Pc6attOBkAQ/edit?usp=sharing)
4 |
5 | ## Why you should know this...
6 | Dynamic programming is a common technique that allows us to solve a problem by breaking it into subproblems and solving those. This makes problems that would take a long time to solve run much quicker!
7 |
8 |
9 | ## Learning Objectives (5 min)
10 |
11 | 1. Implement the 5 steps of Dynamic Programming
12 | 1. Convert recursive Dynamic Programming algorithms into iterative algorithms
13 | 1. Understand patterns in determining subproblems in Dynamic Programming algorithms.
14 |
15 | ## Quiz 3 [20 min]
16 |
17 | ## Overview 1: Dynamic Programming : Iterative Approach [20 min]
18 | [Dynamic Programming](https://en.wikipedia.org/wiki/Dynamic_programming)is the process of simplifying a complicated problem by breaking it down into simpler subproblems.
19 |
20 | Once subproblems are properly identified, they can be computed and the results recombined to solve the original problem. This can be done recursively or iteratively.
21 |
22 | The recursive approach can often be easier to understand and implement, factors such as limited stack depth and function call overhead can make the iterative approach more effective.
23 |
24 | For the iterative approach we need to work from the bottom up and store the values computed for each subproblem in a table and then combine these to solve the entire problem.
25 |
26 | ## Activity 1: Implement the Iterative (bottom up) Fibonacci[10 min]
27 |
28 | ## BREAK
29 |
30 | ## Overview 2: Common Patterns in Dynamic Programming
31 | Two common patterns in Dynamic Programming are the shortest path and sequence. Many DP problems can be reduced to one of these.
32 |
33 | The general sequence DP is defined as find the optimal subsequence in a longer sequence. Examples of sequence problems include:
34 | - Find the largest sorted subsequence in a sequence of numbers.
35 | - Find the optimal line length when justifying text on a page.
36 | - Determine where to put parentheses in a matrix multiplication expression to minimize the amount of work.
37 |
38 | There is a large variety of problems that can be reduced to a sequence. Finding the subproblems in sequence problems can be done in one of three ways:
39 | 1. Prefix: The subproblems are at the beginning of the sequence. Separate the problem into a guess for the last sub-sequence and then solve for the remaining subproblems.
40 | 1. Suffix: The subproblems are at the end of the sequence. Separate the problem into a guess for the first sub-sequence and then solve for the remaining subproblems.
41 | 1. Sub-sequence: The subproblems are in the middle of the sequence. Find an optimal sub-sequence (smallest) and then compute the others. Use this choice only if the methods of prefix or suffix don't work.
42 |
43 | ## Activity 2: Dynamic Programming - Finding Sub Problems[20 min]
44 |
45 | Find subproblems in the problems listed below. For each, start by seeing if you can correlate to shortest path or sequence DP and then use what you know about solving these to solve the problem.
46 |
47 | - [Top 50 Dynamic Programming Problems](https://blog.usejournal.com/top-50-dynamic-programming-practice-problems-4208fed71aa3)
48 |
49 | - [Dynamic Programming : Geeks for Geeks
50 | ](https://www.geeksforgeeks.org/fundamentals-of-algorithms/#DynamicProgramming)
51 |
52 |
53 |
54 | ## Wrap Up (5 min)
55 |
56 | - Review Learning Outcomes
57 | - Overview of homework and topics for next class
58 |
59 |
60 | ## Challenges
61 | [Challenge 2](../Challenges/Challenges.md#challenge-4) : Dynamic Programming
62 |
63 | ## Resources
64 | - [Top 50 Dynamic Programming Problems](https://blog.usejournal.com/top-50-dynamic-programming-practice-problems-4208fed71aa3)
65 | - [7 steps to Solving A DP Problem](https://www.freecodecamp.org/news/follow-these-steps-to-solve-any-dynamic-programming-interview-problem-cc98e508cd0e/)
66 |
67 | - [Dynamic Programming : Geeks for Geeks
68 | ](https://www.geeksforgeeks.org/fundamentals-of-algorithms/#DynamicProgramming)
69 |
70 |
--------------------------------------------------------------------------------
/Lessons-T6-2019/7.Traveling-Salesman.md:
--------------------------------------------------------------------------------
1 | # Traveling Salesman Problem
2 |
3 | ## [Slides](https://docs.google.com/presentation/d/14FHYZYrE0GiH93Wd-F38scIOW84Mm-V0OHpgveqdI9w/edit?usp=sharing)
4 |
5 | ## Why you should know this...
6 | The traveling salesman problem (TSP) is a classic problem in graph theory. It is easy to explain but difficult to solve. Attempts to solve it have led to many new algorithmic approaches and these are applicable to a host of real world problems. Understanding TSP gives a basis for solving these problems.
7 |
8 |
9 |
10 | ## Learning Objectives (5 min)
11 | 1. Describe Eulerian paths and apply algorithms to determine if a graph is Eulerian.
12 | 1. Describe Hamiltonian paths and apply algorithms to determine if a path is Hamiltonian.
13 | 1. Model the Traveling Salesman Problem and explore algorithms for solving it.
14 |
15 |
16 | ## Overview 1: Euler and Hamilton
17 | ### Eulerian Path
18 |
19 | A classic problem in graph theory is the [Seven Bridges of Königsberg](https://en.wikipedia.org/wiki/Seven_Bridges_of_K%C3%B6nigsberg) where the people of the town of Königsberg wanted to find a path across the seven bridges in their town that would cross each bridge exactly once. In 1736, this problem was solved by Leonard Euler, forming the foundation of modern graph theory.
20 |
21 | An **[Eulerian path](https://en.wikipedia.org/wiki/Eulerian_path)** (trail) is a trail that visits every edge exactly once (allowing for revisiting vertices). Note: The notation of path here is not the standard which does not allow repeated vertices.
22 | An **Eulerian cycle** is an Eulerian trail that starts and ends on the same vertex. A graph that has an Eulerian cycle is said to be Eulerian.
23 |
24 | Unlike previous path problems that required a complex algorithm to solve, determining if a graph is Eulerian and has an Eulerian cycle is simple due to Euler's Theorem:
25 |
26 | ```
27 | A connected graph has an Euler cycle iff every vertex has even degree.
28 | ```
29 |
30 | Several linear (`O(E)`) algorithms exist for finding Eulerian paths in a graph.
31 |
32 | ### Hamiltonian Path
33 |
34 | A **[Hamiltonian Path](https://en.wikipedia.org/wiki/Hamiltonian_path_problem)** is a path in an undirected or directed graph that visits each vertex exactly once.
35 | A **Hamiltonian Cycle** is a Hamiltonian Path that starts and ends on the same vertex.
36 |
37 | The problem of finding a Hamiltonian Cycle is hard and in general algorithms that work in small graphs quickly become infeasible in larger graphs since in a n-vertex graph, there are `n!` possible paths.
38 |
39 | Various algorithmic approaches such as dynamic programming can be applied to reduce time complexity from O(n!) to O(n22n).
40 |
41 | Determining if a cycle is Hamiltonian however is easy.
42 |
43 |
44 | ## Activity 1:
45 | - Find Eulerian and Hamiltonian Paths.
46 | - Model problems with Euler and Hamilton graphs.
47 |
48 | ## BREAK
49 |
50 | ## Overview 2 : Traveling Salesman Problem (TSP)
51 | The [Traveling Salesman Problem](https://en.wikipedia.org/wiki/Travelling_salesman_problem)
52 | or TSP is one of the most famous in graph theory. Given a set of cities and a cost (distance) to visit each city, what is the optimal route for the salesman to travel to visit every city, return to where he started, and minimize the cost.
53 |
54 | TSP is a weighted version of a Hamiltonian Cycle so it is equally hard.
55 |
56 | An exact algorithm using dynamic programming is the [Held - Karp algorithm](https://en.wikipedia.org/wiki/Held%E2%80%93Karp_algorithm) that solves it in O(n22n) time.
57 |
58 | ### Held-Karp Algorithm:
59 | The minimum tour on a graph of n vertices can be broken into subproblems of the minimum tour on n-1 vertices and the paths to the first vertex.
60 |
61 | Using dynamic programming, we can recursively compute the minimum tour on the subproblems.
62 |
63 |
64 |
65 |
66 | There are many heuristic algorithms for approximate solutions to the TSP that are much faster than the dynamic programming approach.
67 |
68 | ## Activity 2
69 | Implement Greedy and Dynamic Programming of TSP.
70 |
71 | ## Wrap Up (5 min)
72 |
73 | - Review Learning Outcomes
74 | - Overview of homework and topics for next class
75 |
76 | ## Resources
77 |
78 | - [Dynamic Programming - TSP example](https://medium.com/basecs/less-repetition-more-dynamic-programming-43d29830a630)
79 | - [TSP](https://www.geeksforgeeks.org/traveling-salesman-problem-tsp-implementation/) Geeks for Geeks
80 |
--------------------------------------------------------------------------------
/Lessons-T6-2019/8.Algorithm-Classification.md:
--------------------------------------------------------------------------------
1 | # Algorithm Classification
2 |
3 | ## [Slides](https://docs.google.com/presentation/d/1GG-p9HHQEldQounybTjLKNMtWLgncBAuvlwYWexrXrM/edit?usp=sharing)
4 |
5 | ## Why you should know this...
6 | Now that we've implemented several algorithms, it's time to step back and understand how these algorithms relate to each other. Classification of algorithms in terms of approach and computational complexity provides a lens through which we can both better understand what we know and scope what we don't.
7 |
8 |
9 | ## Learning Objectives (5 min)
10 |
11 | 1. Categorize and compare algorithms based on their paradigm (greedy, divide and conquer, backtracking, dynamic programming )
12 | 1. Analyze the time complexity of common graph algorithms within these paradigms.
13 | 1. Explore computational complexity theory and P, NP, NP-hard, NP-complete categorizations.
14 |
15 | ## Review
16 |
17 | ## Overview 1: Algorithm Paradigms [20 min]
18 |
19 | We've been exploring algorithms that are categorized through the following paradigms.
20 |
21 | - **Greedy Algorithm:** The algorithm builds the solution by always choosing the most optimal piece next. It favors local optimality and while it can be easy to implement it does not always produce a global solution.
22 | - Examples of Greedy Algorithms: Dijkstra's Shortest Path, Prim's Minimum Spanning Tree, Job Sequencing, Graph Coloring
23 |
24 |
25 | - **Divide and Conquer:** The algorithm solves the problem in three steps.
26 | 1. Divide: break the problem into subproblems of the same type.
27 | 1. Conquer: recursively solve the subproblems
28 | 1. Combine: appropriately combine the answers.
29 | It is the basis of many recursive algorithms in graph theory.
30 |
31 | - Examples of Divide and Conquer Algorithms: Merge Sort, graph search, graph component properties.
32 |
33 |
34 | - **Backtracking Algorithms:** The algorithm recursively builds a solution one step at a time. Each step is checked to determine if it can be in the optimal solution, and if not, it is removed and the algorithm backtracks to the previous step.
35 | - Examples of Backtracking Algorithms: Knight's Tour, Maze, Hamiltonian Cycle
36 |
37 |
38 | - **Brute Force Algorithm:** The algorithm recursively finds all possible solutions and then chooses the best one. This approach is only effective for small graphs but is often used when no other approach is known. The brute force approach can also illuminate key components of a solution and lead to more effective approaches like Dynamic Programming or Branch and Bound.
39 |
40 | - **Dynamic Programming:** Algorithms that optimize plain recursion when the same inputs are needed for the recursive step. The results of subproblems are stored the first time they are computed in a recursive step and then the following recursive calls use the stored result. This can reduce time complexity from exponential to polynomial.
41 | - Examples of Dynamic Programming: Bellman-Ford Algorithm, Fibonacci numbers, 0-1 Knapsack Problem, Vertex Cover
42 |
43 |
44 | - **Branch and Bound Algorithms:** The algorithm splits the problem into subproblems through branching and then looks at each branch to determine if it can be part of the optimal solution by comparing it to an upper and lower bound and discarding if it is not better than the current solution. Algorithms are used to optimize the backtracking step in optimization problems.
45 | - Examples of Branch and Bound Algorithms: Knapsack Problem, TSP
46 |
47 | ## Activity 1: Categorize Algorithms
48 | - List through the algorithms used in this class. Which paradigm(s) do they use?
49 | - What is the time complexity of each algorithm?
50 | - Choose a problem that can be modeled with a graph such as the one you are using for your final project or a classic like Traveling Salesman. Can you apply each paradigm in solving it.
51 | - Which paradigms work best?
52 | - Is there a paradigm that can't be applied?
53 |
54 | ## Break [10 min]
55 |
56 | ## Overview 2:
57 |
58 | **Computational Complexity:** is defined as the amount of resources required to run an algorithm or solve a problem. The resource considered is commonly time and we relate the time it takes to run an algorithm to the size of the input. **Asymptotic Complexity** looks at the complexity for large n or when n tends to the infinity by using big O notation.
59 |
60 | Many of the algorithms discussed in this course have a polynomial time computational complexity of `O(V+E)` or similar. When discussing asymptotic on graphs we often state it with respect to `V` and `E` but we use `n` for general complexity. To relate these we can use the fact that `E < V^2` and let `n` represent `V` so `O(V+E)` < `O(n^2)` This is not nearly as accurate but useful for comparing and classifying algorithms.
61 |
62 | However the set of algorithms that can be completed in polynomial time is a small subset of the algorithms used in graph theory. Many algorithms can only be solved by a brute-force approach which takes exponential or factorial time.
63 |
64 | **Computational Models**
65 | When evaluating complexity, we can also consider the model used to compute the solution. Two common computational models are Deterministic and Non - Deterministic.
66 |
67 | - A **Deterministic Model** of computation is a system where each state depends on the previous state and there is no randomness in the system. If we start with the same input, we will always get the same output. All the computer algorithms you have used and written in this class are deterministic algorithms.
68 |
69 | - A **Non Deterministic Model** is a model that can produce different outputs for the same inputs. A [non-deterministic algorithm](https://en.wikipedia.org/wiki/Nondeterministic_algorithm) is one that has multiple choices at every step, but (by magic or a lot of luck) always choose the best guess at each step and thus only arrive at the best solution every time. **What??!**
70 |
71 |
72 | ### P and NP
73 | - **P** is the set of all problems that can be solved in polynomial time on a **deterministic** model (or computer).
74 | - **[NP](https://en.wikipedia.org/wiki/NP_(complexity))** is the set of all decision problems that can be solved in polynomial time on a **non deterministic** machine (if it existed). A **[decision problem](https://en.wikipedia.org/wiki/Decision_problem)** is just a problem that has a yes or no answer. NP is also defined as the set of decision problems where we can verify the yes solutions in polynomial time.
75 |
76 | Another way to think of it is if we look at all the problems that we don't know how to solve in polynomial time, we can group them together by mapping a way we could solve them if we had a really good (magical) computer. We don't have this computer, but the grouping allows us to think about these problems in abstract and develop approximations to their solutions.
77 |
78 |
79 | - The unsolved question is are these two sets the same? Does [P = NP](https://en.wikipedia.org/wiki/P_versus_NP_problem)?
80 | - The answer is generally thought to be no, but if it were yes, the world would be a very different place and the person who proved it would be a **[million dollars richer](https://en.wikipedia.org/wiki/Millennium_Prize_Problems)**.
81 |
82 |
83 | ## Activity 2
84 | With a bit of poetic license, some computer scientist have stretched the P = NP problem into the realm of all understanding.
85 |
86 | >*"If P were equal to NP, then the world would be a profoundly different place than we usually assume it to be. There would be no special value in "creative leaps", no fundamental gap between solving a problem and recognizing the solution once it's found. Everyone who could appreciate a symphony would be Mozart; Everyone who could follow a set-by-step argument would be Gauss."* -[Scott Aaronson](https://www.scottaaronson.com/papers/pnp.pdf)
87 |
88 | Discuss what this would mean in your life.
89 |
90 | ## Wrap Up (5 min)
91 |
92 | - Review Learning Outcomes
93 | - Overview of homework and topics for next class
94 |
95 | ## Resources
96 | 1. [Fundamentals of Algorithms](https://www.geeksforgeeks.org/fundamentals-of-algorithms/) - Geeks for Geeks
97 | 1. [NP Completeness](https://www.geeksforgeeks.org/np-completeness-set-1/) - Geeks for Geeks
98 | 1. [Complexity: P, NP, NP-completeness, Reductions](https://www.youtube.com/watch?v=eHZifpgyH_4&t=1s)
99 | 1. [P Vs NP Problem In A Nutshell](https://medium.com/@bilalaamir/p-vs-np-problem-in-a-nutshell-dbf08133bec5)
100 |
--------------------------------------------------------------------------------
/Lessons-T6-2019/More-Topics.md:
--------------------------------------------------------------------------------
1 | # More Topics
2 |
3 | ## Topological Sorting and Scheduling
4 |
5 |
6 | ### Why you should know this...
7 | Scheduling problems arise often in computer science and elsewhere, including instruction scheduling, logic synthesis, determining the order of completion tasks to perform, data serialization, and more. Topological sorting produces a linear ordering of the vertices that represents the solution.
8 |
9 |
10 | ### Learning Objectives (5 min)
11 |
12 | 1. Model scheduling problems as topological sorting.
13 | 1. Apply topological sorting to scheduling problems.
14 | 1. Use Directed Acyclic Graphs to model and solve problems.
15 |
16 |
17 | ## Graph Coloring & Covering
18 |
19 | ## Why you should know this...
20 | Problems of resource allocation such as scheduling, network distribution, data mining, image capturing can be solved using graph coloring techniques which separate the graph into smaller components or subgraphs.
21 |
22 |
23 | ### Learning Objectives (5 min)
24 |
25 | 1. Apply graph coloring algorithms to find or bound the chromatic number of a graph
26 | 1. Model problems with graph coloring.
27 | 1. Explore common graph algorithms utilizing subgraphs.
28 |
29 |
30 |
31 | ### Overview 1: Coloring and Covering
32 | - **Graph coloring** is a simple way of labelling graph components such as vertices, edges, and regions under some constraints.
33 |
34 | - The **chromatic number** of a graph is the minimum number of colors needed to properly color a graph so that no two adjacent vertices, adjacent edges, or adjacent regions are colored the same.
35 |
36 |
37 |
38 |
39 | ## Resources
40 | - [Graph Coloring Applications](https://www.geeksforgeeks.org/graph-coloring-applications/) Geeks for Geeks
41 |
--------------------------------------------------------------------------------
/Lessons/01-Intro-to-Graph-Theory.md:
--------------------------------------------------------------------------------
1 | # Introduction to Graph Theory
2 |
3 | ### [Slides](https://docs.google.com/presentation/d/1eOGVRA2ziw9swgB1t0VXn2_gnIWl1sd-H5xglgSa3-E/edit?usp=sharing)
4 |
5 |
6 | ## Learning Objectives (5 min)
7 |
8 | 1. Practice modeling real world problems with graph theory.
9 | 1. Implement algorithms from graph theory with diagrams and pseudocode.
10 | 1. Define the Graph ADT and implement in code.
11 |
12 | ## Check-In (5 minutes)
13 |
14 | With a group of 3, answer the following question: _What is one thing that has been bringing you joy over the past 2 weeks?_
15 |
16 | ## Activity 1: Seven Bridges of Königsberg
17 |
18 | With a group of 3, use [this Jamboard](https://jamboard.google.com/d/1xvnmP5g_vBnLk-T65UpL42iL3iIGcIGP5CcVKUvGCr4/edit?usp=sharing) to complete the following:
19 |
20 | 1. See if you can find a solution to the Seven Bridges of Königsberg, crossing each bridge exactly once.
21 | 2. If there are no solutions, why not?
22 |
23 | ## Definitions
24 |
25 | A **vertex** is the fundamental unit of a graph. It can represent a place, a person, etc. The plural of _vertex_ is _vertices_.
26 |
27 | An **edge** is a connection between two vertices. It can be directed (goes only one way) or undirected (goes both ways).
28 |
29 | A **connected graph** is a graph in which there is a **path** (series of edges) between any pair of vertices.
30 |
31 | A **disconnected graph** is a graph in which at least one pair of vertices has no path between them (i.e. they are unreachable).
32 |
33 | An **Euler Path** of an undirected graph is a path such that every edge of the graph is used exactly once.
34 |
35 | ## BREAK [10 min]
36 |
37 | ## Course Overview [20 min]
38 | - Go over syllabus, learning outcomes, course policies, key deliverables.
39 | - Our course learning approach: Model, Implement Solution, Synthesize & Algorithmic Thinking
40 |
41 |
42 | ## Overview 2: Graph Implementations [10 min]
43 |
44 | Graphs can be represented in code in several ways:
45 |
46 | - **Edge List**: Store a list of all edges in the graph. This method is easy to store, but much harder to retrieve data & reason about the graph.
47 |
48 | - **Adjacency Matrix**: Store a **matrix** (or 2D array) of all vertices mapped to all vertices. Two vertices `i`, `j` have an edge between them if `matrix[i][j] == 1`. This method is more space-intensive to store, but quick to look up an edge.
49 |
50 | - **Adjacency List** (preferred): Store a list of vertices, and for each vertex, store a list of its neighbors. This method makes it easier to store _and_ retrieve data.
51 |
52 |
53 | ## Homework
54 | - [Homework 1](Assignments/01-Graph-ADT): Implement the Graph ADT.
55 |
56 | ## Resources:
57 | - [A Gentle Introduction To Graph Theory](https://medium.com/basecs/a-gentle-introduction-to-graph-theory-77969829ead8)
58 | - [How to think in graphs: An illustrative introduction to Graph Theory and its applications](https://medium.com/free-code-camp/i-dont-understand-graph-theory-1c96572a1401)
59 | - [Graph Theory](https://en.wikipedia.org/wiki/Graph_theory#Route_problems)
60 | - [From Theory To Practice: Representing Graphs](https://medium.com/basecs/from-theory-to-practice-representing-graphs-cfd782c5be38)
61 | - [How to think in graphs](https://medium.com/free-code-camp/i-dont-understand-graph-theory-1c96572a1401)
62 | - [Visualgo Graphs](https://visualgo.net/en/graphds)
63 |
--------------------------------------------------------------------------------
/Lessons/02-Graph-Traversals-BFS.md:
--------------------------------------------------------------------------------
1 | # Graph Traversals with Breadth-first Search
2 |
3 | ### [Slides](https://docs.google.com/presentation/d/1bfFSSSj4j9H5nefw1gJfwvViPXt1RzdiyQ6l6ET2wAA/edit)
4 |
5 | ## Learning Objectives
6 |
7 | By the end of today, you should be able to...
8 |
9 | 1. Implement Iterative version of Breadth-first search (BFS).
10 | 1. Find the shortest path between two vertices using Breadth-first search.
11 | 1. Identify use cases for Breadth-first Search.
12 |
13 | ## Activity: The Six Degrees of Kevin Bacon
14 |
15 | With a group of 3, complete the following:
16 |
17 | 1. Explore the [Oracle of Bacon site](https://oracleofbacon.org/) by entering at least 3 actor/actress pairs. See if you can find an actor/actress pair who have a connection chain of 3+.
18 | 1. Discuss with your group: If you had a database of actors & the movies they are in, how would you construct this website? I.e. For any 2 actors, how would you find a shortest connection chain?
19 |
20 | ## Review: BFS with Trees
21 |
22 | When working with trees, Breadth-first Search is also called **Level-order Traversal**.
23 |
24 | ## Activity: BFS with Graphs
25 |
26 | With a group of 3, complete Breadth-first Search on the graph shown below. Make a copy of [this Jamboard](https://jamboard.google.com/d/1YbMou_a8e9o3mFHarZJiP8ccQQ-P837baiaTX2YhI6M/edit?usp=sharing) to get started.
27 |
28 | ## Break
29 |
30 | ## Applications of Breadth-first Search
31 |
32 | A **connected component** of a graph is a set of vertices for which there is a path between any pair of vertices.
33 |
34 | A **bipartite graph** is a graph whose vertices can be categorized into 2 groups (colors), such that no two vertices in the same group (color) are connected by an edge.
35 |
36 | ## Activity: Pair Programming
37 |
38 | With your group of 3, choose who will be the _driver_, the _navigator_, and the _observer_.
39 |
40 | - **Driver**: Share your screen & type in code according to the navigator’s instructions
41 | - **Navigator**: Decide what to do next & how to solve the problem
42 | - **Observer**: Give feedback and help your group if they are stuck!
43 |
44 | Write pseudocode and then real code for the following methods:
45 |
46 | ```py
47 | class Graph:
48 | def is_bipartite(self):
49 | """Return True if the graph is bipartite, False otherwise."""
50 | # ...
51 |
52 | def get_connected_components(self):
53 | """Return a list of connected components."""
54 | # ...
55 | ```
56 |
57 | ## Homework
58 |
59 | - [Homework 1](Assignments/01-Graph-ADT): Implement the Graph ADT.
--------------------------------------------------------------------------------
/Lessons/03-Graph-Traversals-DFS.md:
--------------------------------------------------------------------------------
1 | # Graph Traversals with Depth-first Search
2 |
3 | ### [Slides](https://docs.google.com/presentation/d/1YEGEh2bhklbZKmMpN8dvfLMSsdutSMka1R6aCOlmFdA/edit?usp=sharing)
4 |
5 | ## Learning Objectives
6 |
7 | By the end of today, you should be able to...
8 |
9 | 1. Implement iterative & recursive versions of Depth-first search (DFS).
10 | 1. Find a path between two vertices using Depth-first search.
11 | 1. Identify uses for Depth-first Search.
12 |
13 | ## Activity 1: Solving a Maze
14 |
15 | With a group of 3, solve the maze puzzle:
16 |
17 | - Pretend you are walking in the maze and can only see what’s right in front of you. You have a long piece of string so that you can see where you’ve already visited. With your group, come up with a strategy for solving any maze.
18 | - Go to [this Jamboard](https://jamboard.google.com/d/1yVxwgqIGvnqdKZUPsZOUaqOr6hAVpDiQVpc5Juje-sU/edit?usp=sharing) and trace the path you would follow, using the strategy you came up with in part 1.
19 |
20 | ## Activity 2: Complete a Depth-first Search
21 |
22 | With a group of 3, complete Depth-first Search on the graph shown below. Make a copy of [this Jamboard](https://jamboard.google.com/d/1u3OxPz2ca6pl93NPqdTIYMeiO0xZGlOagmrSUbYDCRg/edit?usp=sharing) to get started.
23 |
24 | ## BREAK
25 |
26 | ## Activity 3: Cycle Detection
27 |
28 | With your group of 3, choose who will be the driver, the navigator, and the observer.
29 |
30 | - Driver: Share your screen & type in code according to the navigator’s instructions
31 | - Navigator: Decide what to do next & how to solve the problem
32 | - Observer: Give feedback and help your group if they are stuck!
33 |
34 | Write pseudocode and then real code for the following method:
35 |
36 | ```py
37 | class Graph:
38 | def contains_cycle(self):
39 | """Return True if the graph contains a cycle, False otherwise."""
40 | # ...
41 | ```
42 |
43 | ## Homework
44 |
45 | - [Homework 2](Assignments/02-Graph-Traversals): Implement graph traversal algorithms using BFS and DFS techniques.
46 |
47 | ## Resources
48 |
49 | 1. [Breadth First Search or BFS for a Graph](https://www.geeksforgeeks.org/breadth-first-search-or-bfs-for-a-graph/)
50 | 1. [Depth First Search or DFS for a Graph](https://www.geeksforgeeks.org/depth-first-search-or-dfs-for-a-graph/)
51 | 1. [Check whether a given graph is Bipartite or not](https://www.geeksforgeeks.org/bipartite-graph/)
52 | 1. [Detect Cycle in a Directed Graph
53 | ](https://www.geeksforgeeks.org/detect-cycle-in-a-graph/)
54 | 1. [Topological Sorting](https://www.geeksforgeeks.org/topological-sorting/)
55 |
56 |
--------------------------------------------------------------------------------
/Lessons/04-Topological-Sort.md:
--------------------------------------------------------------------------------
1 | # Topological Sort
2 |
3 | ### [Slides](https://docs.google.com/presentation/d/1OKrGMviXcOSTGujs1ZNOemUHegLOcLlJUHEy0G6SdkY/edit?usp=sharing)
4 |
5 | ## Learning Objectives
6 |
7 | By the end of today, you should be able to...
8 |
9 | 1. Explain how topological sort can be used to solve real-world problems.
10 | 1. Implement topological sort using Kahn’s Algorithm and Depth-first Search.
11 | 1. Complete graph applications problems by identifying nodes & vertices.
12 |
13 | ## Course Scheduling Activity (15 minutes)
14 |
15 | With a group of 3, fill out [this worksheet](https://docs.google.com/document/d/1c8di9nzsR3Pv32VULs9qhmMZ_GwcF1f8gf_zh5_LDqM/edit?usp=sharing) (parts 1 and 2) to find a course schedule for the 2 schools.
16 |
17 | ## Activity 2 (15 minutes)
18 |
19 | With a group of 3, perform a topological sort for the graph on [this Jamboard](https://jamboard.google.com/d/1dvv2ckWWwFzhB9t2JOuJwPNi9mhTzHl-TOm3ta2o1yM/edit?usp=sharing). Use either Kahn’s Algorithm or Depth-first Search.
20 |
21 | ## BREAK
22 |
23 | ## Pair Programming Activity (30 minutes)
24 |
25 | With a group of 3, choose who will be the driver, the navigator, and the observer.
26 |
27 | - Driver: Share your screen & type in code according to the navigator’s instructions
28 | - Navigator: Decide what to do next & how to solve the problem
29 | - Observer: Give feedback and help your group if they are stuck!
30 |
31 | Write pseudocode and then real code for 1-2 of the following problems:
32 |
33 | [Number of Islands](https://leetcode.com/problems/number-of-islands/) - BFS or DFS
34 | [Rotting Oranges](https://leetcode.com/problems/rotting-oranges/) - BFS
35 | [Word Ladder](https://leetcode.com/problems/word-ladder/) - BFS
36 | [Alien Dictionary](https://leetcode.com/problems/alien-dictionary/) - Topological Sort
37 |
38 |
--------------------------------------------------------------------------------
/Lessons/05-Weighted-Graphs.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/CS-2.2-Graphs-Recursion/f4ed85d10b4c471fb2b12a81cb6bfa9ce6a2360b/Lessons/05-Weighted-Graphs.md
--------------------------------------------------------------------------------
/Lessons/06-More-Weighted-Graphs.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/CS-2.2-Graphs-Recursion/f4ed85d10b4c471fb2b12a81cb6bfa9ce6a2360b/Lessons/06-More-Weighted-Graphs.md
--------------------------------------------------------------------------------
/Lessons/07-Dynamic-Programming.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/CS-2.2-Graphs-Recursion/f4ed85d10b4c471fb2b12a81cb6bfa9ce6a2360b/Lessons/07-Dynamic-Programming.md
--------------------------------------------------------------------------------
/Lessons/08-More-Dynamic-Programming.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/CS-2.2-Graphs-Recursion/f4ed85d10b4c471fb2b12a81cb6bfa9ce6a2360b/Lessons/08-More-Dynamic-Programming.md
--------------------------------------------------------------------------------
/Lessons/09-Max-Flow.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/CS-2.2-Graphs-Recursion/f4ed85d10b4c471fb2b12a81cb6bfa9ce6a2360b/Lessons/09-Max-Flow.md
--------------------------------------------------------------------------------
/Lessons/10-More-Max-Flow.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/CS-2.2-Graphs-Recursion/f4ed85d10b4c471fb2b12a81cb6bfa9ce6a2360b/Lessons/10-More-Max-Flow.md
--------------------------------------------------------------------------------
/Lessons/11-Graph-Applications.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/CS-2.2-Graphs-Recursion/f4ed85d10b4c471fb2b12a81cb6bfa9ce6a2360b/Lessons/11-Graph-Applications.md
--------------------------------------------------------------------------------
/Lessons/12-Graph-Applications-Lab.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/CS-2.2-Graphs-Recursion/f4ed85d10b4c471fb2b12a81cb6bfa9ce6a2360b/Lessons/12-Graph-Applications-Lab.md
--------------------------------------------------------------------------------
/Lessons/13-NP-Complete.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/CS-2.2-Graphs-Recursion/f4ed85d10b4c471fb2b12a81cb6bfa9ce6a2360b/Lessons/13-NP-Complete.md
--------------------------------------------------------------------------------
/Lessons/assets/graph.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/CS-2.2-Graphs-Recursion/f4ed85d10b4c471fb2b12a81cb6bfa9ce6a2360b/Lessons/assets/graph.png
--------------------------------------------------------------------------------
/Projects/Final-Project.md:
--------------------------------------------------------------------------------
1 | # CS 2.2 Final Project
2 |
3 | ## Project Description
4 |
5 | For this project, you will submit 2 videos of algorithm explanations. This will allow you to practice communication skills & will solidify your understanding of graph algorithms.
6 |
7 | ## Project Requirements
8 |
9 | 1. **Choose 2 algorithms** that we've covered during the class. If you wish to use BFS or DFS, please choose an application of those algorithms (e.g. Bipartite or Cycle Detection).
10 | 1. For each chosen algorithm, make a video that accomplishes the following:
11 | - Describes and illustrates a **real-world application** of the algorithm. To illustrate, you can use a whiteboard, pen & paper, Google slides, drawings, etc.
12 | - Explains how to transform the real-world example into a graph.
13 | - Illustrates using the algorithm to solve a **specific** version of the problem (e.g. "I have these ten friends: Amy, Bernard, Chase with these friendships...") similar to how we've done in class.
14 | - Explains, using beginner-friendly language, how to write code to implement the algorithm to solve the given problem.
15 |
16 | ## Rubric
17 |
18 |
19 | | **Criteria** | Needs Improvement | Basic (Passing) | Proficient |
20 | | :---------: | :-------: | :------: | :------: |
21 | | **Desribes & illustrates real-world example** | Video does not describe a real-world example, or gives an example that is too vague. | Video describes & illustrates a concrete real-world example, but does not illustrate exactly how to model it using a graph. | Video describes & illustrates a real-world example, and explains how to turn that real-world example into a graph. |
22 | | **Solves a specific instance of the problem** | Does not solve a specific instance of the problem, or explains in vague terms without giving a step-by-step solution. | Gives a step-by-step solution of how to solve the problem using the chosen algorithm, but may contain minor mistakes or misunderstandings. | Explains in detail how to solve the problem step-by-step. |
23 | | **Explains how to write code to implement the algorithm** | Does not explain code step-by-step, and instead gives a vague explanation or overview | Gives a step-by-step explanation of the algorithm that a beginner could follow, but may contain minor mistakes or misunderstandings. | Thoroughly explains each step of the algorithm as it pertains to the example. |
24 |
25 | A passing project earns an average score of 2 (Basic) across both video submissions.
26 |
27 | ## Examples
28 |
29 | For inspiration, check out algorithm explanation videos on YouTube such as [this video on BFS](https://www.youtube.com/watch?v=oDqjPvD54Ss).
30 |
31 | ## Video Recording Software
32 |
33 | You can use the [QuickTime](https://support.apple.com/kb/dl923?locale=en_US) recording sofware to record a screen capture video, or the Photo Booth software to take a video with your webcam. No need to edit your video or use any fancy software!
34 |
35 | ## Submission
36 |
37 | Please submit your work on [Gradescope](https://gradescope.com).
--------------------------------------------------------------------------------
/Projects/Graph-Project.md:
--------------------------------------------------------------------------------
1 | # CS 2.2 Graph Modeling Project
2 |
3 | ## Project Description
4 | It's your turn to tackle a real world problem using your graph theory skills. You will chose a problem and a set of solutions to implement, using a similar approach to the [Graph Modeling Tutorial](). You will implement graph theory solutions in python for small amounts of data within your problem scope and then innovate towards solutions when working with data at scale.
5 |
6 | ## [Project Rubric](https://docs.google.com/document/d/1hq2D0HFCVIqkEI0HvE3SxCUlhNkSdG1Xoe62b3g9wp4/edit?usp=sharing)
7 |
8 | ## Project requirements
9 |
10 | - **Choose the problem:** Choose a problem from the provided list or a different problem that can be modeled and a graph and has solutions that can be implemented with graph algorithms from this class. **You must use at least 3 different algorithms to define at least 3 different solutions.**
11 | - **Example:** Given a network of friends, find the biggest influencer, the largest group of friends who all know each other, and the longest time it would take for a message to pass from person A to person B via friends.
12 |
13 |
14 | - **Model the problem:** Represent the problem and the desired solutions using graphs, graph properties and algorithms.
15 | - **Example:** The network of friends is modeled with each person being a vertex in a graph and an edge between any two people if they are friends.
16 | - The biggest influencer is the maximum degree of the graph.
17 | - The largest group of friends is the maximal clique number in the graph. This can be approximated by Turán's theorem.
18 | - The time to send a message is the shortest path which can be found via Dijkstra's Algorithm.
19 |
20 |
21 | - **Implement Graph and Algorithms in Python:** Create a python program (from scratch not using graph libraries) that can read in a small (n < 30) version of your problem from a text file and solve the algorithms above. Your code should be:
22 | - fully documented,
23 | - tested and meet [PEP8](https://realpython.com/python-pep8/) standards
24 | - work on any data set with (n < 30) defined to meet problem specifications as defined in your documentation (README)
25 | - Have a README that fully defines the problem scope and solutions
26 | - available as a separate repository on GitHub.
27 | - **Discuss Scale:** What happens with your solutions at scale? (n >>> 30).
28 | - Is your problem still solvable?
29 | - What is the time complexity of the algorithms you are using?
30 | - Discuss in your GitHub README and associated Summary.
31 | - [Stretch] If possible, implement a more scalable solution using tools like Dynamic Programming or by using a different algorithm that solves the same problem faster.
32 | - **Blog or Present:** Create a presentation or blog post of your project.
33 | - **Presentation:** Your presentation should take 5 minutes and have at least 4 slides covering:
34 | - Problem context (real world situation)
35 | - Graph model of problem context with sample data.
36 | - 3 solving / discovering in your problem context with a brief description of the results and the algorithm used to find these results.
37 | - You do not have to present how the algorithms work in detail, but you should be able to answer questions about them.
38 | - **Blog:** Your blog needs to be published on Medium and should cover the following:
39 | - Problem context (real world situation)
40 | - Graph model of problem context with sample data.
41 | - 3 things you are solving / discovering in your problem context with a brief description of the results and the algorithm used to find these results.
42 | - You do not have to describe how the algorithms work in detail, but you should clearly illustrate how that algorithm produces the result in each situation and link to full algorithm descriptions on wikipedia or elsewhere.
43 | - **Scoring**Your presentation or blog will be scored using the Presentation or Blog portion of the [Project Rubric](https://docs.google.com/document/d/1hq2D0HFCVIqkEI0HvE3SxCUlhNkSdG1Xoe62b3g9wp4/edit?usp=sharing)
44 |
45 |
46 | ## Stretch Project Requirements
47 | - Implement a common graph algorithm that was not covered in class on your program.
48 | - Use graph libraries to refactor your code implementations, benchmark, and compare results.
49 |
50 | ## Examples
51 |
52 | An example of a completed project and blog post can be found [here](https://medium.com/@sukhrobgolibboev/modeling-google-maps-using-graph-theory-b7e90a6cf3e0).
53 |
54 | ## List of possible problem choices:
55 | (Do not choose social network as that was already covered in class examples)
56 | - The Internet - e.g. [Google Knowledge Graph](https://searchengineland.com/google-launches-knowledge-graph-121585), [PageRank](https://searchengineland.com/what-is-google-pagerank-a-guide-for-searchers-webmasters-11068)
57 | - Biology - e.g. [Food Webs](https://www.nature.com/scitable/knowledge/library/food-web-concept-and-applications-84077181/)
58 | - [Airplane Scheduling](http://www.math.wm.edu/~rrkinc/hmk_current/AirNets2017.pdf)
59 | - Computer Networks
60 | - Job Scheduling
61 | - [More Applications of Graph Theory](https://en.wikipedia.org/wiki/Graph_theory#Applications)
62 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # CS 2.2 Advanced Recursion and Graphs
2 |
3 | This course covers graph theory, data structures, algorithms, and analysis. Key concepts include graph traversals, pathfinding, recursion, greedy algorithms, memoization and dynamic programming. Students will build an original project whose underlying structure requires the use of graph structures and algorithms to solve real-world problems such as airplane routing, social networking, and board games.
4 |
5 | Graphs can be used to model and solve a wide variety of problems, including systems of roads, airline flights from city to city, how the Internet is connected, or even the sequence of classes you must take to complete your degree here at Make School! Understanding graphs allows you to build models of these problems and use those models to find optimal or best case solutions.
6 |
7 | ## Prerequisites:
8 |
9 | - [CS 1.3](https://github.com/Make-School-Courses/CS-1.3-Core-Data-Structures)
10 |
11 | ## Course Specifics
12 |
13 | **Course Delivery**: Synchronous | 7 weeks | 18 sessions
14 |
15 | **Course Credits**:
16 |
17 | Synchronous: 3 units | 37.5 Contact Hours/Term | 92 Non-Contact Hours/Term | 129.5 Total Hours/Term
18 |
19 | ## Learning Outcomes
20 |
21 | Students by the end of the course will be able to ...
22 |
23 | - Describe common graph algorithms including graph traversals, pathfinding, greedy algorithms, recursion, and dynamic programming.
24 | - Model and solve real world problems using graph algorithms.
25 | - Implement graph algorithms in code.
26 | - Develop algorithmic thinking skills to expand on common graph algorithms and improve problem solving approaches.
27 |
28 | ## Schedule
29 |
30 | **Course Dates:** Monday, May 31 – Friday, July 16, 2021 (7 weeks)
31 |
32 | **Class Times:** Monday, Wednesday, Friday at 2:15pm–4:00pm (19 class sessions)
33 |
34 | | Class | Date | Topics | Assignments Due |
35 | |:-----:|:----------------------:|:---------------------------------------:|:-----:|
36 | | - | Mon, May 31 | **No Class - Memorial Day** | |
37 | | 1 | Wed, June 2 | [Introduction to Graph Theory](Lessons/01-Intro-to-Graph-Theory) | |
38 | | 2 | Fri, June 4 | Lab | |
39 | | 3 | Mon, June 7 | [How to Proof](Lessons/02-Graph-Traversals-BFS)| Module 1 |
40 | | 4 | Wed, June 9 | [Graph Traversals](Lessons/03-Graph-Traversals-DFS) | |
41 | | 5 | Fri, June 11 | Lab | Module 2|
42 | | 6 | Mon, June 14 | [Topological Sort](Lessons/04-Topological-Sort)| |
43 | | 7 | Wed, June 16 | [Graph Applications](https://docs.google.com/presentation/d/1ykYtxuS-L2UemvAykJrW0m11oTyCyDrB6gQbTzaz6jE/edit?usp=sharing) | |
44 | | 8 | Fri, June 18 | Lab | Module 3
45 | | 9 | Mon, June 21 | [Weighted Graph Algorithms](https://docs.google.com/presentation/d/1mvH1YpsiDTl8T_fB6xYF_gkwF_M11DDCme8Agd0EACc/edit?usp=sharing) |
46 | | 10 | Wed, June 23 | [Weighted Graph Algorithms](https://docs.google.com/presentation/d/1mvH1YpsiDTl8T_fB6xYF_gkwF_M11DDCme8Agd0EACc/edit?usp=sharing) |
47 | | 11 | Fri, June 25 | Lab| Module 4 Midterm (you must have modules 1-4 turned in)
48 | | 12 | Mon, June 28 | [Recursion & Dynamic Programming](https://docs.google.com/presentation/d/17WsNYYmEWjOa9fLuiTHxI8Q3N47WWVlOimQOsrmYCkk/edit?usp=sharing) |
49 | | 13 | Wed, June 30 | [Recursion & Dynamic Programming](https://docs.google.com/presentation/d/1yJBf_DUEbzDRW5K0JVjLU8vX50MMGQh4K38r1khDyk4/edit?usp=sharing) |
50 | | 14 | Fri, July 2 | Lab | Module 5
51 | | - | Mon, July 5 | **No Class - Independence Day Observed** |
52 | | 15 | Wed, July 7 | [NP-Complete Algorithms](https://docs.google.com/presentation/d/1nKk05Cw-1G2HvdXKPXixbl_UtpQcjo-iWzFClP_eM8E/edit?usp=sharing) |
53 | | 16 | Fri, July 9 | Lab| Module 6
54 | | 17 | Mon, July 12 | Practice Problems |
55 | | 18 | Wed, July 14 | Practice Problems |
56 | | 19 | Fri, July 16 | Lab | Final Project
57 |
58 |
59 | ## Class Work
60 |
61 | ### Assignments
62 |
63 | ### Coding Modules
64 |
65 | Each lesson will have an associated module consisting of review, conceptual, and coding activities as well as interview prep related to the topic. At the end of each week you will turn your module work into gradescope for feedback and a score.
66 |
67 | ### Final Project
68 |
69 | Students will also create a [final project] applying and implementing an advanced graph related topic
70 |
71 | ## Assignment Submissions
72 |
73 | We will be using [Gradescope](gradescope.com), which allows us to provide fast and accurate feedback on your work. *All assigned work will be submitted through Gradescope, and assignment and exam grades will be returned through Gradescope.*
74 |
75 | As soon as grades are posted, you will be notified immediately so that you can log in and see your feedback. You may also submit regrade requests if you feel we have made a mistake.
76 |
77 | Your Gradescope login is your Make School email, and your password can be changed at [https://gradescope.com/reset_password](https://gradescope.com/reset_password). The same link can be used if you need to set your password for the first time.
78 |
79 | ## Evaluation
80 |
81 | To pass this course you must meet the following requirements:
82 |
83 | * Pass all modules with a score 70% or higher
84 | * Your lowest module will be dropped
85 | * Complete the final project with a score of 70% or higher
86 | * Actively participate in class and abide by the attendance policy
87 | * Make up all classwork from all absences
88 |
89 | ## Course Policies and Format
90 |
91 | * This course will use a self paced format
92 | * You will be given recommended dates to turn assignments in to stay on track, but you can turn in any assignment later than the recommended date with no penalty provided Modules 1-3 are turned in no later than midterm (Fri June 25th) and modules 3-6 and the final project are turned in no later than the last day of class (Fri July 16th)
93 | * You can resubmit any assignment after receiving feedback to improve your score provided it is turned in no later than the last day of class (Fri July 16th)
94 | * Assignments should be completed by the recommended date in the above schedules section in order to receive timely feedback. Students falling behind should connect with the instructor for help staying on pace!
95 | * The absolute last date to turn in Modules 1-3 is Fri June 25th and the last date to turn in modules 3-6 and the final project is Fri July 16th
96 | * Any assignments not complete by the above midterm Fri June 25th and final day of class Fri July 16th dates will receive a score of 0
97 | * Lectures will be given during the first hour of class and will be optional (2:15 pm - 03:15pm on M & W)
98 | * Labs will be during the last portion of the class and all of Friday sessions and attendance will be required (3:30 - 4:00 pm M & W, 2:15 pm - 04:00pm F)
99 |
100 | ## Information Resources
101 |
102 | Any additional resources you may need (online books, etc.) can be found here. You can also find additional resources through the library linked below:
103 |
104 | - [make.sc/library](http://make.sc/library)
105 |
106 |
107 | ## Academic Honesty Policy
108 |
109 | At Make School, we highly encourage collaboration between students on assignments. Working with other people is the best way to learn!
110 |
111 | However, there's a big difference between **collaboration** (writing code together with another person) and **plagiarism** (copying code from a classmate or outside source without providing proper attribution).
112 |
113 | Here are some guidelines to follow in order to avoid plagiarism:
114 |
115 | 1. If you are looking at an outside source for help, **close the window** containing the code before writing your own solution.
116 | 1. Do not write down a line of code unless you **completely understand** how it works. (This is true even if the source you're referencing is the lesson slides/examples/etc!)
117 | 1. If your code is still similar to an outside source or another student's, **provide attribution** by adding a comment to your code explaining where it was taken from.
118 |
119 | We take academic honesty very seriously at Make School. The consequences for violating the policy are as follows:
120 |
121 | - You will be required to write a [Self-Reflection Letter](https://docs.google.com/document/d/140_PHfDh7gu33OZI_caxEtvNzAlAepjnGcbQcXZ-MRo/edit?usp=sharing) to reflect on how your actions affected others.
122 | - If this is your first offense, you may be permitted to redo the assignment for a reduced grade (at the instructor's discretion).
123 | - The incident will be added to your permanent record at Make School and you may be placed on a Participation Improvement Plan (PIP).
124 |
125 | For subsequent offenses, more serious consequences may be considered. For more information, please see [Make School's academic honesty policy](https://make.sc/academic-honesty-policy).
126 |
127 | ## Resources
128 |
129 | The following resources were used in developing this course and are a great place to start for learning more. These resources are used through the Attribution / Share Alike license.
130 | - [Geeks for Geeks](https://www.geeksforgeeks.org/graph-data-structure-and-algorithms/)
131 | - [Wikipedia Graph Theory](https://en.wikipedia.org/wiki/Graph_theory)
132 | - [Runestone Academy Data Structures and Algorithms](https://runestone.academy/runestone/static/pythonds/index.html)
133 |
134 | ## Information Resources
135 |
136 | Any additional resources you may need (online books, etc.) can be found here. You can also find additional resources through the library linked below:
137 |
138 | - [make.sc/library](http://make.sc/library)
139 |
140 | ## Make School Course Policies
141 |
142 | - [Program Learning Outcomes](https://make.sc/program-learning-outcomes) - What you will achieve after finishing Make School, all courses are designed around these outcomes.
143 | - [Grading System](https://make.sc/grading-system) - How grading is done at Make School
144 | - [Code of Conduct, Equity, and Inclusion](https://make.sc/code-of-conduct) - Learn about Diversity and Inclusion at Make School
145 | - [Academic Honesty](https://make.sc/academic-honesty-policy) - Our policies around plagerism, cheating, and other forms of academic misconduct
146 | - [Attendance Policy](https://make.sc/attendance-policy) - What we expect from you in terms of attendance for all classes at Make School
147 | - [Course Credit Policy](https://make.sc/course-credit-policy) - Our policy for how you obtain credit for your courses
148 | - [Disability Services (Academic Accommodations)](https://make.sc/disability-services) - Services and accommodations we provide for students
149 | - [Online Learning Tutorial](https://make.sc/online-learning-tutorial) - How to succeed in online learning at Make School
150 | - [Student Handbook](https://make.sc/student-handbook) - Guidelines, policies, and resources for all Make School students
151 |
--------------------------------------------------------------------------------
/Resources/graph-algorithms.md:
--------------------------------------------------------------------------------
1 | ## Graph Algorithms
2 |
3 | - **Shortest Path with BFS: **
4 | - **Dijkstra's Algorithm: **
5 | - **Prim's Algorithm:**
6 | - **Handshake Lemma:**
7 |
--------------------------------------------------------------------------------
/Resources/graph-problems.md:
--------------------------------------------------------------------------------
1 | Graph Problems
2 |
3 | - Checkerboard Covering: How do you cover a checkerboard with one corner missing using L shaped (two squares in one direction and one square in the perpendicular direction) tiles?
4 | - Knight's Tour: Find a sequence of moves for a knight on a chessboard so that the knight visits every square on the chessboard exactly once. This sequence is called a "tour".
5 |
--------------------------------------------------------------------------------
/Resources/graph-properties.md:
--------------------------------------------------------------------------------
1 | ##Graph Properties
2 | A brief summary of the properties discussed in class - for a complete list see [Graph Properties](https://en.wikipedia.org/wiki/Graph_property)or [Glossary of graph theory terms](https://en.wikipedia.org/wiki/Glossary_of_graph_theory_terms)
3 |
4 | - **Vertex Neighbors / Neighborhood:** The set of vertices adjacent to the vertex.
5 | - **Connected Graph:** A graph is connected if there is a path from each vertex to all the other vertices.
6 | - **Connected Component:** The connected components of a graph are the maximal subgraphs that are (individually) connected.
7 | - **Walk:** A walk is a sequence of edges which joins a sequence of vertices.
8 | - **Directed Walk: ** A directed walk is a sequence of arcs in the same direction which join a sequence of vertices.
9 | - **Path:** - A path is a sequence of vertices reached by their adjacent edges where no vertex is repeated.
10 | - **Cycle:** - A cycle is a sequence of vertices reached by their adjacent edges that starts and ends on the same vertex and has no other repeated vertices.
11 |
12 | - **Directed Cycle:** A directed cycle is a sequence of vertices reached by their adjacent arcs in the same direction that starts and ends on the same vertex and has no other repeated vertices.
13 |
14 |
15 | ## Graph Invariants (Quantitative Properties)
16 | - **Vertex Degree:** The number of edges adjacent to the vertex. The number of neighbors.
17 |
18 | - **Diameter:**
19 |
20 |
21 |
22 | ##Resources
23 | - [Wikipedia - Graph Property](https://en.wikipedia.org/wiki/Graph_property)
24 |
--------------------------------------------------------------------------------
/Web/.nojekyll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/CS-2.2-Graphs-Recursion/f4ed85d10b4c471fb2b12a81cb6bfa9ce6a2360b/Web/.nojekyll
--------------------------------------------------------------------------------
/Web/logo-icononly.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Web/style.css:
--------------------------------------------------------------------------------
1 | :root {
2 | --base-font-weight: 400;
3 | --base-color: white;
4 | --base-font-size: 14px;
5 |
6 | --sidebar-width: 22rem;
7 | --sidebar-nav-link-before-content: "";
8 | --sidebar-nav-link-before-content-l3: "";
9 | --sidebar-name-font-weight: 500;
10 |
11 | --search-result-heading-font-size: 1em;
12 | --search-result-item-font-size: 0.9em;
13 | --search-result-heading-font-weight: 400;
14 | --search-result-heading-margin: 0 0 0.1em;
15 |
16 | --heading-font-weight: 500;
17 | --heading-h1-font-weight: 700;
18 | --heading-h1-font-size: 2.5em;
19 |
20 | --notice-font-style: italic;
21 | --notice-font-weight: 500;
22 |
23 | --blockquote-em-font-style: normal;
24 | --blockquote-em-font-weight: 700;
25 |
26 | --blockquote-font-style: italic;
27 | --blockquote-font-weight: 500;
28 |
29 | --code-font-size: 1em;
30 | --code-font-weight: 500;
31 | --code-tab-size: 2;
32 | }
33 |
34 | .sidebar>h1 {
35 | margin: 2.3rem auto 1rem;
36 | }
37 |
38 | .sidebar>h1>a>img {
39 | height: auto;
40 | }
41 |
42 | .markdown-section {
43 | max-width: 840px;
44 | }
45 |
46 | .markdown-section a:hover {
47 | border-bottom: 1px dashed rgba(255, 255, 255, 0.5);
48 | padding-bottom: 3px;
49 | }
50 |
51 | .sidebar-nav>ul:nth-child(1)>li>a.section-link,
52 | .sidebar-nav>ul:nth-child(1)>li>ul.children>li>a.section-link {
53 | display: block;
54 | }
55 |
56 | #main>h1:nth-child(1) {
57 | display: none;
58 | }
59 |
60 | #main>h1:nth-child(1)[id] {
61 | display: block;
62 | }
63 |
64 | .sidebar ul li a {
65 | color: #333;
66 | font-size: 14px;
67 | font-weight: 400;
68 | overflow: hidden;
69 | text-decoration: none;
70 | text-overflow: ellipsis;
71 | white-space: nowrap;
72 | }
73 |
74 | .sidebar ul li strong a {
75 | font-weight: 700;
76 | }
77 |
78 | .sidebar ul li ul.app-sub-sidebar li a {
79 | font-weight: 400;
80 | }
81 |
82 | .sidebar ul li ul.app-sub-sidebar li a.active {
83 | font-weight: 700;
84 | }
85 |
86 | body .docsify-copy-code-button {
87 | background: none !important;
88 | line-height: 1.5rem;
89 | position: absolute;
90 | word-wrap: normal;
91 | color: #ccc;
92 | font-size: .7rem;
93 | font-weight: 700;
94 | left: 0;
95 | height: 25px;
96 | top: -4px;
97 | text-align: center;
98 | }
99 |
100 | body .docsify-copy-code-button.success {
101 | color: #11A31B;
102 | }
103 |
104 | body .docsify-copy-code-button::after {}
105 |
106 | .app-name-link img {
107 | height: 150px;
108 | width: 150px;
109 | }
110 |
111 | table>tbody>tr>td::before {
112 | display: none;
113 | }
114 |
115 | .btn-edit-on-github {
116 | transition: background-color 0.5s ease;
117 | border: none;
118 | border-radius: 3px;
119 | background-color: var(--theme-color);
120 | position: absolute;
121 | top: var(--sidebar-toggle-offset-top);
122 | right: 0;
123 | margin-right: 45px;
124 | padding: 6px 10px 6px 5px;
125 | height: var(--sidebar-toggle-height);
126 | }
127 |
128 | .btn-edit-on-github a,
129 | .btn-edit-on-github svg {
130 | transition: color 0.5s ease;
131 | color: white;
132 | }
133 |
134 | .btn-edit-on-github a {
135 | text-decoration: none;
136 | position: relative;
137 | font-weight: 700;
138 | top: -1px;
139 | padding-left: 5px;
140 | }
141 |
142 | .btn-edit-on-github:hover {
143 | cursor: pointer;
144 | background-color: var(--mono-tint2);
145 | }
146 |
147 | .btn-edit-on-github:hover svg,
148 | .btn-edit-on-github:hover a {
149 | text-decoration: none;
150 | color: white;
151 | }
152 |
153 | .alert-text {
154 | font-size: 0.8em;
155 | color: red;
156 | font-weight: bold;
157 | }
--------------------------------------------------------------------------------
/Web/sw.js:
--------------------------------------------------------------------------------
1 | /* ===========================================================
2 | * docsify sw.js
3 | * ===========================================================
4 | * Copyright 2016 @huxpro
5 | * Licensed under Apache 2.0
6 | * Register service worker.
7 | * ========================================================== */
8 |
9 | const RUNTIME = 'docsify'
10 | const HOSTNAME_WHITELIST = [
11 | self.location.hostname,
12 | 'fonts.gstatic.com',
13 | 'fonts.googleapis.com',
14 | 'unpkg.com',
15 | 'github.com',
16 | 'github.io',
17 | 'makeschool.com'
18 | ]
19 |
20 | // The Util Function to hack URLs of intercepted requests
21 | const getFixedUrl = (req) => {
22 | var now = Date.now()
23 | var url = new URL(req.url)
24 |
25 | // 1. fixed http URL
26 | // Just keep syncing with location.protocol
27 | // fetch(httpURL) belongs to active mixed content.
28 | // And fetch(httpRequest) is not supported yet.
29 | url.protocol = self.location.protocol
30 |
31 | // 2. add query for caching-busting.
32 | // Github Pages served with Cache-Control: max-age=600
33 | // max-age on mutable content is error-prone, with SW life of bugs can even extend.
34 | // Until cache mode of Fetch API landed, we have to workaround cache-busting with query string.
35 | // Cache-Control-Bug: https://bugs.chromium.org/p/chromium/issues/detail?id=453190
36 | if (url.hostname === self.location.hostname) {
37 | url.search += (url.search ? '&' : '?') + 'cache-bust=' + now
38 | }
39 | return url.href
40 | }
41 |
42 | /**
43 | * @Lifecycle Activate
44 | * New one activated when old isnt being used.
45 | *
46 | * waitUntil(): activating ====> activated
47 | */
48 | self.addEventListener('activate', event => {
49 | event.waitUntil(self.clients.claim())
50 | })
51 |
52 | /**
53 | * @Functional Fetch
54 | * All network requests are being intercepted here.
55 | *
56 | * void respondWith(Promise r)
57 | */
58 | self.addEventListener('fetch', event => {
59 | // Skip some of cross-origin requests, like those for Google Analytics.
60 | if (HOSTNAME_WHITELIST.indexOf(new URL(event.request.url).hostname) > -1) {
61 | // Stale-while-revalidate
62 | // similar to HTTP's stale-while-revalidate: https://www.mnot.net/blog/2007/12/12/stale
63 | // Upgrade from Jake's to Surma's: https://gist.github.com/surma/eb441223daaedf880801ad80006389f1
64 | const cached = caches.match(event.request)
65 | const fixedUrl = getFixedUrl(event.request)
66 | const fetched = fetch(fixedUrl, {
67 | cache: 'no-store'
68 | })
69 | const fetchedCopy = fetched.then(resp => resp.clone())
70 |
71 | // Call respondWith() with whatever we get first.
72 | // If the fetch fails (e.g disconnected), wait for the cache.
73 | // If there’s nothing in cache, wait for the fetch.
74 | // If neither yields a response, return offline pages.
75 | event.respondWith(
76 | Promise.race([fetched.catch(_ => cached), cached])
77 | .then(resp => resp || fetched)
78 | .catch(_ => {
79 | /* eat any errors */
80 | })
81 | )
82 |
83 | // Update the cache with the version we fetched (only for ok status)
84 | event.waitUntil(
85 | Promise.all([fetchedCopy, caches.open(RUNTIME)])
86 | .then(([response, cache]) => response.ok && cache.put(event.request, response))
87 | .catch(_ => {
88 | /* eat any errors */
89 | })
90 | )
91 | }
92 | })
93 |
--------------------------------------------------------------------------------
/_navbar.md:
--------------------------------------------------------------------------------
1 | * **[Syllabus](README.md)**
2 | * **[Tracker](https://www.makeschool.com)**
3 | * [Make School](https://www.makeschool.com)
4 |
--------------------------------------------------------------------------------
/_sidebar.md:
--------------------------------------------------------------------------------
1 | - **[Syllabus](README.md)**
2 | - **Lessons**
3 |
4 | - **Homeworks**
5 |
6 | - **Project**
7 |
8 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | CS 2.2: Advanced Recursion & Graphs
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
19 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
115 |
116 |
117 |
--------------------------------------------------------------------------------