├── CoBattles
├── README.md
└── assets
│ ├── image-1.png
│ ├── image-2.png
│ ├── image-3.png
│ ├── image-4.png
│ └── image.png
├── Coding Challenges
├── Merge Two Linked Lists
│ ├── merging-linked.py
│ ├── old_merge.py
│ └── spiral.py
└── palindromes
│ ├── generatePalindrome.py
│ ├── palindromeFunctional.py
│ ├── palindrome_in_list.py
│ └── test.py
├── LICENSE
├── Live Session
├── Session Management - Slide.pdf
├── Workshop 11 - Client Side Rendering
│ ├── Client Side Rendering - Slide.pdf
│ ├── index.html
│ ├── index.js
│ └── style.css
├── Workshop 13 - Session Management
│ ├── backend
│ │ ├── package-lock.json
│ │ ├── package.json
│ │ ├── server.js
│ │ └── src
│ │ │ ├── app.js
│ │ │ ├── controller
│ │ │ ├── auth.controller.js
│ │ │ └── event.controller.js
│ │ │ ├── middleware
│ │ │ └── jwt.middleware.js
│ │ │ ├── model
│ │ │ ├── auth.model.js
│ │ │ └── events.model.js
│ │ │ └── routes
│ │ │ ├── auth.route.js
│ │ │ └── event.route.js
│ └── frontend
│ │ ├── index.html
│ │ ├── package-lock.json
│ │ └── src
│ │ ├── index.js
│ │ ├── styles
│ │ └── style.css
│ │ └── views
│ │ ├── events.view.js
│ │ └── navbar.view.js
├── Workshop 2 - Sequences
│ ├── Sequences - Slides.pdf
│ ├── image-1.png
│ ├── image-2.png
│ ├── image-3.png
│ └── readme.md
├── Workshop 3 - Divide and Conquer
│ ├── D&C Code Implementation.py
│ ├── Divide and Conquer Algorithms.pdf
│ ├── QuickSort.excalidraw
│ ├── image-1.png
│ ├── image-2.png
│ ├── image-3.png
│ ├── image.png
│ └── readme.md
├── Workshop 4 - Computational Complexity
│ ├── Code
│ │ ├── Sequences Complexities
│ │ │ ├── problem-1.py
│ │ │ ├── problem-2.py
│ │ │ └── problem-3.py
│ │ ├── problem-1.py
│ │ ├── problem-2.py
│ │ ├── problem-3.py
│ │ └── problem-4.py
│ ├── Computational Complexity - Slides.pdf
│ ├── Diagramming.excalidraw
│ ├── assests
│ │ ├── image-1.png
│ │ ├── image-2.png
│ │ ├── image-3.png
│ │ └── image.png
│ └── readme.md
├── Workshop 5 - Constant Time and Storage
│ ├── Constant Time Storage and Access.pdf
│ ├── Live Diagrams.excalidraw
│ └── code
│ │ ├── __pycache__
│ │ └── navigation.cpython-312.pyc
│ │ ├── nav_performance.py
│ │ └── navigation.py
├── Workshop 6 - Hashing
│ ├── code
│ │ └── hashset.py
│ └── planning.excalidraw
└── Workshop 8 - Persistent Data Storage
│ ├── Persistent Storage - Slide.pdf
│ └── database_setup
│ ├── README.md
│ ├── __init__.py
│ ├── config.json
│ ├── data
│ ├── circuits.csv
│ ├── constructor_results.csv
│ ├── constructor_standings.csv
│ ├── constructors.csv
│ ├── driver_standings.csv
│ ├── drivers.csv
│ ├── laptimes.csv
│ ├── pitstops.csv
│ ├── qualifying.csv
│ ├── races.csv
│ ├── results.csv
│ ├── seasons.csv
│ └── status.csv
│ ├── models
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-312.pyc
│ │ ├── ms_sql_model.cpython-312.pyc
│ │ ├── my_sql_model.cpython-312.pyc
│ │ └── postgres_model.cpython-312.pyc
│ ├── ms_sql_model.py
│ ├── my_sql_model.py
│ └── postgres_model.py
│ ├── requirements.txt
│ ├── scripts
│ └── create.sql
│ ├── services
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-312.pyc
│ │ ├── database_connection.cpython-312.pyc
│ │ ├── database_connection_factory.cpython-312.pyc
│ │ └── input_handler.cpython-312.pyc
│ ├── database_connection.py
│ ├── database_connection_factory.py
│ └── input_handler.py
│ └── setup.py
├── README.md
└── Textbook
├── Chapter 11 - Client Side Rendering
└── README.md
├── Chapter 13 - Session Management
└── readme.md
├── Chapter 1: Technical Interview Preparation Roadmap
├── Chapter 1_ Technical Interview Preparation Roadmap 🚀.pdf
└── README.md
├── Chapter 2: Sequences
├── Chapter 2_ Sequences 🧩.pdf
└── README.md
├── Chapter 3: Divide and Conquer Algorithms
├── Chapter 3_ Divide and Conquer 🏹.pdf
└── README.md
├── Chapter 4: Computational Complexity
├── Chapter 4_ Computational Complexity 🧩.pdf
└── README.md
├── Chapter 5 - Constant Time Storage and Access
├── assets
│ ├── image-1.png
│ ├── image-2.png
│ └── image.png
└── readme.md
├── Chapter 6 - Hashing
├── assets
│ ├── image-1.png
│ ├── image-2.png
│ ├── image-3.png
│ ├── image-4.png
│ └── image.png
├── code
│ └── linear-probing.py
└── readme.md
├── Chapter 8 - Persistent Storage
├── README.md
└── assets
│ ├── image-1.png
│ ├── image-2.png
│ ├── image-3.png
│ └── image.png
└── Chapter 9 - Web Applications
├── assets
├── image-1.png
├── image-2.png
├── image-3.png
├── image-4.png
├── image-5.png
├── image.png
└── image1.png
└── readme.md
/CoBattles/README.md:
--------------------------------------------------------------------------------
1 | ### Currently Running -> [CoBattles 1](https://www.hackerrank.com/contests/cobattles/)
2 |
3 | ## Table of Content
4 | - [Introduction](#introduction)
5 | - [CoBattles](#cobattles)
6 | - [Background](#background)
7 | - [Rules](#rules)
8 | - [Navigatin the Platform](#navigating-the-platform)
9 | - [Contests](#contests)
10 | - [CoBattles 1](#cobattles-1)
11 |
12 |
13 |
14 | ## Introduction
15 | As programmers, we can make use of coding challenges to improve our coding and problem-solving skills, these challenges introduce us to abstract problems that often require us to think beyond the repetitive code we write on a day-to-day basis.
16 |
17 | Coding challenges are a great way to not only practice your problem-solving skills, but they also allow you to learn more about your programming language as you look for different ways to optmise your solutions and discover new techniques.
18 |
19 | Coding challenges are a key part of most hiring processes for technical roles, they will usually be part of the application phase where you might be required to complete a coding challenge to get to the next stage.
20 |
21 | Being good at coding challenges won’t only prepare you for the coding challenge part of the application process, but it will also give you the problem-solving practice that you need to perfect your approach before getting into a technical interview where you would need to showcase your ability to take a problem that you haven’t see before and formulate a solution for it.
22 |
23 |
24 | ## CoBattles
25 | CoBattles are a series of coding challenges that aim to get you in the groove of doing coding challenges, each week’s challenges will aim to test a certain aspect of your coding ability with a mixture of challenges that are similar to those found in coding interviews and other challenges that are there to push your problem-solving skills that bit further.
26 |
27 | ### Background
28 | Each week on Monday, a new contest will start, the links can be found [here](#contests), you will need to sign up for the contest in order to participate.
29 |
30 | #### Rules
31 | - Each contest will have a variable number of challenges
32 | - You are not required to complete all of the challenges in a single seating
33 | - You can spread out when you do each challenge while the contest is running
34 | - The time it takes to complete an INDIVIDUAL challenge may affect your final score
35 | - The timer for a specific challenge will start as soon as that challenge is opened
36 | - The scoring for the contest will vary week to week, the contest page will highlight how the specific contest is being scored.
37 |
38 | #### Navigating The Platform
39 | If it's your first time using a coding challenge tool, it might be intimidating and overwhelming at first, but it's important to stay calm and read through the instructions that are provided. There are however a few things that might not be clear, so let's try to clear them up.
40 |
41 | When you get into a challenge, you will be faced with something similar to the image below.
42 | 
43 |
44 | If it's your first time ever doing a coding challenge, you will want to get familiar with the coding interface first before you take a look at the actual problem, once you've done a few coding challenges then everything will be more straightforward.
45 |
46 | 
47 | 1. Change the programming language by clicking on the option on the top right of your screen
48 | 2. There is a lot of code pre-written, look for the function with comments, these comments will let you know which functions to work with
49 | - Most fo the function are for doing background operations, DO NOT TOUCH them
50 | - Read the comments and only edit the functions that you are directed to
51 | 3. Once your code is written, make sure that you test your code first
52 | - Click the "Run Code" (Or run tests depending on the platform)
53 | - Make sure that your code is passing all of the tests before submitting
54 |
55 |
56 |
57 |
58 | On the left side of the screen, you will find the questions section
59 |
60 | 
61 | - Make sure that you read and understand the problem before attempting to write the code
62 | - Look at the input that will be provided and the required output
63 | - Your output has to be exact or your code will fail the tests.
64 | - Look through the input and expected outputs in the examples provided
65 | - Look at the constraints for the problem
66 |
67 |
68 | ## Contests
69 |
70 | ### CoBattles 1
71 | [Currently Running](https://www.hackerrank.com/contests/cobattles/)
72 |
73 | Top 3 👑
74 | - 🥇
75 | - 🥈
76 | - 🥉
77 |
78 |
--------------------------------------------------------------------------------
/CoBattles/assets/image-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/CoBattles/assets/image-1.png
--------------------------------------------------------------------------------
/CoBattles/assets/image-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/CoBattles/assets/image-2.png
--------------------------------------------------------------------------------
/CoBattles/assets/image-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/CoBattles/assets/image-3.png
--------------------------------------------------------------------------------
/CoBattles/assets/image-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/CoBattles/assets/image-4.png
--------------------------------------------------------------------------------
/CoBattles/assets/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/CoBattles/assets/image.png
--------------------------------------------------------------------------------
/Coding Challenges/Merge Two Linked Lists/merging-linked.py:
--------------------------------------------------------------------------------
1 | class ListNode(object):
2 | def __init__(self, val=0, next=None):
3 | self.val = val
4 | self.next = next
5 |
6 | def __str__(self) -> str:
7 | current = self
8 | output = []
9 |
10 | while current:
11 | output.append(f" {current.val} ->")
12 | current = current.next
13 |
14 |
15 | return "".join(output).strip("->")
16 |
17 | def get_merged(list1, list2):
18 |
19 | if (not list1):
20 | return list2
21 |
22 | if (not list2):
23 | return list1
24 |
25 |
26 | if (list1.val < list2.val):
27 | head = list1
28 | tail = list1
29 | list1 = list1.next
30 | else:
31 | head = list2
32 | tail = list2
33 | list2 = list2.next
34 |
35 |
36 |
37 | while (list1 and list2):
38 |
39 | if list1.val < list2.val:
40 | tail.next = list1
41 | tail = tail.next
42 |
43 | next = tail.next
44 | tail.next = None
45 | list1 = next
46 | continue
47 |
48 | tail.next = list2
49 | tail = tail.next
50 |
51 | next = tail.next
52 | tail.next = None
53 | list2 = next
54 |
55 |
56 | if list1:
57 | tail.next = list1
58 | else:
59 | tail.next = list2
60 |
61 | return head
62 |
63 |
64 | """
65 | list1 = [1] -> [2] -> [3] -> null
66 | list2 = [3] -> [4] -> null
67 |
68 | output = [1]
69 | """
70 |
71 |
72 |
73 | def main():
74 | list1 = ListNode(100)
75 | list1.next = ListNode(102)
76 | list1.next.next = ListNode(103)
77 |
78 | list2 = ListNode(1)
79 | list2.next = ListNode(3)
80 | list2.next.next = ListNode(400)
81 |
82 | output = get_merged(list1, list2)
83 | print(output)
84 |
85 | main()
--------------------------------------------------------------------------------
/Coding Challenges/Merge Two Linked Lists/old_merge.py:
--------------------------------------------------------------------------------
1 | class ListNode(object):
2 | def __init__(self, val=0, next=None):
3 | self.val = val
4 | self.next = next
5 |
6 | def __str__(self) -> str:
7 | current = self
8 | output = []
9 |
10 | while current:
11 | output.append(f" {current.val} ->")
12 | current = current.next
13 |
14 |
15 | return "".join(output).strip("->")
16 |
17 | def get_merged(list1, list2):
18 | output = ListNode(list1.val)
19 | head = output
20 | list1 = list1.next
21 |
22 | while (list1 and list2):
23 |
24 | if list1.val < list2.val:
25 | output.next = ListNode(list1.val)
26 | output = output.next
27 | list1 = list1.next
28 | continue
29 |
30 | output.next = ListNode(list2.val)
31 | output = output.next
32 | list2 = list2.next
33 |
34 |
35 | if list1:
36 | output.next = list1
37 | else:
38 | output.next = list2
39 |
40 | return head
41 |
42 |
43 | """
44 | list1 = [1] -> [2] -> [3] -> null
45 | list2 = [3] -> [4] -> null
46 |
47 | output = [1]
48 | """
49 |
50 |
51 |
52 | def main():
53 | list1 = ListNode(1)
54 | list1.next = ListNode(2)
55 | list1.next.next = ListNode(3)
56 |
57 | list2 = ListNode(1)
58 | list2.next = ListNode(3)
59 | list2.next.next = ListNode(4)
60 |
61 | output = get_merged(list1, list2)
62 | print(output)
63 |
64 | main()
--------------------------------------------------------------------------------
/Coding Challenges/Merge Two Linked Lists/spiral.py:
--------------------------------------------------------------------------------
1 | """
2 | https://leetcode.com/problems/spiral-matrix-ii/
3 |
4 | Constraints
5 | - Create nxn grid
6 | - output should be a 2D array that represents the spiral
7 | - Count from 1 - n^2
8 |
9 | Steps
10 | - Generate the grid
11 | - Fill each index with None initially
12 | - Determine the starting direction
13 | - Add numbers to each cell until:
14 | - Run out of bound
15 | - Next position already filled
16 | - If next move is not possible
17 | - Check next direction
18 | - The operations are complete once we reach nxn for our loop
19 | """
20 |
21 | """
22 | 0 - Right
23 | 1 - Down
24 | 2 - left
25 | 3 - Up
26 | """
27 |
28 | def generate_matrix(n):
29 | matrix = [[None for i in range(n)] for x in range(n)]
30 | current_direction = 0
31 | offset = get_offset(current_direction)
32 |
33 | current_position = [0,0]
34 |
35 | for i in range(1, (n*n) + 1):
36 | if (is_in_bound(current_position, n)):
37 | matrix[current_position[0]][current_position[1]] = i
38 |
39 | next_position = [current_position[0] + offset[0], current_position[1] + offset[1]]
40 |
41 | if (not is_in_bound(next_position, n) or next_position_taken(matrix, next_position)):
42 | current_direction = change_direction(current_direction)
43 | offset = get_offset(current_direction)
44 | next_position = [current_position[0] + offset[0], current_position[1] + offset[1]]
45 |
46 | current_position = next_position
47 |
48 | return matrix
49 |
50 | def next_position_taken(matrix, next_position):
51 | return matrix[next_position[0]][next_position[1]]
52 |
53 | def is_in_bound(current_position, n):
54 | # The issue was using AND instead of OR 😞
55 | if (current_position[0] >= n or current_position[0] < 0):
56 | return False
57 | if (current_position[1] >= n or current_position[1] < 0):
58 | return False
59 |
60 | return True
61 |
62 | def print_matrix(matrix):
63 | for x, row in enumerate(matrix):
64 | print()
65 | for y, col in enumerate(matrix[x]):
66 | print(col, end=" ")
67 |
68 |
69 | def change_direction(current_direction: int):
70 | return (current_direction + 1) % 4
71 |
72 | def get_offset(current_direction: int):
73 |
74 | match current_direction:
75 | case 0: return (0, 1)
76 | case 1: return (1, 0)
77 | case 2: return (0, -1)
78 | case 3: return (-1, 0)
79 |
80 |
81 |
82 | if __name__ == '__main__':
83 | print_matrix(generate_matrix(6))
--------------------------------------------------------------------------------
/Coding Challenges/palindromes/generatePalindrome.py:
--------------------------------------------------------------------------------
1 | import random
2 | import string
3 |
4 | def generate_random_string(length):
5 | return ''.join(random.choices(string.ascii_lowercase + string.digits, k=length))
6 |
7 | def generate_palindrome(length):
8 | half = generate_random_string(length // 2)
9 | return half + half[::-1]
10 |
11 |
12 | def getWordList():
13 | return [
14 | generate_palindrome(100),
15 | generate_random_string(100),
16 | generate_palindrome(100),
17 | generate_random_string(100),
18 | generate_palindrome(100),
19 | generate_random_string(100),
20 | generate_palindrome(100),
21 | generate_random_string(100),
22 | generate_palindrome(100),
23 | generate_random_string(100),
24 | generate_palindrome(100),
25 | generate_random_string(100),
26 | generate_palindrome(100),
27 | generate_random_string(100),
28 | generate_palindrome(100),
29 | generate_random_string(100),
30 | generate_palindrome(100),
31 | generate_random_string(100),
32 | generate_palindrome(100),
33 | generate_random_string(100),
34 | generate_palindrome(100),
35 | generate_random_string(100),
36 | generate_palindrome(100),
37 | generate_random_string(100),
38 | generate_palindrome(100),
39 | generate_random_string(100),
40 | generate_palindrome(100),
41 | generate_random_string(100),
42 | generate_palindrome(100),
43 | generate_random_string(100),
44 | generate_palindrome(100),
45 | generate_random_string(100),
46 | generate_palindrome(100),
47 | generate_random_string(100),
48 | generate_palindrome(100),
49 | generate_random_string(100),
50 | generate_palindrome(100),
51 | generate_random_string(100),
52 | generate_palindrome(100),
53 | generate_random_string(100),
54 | generate_palindrome(100),
55 | generate_random_string(100),
56 | generate_palindrome(100),
57 | generate_random_string(100),
58 | generate_palindrome(100),
59 | generate_random_string(100),
60 | generate_palindrome(100),
61 | generate_random_string(100),
62 | generate_palindrome(100),
63 | generate_random_string(100),
64 | generate_palindrome(100),
65 | generate_random_string(100),
66 | generate_palindrome(100),
67 | generate_random_string(100)
68 | ]
--------------------------------------------------------------------------------
/Coding Challenges/palindromes/palindromeFunctional.py:
--------------------------------------------------------------------------------
1 | def isPalindrome(word: str):
2 | reversed_word = list(word)
3 | reversed_word.reverse()
4 |
5 | return "".join(reversed_word) == word
6 |
7 | def getAllPalindromes(words: list[str]):
8 | output = []
9 | for word in words:
10 | if (isPalindrome(word)):
11 | output.append(word)
12 |
13 | return output
14 |
15 | def getPalsFunctionally(words: list[str]):
16 | return my_filter(words, lambda word: word[::-1] == word)
17 |
18 | def my_filter(lst: list, callback):
19 | output = []
20 |
21 | for item in lst:
22 | if (callback(item)):
23 | output.append(item)
24 |
25 | return output
26 |
27 | print(getPalsFunctionally(["aa", "aba", "abc", "abd"]))
--------------------------------------------------------------------------------
/Coding Challenges/palindromes/palindrome_in_list.py:
--------------------------------------------------------------------------------
1 | """
2 | Given a list of strings, return a list of strings that are palindromes.
3 | A palindrome is a word or phrase that is the same forwards and backwards.
4 | For example, “radar” is a palindrome, but “fish” is not.
5 |
6 | Example 1:
7 | Input: ["abc", "cba", "abab"]
8 | Output: ["abc", "abab"]
9 |
10 | Example 2:
11 | Input: ["a", "b", "ab"]
12 | Output: ["ab"]
13 |
14 | Example 3:
15 | Input: ["abc", "cba", "abab", "baba"]
16 | Output: ["baba", "abab"]
17 |
18 | Constraints:
19 | 1 <= list.length <= 100
20 | 1 <= list[i].length <= 100
21 | list[i] consists of lowercase English letters.a
22 | """
23 |
24 | from time import time
25 | from generatePalindrome import getWordList
26 |
27 | def isPalindromeReverse(word: str):
28 | reversed_word = list(word)
29 | reversed_word.reverse()
30 |
31 |
32 | return "".join(reversed_word) == word
33 |
34 | def isPalindromeReverseLoop(word: str):
35 | charList = list(word)
36 | reversed_word = []
37 |
38 | for char in charList[::-1]:
39 | reversed_word.append(char)
40 |
41 | return "".join(reversed_word) == word
42 |
43 | def isPalindomeWindow(word: str):
44 | left = 0
45 | right = len(word) - 1
46 |
47 | output = False
48 |
49 | while (True):
50 | if left >= right:
51 | output = True
52 | break
53 |
54 | if word[left] != word[right]:
55 | output = False
56 | break
57 |
58 | left += 1
59 | right -= 1
60 |
61 | return output
62 |
63 | def getAllPalindromes(words: list[str], isPalindome):
64 | output = []
65 | for word in words:
66 | if (isPalindome(word)):
67 | output.append(word)
68 |
69 | return output
70 |
71 | def runTest(func, name):
72 | words_list = getWordList()
73 | start = time()
74 |
75 | for i in range(10000):
76 | getAllPalindromes(words_list, func)
77 | end = time()
78 |
79 | print(name, end - start)
80 |
81 | runTest(isPalindromeReverse, "Using reverse")
82 | runTest(isPalindomeWindow, "Using window")
83 | runTest(isPalindromeReverseLoop, "Loop to Reverse")
--------------------------------------------------------------------------------
/Coding Challenges/palindromes/test.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Coding Challenges/palindromes/test.py
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/Live Session/Session Management - Slide.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Live Session/Session Management - Slide.pdf
--------------------------------------------------------------------------------
/Live Session/Workshop 11 - Client Side Rendering/Client Side Rendering - Slide.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Live Session/Workshop 11 - Client Side Rendering/Client Side Rendering - Slide.pdf
--------------------------------------------------------------------------------
/Live Session/Workshop 11 - Client Side Rendering/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Document
8 |
9 |
10 |
11 |
12 |
13 |
14 |
16 |
17 |
--------------------------------------------------------------------------------
/Live Session/Workshop 11 - Client Side Rendering/index.js:
--------------------------------------------------------------------------------
1 | const rootElement = document.getElementById("root"); //
2 | const createTodo = document.createElement('button');
3 | const todoItems = [
4 | {
5 | title: "Write code",
6 | isComplete: false
7 | },
8 | {
9 | title: "Review Code",
10 | isComplete: false
11 | },
12 | {
13 | title: "Update Code",
14 | isComplete: true
15 | }
16 | ]
17 |
18 | setUpComponents();
19 |
20 | function setUpComponents(){
21 | rootElement.style.width = "800px";
22 |
23 | createTodo.innerText = "Add New Todo";
24 | createTodoEventListener(createTodo);
25 |
26 | rootElement.appendChild(createTodo);
27 | generateToDo();
28 |
29 | }
30 |
31 | function createTodoEventListener(createButton){
32 | createButton.addEventListener('click', () => {
33 | const todo = prompt("What is the task");
34 | const newTodo = {
35 | title: todo,
36 | isComplete: false
37 | };
38 |
39 | todoItems.push(newTodo);
40 | createTodoComponent(newTodo);
41 | });
42 | }
43 |
44 | function generateToDo(){
45 | for (item of todoItems){
46 | createTodoComponent(item)
47 | }
48 | }
49 |
50 | function createTodoComponent(item){
51 | const todoItemContainer = document.createElement("div");
52 | const todoText = document.createElement('p');
53 | const todoButton = document.createElement('button');
54 |
55 | // Handle todo Text (p tag)
56 | todoText.innerText = item.title;
57 | todoText.className = item.isComplete ? "task-complete" : "task-incomplete";
58 |
59 | // Button (button tag)
60 | todoButton.innerText = "Done";
61 | todoButton.addEventListener('click', () => {
62 | item.isComplete = true;
63 | todoText.className = item.isComplete ? "task-complete" : "task-incomplete";
64 | })
65 |
66 | todoItemContainer.appendChild(todoText);
67 | todoItemContainer.appendChild(todoButton);
68 | todoItemContainer.classList.add("todoItem");
69 |
70 | rootElement.appendChild(todoItemContainer)
71 | }
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/Live Session/Workshop 11 - Client Side Rendering/style.css:
--------------------------------------------------------------------------------
1 | body {
2 | display: flex;
3 | flex-direction: column;
4 | justify-content: center;
5 | align-items: center;
6 |
7 | }
8 |
9 | .todoItem {
10 | background-color: aqua;
11 | display: flex;
12 | justify-content: space-between;
13 | }
14 |
15 | .task-complete {
16 | text-decoration: line-through;
17 | color: grey;
18 | }
19 |
20 | .task-incomplete{
21 | text-decoration: solid;
22 | }
23 |
24 |
--------------------------------------------------------------------------------
/Live Session/Workshop 13 - Session Management/backend/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "backend",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "node --watch server.js"
9 | },
10 | "keywords": [],
11 | "author": "",
12 | "license": "ISC",
13 | "dependencies": {
14 | "bcrypt": "^5.1.1",
15 | "cookie-session": "^2.1.0",
16 | "cors": "^2.8.5",
17 | "express": "^4.19.2",
18 | "jsonwebtoken": "^9.0.2",
19 | "mongoose": "^8.5.1"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Live Session/Workshop 13 - Session Management/backend/server.js:
--------------------------------------------------------------------------------
1 | const app = require("./src/app");
2 |
3 | const PORT = 8000;
4 |
5 | app.set('port', PORT);
6 | app.listen(PORT, () => {
7 | console.log(`Server running on port ${PORT}`);
8 | });
--------------------------------------------------------------------------------
/Live Session/Workshop 13 - Session Management/backend/src/app.js:
--------------------------------------------------------------------------------
1 | const Express = require("express");
2 | const cors = require("cors");
3 | const mongoose = require("mongoose");
4 | const session = require("cookie-session");
5 |
6 | const app = Express();
7 |
8 | const expiryDate = new Date(Date.now() + 60 * 60 * 1000); // 1 hour
9 | app.use(session({
10 | name: "session",
11 | keys: ["key1", "key2"],
12 | cookie: {
13 | secure: true,
14 | httpOnly: true,
15 | domain: "example.com",
16 | path: "path",
17 | expires: expiryDate
18 | }
19 | }))
20 |
21 | app.use(cors());
22 | app.use(Express.json())
23 |
24 | const MONGO_URI = process.env.MONGO_URI || "mongodb://localhost:27017";
25 |
26 | mongoose.connect(MONGO_URI, { useNewUrlParser: true, useUnifiedTopology: true, dbName: "tipp_events" })
27 | .then(() => console.log("Connected to database"))
28 | .catch((err) => console.log(err));
29 |
30 | const authRoute = require("./routes/auth.route");
31 | const eventRoute = require("./routes/event.route");
32 |
33 | app.use("", authRoute);
34 | app.use("", eventRoute);
35 |
36 | module.exports = app;
--------------------------------------------------------------------------------
/Live Session/Workshop 13 - Session Management/backend/src/controller/auth.controller.js:
--------------------------------------------------------------------------------
1 | const authModel = require("../model/auth.model")
2 | const jwt = require("jsonwebtoken");
3 | const JWT_SECRET = "supersecrettoken";
4 |
5 | async function createUser(req, res){
6 | const { email, password } = req.body;
7 |
8 | try{
9 | const user = await authModel.create({ email, password });
10 | console.log(user)
11 | res.status(201).json(user);
12 | } catch(err){
13 | res.status(400).json(err);
14 | }
15 | }
16 |
17 | async function authenticateUser(req, res, next){
18 | const {email, password} = req.body;
19 |
20 | const user = await authModel.findOne({email}).select('+password');
21 |
22 | if (!user){
23 | const error = new Error("User not Found")
24 | error.status = 403
25 | return next(error);
26 | }
27 |
28 |
29 |
30 | try{
31 | const user = await authModel.findOne({email}).select('+password');
32 |
33 | if (!user){
34 | res.status(400).json({error: "User not found"});
35 | }
36 |
37 | user.comparePassword(password, (err, isMatch) => {
38 | if (err) throw err;
39 |
40 | if (isMatch){
41 | const payload = {
42 | id: user._id,
43 | role: user.role
44 | }
45 |
46 | const token = jwt.sign(payload, JWT_SECRET, {expiresIn: "7d"});
47 |
48 | req.session.token = token;
49 |
50 | res.status(200).json({message: "User authenticated", token: token});
51 | } else{
52 | res.status(400).json({message: "Invalid credentials"})
53 | }
54 | });
55 | } catch(err){
56 | res.status(400).json(err);
57 | }
58 | }
59 |
60 | module.exports = {
61 | createUser,
62 | authenticateUser
63 | }
--------------------------------------------------------------------------------
/Live Session/Workshop 13 - Session Management/backend/src/controller/event.controller.js:
--------------------------------------------------------------------------------
1 | const EventModel = require("../model/events.model");
2 |
3 | exports.createEvent = async (req, res) => {
4 | try{
5 | const event = await EventModel.create(req.body);
6 | res.status(201).json(event);
7 | } catch(err){
8 | res.status(400).json(err);
9 | }
10 | }
11 |
12 | exports.getEvents = async (req, res) => {
13 | console.log(req.session)
14 | try{
15 | const events = await EventModel.find();
16 | res.status(200).json(events);
17 | } catch(err){
18 | res.status(400).json(err);
19 | }
20 | }
--------------------------------------------------------------------------------
/Live Session/Workshop 13 - Session Management/backend/src/middleware/jwt.middleware.js:
--------------------------------------------------------------------------------
1 | const jwt = require("jsonwebtoken")
2 | const JWT_SECRET = "supersecrettoken";
3 |
4 | function verifyJwt(req, res, next){
5 | const auth = req.headers.authorization;
6 | // const auth = req.session.token;
7 |
8 | if (auth){
9 | const token = auth.split(" ")[1];
10 | // const token = auth
11 |
12 | jwt.verify(token, JWT_SECRET, (err, user) => {
13 | if (err) return res.sendStatus(403);
14 | req.user = user;
15 |
16 | next();
17 | });
18 | } else{
19 | res.sendStatus(401);
20 | }
21 | }
22 |
23 | function verifyAdmin(req, res, next){
24 |
25 | if (!req.user){
26 | return res.sendStatus(403);
27 | }
28 |
29 | if (req.user.role == "admin"){
30 | next();
31 | }
32 | else{
33 | res.sendStatus(403);
34 | }
35 | }
36 |
37 | module.exports = {verifyJwt, verifyAdmin};
--------------------------------------------------------------------------------
/Live Session/Workshop 13 - Session Management/backend/src/model/auth.model.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("mongoose");
2 | const bcrypt = require("bcrypt");
3 | const SALT = 10;
4 |
5 | const authSchema = mongoose.Schema({
6 | email: {
7 | type: String,
8 | required: true,
9 | unique: true,
10 | lowercase: true,
11 | trim: true,
12 | match: [/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/, 'Please fill a valid email address']
13 | },
14 | password: {
15 | type: String,
16 | required: true,
17 | minlength: 6,
18 | select: false
19 | },
20 | role: {
21 | type: String,
22 | enum: ["user", "admin"],
23 | default: "user"
24 | },
25 | isActive: {
26 | type: Boolean,
27 | default: true
28 | }
29 | });
30 |
31 | authSchema.pre("save", function (next) {
32 | if (!this.isModified("password")) return next();
33 |
34 | bcrypt.hash(this.password, SALT, (err, hash) => {
35 | if (err) return next(err);
36 | this.password = hash;
37 | next();
38 | });
39 | });
40 |
41 | authSchema.methods.comparePassword = function (candidatePassword, cb) {
42 | bcrypt.compare(candidatePassword, this.password, (err, isMatch) => {
43 | if (err) return cb(err);
44 | cb(null, isMatch);
45 | });
46 | };
47 |
48 | module.exports = mongoose.model("Auth", authSchema);
--------------------------------------------------------------------------------
/Live Session/Workshop 13 - Session Management/backend/src/model/events.model.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("mongoose");
2 |
3 | const eventSchema = mongoose.Schema({
4 | title: {
5 | type: String,
6 | required: true
7 | },
8 | description: {
9 | type: String,
10 | required: true
11 | },
12 | date: {
13 | type: String,
14 | required: true
15 | }
16 | });
17 |
18 | module.exports = mongoose.model("Event", eventSchema);
--------------------------------------------------------------------------------
/Live Session/Workshop 13 - Session Management/backend/src/routes/auth.route.js:
--------------------------------------------------------------------------------
1 | const router = require("express").Router();
2 | const { authenticateUser, createUser } = require("../controller/auth.controller")
3 |
4 | router.post("/sign-up", createUser);
5 | router.post("/login", authenticateUser);
6 |
7 | module.exports = router;
--------------------------------------------------------------------------------
/Live Session/Workshop 13 - Session Management/backend/src/routes/event.route.js:
--------------------------------------------------------------------------------
1 | const router = require("express").Router();
2 | const { verifyAdmin, verifyJwt } = require("../middleware/jwt.middleware");
3 | const { createEvent, getEvents } = require("../controller/event.controller");
4 |
5 | router.post("/events", verifyJwt, createEvent);
6 | router.get("/events", getEvents);
7 |
8 | module.exports = router;
--------------------------------------------------------------------------------
/Live Session/Workshop 13 - Session Management/frontend/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Document
9 |
10 |
11 |
12 |
13 |
14 |
15 | HyperEvents
16 |
17 |
20 |
21 |
22 |
23 |
24 |
25 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/Live Session/Workshop 13 - Session Management/frontend/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Workshop 13 - Session Management",
3 | "lockfileVersion": 3,
4 | "requires": true,
5 | "packages": {}
6 | }
7 |
--------------------------------------------------------------------------------
/Live Session/Workshop 13 - Session Management/frontend/src/index.js:
--------------------------------------------------------------------------------
1 | import { getEventsContainer, getPageHeading } from "./views/events.view.js"
2 | import { getAuthenticatedNavbar} from "./views/navbar.view.js"
3 |
4 |
5 | const root = document.getElementById("root");
6 | const userAuth = {
7 | isAuthenticated: false,
8 | role: null
9 | }
10 |
11 | render()
12 |
13 | function render(){
14 | generalUserContent();
15 | generateNavBar();
16 | }
17 |
18 | function generateNavBar(){
19 | const routes = document.getElementById("routes")
20 | routes.appendChild(getAuthenticatedNavbar())
21 | }
22 |
23 | async function generalUserContent(){
24 | const events = await getEvents();
25 |
26 | root.appendChild(getPageHeading());
27 | root.appendChild(getEventsContainer(events));
28 | }
29 |
30 | async function getEvents(){
31 | const response = await fetch("http://localhost:8000/events")
32 | const events = await response.json();
33 | return events
34 | }
--------------------------------------------------------------------------------
/Live Session/Workshop 13 - Session Management/frontend/src/styles/style.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | }
5 |
6 | ul {
7 | list-style: none;
8 | margin: 0;
9 | padding: 0;
10 | }
11 |
12 | nav {
13 | display: flex;
14 | justify-content: space-between;
15 | background-color: aqua;
16 | padding: 20px 150px;
17 | }
18 |
19 | a {
20 | cursor: pointer;
21 | }
22 |
23 | #root {
24 | margin: 50px 150px;
25 | }
26 |
27 | .page-heading{
28 | font-size: 2.5em;
29 | }
30 |
31 | .event-list-container {
32 | margin: 0 5%;
33 | }
34 |
35 | .event-list-container h3, p{
36 | margin: 0;
37 | display: flex;
38 | width: 50%;
39 | }
40 |
41 | .event-list-container ul {
42 | display: flex;
43 | flex-direction: column;
44 | gap: 60px;
45 | }
46 |
47 | .event-list-container li {
48 | display: flex;
49 | flex-direction: column;
50 | justify-content: start;
51 | }
52 |
53 | .event-list-container .event-title {
54 | font-size: 2em;
55 | }
56 |
57 | .event-list-container .event-date {
58 | font-size: 1em;
59 | margin-bottom: 20px;
60 | }
61 |
62 | .event-list-container .event-description{
63 | font-size: 1.2em;
64 | margin-bottom: 20px;
65 | }
66 |
67 | .event-list-container .event-view-button{
68 | width: 50px;
69 | margin-bottom: 20px;
70 | background-color: transparent;
71 | border: none;
72 | cursor: pointer;
73 | }
74 |
75 | .event-list-container hr{
76 | width: 90%;
77 | justify-self: center;
78 | }
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/Live Session/Workshop 13 - Session Management/frontend/src/views/events.view.js:
--------------------------------------------------------------------------------
1 | export function getPageHeading(){
2 | const pageHeadingContainer = document.createElement("section");
3 | pageHeadingContainer.className = "page-heading";
4 |
5 | const header = document.createElement("h1");
6 | header.innerText = "Live Events";
7 |
8 | pageHeadingContainer.appendChild(header)
9 | return pageHeadingContainer;
10 | }
11 |
12 | export function getEventsContainer(events){
13 | const eventsContainer = document.createElement("section");
14 | eventsContainer.className = "event-list-container";
15 |
16 | const eventsList = document.createElement("ul");
17 |
18 | for (let event of events){
19 | const eventCard = createEventCard(event);
20 | eventsList.appendChild(eventCard);
21 | }
22 |
23 | eventsContainer.appendChild(eventsList);
24 |
25 | return eventsContainer;
26 | }
27 |
28 | function createEventCard(event){
29 | const eventCard = document.createElement("li");
30 | eventCard.className = "event-card";
31 |
32 | const eventTitle = document.createElement("h2");
33 | eventTitle.className = "event-title"
34 | eventTitle.innerText = event.title;
35 |
36 | const eventDescription = document.createElement("p");
37 | eventDescription.className = "event-description"
38 | eventDescription.innerText = event.description;
39 |
40 | const eventDate = document.createElement("p");
41 | eventDate.className = "event-date"
42 | eventDate.innerText = event.date;
43 |
44 | eventCard.appendChild(eventTitle);
45 | eventCard.appendChild(eventDate);
46 | eventCard.appendChild(eventDescription);
47 |
48 | return eventCard;
49 | }
50 |
--------------------------------------------------------------------------------
/Live Session/Workshop 13 - Session Management/frontend/src/views/navbar.view.js:
--------------------------------------------------------------------------------
1 | export function getAuthenticatedNavbar(){
2 | const routesList = document.createElement("li");
3 | routesList.classList.add("nav-item");
4 |
5 | while (routesList.firstChild) {
6 | routesList.removeChild(routesList.firstChild);
7 | }
8 |
9 | const userAuth = localStorage.getItem("authenticated");
10 | console.log(userAuth)
11 |
12 | if (!userAuth){
13 | routesList.appendChild(getLoginLink())
14 | }
15 | else {
16 | routesList.appendChild(getCreateEvent());
17 | routesList.appendChild(getLogoutLink());
18 | }
19 |
20 | return routesList;
21 | }
22 |
23 | function getLoginLink(){
24 | const loginLink = document.createElement("a");
25 | loginLink.classList.add("nav-link");
26 | loginLink.textContent = "Login";
27 |
28 | loginLink.addEventListener('click', () => {
29 | const username = prompt("Email");
30 | const password = prompt("Password");
31 |
32 | fetch("http://localhost:8000/login", {
33 | method: "POST",
34 | headers: {
35 | "Content-Type": "application/json"
36 | },
37 | body: JSON.stringify({
38 | email: username,
39 | password: password
40 | })
41 | }).then((response) => {
42 | if (response.ok){
43 | return response.json();
44 | }
45 | else {
46 | throw new Error("Login failed");
47 | }
48 | }).then((data) => {
49 | localStorage.setItem("sessionToken", data.token);
50 | localStorage.setItem("authenticated", true);
51 | window.location.reload();
52 | }).catch((err) => alert("something went wrong"));
53 | });
54 |
55 |
56 | return loginLink;
57 | }
58 |
59 | function getLogoutLink(){
60 | const logoutLink = document.createElement("a");
61 | logoutLink.classList.add("nav-link");
62 | logoutLink.textContent = "Logout";
63 |
64 | logoutLink.addEventListener("click", () => {
65 | localStorage.removeItem("authenticated")
66 | localStorage.removeItem("sessionToken");
67 |
68 | window.location.reload();
69 | })
70 |
71 |
72 |
73 | return logoutLink;
74 | }
75 |
76 | function getCreateEvent(){
77 | const manageAccountLink = document.createElement("a");
78 | manageAccountLink.classList.add("nav-link");
79 | manageAccountLink.textContent = "Create Event";
80 |
81 | manageAccountLink.addEventListener('click', () => {
82 | const title = prompt("Title");
83 | const description = prompt("Description");
84 | const date = prompt("Date");
85 |
86 | fetch("http://localhost:8000/events", {
87 | method: "POST",
88 | headers: {
89 | "Content-Type": "application/json",
90 | "Authorization": `Bearer ${localStorage.getItem("sessionToken")}`
91 | },
92 | body: JSON.stringify({
93 | title: title,
94 | description: description,
95 | date: date
96 | })
97 | }).then((response) => {
98 | if (response.ok){
99 | return response.json();
100 | }
101 | else {
102 | throw new Error("Event creation failed");
103 | }
104 | }).then((data) => {
105 | alert("Event created successfully");
106 | }).catch((err) => alert("something went wrong"));
107 | });
108 |
109 | return manageAccountLink;
110 | }
--------------------------------------------------------------------------------
/Live Session/Workshop 2 - Sequences/Sequences - Slides.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Live Session/Workshop 2 - Sequences/Sequences - Slides.pdf
--------------------------------------------------------------------------------
/Live Session/Workshop 2 - Sequences/image-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Live Session/Workshop 2 - Sequences/image-1.png
--------------------------------------------------------------------------------
/Live Session/Workshop 2 - Sequences/image-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Live Session/Workshop 2 - Sequences/image-2.png
--------------------------------------------------------------------------------
/Live Session/Workshop 2 - Sequences/image-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Live Session/Workshop 2 - Sequences/image-3.png
--------------------------------------------------------------------------------
/Live Session/Workshop 2 - Sequences/readme.md:
--------------------------------------------------------------------------------
1 | ### Planning File
2 | To access the planning, you will need to to open the Planning.excalidraw file, you will need to navigate [here](https://excalidraw.com/) and navigate to the file on your local machine.
3 |
4 | #### 1 - Click of the top left and select open
5 | 
6 |
7 | #### 2 - Select "load from file"
8 | 
9 |
10 | #### 3 - Navigate to the directory and select the `Planning.excalidraw` file
11 | 
--------------------------------------------------------------------------------
/Live Session/Workshop 3 - Divide and Conquer/D&C Code Implementation.py:
--------------------------------------------------------------------------------
1 | books = [
2 | "To Kill a Mockingbird", "1984", "The Great Gatsby", "The Catcher in the Rye",
3 | "Moby-Dick", "War and Peace", "Pride and Prejudice", "The Lord of the Rings",
4 | "The Hobbit", "Jane Eyre", "Wuthering Heights", "Brave New World",
5 | "The Odyssey", "Crime and Punishment", "The Brothers Karamazov",
6 | "Anna Karenina", "Madame Bovary", "The Adventures of Huckleberry Finn",
7 | "Alice's Adventures in Wonderland", "Don Quixote", "The Divine Comedy",
8 | "Ulysses", "One Hundred Years of Solitude", "The Iliad", "The Aeneid",
9 | "The Canterbury Tales", "Les Misérables", "Great Expectations", "Dracula",
10 | "Frankenstein", "The Count of Monte Cristo", "The Scarlet Letter",
11 | "Heart of Darkness", "Catch-22", "Lord of the Flies", "The Sound and the Fury",
12 | "Gone with the Wind", "Slaughterhouse-Five", "The Grapes of Wrath",
13 | "A Tale of Two Cities", "The Old Man and the Sea", "The Stranger",
14 | "The Sun Also Rises", "The Metamorphosis", "The Picture of Dorian Gray",
15 | "A Clockwork Orange", "The Bell Jar", "Beloved", "Invisible Man", "Fahrenheit 451",
16 | "Things Fall Apart", "No Longer at Ease", "Arrow of God", "A Man of the People",
17 | "Anthills of the Savannah", "When Rain Clouds Gather", "Maru", "A Question of Power",
18 | "Petals of Blood", "Weep Not, Child", "The River Between", "A Grain of Wheat",
19 | "Season of Migration to the North", "The Wedding of Zein", "Half of a Yellow Sun",
20 | "Purple Hibiscus", "Americanah", "So Long a Letter", "The Dark Child",
21 | "Chaka", "The Joys of Motherhood", "Nervous Conditions", "The Book of Not",
22 | "The Hairdresser of Harare", "The Beautiful Ones Are Not Yet Born",
23 | "Waiting for the Barbarians", "Disgrace", "Cry, the Beloved Country",
24 | "Mine Boy", "Burger's Daughter", "July's People"
25 | ]
26 |
27 |
28 |
29 | # Sorting the books alphabetically
30 | def quicksort(arr):
31 | # Base case: an array of 0 or 1 elements is already sorted
32 | if len(arr) <= 1:
33 | return arr
34 |
35 | # Choose the pivot element (using the middle element for simplicity)
36 | pivot = arr[len(arr) // 2]
37 |
38 | # Partition the array into three parts: less than, equal to, and greater than the pivot
39 | left = [x for x in arr if x < pivot]
40 | middle = [x for x in arr if x == pivot]
41 | right = [x for x in arr if x > pivot]
42 |
43 | # Recursively sort the left and right parts and concatenate the result
44 | return quicksort(left) + middle + quicksort(right)
45 |
46 |
47 |
48 | def binary_search(book_list, target):
49 | # Initialize left and right pointers to the beginning and end of the list
50 | left, right = 0, len(book_list) - 1
51 |
52 | # Continue searching as long as left pointer does not exceed right pointer
53 | while left <= right:
54 | # Calculate the middle index of the current segment
55 | mid = (left + right) // 2
56 |
57 | # Check if the middle element is the target
58 | if book_list[mid] == target:
59 | return mid # Target found at index mid
60 |
61 | # If target is greater than the middle element, search in the right half
62 | elif book_list[mid] < target:
63 | left = mid + 1 # Update left pointer to mid + 1
64 |
65 | # If target is less than the middle element, search in the left half
66 | else:
67 | right = mid - 1 # Update right pointer to mid - 1
68 |
69 | # If target is not found, return -1
70 | return -1
71 |
72 | sorted_books = quicksort(books)
73 | print("Sorted Books (Case-Insensitive):", sorted_books)
74 | # Example usage of binary search
75 | book_to_find = "Things Fall Apart"
76 | index = binary_search(sorted_books, book_to_find)
77 | if index != -1:
78 | print(f"Book '{book_to_find}' found at index {index}.")
79 | else:
80 | print(f"Book '{book_to_find}' not found.")
--------------------------------------------------------------------------------
/Live Session/Workshop 3 - Divide and Conquer/Divide and Conquer Algorithms.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Live Session/Workshop 3 - Divide and Conquer/Divide and Conquer Algorithms.pdf
--------------------------------------------------------------------------------
/Live Session/Workshop 3 - Divide and Conquer/image-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Live Session/Workshop 3 - Divide and Conquer/image-1.png
--------------------------------------------------------------------------------
/Live Session/Workshop 3 - Divide and Conquer/image-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Live Session/Workshop 3 - Divide and Conquer/image-2.png
--------------------------------------------------------------------------------
/Live Session/Workshop 3 - Divide and Conquer/image-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Live Session/Workshop 3 - Divide and Conquer/image-3.png
--------------------------------------------------------------------------------
/Live Session/Workshop 3 - Divide and Conquer/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Live Session/Workshop 3 - Divide and Conquer/image.png
--------------------------------------------------------------------------------
/Live Session/Workshop 3 - Divide and Conquer/readme.md:
--------------------------------------------------------------------------------
1 | ### Planning File
2 | To access the planning, you will need to to open the Planning.excalidraw file, you will need to navigate [here](https://excalidraw.com/) and navigate to the file on your local machine.
3 |
4 | #### 1 - Click of the top left and select open
5 | 
6 |
7 | #### 2 - Select "load from file"
8 | 
9 |
10 | #### 3 - Navigate to the directory and select the `Planning.excalidraw` file
11 | 
--------------------------------------------------------------------------------
/Live Session/Workshop 4 - Computational Complexity/Code/Sequences Complexities/problem-1.py:
--------------------------------------------------------------------------------
1 | def get_final_order(children: list, moves: int):
2 | standing = None # 0 Steps
3 |
4 | for i in range(moves): # n steps
5 | for seat, child in enumerate(children): # nxm steps
6 |
7 | if standing: # 1 x (n x m)
8 | child = standing # 0 Steps
9 |
10 | if seat + 1 == len(children): # 1 x (n x m)
11 | children[0] = child # 0 Steps
12 | continue # 0 Steps
13 |
14 | standing = children[seat + 1] # 1 x (n x m) - 1
15 | children[seat + 1] = child # 1 x (n x m) - 1
16 |
17 | return children
18 |
19 | # (nxm) + (nxm) + (nxm) + ((nxm) - 1) + ((nxm) - 1)
20 | # 3(nxm) + 2(nxm - 2)
21 | # 5(nxm) - 2
22 | # O(mn)
--------------------------------------------------------------------------------
/Live Session/Workshop 4 - Computational Complexity/Code/Sequences Complexities/problem-2.py:
--------------------------------------------------------------------------------
1 | from array import array
2 |
3 | def get_final_order(children: array, moves: int):
4 | final_order = array('i', [0] * len(children)) # 0 Steps
5 |
6 | for seat, child in enumerate(children): # n
7 | next_seat = (seat + moves) % len(children) # 2(n)
8 | final_order[next_seat] = child # 0 steps
9 |
10 | return final_order
11 |
12 | # n + 2(n)
13 | # 3(n)
14 | # O(n)
--------------------------------------------------------------------------------
/Live Session/Workshop 4 - Computational Complexity/Code/Sequences Complexities/problem-3.py:
--------------------------------------------------------------------------------
1 | def get_final_order(children: list, moves: int):
2 | last_wrapper_index = len(children) - (moves % len(children)) # 2 steps
3 | return children[last_wrapper_index:] + children[:last_wrapper_index] # 1 step
4 |
5 | # 2 + 1
6 | # 3
7 | # O(1)
--------------------------------------------------------------------------------
/Live Session/Workshop 4 - Computational Complexity/Code/problem-1.py:
--------------------------------------------------------------------------------
1 | '''
2 | Create a function that returns the sum of three numbers,
3 | The operations cannot be performed on a single line.
4 | '''
5 |
6 | def sum_three_numbers(num1, num2, num3):
7 | first_part = num1 + num2
8 | return first_part + num3
9 |
--------------------------------------------------------------------------------
/Live Session/Workshop 4 - Computational Complexity/Code/problem-2.py:
--------------------------------------------------------------------------------
1 | '''
2 | Create a function that takes in a list of numbers,
3 | Calculate the sum of the numbers without using any built in methods
4 | '''
5 |
6 | def get_sum(numbers: list):
7 | output = 0
8 |
9 | for number in numbers:
10 | output += number
11 |
12 | return output
13 |
--------------------------------------------------------------------------------
/Live Session/Workshop 4 - Computational Complexity/Code/problem-3.py:
--------------------------------------------------------------------------------
1 | '''
2 | Create a function that takes in a list of numbers,
3 | you will need to return another list that contains only the even numbers
4 | that are preseent in the original list.
5 | '''
6 |
7 | def get_even_numbers(numbers: list):
8 | output = []
9 |
10 | for number in numbers:
11 | if number % 2 == 0:
12 | output.append(number)
13 |
14 | return output
15 |
--------------------------------------------------------------------------------
/Live Session/Workshop 4 - Computational Complexity/Code/problem-4.py:
--------------------------------------------------------------------------------
1 | '''
2 | You are given a string 'sentence' an arrangement of characters 'substring'
3 | You need to create a function that counts the number of times that `substring` occurs in `sentence`
4 | '''
5 |
6 | def get_substring_count(sentence, substring):
7 | counter = 0
8 | substring_length = len(substring)
9 |
10 | for i in range(len(sentence)):
11 | start_index = i
12 | end_index = i + substring_length
13 |
14 | if (end_index > len(sentence)):
15 | break
16 |
17 | current_substring = ''.join([sentence[char] for char in range(start_index, end_index)])
18 |
19 | if current_substring == substring:
20 | counter += 1
21 |
22 |
23 | return counter
24 |
25 |
26 | # def get_substring_count(sentence, substring):
27 | # counter = 0
28 | # substring_length = len(substring)
29 |
30 | # for i in range(len(sentence)):
31 | # start_index = i
32 | # end_index = i + substring_length
33 |
34 | # if (end_index > len(sentence)):
35 | # break
36 |
37 | # current_substring = sentence[start_index:end_index]
38 | # print(current_substring)
39 |
40 | # if current_substring == substring:
41 | # counter += 1
42 |
43 |
44 | # return counter
--------------------------------------------------------------------------------
/Live Session/Workshop 4 - Computational Complexity/Computational Complexity - Slides.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Live Session/Workshop 4 - Computational Complexity/Computational Complexity - Slides.pdf
--------------------------------------------------------------------------------
/Live Session/Workshop 4 - Computational Complexity/assests/image-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Live Session/Workshop 4 - Computational Complexity/assests/image-1.png
--------------------------------------------------------------------------------
/Live Session/Workshop 4 - Computational Complexity/assests/image-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Live Session/Workshop 4 - Computational Complexity/assests/image-2.png
--------------------------------------------------------------------------------
/Live Session/Workshop 4 - Computational Complexity/assests/image-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Live Session/Workshop 4 - Computational Complexity/assests/image-3.png
--------------------------------------------------------------------------------
/Live Session/Workshop 4 - Computational Complexity/assests/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Live Session/Workshop 4 - Computational Complexity/assests/image.png
--------------------------------------------------------------------------------
/Live Session/Workshop 4 - Computational Complexity/readme.md:
--------------------------------------------------------------------------------
1 | ### Planning File
2 | To access the planning, you will need to to open the Planning.excalidraw file, you will need to navigate [here](https://excalidraw.com/) and navigate to the file on your local machine.
3 |
4 | #### 1 - Click of the top left and select open
5 | 
6 |
7 | #### 2 - Select "load from file"
8 | 
9 |
10 | #### 3 - Navigate to the directory and select the `Planning.excalidraw` file
11 | 
12 |
--------------------------------------------------------------------------------
/Live Session/Workshop 5 - Constant Time and Storage/Constant Time Storage and Access.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Live Session/Workshop 5 - Constant Time and Storage/Constant Time Storage and Access.pdf
--------------------------------------------------------------------------------
/Live Session/Workshop 5 - Constant Time and Storage/code/__pycache__/navigation.cpython-312.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Live Session/Workshop 5 - Constant Time and Storage/code/__pycache__/navigation.cpython-312.pyc
--------------------------------------------------------------------------------
/Live Session/Workshop 5 - Constant Time and Storage/code/nav_performance.py:
--------------------------------------------------------------------------------
1 | from timeit import timeit
2 | import navigation
3 | import random
4 |
5 | def run(function_a, function_b, args_a: tuple):
6 | performance_a = []
7 | performance_b = []
8 | iterations = 500
9 |
10 | for i in range(1):
11 | performance_a.append(timeit(lambda: function_a(*args_a), number=iterations))
12 | performance_b.append(timeit(lambda: function_b(*args_a), number=iterations))
13 |
14 | average_a = sum(performance_a) / len(performance_a)
15 | average_b = sum(performance_b) / len(performance_b)
16 |
17 | return average_a, average_b
18 |
19 | def generate_large_graph(num_nodes, max_edges_per_node):
20 | graph = {f'node_{i}': [] for i in range(num_nodes)}
21 |
22 | for i in range(num_nodes):
23 | num_edges = random.randint(1, max_edges_per_node)
24 | connections = random.sample(range(num_nodes), num_edges)
25 | connections = [f'node_{j}' for j in connections if j != i]
26 | graph[f'node_{i}'] = connections
27 |
28 | return graph
29 |
30 |
31 |
32 | if __name__ == "__main__":
33 | num_nodes = 1000
34 | num_edges_per_node = 5
35 | large_graph = generate_large_graph(num_nodes, num_edges_per_node)
36 | navigation.map = large_graph
37 |
38 | normal, constant = run(navigation.find_path, navigation.find_path_opt, ('node_998', 'node_2'))
39 |
40 | print('O(n) DS', normal, '\nO(1) DS:', constant)
41 |
42 |
43 |
--------------------------------------------------------------------------------
/Live Session/Workshop 5 - Constant Time and Storage/code/navigation.py:
--------------------------------------------------------------------------------
1 | '''
2 | Given a starting position, determine if it's possible to
3 | reach a certain goal.
4 | '''
5 |
6 | from timeit import timeit
7 |
8 | map = {}
9 |
10 | def find_path(start, goal):
11 | travelled = []
12 | possible_moves = [start]
13 |
14 | while len(possible_moves) > 0:
15 | current_position = possible_moves.pop(0)
16 | travelled.append(current_position)
17 |
18 | if (current_position == goal):
19 | return True
20 |
21 | for move in map[current_position]:
22 | if (move not in travelled):
23 | possible_moves.append(move)
24 |
25 |
26 | def find_path_opt(start, goal):
27 | travelled = set()
28 | possible_moves = [start]
29 |
30 | while len(possible_moves) > 0:
31 | current_position = possible_moves.pop(0)
32 | travelled.add(current_position)
33 |
34 | if (current_position == goal):
35 | return True
36 |
37 | for move in map[current_position]:
38 | if (move not in travelled):
39 | possible_moves.append(move)
40 |
41 |
--------------------------------------------------------------------------------
/Live Session/Workshop 6 - Hashing/code/hashset.py:
--------------------------------------------------------------------------------
1 | class HashSet:
2 | def __init__(self, size: int, load_factor: float) -> None:
3 | self.__size = size
4 | self.__filled_spaces = 0
5 | self.__load_factor = 1 if load_factor > 1 else load_factor
6 | self.__internal_array = [None] * size
7 |
8 | def add(self, value: str):
9 | self.__resize_array()
10 |
11 | index = hash
12 | self.__internal_array[index] = value
13 | self.__filled_spaces += 1
14 |
15 |
16 |
17 | def __resize_array(self):
18 | filled_percentage = self.__filled_spaces / self.__size
19 |
20 | if filled_percentage < self.__load_factor:
21 | return
22 |
23 | old_values = [value for value in self.__internal_array if value is not None]
24 |
25 | self.__size = self.__size * 2
26 | self.__internal_array = [None] * self.__size
27 |
28 | for value in old_values:
29 | self.add(value)
30 |
31 | def contains(self, value: str):
32 | index = self.__hash(value)
33 | index = self.__linear_probing_search(index, value)
34 | return index > -1
35 |
36 | def __linear_probing_search(self, index, value, count=0):
37 | if self.__internal_array[index] == value:
38 | return index
39 |
40 | if count == self.__size:
41 | return -1
42 |
43 | if index == self.__size - 1:
44 | index = -1
45 |
46 | return self.__linear_probing_search(index + 1, value, count + 1)
47 |
48 |
49 | def __hash(self, value: str):
50 | ascii_values = sum([ord(char) for char in value])
51 | return ascii_values % self.__size
52 |
53 | def __linear_probing_insertion(self, index):
54 | if self.__internal_array[index] is None:
55 | return index
56 |
57 | print("collison")
58 |
59 | if (index == self.__size - 1):
60 | index = -1
61 |
62 | return self.__linear_probing_insertion(index + 1)
63 |
64 |
65 |
66 |
67 | def print_internal_array(self):
68 | return print(self.__internal_array)
69 |
70 |
71 |
72 |
73 | my_set = HashSet(4, 0.75)
74 |
75 | for fruit in ["apple", "banana", "orange", "pear", "mango", "grape", "strawberry"]:
76 | my_set.add(fruit)
77 |
78 | my_set.print_internal_array()
--------------------------------------------------------------------------------
/Live Session/Workshop 8 - Persistent Data Storage/Persistent Storage - Slide.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Live Session/Workshop 8 - Persistent Data Storage/Persistent Storage - Slide.pdf
--------------------------------------------------------------------------------
/Live Session/Workshop 8 - Persistent Data Storage/database_setup/README.md:
--------------------------------------------------------------------------------
1 | # Database Setup
2 | Run this script to create the tables and insert the data into the tables.
3 |
4 | If you already have data in the tables, all of the existing data will be removed and replaced with the new data.
5 |
6 | Follow the guide below to help you use the tool, you do not need to touch any of the code, the service should work for postgres, ms sql server and my sql, just make sure that you have all of your credentails.
7 |
8 | ### Prerequisites
9 | - Your database service must be running
10 | - The database that you want to store the values in should be created
11 |
12 | # Environment set up
13 |
14 | ## Packages
15 | - Pandas
16 | - sqlalchemy
17 | - pydantic
18 |
19 | ### Setting up virtual Environment
20 | If you don't want the packages to be installed to your local environment, you can set up a virtual environment using the following steps.
21 |
22 | *Windows*
23 | ```shell
24 | python -m venv venv
25 | ```
26 |
27 | ```shell
28 | python -m venv venv
29 | ```
30 |
31 | ```shell
32 | source venv/Scripts/activate
33 | ```
34 |
35 | Close the environment when you are done
36 | ```shell
37 | deactivate
38 | ```
39 |
40 | *Linux/Mac*
41 | ```shell
42 | python -m venv venv
43 | ```
44 |
45 | ```shell
46 | source venv/bin/activate
47 | ```
48 |
49 | Close the environment when you are done
50 | ```shell
51 | deactivate
52 | ```
53 |
54 | ### Install Packages
55 | ```shell
56 | pip install -r requirements.txt
57 | ```
58 |
59 | # Data
60 |
61 | ## Create data directory
62 | You will need to have a directory in the root called `data` this will store your CSV files.
63 |
64 | ## CSV Data
65 | Make sure that all of the files in this directory have the same names as the tables in your database. Each column in the CSV will also need to correspond with the columns in the tables that will be created.
66 |
67 | # Running the script
68 |
69 | ## Create.sql
70 | in the `scripts` directory, you will need to have a `create.sql`, this file should contain the create table scripts for your database. The schema for the tables need to match the columns in the .csv file in the `data` directroy.
71 |
72 | ## Config file
73 | The easiest way to run the applicaiton would be to use a config file. The data that you write in the file will depend on the database type that you are using, you can copy the template for the different databases from the code below.
74 |
75 | When using the config file, you must make sure that you include the `service` and `connection_string`, these are used for connecting to the right database service and passing the credentials to the database.
76 |
77 | Within the `connection_string` object, `database` is a mandetory field, this is required to make sure that the service is connecting to the right database. Additionally, the database needs to exist before connecting to the service.
78 |
79 | Besides the mandetory fields, any missing values will be given default values based on the service being used.
80 |
81 | You can create your `config.json` file using the templates below (copy and paste the json), you can then fill in the data that is relevant to your setup. If there are any fields that don't need to be filled out, you can delete the field, do not leave it blank, but remember that `database` is mandetory.
82 |
83 |
84 | ### Process
85 | To populate the database, you will need to run the following command in your terminal, make sure that the terminal is opened to the same directory as the `setup.py` file for the command to work.
86 |
87 | **Step 1**
88 |
89 | Update the `config.json` file with the values for your database of choice. You can copy the templates below and replace the values where needed. Remember that the `service`, `connection_string` and `database` fields are mandetory, the process will not run if any of those fields are empty.
90 |
91 | **Step 2**
92 |
93 | Run the following command to start the process using the `config.json` file.
94 | ```shell
95 | python setup.py -cf config.json
96 | ```
97 |
98 | **Step 3**
99 |
100 | Go through the steps and wait for the process to finish, it might take a bit of time depending on the machine that you are using.
101 |
102 |
103 | #### Postgres
104 |
105 | Template
106 | ```json
107 | {
108 | "service": "postgres",
109 | "connection_string": {
110 | "username": "[your-username]",
111 | "password": "[your-password]",
112 | "database": "[database-name]",
113 | "port": 5432,
114 | "server": "[server-name]"
115 | }
116 | }
117 | ```
118 |
119 | Example
120 | ```json
121 | {
122 | "service": "postgres",
123 | "connection_string": {
124 | "username": "postgres",
125 | "password": "mysecretpassword",
126 | "database": "film_rental",
127 | "server": "localhost",
128 | "port": 5432
129 | }
130 | }
131 | ```
132 |
133 | ##### MySQL
134 |
135 | Template
136 | ```json
137 | {
138 | "service": "mysql",
139 | "connection_string": {
140 | "username": "[your-username]",
141 | "password": "[your-password]",
142 | "database": "[database-name]",
143 | "port": 3306,
144 | "server": "[server-name]"
145 | }
146 | }
147 | ```
148 |
149 | Example
150 | ```json
151 | {
152 | "service": "mysql",
153 | "connection_string": {
154 | "username": "mysql",
155 | "password": "mysecretpassword",
156 | "database": "film_rental",
157 | "server": "localhost",
158 | "port": 3306
159 | }
160 | }
161 | ```
162 |
163 | ##### MS SQL Server
164 |
165 | Template
166 | ```json
167 | {
168 | "service": "ms_sql_server",
169 | "connection_string": {
170 | "username": "[your-username]",
171 | "password": "[your-password]",
172 | "database": "[database-name]",
173 | "server": "[server-name]",
174 | "driver": "[Driver Version]"
175 | }
176 | }
177 | ```
178 |
179 | Example
180 | ```json
181 | {
182 | "service": "ms_sql_server",
183 | "connection_string": {
184 | "username": "user1",
185 | "password": "mysecretpassword",
186 | "database": "film_rental",
187 | "server": "localhost",
188 | "driver": "SQL Server Native Client 11.0"
189 | }
190 | }
191 | ```
192 |
193 | *NOTES*
194 | - If the database has a URL, you can put the URL as the `server`
195 |
196 | ## Command Line
197 |
198 | If you don't want to use the config file, you can make use of flags to pass the different paramters, you can get a full list of the paramters that you can pass by running the following command in your terminal, firstly make sure that the terminal is open to the same directory as the `setup.py` file.
199 |
200 | ```shell
201 | python setup.py -h
202 | ```
203 |
204 | The `-db` and `-s` flags are mandetory, the setup will not be performed without these two flags, if any other flags are left out, the defaults for that database system will be used.
205 |
206 | Example using Postgres
207 | ```shell
208 | python script.py -s postgres -sr localhost -p 5432 -db film_rental -u postgres -pw postgres
209 | ```
210 |
211 | # Additional
212 |
213 | Once the script has run, you can go into Azure Data Studio (Or the tool of your choice) and create a new query, you can run a select statment in one of the table to make sure that the values exist.
214 |
215 | ```sql
216 | SELECT *
217 | FROM rental
218 | ```
219 |
220 | If that command works, then you can run the following command to set the NULL values for the films that were not returned.
221 |
222 | ```sql
223 | UPDATE rental
224 | SET return_date = NULL
225 | WHERE return_date = '1800-01-01 00:00:00+00'
226 | ```
--------------------------------------------------------------------------------
/Live Session/Workshop 8 - Persistent Data Storage/database_setup/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Live Session/Workshop 8 - Persistent Data Storage/database_setup/__init__.py
--------------------------------------------------------------------------------
/Live Session/Workshop 8 - Persistent Data Storage/database_setup/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "service": "postgres",
3 | "connection_string": {
4 | "username": "postgres",
5 | "password": "superstrongpassword",
6 | "database": "f_one",
7 | "port": 5432,
8 | "server": "localhost"
9 | }
10 | }
--------------------------------------------------------------------------------
/Live Session/Workshop 8 - Persistent Data Storage/database_setup/data/circuits.csv:
--------------------------------------------------------------------------------
1 | circuitId,circuitRef,name,location,country,lat,lng,alt,url
2 | 1,albert_park,Albert Park Grand Prix Circuit,Melbourne,Australia,-37.8497,144.968,10,http://en.wikipedia.org/wiki/Melbourne_Grand_Prix_Circuit
3 | 2,sepang,Sepang International Circuit,Kuala Lumpur,Malaysia,2.76083,101.738,,http://en.wikipedia.org/wiki/Sepang_International_Circuit
4 | 3,bahrain,Bahrain International Circuit,Sakhir,Bahrain,26.0325,50.5106,,http://en.wikipedia.org/wiki/Bahrain_International_Circuit
5 | 4,catalunya,Circuit de Barcelona-Catalunya,MontmelÃ_,Spain,41.57,2.26111,,http://en.wikipedia.org/wiki/Circuit_de_Barcelona-Catalunya
6 | 5,istanbul,Istanbul Park,Istanbul,Turkey,40.9517,29.405,,http://en.wikipedia.org/wiki/Istanbul_Park
7 | 6,monaco,Circuit de Monaco,Monte-Carlo,Monaco,43.7347,7.42056,,http://en.wikipedia.org/wiki/Circuit_de_Monaco
8 | 7,villeneuve,Circuit Gilles Villeneuve,Montreal,Canada,45.5,-73.5228,,http://en.wikipedia.org/wiki/Circuit_Gilles_Villeneuve
9 | 8,magny_cours,Circuit de Nevers Magny-Cours,Magny Cours,France,46.8642,3.16361,,http://en.wikipedia.org/wiki/Circuit_de_Nevers_Magny-Cours
10 | 9,silverstone,Silverstone Circuit,Silverstone,UK,52.0786,-1.01694,,http://en.wikipedia.org/wiki/Silverstone_Circuit
11 | 10,hockenheimring,Hockenheimring,Hockenheim,Germany,49.3278,8.56583,,http://en.wikipedia.org/wiki/Hockenheimring
12 | 11,hungaroring,Hungaroring,Budapest,Hungary,47.5789,19.2486,,http://en.wikipedia.org/wiki/Hungaroring
13 | 12,valencia,Valencia Street Circuit,Valencia,Spain,39.4589,-0.331667,,http://en.wikipedia.org/wiki/Valencia_Street_Circuit
14 | 13,spa,Circuit de Spa-Francorchamps,Spa,Belgium,50.4372,5.97139,,http://en.wikipedia.org/wiki/Circuit_de_Spa-Francorchamps
15 | 14,monza,Autodromo Nazionale di Monza,Monza,Italy,45.6156,9.28111,,http://en.wikipedia.org/wiki/Autodromo_Nazionale_Monza
16 | 15,marina_bay,Marina Bay Street Circuit,Marina Bay,Singapore,1.2914,103.864,,http://en.wikipedia.org/wiki/Marina_Bay_Street_Circuit
17 | 16,fuji,Fuji Speedway,Oyama,Japan,35.3717,138.927,,http://en.wikipedia.org/wiki/Fuji_Speedway
18 | 17,shanghai,Shanghai International Circuit,Shanghai,China,31.3389,121.22,,http://en.wikipedia.org/wiki/Shanghai_International_Circuit
19 | 18,interlagos,AutÃ_dromo José Carlos Pace,São Paulo,Brazil,-23.7036,-46.6997,,http://en.wikipedia.org/wiki/Aut%C3%B3dromo_Jos%C3%A9_Carlos_Pace
20 | 19,indianapolis,Indianapolis Motor Speedway,Indianapolis,USA,39.795,-86.2347,,http://en.wikipedia.org/wiki/Indianapolis_Motor_Speedway
21 | 20,nurburgring,NÃ_rburgring,NÃ_rburg,Germany,50.3356,6.9475,,http://en.wikipedia.org/wiki/N%C3%BCrburgring
22 | 21,imola,Autodromo Enzo e Dino Ferrari,Imola,Italy,44.3439,11.7167,,http://en.wikipedia.org/wiki/Autodromo_Enzo_e_Dino_Ferrari
23 | 22,suzuka,Suzuka Circuit,Suzuka,Japan,34.8431,136.541,,http://en.wikipedia.org/wiki/Suzuka_Circuit
24 | 23,osterreichring,A1-Ring,Spielburg,Austria,47.2197,14.7647,,http://en.wikipedia.org/wiki/A1-Ring
25 | 24,yas_marina,Yas Marina Circuit,Abu Dhabi,UAE,24.4672,54.6031,,http://en.wikipedia.org/wiki/Yas_Marina_Circuit
26 | 25,galvez,AutÃ_dromo Juan y Oscar Gálvez,Buenos Aires,Argentina,-34.6943,-58.4593,,http://en.wikipedia.org/wiki/Aut%C3%B3dromo_Oscar_Alfredo_G%C3%A1lvez
27 | 26,jerez,Circuito de Jerez,Jerez de la Frontera,Spain,36.7083,-6.03417,,http://en.wikipedia.org/wiki/Circuito_Permanente_de_Jerez
28 | 27,estoril,AutÃ_dromo do Estoril,Estoril,Portugal,38.7506,-9.39417,,http://en.wikipedia.org/wiki/Aut%C3%B3dromo_do_Estoril
29 | 28,okayama,Okayama International Circuit,Okayama,Japan,34.915,134.221,,http://en.wikipedia.org/wiki/TI_Circuit
30 | 29,adelaide,Adelaide Street Circuit,Adelaide,Australia,-34.9272,138.617,,http://en.wikipedia.org/wiki/Adelaide_Street_Circuit
31 | 30,kyalami,Kyalami,Midrand,South Africa,-25.9894,28.0767,,http://en.wikipedia.org/wiki/Kyalami
32 | 31,donington,Donington Park,Castle Donington,UK,52.8306,-1.37528,,http://en.wikipedia.org/wiki/Donington_Park
33 | 32,rodriguez,AutÃ_dromo Hermanos RodrÃ_guez,Mexico City,Mexico,19.4042,-99.0907,,http://en.wikipedia.org/wiki/Aut%C3%B3dromo_Hermanos_Rodr%C3%ADguez
34 | 33,phoenix,Phoenix street circuit,Phoenix,USA,33.4479,-112.075,,http://en.wikipedia.org/wiki/Phoenix_street_circuit
35 | 34,ricard,Circuit Paul Ricard,Le Castellet,France,43.2506,5.79167,,http://en.wikipedia.org/wiki/Paul_Ricard_Circuit
36 | 35,yeongam,Korean International Circuit,Yeongam County,Korea,34.7333,126.417,,http://en.wikipedia.org/wiki/Korean_International_Circuit
37 | 36,jacarepagua,AutÃ_dromo Internacional Nelson Piquet,Rio de Janeiro,Brazil,-22.9756,-43.395,,http://en.wikipedia.org/wiki/Aut%C3%B3dromo_Internacional_Nelson_Piquet
38 | 37,detroit,Detroit Street Circuit,Detroit,USA,42.3298,-83.0401,,http://en.wikipedia.org/wiki/Detroit_street_circuit
39 | 38,brands_hatch,Brands Hatch,Kent,UK,51.3569,0.263056,,http://en.wikipedia.org/wiki/Brands_Hatch
40 | 39,zandvoort,Circuit Park Zandvoort,Zandvoort,Netherlands,52.3888,4.54092,,http://en.wikipedia.org/wiki/Circuit_Zandvoort
41 | 40,zolder,Zolder,Heusden-Zolder,Belgium,50.9894,5.25694,,http://en.wikipedia.org/wiki/Zolder
42 | 41,dijon,Dijon-Prenois,Dijon,France,47.3625,4.89913,,http://en.wikipedia.org/wiki/Dijon-Prenois
43 | 42,dallas,Fair Park,Dallas,USA,32.7774,-96.7587,,http://en.wikipedia.org/wiki/Fair_Park
44 | 43,long_beach,Long Beach,California,USA,33.7651,-118.189,,"http://en.wikipedia.org/wiki/Long_Beach,_California"
45 | 44,las_vegas,Las Vegas Street Circuit,Nevada,USA,36.1162,-115.174,,"http://en.wikipedia.org/wiki/Las_Vegas,_Nevada"
46 | 45,jarama,Jarama,Madrid,Spain,40.6171,-3.58558,,http://en.wikipedia.org/wiki/Circuito_Permanente_Del_Jarama
47 | 46,watkins_glen,Watkins Glen,New York State,USA,42.3369,-76.9272,,http://en.wikipedia.org/wiki/Watkins_Glen_International
48 | 47,anderstorp,Scandinavian Raceway,Anderstorp,Sweden,57.2653,13.6042,,http://en.wikipedia.org/wiki/Scandinavian_Raceway
49 | 48,mosport,Mosport International Raceway,Ontario,Canada,44.0481,-78.6756,,http://en.wikipedia.org/wiki/Mosport
50 | 49,montjuic,Montjuïc,Barcelona,Spain,41.3664,2.15167,,http://en.wikipedia.org/wiki/Montju%C3%AFc_circuit
51 | 50,nivelles,Nivelles-Baulers,Brussels,Belgium,50.6211,4.32694,,http://en.wikipedia.org/wiki/Nivelles-Baulers
52 | 51,charade,Charade Circuit,Clermont-Ferrand,France,45.7472,3.03889,,http://en.wikipedia.org/wiki/Charade_Circuit
53 | 52,tremblant,Circuit Mont-Tremblant,Quebec,Canada,46.1877,-74.6099,,http://en.wikipedia.org/wiki/Circuit_Mont-Tremblant
54 | 53,essarts,Rouen-Les-Essarts,Rouen,France,49.3306,1.00458,,http://en.wikipedia.org/wiki/Rouen-Les-Essarts
55 | 54,lemans,Le Mans,Le Mans,France,47.95,0.224231,,http://en.wikipedia.org/wiki/Circuit_de_la_Sarthe#Bugatti_Circuit
56 | 55,reims,Reims-Gueux,Reims,France,49.2542,3.93083,,http://en.wikipedia.org/wiki/Reims-Gueux
57 | 56,george,Prince George Circuit,Eastern Cape Province,South Africa,-33.0486,27.8736,,http://en.wikipedia.org/wiki/Prince_George_Circuit
58 | 57,zeltweg,Zeltweg,Styria,Austria,47.2039,14.7478,,http://en.wikipedia.org/wiki/Zeltweg_Airfield
59 | 58,aintree,Aintree,Liverpool,UK,53.4769,-2.94056,,http://en.wikipedia.org/wiki/Aintree_Motor_Racing_Circuit
60 | 59,boavista,Circuito da Boavista,Oporto,Portugal,41.1705,-8.67325,,http://en.wikipedia.org/wiki/Circuito_da_Boavista
61 | 60,riverside,Riverside International Raceway,California,USA,33.937,-117.273,,http://en.wikipedia.org/wiki/Riverside_International_Raceway
62 | 61,avus,AVUS,Berlin,Germany,52.4806,13.2514,,http://en.wikipedia.org/wiki/AVUS
63 | 62,monsanto,Monsanto Park Circuit,Lisbon,Portugal,38.7197,-9.20306,,http://en.wikipedia.org/wiki/Monsanto_Park_Circuit
64 | 63,sebring,Sebring International Raceway,Florida,USA,27.4547,-81.3483,,http://en.wikipedia.org/wiki/Sebring_Raceway
65 | 64,ain-diab,Ain Diab,Casablanca,Morocco,33.5786,-7.6875,,http://en.wikipedia.org/wiki/Ain-Diab_Circuit
66 | 65,pescara,Pescara Circuit,Pescara,Italy,42.475,14.1508,,http://en.wikipedia.org/wiki/Pescara_Circuit
67 | 66,bremgarten,Circuit Bremgarten,Bern,Switzerland,46.9589,7.40194,,http://en.wikipedia.org/wiki/Circuit_Bremgarten
68 | 67,pedralbes,Circuit de Pedralbes,Barcelona,Spain,41.3903,2.11667,,http://en.wikipedia.org/wiki/Pedralbes_Circuit
69 | 68,buddh,Buddh International Circuit,Uttar Pradesh,India,28.3487,77.5331,,http://en.wikipedia.org/wiki/Buddh_International_Circuit
70 | 69,americas,Circuit of the Americas,Austin,USA,30.1328,-97.6411,,http://en.wikipedia.org/wiki/Circuit_of_the_Americas
71 | 70,red_bull_ring,Red Bull Ring,Spielburg,Austria,47.2197,14.7647,,http://en.wikipedia.org/wiki/Red_Bull_Ring
72 | 71,sochi,Sochi Autodrom,Sochi,Russia,43.4057,39.9578,,http://en.wikipedia.org/wiki/Sochi_Autodrom
73 | 72,port_imperial,Port Imperial Street Circuit,New Jersey,USA,40.7769,-74.0111,,http://en.wikipedia.org/wiki/Port_Imperial_Street_Circuit
74 | 73,BAK,Baku City Circuit,Baku,Azerbaijan,40.3725,49.8533,,http://en.wikipedia.org/wiki/Baku_City_Circuit
75 |
--------------------------------------------------------------------------------
/Live Session/Workshop 8 - Persistent Data Storage/database_setup/data/constructors.csv:
--------------------------------------------------------------------------------
1 | constructorId,constructorRef,name,nationality,url
2 | 1,mclaren,McLaren,British,http://en.wikipedia.org/wiki/McLaren
3 | 2,bmw_sauber,BMW Sauber,German,http://en.wikipedia.org/wiki/BMW_Sauber
4 | 3,williams,Williams,British,http://en.wikipedia.org/wiki/Williams_Grand_Prix_Engineering
5 | 4,renault,Renault,French,http://en.wikipedia.org/wiki/Renault_F1
6 | 5,toro_rosso,Toro Rosso,Italian,http://en.wikipedia.org/wiki/Scuderia_Toro_Rosso
7 | 6,ferrari,Ferrari,Italian,http://en.wikipedia.org/wiki/Scuderia_Ferrari
8 | 7,toyota,Toyota,Japanese,http://en.wikipedia.org/wiki/Toyota_Racing
9 | 8,super_aguri,Super Aguri,Japanese,http://en.wikipedia.org/wiki/Super_Aguri_F1
10 | 9,red_bull,Red Bull,Austrian,http://en.wikipedia.org/wiki/Red_Bull_Racing
11 | 10,force_india,Force India,Indian,http://en.wikipedia.org/wiki/Force_India
12 | 11,honda,Honda,Japanese,http://en.wikipedia.org/wiki/Honda_Racing_F1
13 | 12,spyker,Spyker,Dutch,http://en.wikipedia.org/wiki/Spyker_F1
14 | 13,mf1,MF1,Russian,http://en.wikipedia.org/wiki/Midland_F1_Racing
15 | 14,spyker_mf1,Spyker MF1,Dutch,http://en.wikipedia.org/wiki/Midland_F1_Racing
16 | 15,sauber,Sauber,Swiss,http://en.wikipedia.org/wiki/Sauber
17 | 16,bar,BAR,British,http://en.wikipedia.org/wiki/British_American_Racing
18 | 17,jordan,Jordan,Irish,http://en.wikipedia.org/wiki/Jordan_Grand_Prix
19 | 18,minardi,Minardi,Italian,http://en.wikipedia.org/wiki/Minardi
20 | 19,jaguar,Jaguar,British,http://en.wikipedia.org/wiki/Jaguar_Racing
21 | 20,prost,Prost,French,http://en.wikipedia.org/wiki/Prost_Grand_Prix
22 | 21,arrows,Arrows,British,http://en.wikipedia.org/wiki/Arrows_Grand_Prix_International
23 | 22,benetton,Benetton,Italian,http://en.wikipedia.org/wiki/Benetton_Formula
24 | 23,brawn,Brawn,British,http://en.wikipedia.org/wiki/Brawn_GP
25 | 24,stewart,Stewart,British,http://en.wikipedia.org/wiki/Stewart_Grand_Prix
26 | 25,tyrrell,Tyrrell,British,http://en.wikipedia.org/wiki/Tyrrell_Racing
27 | 26,lola,Lola,British,http://en.wikipedia.org/wiki/MasterCard_Lola
28 | 27,ligier,Ligier,French,http://en.wikipedia.org/wiki/Ligier
29 | 28,forti,Forti,Italian,http://en.wikipedia.org/wiki/Forti
30 | 29,footwork,Footwork,British,http://en.wikipedia.org/wiki/Footwork_Arrows
31 | 30,pacific,Pacific,British,http://en.wikipedia.org/wiki/Pacific_Racing
32 | 31,simtek,Simtek,British,http://en.wikipedia.org/wiki/Simtek
33 | 32,team_lotus,Team Lotus,British,http://en.wikipedia.org/wiki/Team_Lotus
34 | 33,larrousse,Larrousse,French,http://en.wikipedia.org/wiki/Larrousse
35 | 34,brabham,Brabham,British,http://en.wikipedia.org/wiki/Brabham
36 | 35,dallara,Dallara,Italian,http://en.wikipedia.org/wiki/Dallara
37 | 36,fondmetal,Fondmetal,Italian,http://en.wikipedia.org/wiki/Fondmetal
38 | 37,march,March,British,http://en.wikipedia.org/wiki/March_Engineering
39 | 38,moda,Andrea Moda,Italian,http://en.wikipedia.org/wiki/Andrea_Moda_Formula
40 | 39,ags,AGS,French,http://en.wikipedia.org/wiki/Automobiles_Gonfaronnaises_Sportives
41 | 40,lambo,Lambo,Italian,http://en.wikipedia.org/wiki/Modena_(racing_team)
42 | 41,leyton,Leyton House,British,http://en.wikipedia.org/wiki/Leyton_House
43 | 42,coloni,Coloni,Italian,http://en.wikipedia.org/wiki/Enzo_Coloni_Racing_Car_Systems
44 | 44,eurobrun,Euro Brun,Italian,http://en.wikipedia.org/wiki/Euro_Brun
45 | 45,osella,Osella,Italian,http://en.wikipedia.org/wiki/Osella
46 | 46,onyx,Onyx,British,http://en.wikipedia.org/wiki/Onyx_(racing_team)
47 | 47,life,Life,Italian,http://en.wikipedia.org/wiki/Life_(Racing_Team)
48 | 48,rial,Rial,German,http://en.wikipedia.org/wiki/Rial_%28racing_team%29
49 | 49,zakspeed,Zakspeed,German,http://en.wikipedia.org/wiki/Zakspeed
50 | 50,ram,RAM,British,http://en.wikipedia.org/wiki/RAM_Racing
51 | 51,alfa,Alfa Romeo,Italian,http://en.wikipedia.org/wiki/Alfa_Romeo_(Formula_One)
52 | 52,spirit,Spirit,British,http://en.wikipedia.org/wiki/Spirit_(racing_team)
53 | 53,toleman,Toleman,British,http://en.wikipedia.org/wiki/Toleman
54 | 54,ats,ATS,Italian,http://en.wikipedia.org/wiki/ATS_(wheels)
55 | 55,theodore,Theodore,Hong Kong,http://en.wikipedia.org/wiki/Theodore_Racing
56 | 56,fittipaldi,Fittipaldi,Brazilian,http://en.wikipedia.org/wiki/Fittipaldi_%28constructor%29
57 | 57,ensign,Ensign,British,http://en.wikipedia.org/wiki/Ensign_%28racing_team%29
58 | 58,shadow,Shadow,British,http://en.wikipedia.org/wiki/Shadow_Racing_Cars
59 | 59,wolf,Wolf,Canadian,http://en.wikipedia.org/wiki/Walter_Wolf_Racing
60 | 60,merzario,Merzario,Italian,http://en.wikipedia.org/wiki/Merzario
61 | 61,kauhsen,Kauhsen,German,http://en.wikipedia.org/wiki/Kauhsen
62 | 62,rebaque,Rebaque,Mexican,http://en.wikipedia.org/wiki/Rebaque
63 | 63,surtees,Surtees,British,http://en.wikipedia.org/wiki/Surtees
64 | 64,hesketh,Hesketh,British,http://en.wikipedia.org/wiki/Hesketh_Racing
65 | 65,martini,Martini,French,http://en.wikipedia.org/wiki/Martini_(cars)
66 | 66,brm,BRM,British,http://en.wikipedia.org/wiki/BRM
67 | 67,penske,Penske,American,http://en.wikipedia.org/wiki/Penske_Racing
68 | 68,lec,LEC,British,http://en.wikipedia.org/wiki/LEC_(Formula_One)
69 | 69,mcguire,McGuire,Australian,http://en.wikipedia.org/wiki/McGuire_(Formula_One)
70 | 70,boro,Boro,Dutch,http://en.wikipedia.org/wiki/Boro_(Formula_One)
71 | 71,apollon,Apollon,Swiss,http://en.wikipedia.org/wiki/Apollon_(Formula_One)
72 | 72,kojima,Kojima,Japanese,http://en.wikipedia.org/wiki/Kojima_Engineering
73 | 73,parnelli,Parnelli,American,http://en.wikipedia.org/wiki/Parnelli
74 | 74,maki,Maki,Japanese,http://en.wikipedia.org/wiki/Maki_(cars)
75 | 75,hill,Embassy Hill,British,http://en.wikipedia.org/wiki/Hill_(constructor)
76 | 76,lyncar,Lyncar,British,http://en.wikipedia.org/wiki/Lyncar
77 | 77,trojan,Trojan,British,http://en.wikipedia.org/wiki/Trojan_(Racing_team)
78 | 78,amon,Amon,New Zealand,http://en.wikipedia.org/wiki/Amon_(Formula_One_team)
79 | 79,token,Token,British,http://en.wikipedia.org/wiki/Token_(Racing_team)
80 | 80,iso_marlboro,Iso Marlboro,British,http://en.wikipedia.org/wiki/Iso_Marlboro
81 | 81,tecno,Tecno,Italian,http://en.wikipedia.org/wiki/Tecno
82 | 82,matra,Matra,French,http://en.wikipedia.org/wiki/Matra
83 | 83,politoys,Politoys,British,http://en.wikipedia.org/wiki/Frank_Williams_Racing_Cars
84 | 84,connew,Connew,British,http://en.wikipedia.org/wiki/Connew
85 | 85,bellasi,Bellasi,Swiss,http://en.wikipedia.org/wiki/Bellasi
86 | 86,tomaso,De Tomaso,Italian,http://en.wikipedia.org/wiki/De_Tomaso
87 | 87,cooper,Cooper,British,http://en.wikipedia.org/wiki/Cooper_Car_Company
88 | 88,eagle,Eagle,American,http://en.wikipedia.org/wiki/Anglo_American_Racers
89 | 89,lds,LDS,South African,http://en.wikipedia.org/wiki/LDS_(automobile)
90 | 90,protos,Protos,British,http://en.wikipedia.org/wiki/Protos_(constructor)
91 | 91,shannon,Shannon,British,http://en.wikipedia.org/wiki/Shannon_(Formula_One)
92 | 92,scirocco,Scirocco,British,http://en.wikipedia.org/wiki/Scirocco-Powell
93 | 93,re,RE,Rhodesian,http://en.wikipedia.org/wiki/RE_%28automobile%29
94 | 94,brp,BRP,British,http://en.wikipedia.org/wiki/British_Racing_Partnership
95 | 95,porsche,Porsche,German,http://en.wikipedia.org/wiki/Porsche_in_Formula_One
96 | 96,derrington,Derrington,British,http://en.wikipedia.org/wiki/Derrington-Francis
97 | 97,gilby,Gilby,British,http://en.wikipedia.org/wiki/Gilby
98 | 98,stebro,Stebro,Canadian,http://en.wikipedia.org/wiki/Stebro
99 | 99,emeryson,Emeryson,British,http://en.wikipedia.org/wiki/Emeryson
100 | 100,enb,ENB,Belgium,http://en.wikipedia.org/wiki/Ecurie_Nationale_Belge
101 | 101,jbw,JBW,British,http://en.wikipedia.org/wiki/JBW
102 | 102,ferguson,Ferguson,British,http://en.wikipedia.org/wiki/Ferguson_Research_Ltd.
103 | 103,mbm,MBM,Swiss,http://en.wikipedia.org/wiki/Monteverdi_Basel_Motors
104 | 104,behra-porsche,Behra-Porsche,Italian,http://en.wikipedia.org/wiki/Behra-Porsche
105 | 105,maserati,Maserati,Italian,http://en.wikipedia.org/wiki/Maserati
106 | 106,scarab,Scarab,American,http://en.wikipedia.org/wiki/Scarab_(constructor)
107 | 107,watson,Watson,American,http://en.wikipedia.org/wiki/A.J._Watson
108 | 108,epperly,Epperly,American,http://en.wikipedia.org/wiki/Epperly
109 | 109,phillips,Phillips,American,http://en.wikipedia.org/wiki/Phillips_(constructor)
110 | 110,lesovsky,Lesovsky,American,http://en.wikipedia.org/wiki/Lesovsky
111 | 111,trevis,Trevis,American,http://en.wikipedia.org/wiki/Trevis
112 | 112,meskowski,Meskowski,American,http://en.wikipedia.org/wiki/Meskowski
113 | 113,kurtis_kraft,Kurtis Kraft,American,http://en.wikipedia.org/wiki/Kurtis_Kraft
114 | 114,kuzma,Kuzma,American,http://en.wikipedia.org/wiki/Kuzma_(constructor)
115 | 115,vhristensen,Christensen,American,http://en.wikipedia.org/wiki/Christensen_(constructor)
116 | 116,ewing,Ewing,American,http://en.wikipedia.org/wiki/Ewing_(constructor)
117 | 117,aston_martin,Aston Martin,British,http://en.wikipedia.org/wiki/Aston_Martin
118 | 118,vanwall,Vanwall,British,http://en.wikipedia.org/wiki/Vanwall
119 | 119,moore,Moore,American,http://en.wikipedia.org/wiki/Moore_(constructor)
120 | 120,dunn,Dunn,American,http://en.wikipedia.org/wiki/Dunn_Engineering
121 | 121,elder,Elder,American,http://en.wikipedia.org/wiki/Elder_(constructor)
122 | 122,sutton,Sutton,American,http://en.wikipedia.org/wiki/Sutton_(constructor)
123 | 123,fry,Fry,British,http://en.wikipedia.org/wiki/Fry_(racing_team)
124 | 124,tec-mec,Tec-Mec,Italian,http://en.wikipedia.org/wiki/Tec-Mec
125 | 125,connaught,Connaught,British,http://en.wikipedia.org/wiki/Connaught_Engineering
126 | 126,alta,Alta,British,http://en.wikipedia.org/wiki/Alta_auto_racing_team
127 | 127,osca,OSCA,Italian,http://en.wikipedia.org/wiki/Officine_Specializate_Costruzione_Automobili
128 | 128,gordini,Gordini,French,http://en.wikipedia.org/wiki/Gordini
129 | 129,stevens,Stevens,American,http://en.wikipedia.org/wiki/Stevens_(constructor)
130 | 130,bugatti,Bugatti,French,http://en.wikipedia.org/wiki/Bugatti
131 | 131,mercedes,Mercedes,German,http://en.wikipedia.org/wiki/Mercedes-Benz_in_Formula_One
132 | 132,lancia,Lancia,Italian,http://en.wikipedia.org/wiki/Lancia_in_Formula_One
133 | 133,hwm,HWM,British,http://en.wikipedia.org/wiki/Hersham_and_Walton_Motors
134 | 134,schroeder,Schroeder,American,http://en.wikipedia.org/wiki/Schroeder_(constructor)
135 | 135,pawl,Pawl,American,http://en.wikipedia.org/wiki/Pawl_(constructor)
136 | 136,pankratz,Pankratz,American,http://en.wikipedia.org/wiki/Pankratz
137 | 137,arzani-volpini,Arzani-Volpini,Italian,http://en.wikipedia.org/wiki/Arzani-Volpini
138 | 138,nichels,Nichels,American,http://en.wikipedia.org/wiki/Nichels
139 | 139,bromme,Bromme,American,http://en.wikipedia.org/wiki/Bromme
140 | 140,klenk,Klenk,German,http://en.wikipedia.org/wiki/Klenk
141 | 141,simca,Simca,French,http://en.wikipedia.org/wiki/Simca
142 | 142,turner,Turner,American,http://en.wikipedia.org/wiki/Turner_(constructor)
143 | 143,del_roy,Del Roy,American,http://en.wikipedia.org/wiki/Del_Roy
144 | 144,veritas,Veritas,German,http://en.wikipedia.org/wiki/Veritas_(constructor)
145 | 145,bmw,BMW,German,http://en.wikipedia.org/wiki/BMW
146 | 146,emw,EMW,East German,http://en.wikipedia.org/wiki/Eisenacher_Motorenwerk
147 | 147,afm,AFM,German,http://en.wikipedia.org/wiki/Alex_von_Falkenhausen_Motorenbau
148 | 148,frazer_nash,Frazer Nash,British,http://en.wikipedia.org/wiki/Frazer_Nash
149 | 149,sherman,Sherman,American,http://en.wikipedia.org/wiki/Sherman_(constructor)
150 | 150,deidt,Deidt,American,http://en.wikipedia.org/wiki/Deidt
151 | 151,era,ERA,British,http://en.wikipedia.org/wiki/English_Racing_Automobiles
152 | 152,butterworth,Aston Butterworth,British,http://en.wikipedia.org/wiki/Aston_Butterworth
153 | 153,cisitalia,Cisitalia,Italian,http://en.wikipedia.org/wiki/Cisitalia
154 | 154,lago,Talbot-Lago,French,http://en.wikipedia.org/wiki/Talbot-Lago
155 | 155,hall,Hall,American,http://en.wikipedia.org/wiki/Hall_(constructor)
156 | 156,marchese,Marchese,American,http://en.wikipedia.org/wiki/Marchese_(constructor)
157 | 157,langley,Langley,American,http://en.wikipedia.org/wiki/Langley_(constructor)
158 | 158,rae,Rae,American,http://en.wikipedia.org/wiki/Rae_(motorsport)
159 | 159,olson,Olson,American,http://en.wikipedia.org/wiki/Olson_(constructor)
160 | 160,wetteroth,Wetteroth,American,http://en.wikipedia.org/wiki/Wetteroth
161 | 161,adams,Adams,American,http://en.wikipedia.org/wiki/Adams_(constructor)
162 | 162,snowberger,Snowberger,American,http://en.wikipedia.org/wiki/Snowberger
163 | 163,milano,Milano,Italian,http://en.wikipedia.org/wiki/Scuderia_Milano
164 | 164,hrt,HRT,Spanish,http://en.wikipedia.org/wiki/Hispania_Racing
165 | 167,cooper-maserati,Cooper-Maserati,British,http://en.wikipedia.org/wiki/Cooper_Car_Company
166 | 166,virgin,Virgin,British,http://en.wikipedia.org/wiki/Virgin_Racing
167 | 168,cooper-osca,Cooper-OSCA,British,http://en.wikipedia.org/wiki/Cooper_Car_Company
168 | 169,cooper-borgward,Cooper-Borgward,British,http://en.wikipedia.org/wiki/Cooper_Car_Company
169 | 170,cooper-climax,Cooper-Climax,British,http://en.wikipedia.org/wiki/Cooper_Car_Company
170 | 171,cooper-castellotti,Cooper-Castellotti,British,http://en.wikipedia.org/wiki/Cooper_Car_Company
171 | 172,lotus-climax,Lotus-Climax,British,http://en.wikipedia.org/wiki/Team_Lotus
172 | 173,lotus-maserati,Lotus-Maserati,British,http://en.wikipedia.org/wiki/Team_Lotus
173 | 174,de_tomaso-osca,De Tomaso-Osca,Italian,http://en.wikipedia.org/wiki/De_Tomaso
174 | 175,de_tomaso-alfa_romeo,De Tomaso-Alfa Romeo,Italian,http://en.wikipedia.org/wiki/De_Tomaso
175 | 176,lotus-brm,Lotus-BRM,British,http://en.wikipedia.org/wiki/Team_Lotus
176 | 177,lotus-borgward,Lotus-Borgward,British,http://en.wikipedia.org/wiki/Team_Lotus
177 | 178,cooper-alfa_romeo,Cooper-Alfa Romeo,British,http://en.wikipedia.org/wiki/Cooper_Car_Company
178 | 179,de_tomaso-ferrari,De Tomaso-Ferrari,Italian,http://en.wikipedia.org/wiki/De_Tomaso
179 | 180,lotus-ford,Lotus-Ford,British,http://en.wikipedia.org/wiki/Team_Lotus
180 | 181,brabham-brm,Brabham-BRM,British,http://en.wikipedia.org/wiki/Brabham
181 | 182,brabham-ford,Brabham-Ford,British,http://en.wikipedia.org/wiki/Brabham
182 | 183,brabham-climax,Brabham-Climax,British,http://en.wikipedia.org/wiki/Brabham
183 | 184,lds-climax,LDS-Climax,South African,http://en.wikipedia.org/wiki/LDS_(automobile)
184 | 185,lds-alfa_romeo,LDS-Alfa Romeo,South African,http://en.wikipedia.org/wiki/LDS_(automobile)
185 | 186,cooper-ford,Cooper-Ford,British,http://en.wikipedia.org/wiki/Cooper_Car_Company
186 | 187,mclaren-ford,McLaren-Ford,British,http://en.wikipedia.org/wiki/Team_McLaren
187 | 188,mclaren-seren,McLaren-Serenissima,British,http://en.wikipedia.org/wiki/Team_McLaren
188 | 189,eagle-climax,Eagle-Climax,American,http://en.wikipedia.org/wiki/Anglo_American_Racers
189 | 190,eagle-weslake,Eagle-Weslake,American,http://en.wikipedia.org/wiki/Anglo_American_Racers
190 | 191,brabham-repco,Brabham-Repco,British,http://en.wikipedia.org/wiki/Brabham
191 | 192,cooper-ferrari,Cooper-Ferrari,British,http://en.wikipedia.org/wiki/Cooper_Car_Company
192 | 193,cooper-ats,Cooper-ATS,British,http://en.wikipedia.org/wiki/Cooper_Car_Company
193 | 194,mclaren-brm,McLaren-BRM,British,http://en.wikipedia.org/wiki/McLaren_(racing)
194 | 195,cooper-brm,Cooper-BRM,British,http://en.wikipedia.org/wiki/Cooper_Car_Company
195 | 196,matra-ford,Matra-Ford,French,http://en.wikipedia.org/wiki/Matra
196 | 197,brm-ford,BRM-Ford,British,http://en.wikipedia.org/wiki/BRM
197 | 198,mclaren-alfa_romeo,McLaren-Alfa Romeo,British,http://en.wikipedia.org/wiki/McLaren_(racing)
198 | 199,march-alfa_romeo,March-Alfa Romeo,British,http://en.wikipedia.org/wiki/March_Engineering
199 | 200,march-ford,March-Ford,British,http://en.wikipedia.org/wiki/March_Engineering
200 | 201,lotus-pw,Lotus-Pratt & Whitney,British,http://en.wikipedia.org/wiki/Team_Lotus
201 | 202,shadow-ford,Shadow-Ford,British,http://en.wikipedia.org/wiki/Shadow_Racing_Cars
202 | 203,shadow-matra,Shadow-Matra,British,http://en.wikipedia.org/wiki/Shadow_Racing_Cars
203 | 204,brabham-alfa_romeo,Brabham-Alfa Romeo,British,http://en.wikipedia.org/wiki/Brabham
204 | 205,lotus_racing,Lotus,Malaysian,http://en.wikipedia.org/wiki/Lotus_Racing
205 | 206,marussia,Marussia,Russian,http://en.wikipedia.org/wiki/Marussia_F1
206 | 207,caterham,Caterham,Malaysian,http://en.wikipedia.org/wiki/Caterham_F1
207 | 208,lotus_f1,Lotus F1,British,http://en.wikipedia.org/wiki/Lotus_F1
208 | 209,manor,Manor Marussia,British,http://en.wikipedia.org/wiki/Manor_Motorsport
209 | 210,haas,Haas F1 Team,American,http://en.wikipedia.org/wiki/Haas_F1_Team
210 |
--------------------------------------------------------------------------------
/Live Session/Workshop 8 - Persistent Data Storage/database_setup/data/seasons.csv:
--------------------------------------------------------------------------------
1 | year,url
2 | 2009,http://en.wikipedia.org/wiki/2009_Formula_One_season
3 | 2008,http://en.wikipedia.org/wiki/2008_Formula_One_season
4 | 2007,http://en.wikipedia.org/wiki/2007_Formula_One_season
5 | 2006,http://en.wikipedia.org/wiki/2006_Formula_One_season
6 | 2005,http://en.wikipedia.org/wiki/2005_Formula_One_season
7 | 2004,http://en.wikipedia.org/wiki/2004_Formula_One_season
8 | 2003,http://en.wikipedia.org/wiki/2003_Formula_One_season
9 | 2002,http://en.wikipedia.org/wiki/2002_Formula_One_season
10 | 2001,http://en.wikipedia.org/wiki/2001_Formula_One_season
11 | 2000,http://en.wikipedia.org/wiki/2000_Formula_One_season
12 | 1999,http://en.wikipedia.org/wiki/1999_Formula_One_season
13 | 1998,http://en.wikipedia.org/wiki/1998_Formula_One_season
14 | 1997,http://en.wikipedia.org/wiki/1997_Formula_One_season
15 | 1996,http://en.wikipedia.org/wiki/1996_Formula_One_season
16 | 1995,http://en.wikipedia.org/wiki/1995_Formula_One_season
17 | 1994,http://en.wikipedia.org/wiki/1994_Formula_One_season
18 | 1993,http://en.wikipedia.org/wiki/1993_Formula_One_season
19 | 1992,http://en.wikipedia.org/wiki/1992_Formula_One_season
20 | 1991,http://en.wikipedia.org/wiki/1991_Formula_One_season
21 | 1990,http://en.wikipedia.org/wiki/1990_Formula_One_season
22 | 2010,http://en.wikipedia.org/wiki/2010_Formula_One_season
23 | 1989,http://en.wikipedia.org/wiki/1989_Formula_One_season
24 | 1988,http://en.wikipedia.org/wiki/1988_Formula_One_season
25 | 1987,http://en.wikipedia.org/wiki/1987_Formula_One_season
26 | 1986,http://en.wikipedia.org/wiki/1986_Formula_One_season
27 | 1985,http://en.wikipedia.org/wiki/1985_Formula_One_season
28 | 1984,http://en.wikipedia.org/wiki/1984_Formula_One_season
29 | 1983,http://en.wikipedia.org/wiki/1983_Formula_One_season
30 | 1982,http://en.wikipedia.org/wiki/1982_Formula_One_season
31 | 1981,http://en.wikipedia.org/wiki/1981_Formula_One_season
32 | 1980,http://en.wikipedia.org/wiki/1980_Formula_One_season
33 | 1979,http://en.wikipedia.org/wiki/1979_Formula_One_season
34 | 1978,http://en.wikipedia.org/wiki/1978_Formula_One_season
35 | 1977,http://en.wikipedia.org/wiki/1977_Formula_One_season
36 | 1976,http://en.wikipedia.org/wiki/1976_Formula_One_season
37 | 1975,http://en.wikipedia.org/wiki/1975_Formula_One_season
38 | 1974,http://en.wikipedia.org/wiki/1974_Formula_One_season
39 | 1973,http://en.wikipedia.org/wiki/1973_Formula_One_season
40 | 1972,http://en.wikipedia.org/wiki/1972_Formula_One_season
41 | 1971,http://en.wikipedia.org/wiki/1971_Formula_One_season
42 | 1970,http://en.wikipedia.org/wiki/1970_Formula_One_season
43 | 1969,http://en.wikipedia.org/wiki/1969_Formula_One_season
44 | 1968,http://en.wikipedia.org/wiki/1968_Formula_One_season
45 | 1967,http://en.wikipedia.org/wiki/1967_Formula_One_season
46 | 1966,http://en.wikipedia.org/wiki/1966_Formula_One_season
47 | 1965,http://en.wikipedia.org/wiki/1965_Formula_One_season
48 | 1964,http://en.wikipedia.org/wiki/1964_Formula_One_season
49 | 1963,http://en.wikipedia.org/wiki/1963_Formula_One_season
50 | 1962,http://en.wikipedia.org/wiki/1962_Formula_One_season
51 | 1961,http://en.wikipedia.org/wiki/1961_Formula_One_season
52 | 1960,http://en.wikipedia.org/wiki/1960_Formula_One_season
53 | 1959,http://en.wikipedia.org/wiki/1959_Formula_One_season
54 | 1958,http://en.wikipedia.org/wiki/1958_Formula_One_season
55 | 1957,http://en.wikipedia.org/wiki/1957_Formula_One_season
56 | 1956,http://en.wikipedia.org/wiki/1956_Formula_One_season
57 | 1955,http://en.wikipedia.org/wiki/1955_Formula_One_season
58 | 1954,http://en.wikipedia.org/wiki/1954_Formula_One_season
59 | 1953,http://en.wikipedia.org/wiki/1953_Formula_One_season
60 | 1952,http://en.wikipedia.org/wiki/1952_Formula_One_season
61 | 1951,http://en.wikipedia.org/wiki/1951_Formula_One_season
62 | 1950,http://en.wikipedia.org/wiki/1950_Formula_One_season
63 | 2011,http://en.wikipedia.org/wiki/2011_Formula_One_season
64 | 2012,http://en.wikipedia.org/wiki/2012_Formula_One_season
65 | 2013,http://en.wikipedia.org/wiki/2013_Formula_One_season
66 | 2014,http://en.wikipedia.org/wiki/2014_Formula_One_season
67 | 2015,http://en.wikipedia.org/wiki/2015_Formula_One_season
68 | 2016,https://en.wikipedia.org/wiki/2016_Formula_One_season
69 | 2017,https://en.wikipedia.org/wiki/2017_Formula_One_season
70 | 2018,http://en.wikipedia.org/wiki/2018_FIA_Formula_One_World_Championship
71 |
--------------------------------------------------------------------------------
/Live Session/Workshop 8 - Persistent Data Storage/database_setup/data/status.csv:
--------------------------------------------------------------------------------
1 | statusId,status
2 | 1,Finished
3 | 2,Disqualified
4 | 3,Accident
5 | 4,Collision
6 | 5,Engine
7 | 6,Gearbox
8 | 7,Transmission
9 | 8,Clutch
10 | 9,Hydraulics
11 | 10,Electrical
12 | 11,+1 Lap
13 | 12,+2 Laps
14 | 13,+3 Laps
15 | 14,+4 Laps
16 | 15,+5 Laps
17 | 16,+6 Laps
18 | 17,+7 Laps
19 | 18,+8 Laps
20 | 19,+9 Laps
21 | 20,Spun off
22 | 21,Radiator
23 | 22,Suspension
24 | 23,Brakes
25 | 24,Differential
26 | 25,Overheating
27 | 26,Mechanical
28 | 27,Tyre
29 | 28,Driver Seat
30 | 29,Puncture
31 | 30,Driveshaft
32 | 31,Retired
33 | 32,Fuel pressure
34 | 33,Front wing
35 | 34,Water pressure
36 | 35,Refuelling
37 | 36,Wheel
38 | 37,Throttle
39 | 38,Steering
40 | 39,Technical
41 | 40,Electronics
42 | 41,Broken wing
43 | 42,Heat shield fire
44 | 43,Exhaust
45 | 44,Oil leak
46 | 45,+11 Laps
47 | 46,Wheel rim
48 | 47,Water leak
49 | 48,Fuel pump
50 | 49,Track rod
51 | 50,+17 Laps
52 | 51,Oil pressure
53 | 53,+13 Laps
54 | 54,Withdrew
55 | 55,+12 Laps
56 | 56,Engine fire
57 | 58,+26 Laps
58 | 59,Tyre puncture
59 | 60,Out of fuel
60 | 61,Wheel nut
61 | 62,Not classified
62 | 63,Pneumatics
63 | 64,Handling
64 | 65,Rear wing
65 | 66,Fire
66 | 67,Wheel bearing
67 | 68,Physical
68 | 69,Fuel system
69 | 70,Oil line
70 | 71,Fuel rig
71 | 72,Launch control
72 | 73,Injured
73 | 74,Fuel
74 | 75,Power loss
75 | 76,Vibrations
76 | 77,107% Rule
77 | 78,Safety
78 | 79,Drivetrain
79 | 80,Ignition
80 | 81,Did not qualify
81 | 82,Injury
82 | 83,Chassis
83 | 84,Battery
84 | 85,Stalled
85 | 86,Halfshaft
86 | 87,Crankshaft
87 | 88,+10 Laps
88 | 89,Safety concerns
89 | 90,Not restarted
90 | 91,Alternator
91 | 92,Underweight
92 | 93,Safety belt
93 | 94,Oil pump
94 | 95,Fuel leak
95 | 96,Excluded
96 | 97,Did not prequalify
97 | 98,Injection
98 | 99,Distributor
99 | 100,Driver unwell
100 | 101,Turbo
101 | 102,CV joint
102 | 103,Water pump
103 | 104,Fatal accident
104 | 105,Spark plugs
105 | 106,Fuel pipe
106 | 107,Eye injury
107 | 108,Oil pipe
108 | 109,Axle
109 | 110,Water pipe
110 | 111,+14 Laps
111 | 112,+15 Laps
112 | 113,+25 Laps
113 | 114,+18 Laps
114 | 115,+22 Laps
115 | 116,+16 Laps
116 | 117,+24 Laps
117 | 118,+29 Laps
118 | 119,+23 Laps
119 | 120,+21 Laps
120 | 121,Magneto
121 | 122,+44 Laps
122 | 123,+30 Laps
123 | 124,+19 Laps
124 | 125,+46 Laps
125 | 126,Supercharger
126 | 127,+20 Laps
127 | 128,+42 Laps
128 | 129,Engine misfire
129 | 130,Collision damage
130 | 131,Power Unit
131 | 132,ERS
132 | 133,+49 Laps
133 | 134,+38 Laps
134 | 135,Brake duct
135 | 136,Seat
136 |
--------------------------------------------------------------------------------
/Live Session/Workshop 8 - Persistent Data Storage/database_setup/models/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Live Session/Workshop 8 - Persistent Data Storage/database_setup/models/__init__.py
--------------------------------------------------------------------------------
/Live Session/Workshop 8 - Persistent Data Storage/database_setup/models/__pycache__/__init__.cpython-312.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Live Session/Workshop 8 - Persistent Data Storage/database_setup/models/__pycache__/__init__.cpython-312.pyc
--------------------------------------------------------------------------------
/Live Session/Workshop 8 - Persistent Data Storage/database_setup/models/__pycache__/ms_sql_model.cpython-312.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Live Session/Workshop 8 - Persistent Data Storage/database_setup/models/__pycache__/ms_sql_model.cpython-312.pyc
--------------------------------------------------------------------------------
/Live Session/Workshop 8 - Persistent Data Storage/database_setup/models/__pycache__/my_sql_model.cpython-312.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Live Session/Workshop 8 - Persistent Data Storage/database_setup/models/__pycache__/my_sql_model.cpython-312.pyc
--------------------------------------------------------------------------------
/Live Session/Workshop 8 - Persistent Data Storage/database_setup/models/__pycache__/postgres_model.cpython-312.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Live Session/Workshop 8 - Persistent Data Storage/database_setup/models/__pycache__/postgres_model.cpython-312.pyc
--------------------------------------------------------------------------------
/Live Session/Workshop 8 - Persistent Data Storage/database_setup/models/ms_sql_model.py:
--------------------------------------------------------------------------------
1 | """
2 | WARNING: DO NOT MAKE ANY CHANGES TO THE CODE,
3 | PLEASE FOLLOW THE INSTRUCTIONS IN THE README FILE TO SET EVERYTHING UP
4 | """
5 | from pydantic import BaseModel, Field
6 |
7 | class SQLServer(BaseModel):
8 | user: str = Field(default="")
9 | password: str = Field(default="")
10 | server: str = Field(default="localhost")
11 | driver: str = Field(default="SQL Server Native Client 11.0")
12 | database: str
13 |
14 | def __str__(self) -> str:
15 | credentials = ":".join([self.user, self.password, "@"]) if self.user and self.password else ""
16 | return f'mssql+pyodbc://{credentials}{self.server}/{self.database}?driver={self.driver}'
--------------------------------------------------------------------------------
/Live Session/Workshop 8 - Persistent Data Storage/database_setup/models/my_sql_model.py:
--------------------------------------------------------------------------------
1 | """
2 | WARNING: DO NOT MAKE ANY CHANGES TO THE CODE,
3 | PLEASE FOLLOW THE INSTRUCTIONS IN THE README FILE TO SET EVERYTHING UP
4 | """
5 | from pydantic import BaseModel, Field
6 |
7 | class MySQL(BaseModel):
8 | user: str = Field(default="")
9 | password: str = Field(default="")
10 | server: str = Field(default="locahost")
11 | port: int = Field(default=3306)
12 | database: str
13 |
14 | def __str__(self) -> str:
15 | credentials = ":".join([self.user, self.password, '@']) if self.user and self.password else ""
16 |
17 | return f'mysql+pymysql://{credentials}{self.server}:{self.port}/{self.database}'
--------------------------------------------------------------------------------
/Live Session/Workshop 8 - Persistent Data Storage/database_setup/models/postgres_model.py:
--------------------------------------------------------------------------------
1 | """
2 | WARNING: DO NOT MAKE ANY CHANGES TO THE CODE,
3 | PLEASE FOLLOW THE INSTRUCTIONS IN THE README FILE TO SET EVERYTHING UP
4 | """
5 | from pydantic import BaseModel, Field
6 |
7 | class Postgres(BaseModel):
8 | user: str = Field(default="postgres")
9 | password: str = Field(default="postgres")
10 | server: str = Field(default="localhost")
11 | port: int = Field(default=5432)
12 | database: str
13 |
14 | def __str__(self) -> str:
15 | credentials = ":".join([self.user, self.password]) if self.user and self.password else ""
16 |
17 | return f"postgresql://{credentials}@{self.server}:{self.port}/{self.database}"
--------------------------------------------------------------------------------
/Live Session/Workshop 8 - Persistent Data Storage/database_setup/requirements.txt:
--------------------------------------------------------------------------------
1 | annotated-types==0.6.0
2 | greenlet==3.0.3
3 | numpy==1.26.4
4 | pandas==2.2.2
5 | psycopg2==2.9.9
6 | pydantic==2.7.1
7 | pydantic_core==2.18.2
8 | python-dateutil==2.9.0.post0
9 | pytz==2024.1
10 | six==1.16.0
11 | SQLAlchemy==2.0.30
12 | typing_extensions==4.11.0
13 | tzdata==2024.1
14 |
--------------------------------------------------------------------------------
/Live Session/Workshop 8 - Persistent Data Storage/database_setup/scripts/create.sql:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Live Session/Workshop 8 - Persistent Data Storage/database_setup/scripts/create.sql
--------------------------------------------------------------------------------
/Live Session/Workshop 8 - Persistent Data Storage/database_setup/services/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Live Session/Workshop 8 - Persistent Data Storage/database_setup/services/__init__.py
--------------------------------------------------------------------------------
/Live Session/Workshop 8 - Persistent Data Storage/database_setup/services/__pycache__/__init__.cpython-312.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Live Session/Workshop 8 - Persistent Data Storage/database_setup/services/__pycache__/__init__.cpython-312.pyc
--------------------------------------------------------------------------------
/Live Session/Workshop 8 - Persistent Data Storage/database_setup/services/__pycache__/database_connection.cpython-312.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Live Session/Workshop 8 - Persistent Data Storage/database_setup/services/__pycache__/database_connection.cpython-312.pyc
--------------------------------------------------------------------------------
/Live Session/Workshop 8 - Persistent Data Storage/database_setup/services/__pycache__/database_connection_factory.cpython-312.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Live Session/Workshop 8 - Persistent Data Storage/database_setup/services/__pycache__/database_connection_factory.cpython-312.pyc
--------------------------------------------------------------------------------
/Live Session/Workshop 8 - Persistent Data Storage/database_setup/services/__pycache__/input_handler.cpython-312.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Live Session/Workshop 8 - Persistent Data Storage/database_setup/services/__pycache__/input_handler.cpython-312.pyc
--------------------------------------------------------------------------------
/Live Session/Workshop 8 - Persistent Data Storage/database_setup/services/database_connection.py:
--------------------------------------------------------------------------------
1 | """
2 | WARNING: DO NOT MAKE ANY CHANGES TO THE CODE,
3 | PLEASE FOLLOW THE INSTRUCTIONS IN THE README FILE TO SET EVERYTHING UP
4 | """
5 |
6 | import json
7 | import os
8 | from sqlalchemy import create_engine, text
9 | from services.database_connection_factory import get_database_model
10 |
11 |
12 | def get_database_engine(service: str, config: dict):
13 | model = get_database_model(service, config)
14 |
15 | if model is None:
16 | return None
17 |
18 | if not model:
19 | return None
20 |
21 |
22 | try:
23 | engine = create_engine(str(model))
24 | __test_engine_connection(engine)
25 |
26 | return engine
27 | except Exception as e:
28 | print(e)
29 | return None
30 |
31 |
32 | def __test_engine_connection(engine):
33 | with engine.connect() as conn:
34 | conn.execute(text("SELECT 1"))
35 |
36 |
37 |
38 | def read_json(file_path: str):
39 | if not os.path.exists(file_path):
40 | return None
41 |
42 | with open(file_path, 'r') as file:
43 | return json.load(file)
44 |
45 | def is_valid_config(config: dict):
46 | if config.get('service') == None:
47 | return False
48 |
49 | if config.get('connection_string') == None:
50 | return False
51 |
52 | return True
--------------------------------------------------------------------------------
/Live Session/Workshop 8 - Persistent Data Storage/database_setup/services/database_connection_factory.py:
--------------------------------------------------------------------------------
1 | """
2 | WARNING: DO NOT MAKE ANY CHANGES TO THE CODE,
3 | PLEASE FOLLOW THE INSTRUCTIONS IN THE README FILE TO SET EVERYTHING UP
4 | """
5 |
6 | from models.ms_sql_model import SQLServer
7 | from models.postgres_model import Postgres
8 | from models.my_sql_model import MySQL
9 |
10 | def get_database_model(service: str, config_data: dict[str]):
11 | try:
12 | return __get_connection_from_service(service, config_data)
13 | except Exception as e:
14 | print(f'Error: {e}')
15 | return None
16 |
17 |
18 | def __get_connection_from_service(service: str, config_data: dict[str]):
19 | if service == 'ms_sql_server':
20 | return SQLServer(**config_data)
21 | elif service == 'postgres':
22 | return Postgres(**config_data)
23 | elif service == 'mysql':
24 | return MySQL(**config_data)
25 | else:
26 | None
--------------------------------------------------------------------------------
/Live Session/Workshop 8 - Persistent Data Storage/database_setup/services/input_handler.py:
--------------------------------------------------------------------------------
1 | """
2 | WARNING: DO NOT MAKE ANY CHANGES TO THE CODE,
3 | PLEASE FOLLOW THE INSTRUCTIONS IN THE README FILE TO SET EVERYTHING UP
4 | """
5 |
6 | import argparse
7 | from services.database_connection import read_json, is_valid_config
8 |
9 | def get_args():
10 | parser = argparse.ArgumentParser()
11 |
12 | # Create arguments that take postgresql connection details
13 | parser.add_argument("-u", "--user", help="The username of the database you want to connect to")
14 | parser.add_argument("-pw", "--password", help="The password of the database you want to connect to")
15 | parser.add_argument("-sr", "--server", help="The host of the database you want to connect to")
16 | parser.add_argument("-p", "--port", help="The port of the database you want to connect to")
17 | parser.add_argument("-dr", "--driver", help="The driver for MS SQL Server")
18 | parser.add_argument("-db", "--database", help="The name of the database you want to connect to")
19 | parser.add_argument("-cf", "--config", help="The path to the config file")
20 | parser.add_argument("-s", "--service", help="The connection type")
21 |
22 | args = parser.parse_args()
23 |
24 | return args
25 |
26 | def is_args_valid(args):
27 | if not args.config and not (args.database and args.service):
28 | return False
29 |
30 | return True
31 |
32 | def get_database_details(args: dict):
33 | if args.get('config'):
34 | data = read_json(args['config'])
35 |
36 | if not is_valid_config(data):
37 | return None
38 |
39 | print(type(data))
40 | return data['service'], data['connection_string']
41 |
42 |
43 | if args.get('database') == None:
44 | return None
45 |
46 | service = args.get('service')
47 | return service, args
48 |
49 |
50 |
51 | if __name__ == "__main__":
52 | args = get_args()
53 |
54 | if not is_args_valid(args):
55 | print("Please provide a config file or connection details")
56 | exit()
57 |
58 | # Remove None values from args and convert to dictionary
59 | args = {k: v for k, v in args.__dict__.items() if v is not None}
60 |
61 | print(args)
--------------------------------------------------------------------------------
/Live Session/Workshop 8 - Persistent Data Storage/database_setup/setup.py:
--------------------------------------------------------------------------------
1 | """
2 | WARNING:
3 | DO NOT MAKE ANY CHANGES TO THE CODE,
4 | PLEASE FOLLOW THE INSTRUCTIONS IN THE README FILE TO SET EVERYTHING UP
5 | """
6 |
7 | import os
8 | import pandas as pd
9 | import threading
10 | import time
11 | from sqlalchemy import text, insert, Table, MetaData
12 |
13 | from services.database_connection import get_database_engine
14 | from services.input_handler import get_args, is_args_valid, get_database_details
15 |
16 | def insert_to_database(file_name, table_name, engine):
17 | df = pd.read_csv(file_name)
18 |
19 | table_name = Table(table_name, MetaData(), autoload_with=engine)
20 |
21 | print(table_name)
22 |
23 | with engine.connect() as conn:
24 | for i, row in df.iterrows():
25 | values = row.to_dict()
26 |
27 | stmt = insert(table_name).values(**values)
28 | conn.execute(stmt)
29 | conn.commit()
30 |
31 | def insert_all_data(engine):
32 | tables = __get_file_names("./data")
33 |
34 | with engine.connect() as conn:
35 | for name in tables:
36 | try:
37 | insert_to_database(f"data/{name}.csv", name, engine)
38 | except Exception as e:
39 | conn.rollback()
40 |
41 | def __get_file_names(directory):
42 | file_names = []
43 | for filename in os.listdir(directory):
44 | if os.path.isfile(os.path.join(directory, filename)):
45 | file_names.append(filename.replace(".csv", ""))
46 |
47 | return file_names
48 |
49 | def reset_database_tables(engine):
50 | if not os.path.exists('scripts/create.sql'):
51 | print("\033[91m")
52 | print("Important database file missing, please pull the repository again to reset the dependencies")
53 | print("\033[0m")
54 |
55 | exit()
56 |
57 | with open('scripts/create.sql', 'r') as f:
58 | scripts = f.readlines()
59 |
60 | with engine.connect() as conn:
61 | for script in scripts:
62 |
63 | script = text(script)
64 | try:
65 | conn.execute(script)
66 | conn.commit()
67 | except Exception as e:
68 | conn.rollback()
69 |
70 |
71 | def loading_animation():
72 | emojis = ['⚫','🔵','🟢','🟡','🟠','🔴']
73 | idx = 0
74 | while not done:
75 | print(f'{emojis[idx % len(emojis)]}', end='\r')
76 | idx += 1
77 | time.sleep(0.5)
78 |
79 | if __name__ in "__main__":
80 | global done
81 | done = False
82 |
83 | args = get_args()
84 |
85 | if not is_args_valid(args):
86 | print("\033[91m")
87 | print("Please add all the connection details")
88 | print("Example: python script.py -s postgres -sr localhost -p 5432 -db postgres -u postgres -pw postgres")
89 | print("\033[0m")
90 | print("For help: python script.py -h")
91 | exit()
92 |
93 | args = {k: v for k, v in args.__dict__.items() if v is not None}
94 | db_details = get_database_details(args)
95 |
96 | if not db_details:
97 | print("\033[91m")
98 | print("Please provide a config file or connection details")
99 | print("\033[0m")
100 | exit()
101 |
102 | engine = get_database_engine(db_details[0], db_details[1])
103 |
104 | if (engine == None):
105 | print("error loading the database engine")
106 | exit()
107 |
108 | confirm_next_step = ''
109 |
110 |
111 | print("\033[92m")
112 |
113 | print("All of the data in the database will be deleted past this step")
114 | while confirm_next_step not in ['y', 'n']:
115 | confirm_next_step = input("Are you sure you want to continue? (y/n): ").lower()
116 |
117 | print("\033[0m")
118 |
119 | if confirm_next_step == 'n':
120 | print("Exiting...")
121 | exit()
122 |
123 | animation_thread = threading.Thread(target=loading_animation)
124 | animation_thread.start()
125 |
126 | print('Resetting Database')
127 | reset_database_tables(engine)
128 |
129 |
130 | print('Inserting data')
131 | insert_all_data(engine)
132 |
133 | done = True
134 | animation_thread.join()
135 |
136 | print('DONE')
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Technical Interview Preparation Program 🚀
2 |
3 | Welcome to the Technical Interview Preparation Program repository! 🎉 This comprehensive program is designed to equip you with the knowledge, skills, and confidence to ace your technical interviews and land your dream job in the tech industry. 💼
4 |
5 | ## Table of Contents 📚
6 |
7 | 1. [Introduction](#introduction)
8 | 2. [Chapters](#chapters)
9 |
10 | - [Chapter 1: Technical Interview Preparation Roadmap](#chapter-1-technical-interview-preparation-roadmap)
11 | - [Chapter 2: Sequences](#chapter-2-sequences)
12 | - [Chapter 3: Divide and Conquer Algorithms](#chapter-3-divide-and-conquer-algorithms)
13 | - [Chapter 4: Computational Complexity](#chapter-4-computational-complexity)
14 |
15 | 3. [Getting Started](#getting-started)
16 | 4. [Contributing](#contributing)
17 | 5. [License](#license)
18 |
19 | ## Introduction
20 |
21 | The Technical Interview Preparation Program is a curated collection of resources, tutorials, and practice problems to help you master the essential concepts and techniques required for success in technical interviews. Whether you're a software engineer, data scientist, or a student aspiring to break into the tech industry, this program has something for everyone. 🙌
22 |
23 | ## Chapters
24 |
25 | ### [Chapter 1: Technical Interview Preparation Roadmap](chapter1-roadmap.md)
26 |
27 | In this chapter, we provide a comprehensive roadmap to guide you through the technical interview preparation process. From understanding the interview landscape to developing a strong problem-solving mindset, this chapter lays the foundation for your journey. 🗺️
28 |
29 | ### [Chapter 2: Sequences](chapter2-sequences.md)
30 |
31 | Sequences are a fundamental concept in programming and are frequently encountered in technical interviews. This chapter dives deep into the world of sequences, exploring various data structures, algorithms, and problem-solving techniques. 🧩
32 |
33 | ### [Chapter 3: Divide and Conquer Algorithms](chapter3-divide-and-conquer.md)
34 |
35 | Divide and Conquer is a powerful algorithmic paradigm that breaks down complex problems into smaller, more manageable subproblems. In this chapter, we explore the principles of Divide and Conquer and apply them to solve a range of problems efficiently. ⚔️
36 |
37 | ### [Chapter 4: Computational Complexity](chapter4-computational-complexity.md)
38 |
39 | Understanding computational complexity is crucial for designing efficient algorithms and optimizing code performance. This chapter demystifies the concepts of time and space complexity, Big O notation, and provides techniques for analyzing and optimizing algorithms. 🔬
40 |
41 | 🚧 More chapters are currently in progress and will be added soon! Stay tuned for updates. 🚧
42 |
43 | ## Getting Started
44 |
45 | To get started with the Technical Interview Preparation Program, simply clone this repository to your local machine and explore the chapters in the order that suits your learning style and goals. Each chapter contains detailed explanations, code examples, and practice problems to reinforce your understanding. 💻
46 |
47 | ```bash
48 | git clone https://github.com/skills-cogrammar/Technical-Interview-Preperation.git
49 | ```
50 |
51 | Feel free to customize your learning journey by focusing on the topics that are most relevant to your target roles and companies. Happy learning! 😄
52 |
53 | ## Contributing
54 |
55 | We welcome contributions from the community to make this program even better. If you have suggestions for new topics, examples, or improvements, please feel free to open an issue or submit a pull request. Together, we can create a valuable resource for aspiring tech professionals worldwide. 🌍
56 |
57 | ## License
58 |
59 | This repository is licensed under the [Apache License 2.0](LICENSE). You are free to use, modify, and distribute the content in accordance with the terms and conditions of this license. Please see the LICENSE file for more details. 📜
60 |
61 | Let's embark on this exciting journey of technical interview preparation together! 🚀 Remember, success is not just about reaching the destination, but also about enjoying the process and growing along the way. 🌱
62 |
63 | Happy coding and best of luck with your interviews! 💪
64 |
--------------------------------------------------------------------------------
/Textbook/Chapter 13 - Session Management/readme.md:
--------------------------------------------------------------------------------
1 | # Chapter 13 - Session Management
2 |
3 | Nearly every application now requires you to create an account to access the service, this feature allows for the application experience to be more personalized and/or prevent unauthorised access to sensitive information.
4 |
5 | The distributed nature of modern software presents a few challenges when it comes to ensuring that the interaction between a client and a server is handled correctly. When applications mostly ran natively, the application would only communicate with the server at the initial login and the rest of the operations would be carried out natively, but now, we need constant communication with the server and with each request, the server needs to be aware of who it’s communicating with.
6 |
7 | Session management is responsible for ensuring that the communication between the client and the server is only between specific parties, it ensures that the server is able to identify who is making a request and act accordingly.
8 |
9 | In this chapter, we will take a look at how we can secure the communication between a client application and a server.
10 |
11 | # 13.1 Client Side Rendering
12 |
13 | Client-side rendering is the process of a browser creating HTML elements from JavaScript code. To have client-side rendering, we need to send all of the required code and files from our server to the client-side application.
14 |
15 | Understanding how client-side rendering works allows us to make a few assumptions about the security of our applications.
16 |
17 | Since all of the code that is required for our user-facing application has to be sent to the user's browser we can safely assume that having sensitive connection details like database connections would be a pretty bad idea since anyone who has access to the application would have access to those details.
18 |
19 | To solve the problem, we usually make use of a server for handling all sensitive operations, our servers can securely connect to our databases, internal systems and anything else that we wouldn’t want a user to have access to or knowledge of.
20 |
21 | # 13.2 Access Control
22 |
23 | When building applications that have personalization features or handle sensitive information, it’s important to make sure that there are measures in place that prevent unwanted access to certain resources.
24 |
25 | The two main concepts of access control are **Authentication** and **Authorization.** These two concepts are often used interchangeably, but the truth is that these are two completely different concepts that are concerned with different aspects of what a user can do with a system.
26 |
27 | Authentication is implemented as the first step before the user can access the system, this usually involves some sort of interface where the user enters credentials to gain access to the system.
28 |
29 | Authorization on the other hand is an “invisible” force, the user shouldn’t be able to make changes to their level of access, this is usually done by a third party and the information is stored internally, the user only knows their level of authorization based on how much of the system they can access.
30 |
31 | ## 13.2.1 Authentication
32 |
33 | *Who are you?*
34 |
35 | Authentication is concerned with knowing who the client/user is. We can set restrictions on our application that ensure that only authenticated users can access our platforms, you would be familiar with this when logging into a social media platform, or your company/school's system.
36 |
37 | Authentication is a key part of many modern applications that focus on custom user experiences, this could be social media applications where each user will have their own posts and follow a unique set of people. Authentication is also important for productivity tools like Notion where each person needs to log in to access their notes which are isolated from other users.
38 |
39 | Some common authentication techniques include
40 |
41 | - Password-based authentication
42 | - Most common
43 | - Requires a password and a uniquely identifying field
44 | - Multi-factor authentication
45 | - Built on password-based authentication and requires another thing
46 | - One-time password (OTP)
47 | - Biometric
48 | - Security Question
49 | - Token-based Authentication
50 | - A unique sequence of characters that link to a specific user
51 | - Typically used for HTTP communications
52 | - Common when connecting to APIs (API Keys)
53 |
54 | ## 13.2.2 Authorization
55 |
56 | *What can you do?*
57 |
58 | Authorization as the name implies, is focused on keeping track of what a user is authorized to do.
59 |
60 | Authorization builds on authentication and specifies what each authenticated user can do within the system.
61 |
62 | If you think of a company system, all users can authenticate (log in) the same way, but some users can access more parts of the system than others.
63 |
64 | Authorization is not only important when it comes to setting up your applications, but it’s important for all of the services that you work with, this includes your database services and the operating systems that your application is running on.
65 |
66 | There are a few different approaches to authorization:
67 |
68 | - **Role-based Access Control** (RBAC)
69 | - This is the most popular approach
70 | - Users are broken up into different groups
71 | - Each group will have access to certain features, a user in a group will inherit all of the access while they are part of that group.
72 | - **Discretionary Access Control (DAC)**
73 | - Allows the owner of a resource to grant access to other users
74 | - The owner can grant access to different users or groups
75 | - **Mandatory Access Control (MAC)**
76 | - Access is controlled by a central authority based on pre-defined security labels
77 | - Users and resources are assigned security labels and access is granted based on the label
78 | - **Attribute-Based Access Control (ABAC)**
79 | - Granular approach
80 | - Allows for fine-grained access control based on attributes, resources and environments
81 |
82 | When setting authorization rules, it’s important to be as restrictive as possible, each user/group should only have access to the things that they need, for example, if you are building a database for a business, the sales team would not need to have access to anything other than the sales data and maybe certain parts of the user data, but they would not need to have access to employee details or company revenue data.
83 |
84 | # 13.3 Session Management
85 |
86 | Circling back to the discussion on client-side rendered applications, we know that we can’t have direct access to our databases or other sensitive services from our client application.
87 |
88 | Session management is responsible for ensuring that a client application can let the server know who is trying to access certain resources and it allows the server to send information that is relevant based on the user's identity and authorization.
89 |
90 | ### 13.3.1 HTTP
91 |
92 | HTTP is the most common approach for communication between the client and the server, but it’s important to keep in mind that HTTP is a stateless protocol, this means that every request that is made to a server should be independent of any prior requests, as long as a user include all of the required data for a call, they should get a consistent result.
93 |
94 | Keeping in mind that our server is responsible for all private operations, one would assume that session management would be handled on the server where we can keep track of all of the active users in some sort of database, the problem is that this approach violates the statelessness principle since the server has to store some sort of state that indicates which users are having a session.
95 |
96 | ### 13.3.2 Session Token
97 |
98 | Session tokens are a good tool for keeping track of a user. Session tokens are generated on the server once the user has been authenticated, the process would look something like this:
99 |
100 | 1. The user sends their credentials (email+password, access token, etc)
101 | 2. The server verifies that the details are correct (looking into the database, using a third-party tool)
102 | 3. A token containing identifying information about the user is generated
103 | 4. The token is returned to the client
104 | 5. The client stores the token and sends the token with each request
105 | 6. The server verifies the token is correct and valid before making a response.
106 |
107 | The token-based approach requires the client to store the token in a manner that is both easy to access throughout the application, but also secure, here are a few common places where tokens can be stored on the client side.
108 |
109 | - Cookies
110 | - The server creates a cookie that is sent out to the client, the client application automatically saves this cookie and automatically sends it with every request that is made
111 | - Pros
112 | - Simple to implement
113 | - Widely supported by browsers
114 | - Accessible by client-side JavaScript
115 | - Cons
116 | - Accessible by client-side JavaScript
117 | - Normal cookies can be stolen by Cross Site Scripting (XSS) attacks or when sending through HTTP
118 | - HttpOnly Cookies
119 | - Ensures the normal cookies are secure
120 | - Pros
121 | - Can’t be accessed by client-side JavaScript removing the risk of XSS
122 | - Most secure approach
123 | - Cons
124 | - Requires HTTPS (which isn’t really a con)
125 | - LocalStorage
126 | - Stores information in the memory of the browser and can be accessed by the specific website that stores the data
127 | - Pros
128 | - Able to store a lot of data
129 | - More control over when data is sent since it’s not sent automatically with each request
130 | - Cons
131 | - Requires JavaScript to access making it vulnerable to XSS
132 | - Data is persisted until manually cleaned, when you leave a site and come back, the local storage will still be there.
133 | - Session Storage
134 | - A temporary version of local storage, it only persists the data for a single tab of a given website and clears when that browser tab is closed
135 | - Pros
136 | - Same control of local storage
137 | - The data is cleared once the session ends
138 | - Cons
139 | - All the same as local storage.
140 |
141 | ### 13.3.2 Securing a Session Token
142 |
143 | Whenever data is being transferred over the internet, there are risks, this is true for our session tokens since they need to be passed between the client and the server.
144 |
145 | It’s very important to make sure that our session tokens are kept securely as they determine who a user is and what they can do.
146 |
147 | If a general user's token is stolen, the person who has this token can impersonate them, if you’re building a banking application, you can imagine the problems this could cause. For a company system, if an admin token is stolen, the person who has this token can access sensitive information about the company and make changes to different things within the system.
148 |
149 | ### The Token
150 |
151 | We can start at the lowest level which would be ensuring that the token itself is safe. We want to make sure that the token that is sent out has safety measures that prevent someone from gaining further information if the token is wrongfully accessed, we can do this by:
152 |
153 | - Encrypting the token
154 | - Using a 128-character token is the recommended approach
155 | - This can be done through the use of a [JSON Web Token](https://jwt.io/) (JWT)
156 | - Use a strong `secret` when setting up your JWT
157 | - The `secret` is the password that will be used to encrypt and decrypt your token
158 | - A good approach would be to generate a random key and keep this key secure
159 | - Anyone with the `secret` will be able to decrypt the JWT
160 | - Set the token to expire
161 | - The token should expire after a set amount of time, the life of the token depends on the use case
162 | - Social media login - The token can last for a few months before reauthentication is required
163 | - Work-related - the token can expire after a day before requiring reauthentication
164 | - Banking - The token can expire after a few minutes before requiring reauthentication
165 | - There are more advanced techniques for defining the life of a token
166 | - Limit the amount of information in the token
167 | - Although the encryption of the JWT should protect the information, it’s still important to limit the information that is passed in the token
168 | - Only send
169 | - User ID - for linking the request to a database user
170 | - Role - for faster access to what the user is allowed to do
171 | - Depending on server resources, it would be better to access this through a call to the database, but to reduce the number of calls made to the server, it can be stored in the token.
172 |
173 | ### The communication
174 |
175 | A well-defined token does not mean that the communication is completely safe, even if someone is not able to decrypt the token, it can still be stolen and used allowing the person to make requests as if they are the rightful recipient.
176 |
177 | Session jacking happens when an attacker obtains a user's session token and makes requests to the server pretending to be the original owner of the session. This is one of the reasons why expiring session tokens are important as the attacker will have limited time to do what they want to do before the session expires.
178 |
179 | Like all communication, we need to make sure that an attacker is not able to steal information or add their own information that would undermine the client-server communication.
180 |
181 | Here is how we can secure a user session
182 |
183 | - Force **HTTPS (TLS)** - All communication should be sent through secure HTTPS, this ensures that all traffic is encrypted preventing hackers from seeing any data that is in transit
184 | - Use **HttpOnly Cookies** - These cookies are attached by the server and automatically attached to every request that the user sends.
185 | - These types of cookies cannot be accessed by JavaScript preventing any external scripts that run on the application from accessing the tokens.
186 | - Use **SameSite** attribute for cookies - This defines whether a website requesting on behalf of the client application can send cookies with the request
187 | - **Expires and Max-Age** - This will set the life of the cookies, once the cookie reaches its max-age, it will be cleared requiring the user to authenticate since there would be no token sent with the requests.
188 |
189 | # 13.4 Conclusion
190 |
191 | We have seen how user sessions can be managed and secured, but like all things in tech, the concepts are better understood when seen and done, below are some resources that you can look at for a deeper dive into the security implications as well as some videos that show how these concepts can be applied practically.
192 |
193 | It is highly recommended that you take a look at all of the different topics that are covered on OWASP when developing applications as they keep an updated list of vulnerabilities that are common in different types of applications. They also provide some useful tips on how to secure your applications.
194 |
195 | # Resources
196 |
197 | ### Theory and Articles
198 |
199 | - [https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html](https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html)
200 | - [https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html](https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html)
201 | - [https://www.infosectrain.com/blog/what-is-session-management/](https://www.infosectrain.com/blog/what-is-session-management/)
202 | - [https://www.authgear.com/post/session-management](https://www.authgear.com/post/session-management)
203 |
204 | ### Practical Implementations
205 |
206 | - [**Back to Basics: Managing Your Web Application’s Session**](https://www.youtube.com/watch?v=uRmdTJva7vI)
207 | - [**How Sessions work in Web Servers**](https://www.youtube.com/watch?v=5beyFcuTw20&t=82s)
208 | - [**Session Management Reimagined: What is session management?**](https://www.youtube.com/watch?v=Pjbzvxas4kM)
209 | - [**Web App Pentesting - HTTP Cookies & Sessions**](https://www.youtube.com/watch?v=zHBpJA5XfDk)
210 |
211 | ### Additional Resources
212 |
213 | - [Auth0 - Authentication Service](https://auth0.com/)
214 | - [OAuth](https://oauth.net/2/)
215 | - [JWT](https://jwt.io/)
216 |
--------------------------------------------------------------------------------
/Textbook/Chapter 1: Technical Interview Preparation Roadmap/Chapter 1_ Technical Interview Preparation Roadmap 🚀.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Textbook/Chapter 1: Technical Interview Preparation Roadmap/Chapter 1_ Technical Interview Preparation Roadmap 🚀.pdf
--------------------------------------------------------------------------------
/Textbook/Chapter 1: Technical Interview Preparation Roadmap/README.md:
--------------------------------------------------------------------------------
1 | # Chapter 1: Technical Interview Preparation Roadmap 🚀
2 |
3 | ## 1.1 Introduction 🌟
4 |
5 | Congratulations on taking the first step towards your dream job in the tech industry! 🎉 As you embark on this exciting journey, it's crucial to understand the importance of technical interview preparation. In today's competitive job market, having a solid foundation in technical skills and the ability to showcase them during interviews can make all the difference. 💪
6 |
7 | In this chapter, we'll guide you through the key aspects of the Technical Interview Preparation Program. Our goal is to equip you with the knowledge, strategies, and confidence needed to ace your interviews and land your ideal role. Get ready to dive into a world of problem-solving, portfolio building, and continuous learning! 🌍
8 |
9 | ## 1.2 Key People in the Interview Process 🗝️
10 |
11 | Before we delve into the specifics of technical interview preparation, let's take a moment to understand the key players you'll encounter during the interview process. Each of these individuals plays a distinct role and has specific expectations from candidates.
12 |
13 | ### 1.2.1 Recruiter 🕵️♀️
14 |
15 | Think of the recruiter as the gatekeeper to your dream job. Their primary responsibility is to **identify talented individuals who align with the company's requirements**. To catch a recruiter's attention, you need to ensure that your professional profile, such as your LinkedIn, website, and GitHub, matches the job description.
16 |
17 | Here are some tips to stand out to recruiters:
18 |
19 | - Tailor your professional profile to **highlight relevant skills and experiences** ✨
20 | - **Showcase your projects and achievements** in a clear and concise manner 📊
21 | - Make your work easily accessible through **well-organized repositories and portfolios** 📁
22 |
23 | Remember, recruiters often have to sift through numerous applications, so making a strong first impression is vital. 💥
24 |
25 | ### 1.2.2 The Hiring Manager 👨💼👩💼
26 |
27 | Once you've passed the initial screening by the recruiter, you'll likely encounter the hiring manager. Their role is to **assess whether you possess the necessary skills and experience for the position**. They'll delve deeper into your background, verify the information provided in your application, and gauge your understanding of the role and the company.
28 |
29 | To impress the hiring manager, consider the following:
30 |
31 | - Be prepared to **articulate and expand upon the information on your CV** 📜
32 | - Research the company and demonstrate genuine interest in their mission and products 🔍
33 | - Show a willingness to learn and adapt to new technologies and methodologies 🧠
34 | - Provide **examples of how your skills and experiences align with the role's requirements** 🎯
35 |
36 | Demonstrating a strong fit for the role and the company culture can significantly boost your chances of moving forward in the interview process. 🚀
37 |
38 | ### 1.2.3 The Technical Interviewers 👩💻👨💻
39 |
40 | The final and most crucial stage of the interview process is the technical interview. This is where you'll meet with experienced members of the development or data science team. Their goal is to **assess your problem-solving abilities, technical knowledge, and potential to contribute to the team**.
41 |
42 | To excel in technical interviews, keep these points in mind:
43 |
44 | - Demonstrate a **structured and logical approach** to solving problems 🧩
45 | - **Communicate your thought process** clearly and concisely 💬
46 | - **Justify your implementation choices and discuss trade-offs** ⚖️
47 | - Draw **connections between your past projects and the given scenario or problem** 🔗
48 |
49 | Technical interviewers are looking for candidates who can think critically, communicate effectively, and showcase their skills through practical applications. 💡
50 |
51 | ## 1.3 Developing Your Technical Skills 🛠️
52 |
53 | Now that you understand the key people involved in the interview process, let's shift our focus to developing your technical skills. Continuous learning and skill development are essential for success in the tech industry.
54 |
55 | Here are some recommended areas to focus on (of which some were covered in the bootcamp software engineering and data science curricula):
56 |
57 | - **Data Structures and Algorithms:** Gain a deep understanding of commonly used data structures like _arrays, linked lists, stacks, queues, trees, and graphs_. Practice solving algorithmic problems and analyze their time and space complexity. Some good platforms to practice include _[LeetCode](https://leetcode.com/)_ and _[HackerRank](https://www.hackerrank.com/)_. 📈
58 | - **Databases:** Familiarize yourself with relational databases (e.g., MySQL, PostgreSQL) and NoSQL databases (e.g., MongoDB, Cassandra). Understand concepts like **data modeling, querying, and optimization**. 🗄️
59 | - **Web Development:** Learn the fundamentals of front-end technologies like _HTML, CSS, and JavaScript. Explore web frameworks such as React, Angular, or Vue.js_. Gain knowledge of server-side programming languages like Node.js, Python, or Ruby on Rails. 🌐
60 | - **Machine Learning:** Dive into the world of machine learning algorithms, including _regression, classification, clustering, and neural networks_. Understand the process of _data preprocessing, feature selection, model training, and evaluation_. 🤖
61 | - **Cloud Computing:** Familiarize yourself with cloud platforms like _Amazon Web Services (AWS), Google Cloud Platform (GCP), or Microsoft Azure_. Learn about key services such as storage, compute, and deployment. ☁️
62 |
63 | Remember, the goal is **not to become an expert in every domain but to have a solid foundation in the core concepts and technologies relevant to your desired role**. Focus on building practical skills through hands-on projects and coding exercises. 💪
64 |
65 | ## 1.4 Building Your Portfolio 📁
66 |
67 | In addition to developing your technical skills, **building an impressive portfolio is crucial for showcasing your abilities to potential employers**. Personal projects demonstrate your passion, creativity, and initiative, **setting you apart from other candidates**.
68 |
69 | Here are some project ideas to consider:
70 |
71 | ### Data Science Projects 📊
72 |
73 | - **Kaggle Exploratory Data Analysis:** Participate in Kaggle competitions and perform in-depth exploratory data analysis on real-world datasets. _Share your insights, visualizations, and findings through well-documented notebooks_ 📓. You could do this in a non-competitive way as well through doing your own analysis on datasets you find interesting and simply sharing your findings.
74 | - **Machine Learning Model Optimization:** Choose a machine learning problem and _experiment with different algorithms, hyperparameter tuning, and feature engineering techniques to improve model performance. Document your process and results_ 🧪.
75 | - **Open Source Contributions:** Contribute to open-source data science projects on platforms like GitHub. _Look for opportunities to enhance existing codebases, add new features, or fix bugs_ 🐛. Collaborate with other data enthusiasts and learn from their experiences. 🤝
76 |
77 | ### Software Engineering Projects 💻
78 |
79 | - **Creating APIs:** Build RESTful APIs using frameworks like _Express.js, Flask, or Django_. Design intuitive endpoints, implement authentication and authorization, and document your API using tools like Swagger. 🔒
80 | - **Developing Desktop Applications:** Create desktop applications using Python's Tkinter library or Java's JavaFX. _Develop user-friendly interfaces and implement functionality that solves real-world problems_ 🖥️.
81 | - **Building Social Media Bots:** Leverage the APIs provided by social media platforms to _build bots that automate tasks, analyze data, or engage with users_ 🤖. Explore libraries like Tweepy for Twitter or Facebook's Graph API.
82 |
83 | ### Portfolio Website 🖌️
84 |
85 | In addition to individual projects, create a portfolio website to **showcase your work in a professional and visually appealing manner**. Use platforms like GitHub Pages, Netlify, or Heroku to host your website. Include project descriptions, code snippets, and live demos to give potential employers a comprehensive view of your skills and achievements.
86 |
87 | Remember, the key is to demonstrate your ability to apply the concepts learned in the bootcamp to real-world scenarios. **Choose projects that align with your interests and the roles you aspire to pursue.**
88 |
89 | ## 1.5 Strategies for Impressing Interviewers 🎯
90 |
91 | With your technical skills sharpened and an impressive portfolio in hand, it's time to focus on strategies to impress interviewers. Let's break it down into two key areas: impressing the hiring manager and impressing the technical interviewers.
92 |
93 | ### 1.5.1 Impressing the Hiring Manager 👨💼👩💼
94 |
95 | When meeting with the hiring manager, your goal is to demonstrate your **fit for the role and the company**. Here are some tips to make a lasting impression:
96 |
97 | - **Be consistent with your CV:** Ensure that the information you provide during the interview aligns with what's mentioned in your CV. _Be prepared to elaborate on your experiences and achievements_ 🗣️.
98 | - **Demonstrate a desire to learn:** Show enthusiasm for _acquiring new skills and knowledge_ 🌱. Discuss how you stay updated with the latest industry trends and technologies. **A good attitude overrules a pretense of expertise almost every time** 😄.
99 | - **Research the company and role:** Conduct thorough research on the company, its products, and the specific role you're applying for. Demonstrate your understanding of their mission, values, and how you can contribute to their goals. 🔍
100 |
101 | Here's an example of how you can respond to a common question from a hiring manager:
102 |
103 | > Question: I noticed that you don't have experience with [specific technology] mentioned in the job description. How do you plan to address this gap?
104 |
105 | > Answer: While I haven't worked directly with [specific technology], I have experience with [related technology/concept]. I'm a quick learner and have a track record of successfully picking up new technologies on the job. I'm excited about the opportunity to expand my skill set and contribute to the team's success. I've already started exploring [specific technology] through online tutorials and documentation to gain a basic understanding. 🚀
106 |
107 | ### 1.5.2 Impressing the Technical Interviewers 👩💻👨💻
108 |
109 | Technical interviews are your chance to shine and showcase your problem-solving abilities. Here are some strategies to impress the technical interviewers:
110 |
111 | - **Have a problem-solving strategy:** Approach coding questions with a structured and logical mindset. _Break down the problem into smaller subproblems, identify edge cases, and discuss your thought process out loud_ 🧩.
112 | - **Ask clarifying questions:** _Before diving into the solution, ask questions to clarify any ambiguities or assumptions_ ❓. This shows your attention to detail and ability to gather requirements.
113 | - **Communicate your thought process:** As you code, _explain your approach, the trade-offs you're considering, and the reasoning behind your decisions_ 💬. This gives the interviewer insight into your problem-solving skills.
114 | - **Justify your design choices:** Be prepared to discuss _why you chose a particular data structure, algorithm, or design pattern_ 🏗️. Explain the benefits and drawbacks of your approach (Remember big-O complexity? 🙂).
115 |
116 | Here's an example of how you can tackle a coding question during a technical interview:
117 |
118 | > Question: Implement a function that takes a string as input and returns true if it's a palindrome (reads the same forwards and backwards), ignoring case and non-alphanumeric characters.
119 |
120 | > Clarifying Questions:
121 | >
122 | > - Is an empty string considered a palindrome?
123 | > - Should the function handle Unicode characters?
124 | > - Is the input guaranteed to be a string, or should we handle other data types?
125 |
126 | > Solution:
127 | >
128 | > ```python
129 | > def is_palindrome(s):
130 | > # Convert the string to lowercase and remove non-alphanumeric characters
131 | > s = ''.join(c.lower() for c in s if c.isalnum())
132 | >
133 | > # Compare the string with its reverse
134 | > return s == s[::-1]
135 | > ```
136 |
137 | > Explanation:
138 | >
139 | > - First, we convert the string to lowercase and remove all non-alphanumeric characters using a list comprehension and the `isalnum()` method.
140 | > - Then, we compare the modified string with its reverse using slicing (`s[::-1]`).
141 | > - If the modified string is equal to its reverse, it's a palindrome, and we return `True`. Otherwise, we return `False`.
142 | >
143 | > Time Complexity: O(n), where n is the length of the string.
144 | > Space Complexity: O(n) to store the modified string.
145 |
146 | By following these strategies and providing clear explanations, you demonstrate your technical prowess and leave a positive impression on the interviewers. 💪
147 |
148 | ## 1.6 Common Pitfalls and How to Avoid Them ⚠️
149 |
150 | While preparing for technical interviews, it's essential to be aware of common pitfalls that candidates often encounter. Let's discuss a few of them and how you can avoid them:
151 |
152 | - **Lack of role-relevant skills and concepts:** Make sure you have a solid understanding of the skills and concepts relevant to the role you're applying for. Review the job description and research the technologies and methodologies commonly used in that domain. 🔍
153 | - **Inability to explain problem-solving methodology:** Practice articulating your thought process and problem-solving approach. Engage in mock interviews with peers or mentors to gain confidence in communicating your ideas effectively. 🗣️
154 | - **Insufficient depth in theoretical concepts:** While practical skills are crucial, having a strong grasp of theoretical concepts is equally important. Dive deeper into the fundamentals of your domain, whether it's data structures, algorithms, machine learning, or software design principles. 📚
155 | - **Inadequate business-related problem-solving skills:** Understand how your technical skills can be applied to solve real-world business problems. Research case studies and practice problem-solving scenarios that align with the company's domain and challenges. 💼
156 |
157 | By being mindful of these pitfalls and actively working on addressing them, you'll be better prepared to tackle the challenges that come your way during technical interviews. 💪
158 |
159 | ## 1.7 Conclusion 🎉
160 |
161 | Congratulations on making it to the end of this chapter! You're now equipped with the knowledge and strategies to excel in your technical interviews. Remember, the key to success lies in continuous learning, practice, and perseverance.
162 |
163 | Let's recap the main points we covered:
164 |
165 | - Understanding the key people in the interview process and what they look for in candidates 🗝️
166 | - Developing your technical skills in areas such as data structures, algorithms, databases, web development, machine learning, and cloud computing 🛠️
167 | - Building an impressive portfolio through personal projects and open-source contributions 📁
168 | - Strategies for impressing hiring managers and technical interviewers 🎯
169 | - Common pitfalls to avoid during the interview process ⚠️
170 |
171 | As you embark on your journey, remember to stay curious, seek feedback, and never stop learning. The tech industry is constantly evolving, and staying up-to-date with the latest trends and technologies will give you a competitive edge.
172 |
173 | Believe in yourself and your abilities. **You have the potential to make a significant impact in the world of technology.** Stay focused, stay passionate, and most importantly, enjoy the process 😉.
174 |
--------------------------------------------------------------------------------
/Textbook/Chapter 2: Sequences/Chapter 2_ Sequences 🧩.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Textbook/Chapter 2: Sequences/Chapter 2_ Sequences 🧩.pdf
--------------------------------------------------------------------------------
/Textbook/Chapter 3: Divide and Conquer Algorithms/Chapter 3_ Divide and Conquer 🏹.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Textbook/Chapter 3: Divide and Conquer Algorithms/Chapter 3_ Divide and Conquer 🏹.pdf
--------------------------------------------------------------------------------
/Textbook/Chapter 3: Divide and Conquer Algorithms/README.md:
--------------------------------------------------------------------------------
1 | # Chapter 3: Divide and Conquer 🏹
2 |
3 | ## 3.1 Introduction 🌟
4 |
5 | Welcome to the fascinating world of Divide and Conquer! 🎉 In this chapter, we'll explore one of the most powerful problem-solving techniques in software engineering and data science. Divide and Conquer is a paradigm that allows us to tackle complex problems by breaking them down into smaller, more manageable subproblems. By solving these subproblems recursively and combining their solutions, we can efficiently solve the original problem. 💪
6 |
7 | Divide and Conquer has wide-ranging applications, from efficient sorting and searching algorithms to optimization problems and parallel computing. Whether you're a software engineer building scalable systems or a data scientist analyzing large datasets, understanding and applying Divide and Conquer will be a valuable tool in your arsenal. 🛠️
8 |
9 | So, let's embark on this exciting journey and uncover the power of Divide and Conquer! 🚀
10 |
11 | ## 3.2 Understanding Divide and Conquer 💡
12 |
13 | At its core, Divide and Conquer consists of three key steps:
14 |
15 | 1. **Divide**: Break down the problem into smaller subproblems of the same type.
16 | 2. **Conquer**: Solve each subproblem recursively.
17 | 3. **Combine**: Combine the solutions of the subproblems to obtain the solution to the original problem.
18 |
19 | The beauty of Divide and Conquer lies in its recursive nature. By repeatedly dividing the problem into smaller subproblems until they become simple enough to solve directly, we can efficiently tackle complex problems. 🌿
20 |
21 | To illustrate this concept, let's consider a classic example: finding the maximum element in an array. 🔍
22 |
23 | ```python
24 | def find_max(arr):
25 | # Base case: if the array has only one element, return it
26 | if len(arr) == 1:
27 | return arr[0]
28 |
29 | # Divide the array into two halves
30 | mid = len(arr) // 2
31 | left_half = arr[:mid]
32 | right_half = arr[mid:]
33 |
34 | # Conquer: recursively find the maximum in each half
35 | left_max = find_max(left_half)
36 | right_max = find_max(right_half)
37 |
38 | # Combine: return the maximum of the two halves
39 | return max(left_max, right_max)
40 | ```
41 |
42 | In this example, we divide the array into two halves, recursively find the maximum element in each half, and then combine the results by returning the maximum of the two halves. This approach reduces the problem size by half at each recursive step, leading to an efficient solution. 💪
43 |
44 | ## 3.3 Analyzing Divide and Conquer Algorithms 🔍
45 |
46 | To analyze the efficiency of Divide and Conquer algorithms, we often use recurrence relations. A recurrence relation is an equation that describes the running time of an algorithm in terms of its input size. 📈
47 |
48 | For example, let's consider the recurrence relation for the Merge Sort algorithm:
49 |
50 | ```
51 | T(n) = 2T(n/2) + O(n)
52 | ```
53 |
54 | This recurrence states that the running time of Merge Sort on an input of size n is equal to the time taken to solve two subproblems of size n/2 (the Divide step), plus the time taken to merge the sorted subarrays (the Combine step), which is O(n).
55 |
56 | To solve recurrence relations and determine the time complexity of Divide and Conquer algorithms, we can use the Master Theorem. The Master Theorem provides a general formula for solving recurrences of the form:
57 |
58 | ```
59 | T(n) = aT(n/b) + f(n)
60 | ```
61 |
62 | where a ≥ 1, b > 1, and f(n) is an asymptotically positive function.
63 |
64 | The Master Theorem states that the solution to the recurrence depends on the relationship between the terms a, b, and f(n). It provides three cases:
65 |
66 | 1. If f(n) = O(n^(log_b(a) - ε)) for some constant ε > 0, then T(n) = Θ(n^log_b(a)).
67 | 2. If f(n) = Θ(n^log_b(a)), then T(n) = Θ(n^log_b(a) \* log(n)).
68 | 3. If f(n) = Ω(n^(log*b(a) + ε)) for some constant ε > 0, and if a * f(n/b) ≤ c \_ f(n) for some constant c < 1 and sufficiently large n, then T(n) = Θ(f(n)).
69 |
70 | By applying the Master Theorem, we can determine the time complexity of Divide and Conquer algorithms based on the recurrence relation they follow. 🎯
71 |
72 | ## 3.4 Classic Divide and Conquer Algorithms 🌈
73 |
74 | Now, let's explore some classic Divide and Conquer algorithms that showcase the power and efficiency of this paradigm.
75 |
76 | ### Merge Sort 🔢
77 |
78 | Merge Sort is a sorting algorithm that follows the Divide and Conquer approach. It divides the input array into two halves, recursively sorts each half, and then merges the sorted halves to obtain the final sorted array.
79 |
80 | Here's the pseudocode for Merge Sort:
81 |
82 | ```
83 | MergeSort(arr):
84 | if len(arr) <= 1:
85 | return arr
86 | mid = len(arr) // 2
87 | left_half = MergeSort(arr[:mid])
88 | right_half = MergeSort(arr[mid:])
89 | return Merge(left_half, right_half)
90 |
91 | Merge(left, right):
92 | result = []
93 | i = j = 0
94 | while i < len(left) and j < len(right):
95 | if left[i] <= right[j]:
96 | result.append(left[i])
97 | i += 1
98 | else:
99 | result.append(right[j])
100 | j += 1
101 | result.extend(left[i:])
102 | result.extend(right[j:])
103 | return result
104 | ```
105 |
106 | Let's step through an example to understand how Merge Sort works:
107 |
108 | ```
109 | Input: [8, 4, 2, 1, 7, 5, 6, 3]
110 |
111 | Divide:
112 | [8, 4, 2, 1] | [7, 5, 6, 3]
113 | [8, 4] | [2, 1] | [7, 5] | [6, 3]
114 | [8] | [4] | [2] | [1] | [7] | [5] | [6] | [3]
115 |
116 | Conquer (Recursive Sorting):
117 | [4, 8] | [1, 2] | [5, 7] | [3, 6]
118 | [1, 2, 4, 8] | [3, 5, 6, 7]
119 |
120 | Combine (Merge):
121 | [1, 2, 3, 4, 5, 6, 7, 8]
122 |
123 | Output: [1, 2, 3, 4, 5, 6, 7, 8]
124 | ```
125 |
126 | Merge Sort has a time complexity of O(n log n) in all cases (best, average, and worst) because it always divides the input into two halves and performs a linear-time merge operation. The space complexity is O(n) due to the auxiliary space required for merging. 🌟
127 |
128 | ### Quick Sort 🚀
129 |
130 | Quick Sort is another efficient sorting algorithm that follows the Divide and Conquer paradigm. It selects a pivot element from the array and partitions the other elements into two subarrays, according to whether they are less than or greater than the pivot. The subarrays are then recursively sorted.
131 |
132 | Here's the pseudocode for Quick Sort:
133 |
134 | ```
135 | QuickSort(arr, low, high):
136 | if low < high:
137 | pivot_index = Partition(arr, low, high)
138 | QuickSort(arr, low, pivot_index - 1)
139 | QuickSort(arr, pivot_index + 1, high)
140 |
141 | Partition(arr, low, high):
142 | pivot = arr[high]
143 | i = low - 1
144 | for j = low to high - 1:
145 | if arr[j] <= pivot:
146 | i += 1
147 | Swap(arr[i], arr[j])
148 | Swap(arr[i + 1], arr[high])
149 | return i + 1
150 | ```
151 |
152 | Let's walk through an example to see Quick Sort in action:
153 |
154 | ```
155 | Input: [8, 4, 2, 1, 7, 5, 6, 3]
156 |
157 | Partition:
158 | Pivot = 3
159 | [2, 1, 3, 4, 7, 5, 6, 8]
160 |
161 | Pivot = 6
162 | [2, 1, 3, 4, 5, 6, 7, 8]
163 |
164 | Conquer (Recursive Sorting):
165 | [2, 1] | [3, 4, 5] | [7, 8]
166 |
167 | [1, 2] | [3, 4, 5] | [7, 8]
168 |
169 | Combine:
170 | [1, 2, 3, 4, 5, 6, 7, 8]
171 |
172 | Output: [1, 2, 3, 4, 5, 6, 7, 8]
173 | ```
174 |
175 | The time complexity of Quick Sort depends on the choice of pivot and the partitioning strategy. On average, Quick Sort has a time complexity of O(n log n). However, in the worst case, when the pivot selection is not balanced, the time complexity can degrade to O(n^2). The space complexity is O(log n) due to the recursive calls. 🚀
176 |
177 | ### Binary Search 🎯
178 |
179 | Binary Search is a Divide and Conquer algorithm used to efficiently search for a target element in a sorted array. It repeatedly divides the search interval in half by comparing the middle element with the target until the target is found or the interval is empty.
180 |
181 | Here's the pseudocode for Binary Search:
182 |
183 | ```
184 | BinarySearch(arr, target):
185 | low = 0
186 | high = len(arr) - 1
187 | while low <= high:
188 | mid = (low + high) // 2
189 | if arr[mid] == target:
190 | return mid
191 | elif arr[mid] < target:
192 | low = mid + 1
193 | else:
194 | high = mid - 1
195 | return -1
196 | ```
197 |
198 | Let's see Binary Search in action with an example:
199 |
200 | ```
201 | Input:
202 | arr = [2, 4, 6, 8, 10, 12, 14, 16]
203 | target = 10
204 |
205 | Search:
206 | low = 0, high = 7, mid = 3
207 | arr[3] = 8 < 10, low = mid + 1 = 4
208 |
209 | low = 4, high = 7, mid = 5
210 | arr[5] = 12 > 10, high = mid - 1 = 4
211 |
212 | low = 4, high = 4, mid = 4
213 | arr[4] = 10 == 10, return mid
214 |
215 | Output: 4
216 | ```
217 |
218 | Binary Search has a time complexity of O(log n) since it eliminates half of the search space in each iteration. The space complexity is O(1) as it only uses a constant amount of extra space. 🎉
219 |
220 | ### Strassen's Matrix Multiplication ✖️
221 |
222 | Strassen's algorithm is a Divide and Conquer algorithm for matrix multiplication that improves upon the traditional naive approach. The naive approach multiplies two n x n matrices using nested loops, resulting in a time complexity of O(n^3).
223 |
224 | Strassen's algorithm, on the other hand, divides the matrices into smaller submatrices, recursively computes seven matrix multiplications, and combines the results to obtain the final product matrix. By reducing the number of recursive multiplications, Strassen's algorithm achieves a time complexity of approximately O(n^2.8074).
225 |
226 | Here's a high-level overview of Strassen's algorithm:
227 |
228 | ```
229 | StrassenMultiply(A, B):
230 | if A and B are 1x1 matrices:
231 | return A \* B
232 | else:
233 | Divide A and B into 2x2 submatrices
234 | Compute 7 matrix multiplications recursively using the submatrices
235 | Combine the results of the 7 multiplications to obtain the final product matrix
236 | ```
237 |
238 | While the implementation details of Strassen's algorithm are beyond the scope of this chapter, it's important to understand its significance in improving the efficiency of matrix multiplication for large matrices. 🔥
239 |
240 | ## 3.5 Applying Divide and Conquer to Problem-Solving 🎯
241 |
242 | Now that we've explored some classic Divide and Conquer algorithms, let's discuss how to apply this paradigm to solve problems effectively.
243 |
244 | ### Recognizing Divide and Conquer Problems 🧐
245 |
246 | To apply Divide and Conquer, you need to identify problems that exhibit the following characteristics:
247 |
248 | 1. The problem can be divided into smaller subproblems of the same type.
249 | 2. The subproblems can be solved independently and recursively.
250 | 3. The solutions to the subproblems can be combined to solve the original problem.
251 |
252 | Some common problem domains where Divide and Conquer is applicable include:
253 |
254 | - Sorting and searching
255 | - Optimization problems
256 | - Graph algorithms
257 | - Geometric algorithms
258 | - Numerical algorithms
259 |
260 | ### Designing Divide and Conquer Algorithms 🎨
261 |
262 | When designing a Divide and Conquer algorithm, follow these steps:
263 |
264 | 1. **Identify subproblems and base cases**: Determine how to divide the problem into smaller subproblems and define the base cases that can be solved directly.
265 |
266 | 2. **Define the recursive structure**: Express the solution to the problem in terms of solutions to smaller subproblems.
267 |
268 | 3. **Combine subproblem solutions**: Specify how to combine the solutions of the subproblems to obtain the solution to the original problem.
269 |
270 | Let's design a Divide and Conquer algorithm to find the maximum subarray sum in an array of integers. 💪
271 |
272 | ```python
273 | def max_subarray_sum(arr):
274 | # Base case: if the array has only one element, return it
275 | if len(arr) == 1:
276 | return arr[0]
277 |
278 | # Divide the array into two halves
279 | mid = len(arr) // 2
280 | left_half = arr[:mid]
281 | right_half = arr[mid:]
282 |
283 | # Conquer: recursively find the maximum subarray sum in each half
284 | left_sum = max_subarray_sum(left_half)
285 | right_sum = max_subarray_sum(right_half)
286 |
287 | # Find the maximum subarray sum crossing the midpoint
288 | cross_left_sum = cross_right_sum = 0
289 | left_max = right_max = float('-inf')
290 | for i in range(mid - 1, -1, -1):
291 | cross_left_sum += arr[i]
292 | left_max = max(left_max, cross_left_sum)
293 | for i in range(mid, len(arr)):
294 | cross_right_sum += arr[i]
295 | right_max = max(right_max, cross_right_sum)
296 | cross_sum = left_max + right_max
297 |
298 | # Combine: return the maximum of the three sums
299 |
300 | return max(left_sum, right_sum, cross_sum)
301 | ```
302 |
303 | In this algorithm, we divide the array into two halves, recursively find the maximum subarray sum in each half, and also consider the possibility of the maximum subarray crossing the midpoint. We then return the maximum of the three sums. 🌟
304 |
305 | ### Optimizing Divide and Conquer Algorithms ⚡
306 |
307 | While Divide and Conquer algorithms are efficient, there are techniques to optimize them further:
308 |
309 | 1. **Memoization**: Store the results of solved subproblems to avoid redundant computations.
310 |
311 | 2. **Dynamic Programming**: Build solutions to larger subproblems iteratively by combining solutions to smaller subproblems.
312 |
313 | By incorporating memoization or dynamic programming, you can eliminate duplicate subproblem computations and improve the overall efficiency of your Divide and Conquer algorithms. 🚀
314 |
315 | ## 3.6 Divide and Conquer in Action 🌍
316 |
317 | Divide and Conquer has numerous real-world applications across various domains. Let's explore a few examples:
318 |
319 | 1. **Efficient searching in large datasets**: Divide and Conquer algorithms like Binary Search enable efficient searching in large sorted datasets, such as database indexes or phone directories. 📞
320 |
321 | 2. **Parallel and distributed computing**: Divide and Conquer is well-suited for parallel and distributed computing environments. By dividing tasks into smaller subtasks that can be processed independently, you can leverage the power of multiple processors or machines to solve problems faster. 🖥️
322 |
323 | 3. **Image and signal processing**: Divide and Conquer techniques are used in image and signal processing algorithms, such as Fast Fourier Transform (FFT) and image compression algorithms like QuadTree. These algorithms efficiently process large amounts of data by recursively dividing and conquering subproblems. 📸
324 |
325 | In coding interviews, Divide and Conquer problems are common, as they test your ability to break down complex problems and design efficient algorithms. Here are a few examples of interview questions that can be solved using Divide and Conquer:
326 |
327 | 1. **Merge k Sorted Lists**: Given an array of k linked lists, each sorted in ascending order, merge all the lists into one sorted linked list.
328 |
329 | 2. **Kth Largest Element in an Array**: Find the kth largest element in an unsorted array.
330 |
331 | 3. **Closest Pair of Points**: Given a set of points in a 2D plane, find the pair of points with the smallest Euclidean distance.
332 |
333 | When approaching these problems, break them down into smaller subproblems, solve them recursively, and combine the results to obtain the final solution. Discuss your thought process with the interviewer and optimize your algorithms when possible. 💡
334 |
335 | ## 3.7 Advanced Topics and Extensions 🚀
336 |
337 | Divide and Conquer is a versatile paradigm that extends to various advanced topics and problem domains. Let's briefly explore a few of them:
338 |
339 | 1. **Randomized algorithms**: Randomized algorithms incorporate randomness into the Divide and Conquer approach. Examples include Randomized Quick Sort and Karger's algorithm for finding minimum cuts in graphs. 🎲
340 |
341 | 2. **Geometric algorithms**: Divide and Conquer is used in many geometric algorithms, such as finding the closest pair of points, constructing Voronoi diagrams, and performing range queries efficiently. 📐
342 |
343 | 3. **Optimization problems**: Divide and Conquer can be applied to optimization problems, such as the Knapsack problem and the Longest Common Subsequence problem. By dividing the problem into smaller subproblems and combining their solutions, you can find the optimal solution efficiently. 🎯
344 |
345 | These advanced topics demonstrate the power and flexibility of Divide and Conquer in tackling complex problems across different domains. 💪
346 |
347 | ## 3.8 Conclusion 💫
348 |
349 | Congratulations on making it through this chapter on Divide and Conquer! 🎉 You've learned the fundamental concepts, analyzed algorithms, and explored real-world applications of this powerful problem-solving technique.
350 |
351 | To recap, Divide and Conquer involves breaking down a problem into smaller subproblems, solving them recursively, and combining their solutions to solve the original problem. By analyzing recurrence relations and applying the Master Theorem, you can determine the time complexity of Divide and Conquer algorithms.
352 |
353 | We explored classic algorithms like Merge Sort, Quick Sort, Binary Search, and Strassen's Matrix Multiplication, which showcase the efficiency and elegance of Divide and Conquer. We also discussed how to recognize problems suitable for Divide and Conquer, design algorithms, and optimize them using techniques like memoization and dynamic programming.
354 |
355 | Remember, mastering Divide and Conquer takes practice and perseverance. Keep exploring new problems, analyzing algorithms, and applying the concepts you've learned. With time and effort, you'll become a proficient problem solver and tackle complex challenges with confidence. 💪
356 |
357 | So, go forth and conquer! 🌟 Happy coding! 💻
358 |
--------------------------------------------------------------------------------
/Textbook/Chapter 4: Computational Complexity/Chapter 4_ Computational Complexity 🧩.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Textbook/Chapter 4: Computational Complexity/Chapter 4_ Computational Complexity 🧩.pdf
--------------------------------------------------------------------------------
/Textbook/Chapter 5 - Constant Time Storage and Access/assets/image-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Textbook/Chapter 5 - Constant Time Storage and Access/assets/image-1.png
--------------------------------------------------------------------------------
/Textbook/Chapter 5 - Constant Time Storage and Access/assets/image-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Textbook/Chapter 5 - Constant Time Storage and Access/assets/image-2.png
--------------------------------------------------------------------------------
/Textbook/Chapter 5 - Constant Time Storage and Access/assets/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Textbook/Chapter 5 - Constant Time Storage and Access/assets/image.png
--------------------------------------------------------------------------------
/Textbook/Chapter 6 - Hashing/assets/image-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Textbook/Chapter 6 - Hashing/assets/image-1.png
--------------------------------------------------------------------------------
/Textbook/Chapter 6 - Hashing/assets/image-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Textbook/Chapter 6 - Hashing/assets/image-2.png
--------------------------------------------------------------------------------
/Textbook/Chapter 6 - Hashing/assets/image-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Textbook/Chapter 6 - Hashing/assets/image-3.png
--------------------------------------------------------------------------------
/Textbook/Chapter 6 - Hashing/assets/image-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Textbook/Chapter 6 - Hashing/assets/image-4.png
--------------------------------------------------------------------------------
/Textbook/Chapter 6 - Hashing/assets/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Textbook/Chapter 6 - Hashing/assets/image.png
--------------------------------------------------------------------------------
/Textbook/Chapter 6 - Hashing/code/linear-probing.py:
--------------------------------------------------------------------------------
1 | class HashSet:
2 | def __init__(self, size: int, load_factor: float) -> None:
3 | self.__size = size
4 | self.__filled_spaces = 0
5 | self.__load_factor = 1 if load_factor > 1 else load_factor
6 | self.__internal_array = [None] * size
7 |
8 | def add(self, value: str):
9 | self.__resize_array()
10 |
11 | index = hash
12 | self.__internal_array[index] = value
13 | self.__filled_spaces += 1
14 |
15 |
16 |
17 | def __resize_array(self):
18 | filled_percentage = self.__filled_spaces / self.__size
19 |
20 | if filled_percentage < self.__load_factor:
21 | return
22 |
23 | old_values = [value for value in self.__internal_array if value is not None]
24 |
25 | self.__size = self.__size * 2
26 | self.__internal_array = [None] * self.__size
27 |
28 | for value in old_values:
29 | self.add(value)
30 |
31 | def contains(self, value: str):
32 | index = self.__hash(value)
33 | index = self.__linear_probing_search(index, value)
34 | return index > -1
35 |
36 | def __linear_probing_search(self, index, value, count=0):
37 | if self.__internal_array[index] == value:
38 | return index
39 |
40 | if count == self.__size:
41 | return -1
42 |
43 | if index == self.__size - 1:
44 | index = -1
45 |
46 | return self.__linear_probing_search(index + 1, value, count + 1)
47 |
48 |
49 | def __hash(self, value: str):
50 | ascii_values = sum([ord(char) for char in value])
51 | return ascii_values % self.__size
52 |
53 | def __linear_probing_insertion(self, index):
54 | if self.__internal_array[index] is None:
55 | return index
56 |
57 | print("collison")
58 |
59 | if (index == self.__size - 1):
60 | index = -1
61 |
62 | return self.__linear_probing_insertion(index + 1)
63 |
64 |
65 |
66 |
67 | def print_internal_array(self):
68 | return print(self.__internal_array)
69 |
70 |
71 |
72 |
73 | my_set = HashSet(4, 0.75)
74 |
75 | for fruit in ["apple", "banana", "orange", "pear", "mango", "grape", "strawberry"]:
76 | my_set.add(fruit)
77 |
78 | my_set.print_internal_array()
79 |
--------------------------------------------------------------------------------
/Textbook/Chapter 6 - Hashing/readme.md:
--------------------------------------------------------------------------------
1 | # Chapter 6 Hashing
2 | ## 6.1 Introduction
3 | We’ve looked at lists and arrays and saw how useful they are at storing collections of related data, but while looking at complexity, we saw that a lot of operations for lists and arrays are performed at an O(n) time complexity which is not ideal for some situations.
4 |
5 | Hashing data structures are built on top of linear data structures and make operations like reading, writing and deleting a lot more efficient, offering a constant time complexity for each of these operations.
6 |
7 | You might be familiar with dictionaries and sets in Python, these are two examples of how hashing algorithms are implemented in code, but we will be diving a bit deeper and understanding how we can create our own hashing data structures so that we can answer interview questions on this topic.
8 | ## 6.2 Revisiting Linear Data Structures
9 | There are two data structures that we commonly use when we want to store data, the list and the array. The two are often incorrectly used interchangeably, but there are fundamental differences between the two.
10 |
11 | ### 6.2.1 Arrays
12 | An array stores an ordered collection of values, when we declare an array, we need to specify the max size of the array and the data type of the values that we are going to be storing.
13 |
14 | We cannot add or remove items from our array, we can only reference and update the indexes. If we were to declare an array of integers with a length of 5, it could be visually represented like this:
15 |
16 | | Index | Value | |
17 | | ----- | ----- | --- |
18 | | 0 | 0 | |
19 | | 1 | 0 | |
20 | | 2 | 0 | |
21 | | 3 | 0 | |
22 | | 4 | 0 | |
23 | Python does not support the array, but it's important to know about it as it is part of many other languages and will be key to how we perform hashing.
24 |
25 | We can take a look at how an array would be implemented in C# just as a reference
26 | ```c#
27 | public void main(string[] args)
28 | {
29 | int[] numbers = int[10]; // Declaring an array of integers of size 10
30 |
31 | numbers[0] = 10; // setting the value of the first index to 10
32 | WriteLine(number[1].ToString()); // returns 0, primitive values can't be null
33 | }
34 | ```
35 |
36 | ### 6.2.2 List
37 | A list can be defined as a dynamic array. Unlike an array, we don't need to declare the max size of our list when we create the object, the list will grow and shrink as we add and remove items.
38 |
39 | The dynamic nature of the list is good as it allows us to work on problems where we don't know the total number of values that we are going to work with, this removes the overhead that might come with allocating a lot of space to an array and not using all of the preallocated spaces.
40 |
41 | ```python
42 | my_list = []
43 | my_list.append("1")
44 | my_list.append("2")
45 | my_list.append("3")
46 | my_list.append("4")
47 |
48 | print(my_list[2]) # returns 3
49 | ```
50 |
51 | ### 6.2.3 Accessing Values
52 | Arrays and lists can be very efficient at some operations. Inserting values into a list can be an O(1) operation if we are adding values to the end of the list, deletes can also be O(1) when we are removing from the end of the list. These operations are constant because we don't have to shift the values that come after when we do an insert or delete.
53 |
54 | Another operation that is constant time for both arrays and lists, is getting a specific value at a given index, this will always be an O(1) operation.
55 |
56 | So we can see that there are a few ways to get values at a constant time complexity with these two data structures, but we can also see that the conditions need to be perfect in order for us to use these efficiencies. What if we wanted to delete an item in the 4th position in a list of 10000 items, we would need to shift the remaining 9996 items one place up.
57 |
58 | Now imagine that we are looking for a specific value to delete, assuming our list is not ordered, we would firstly need to search for it, which would be O(n), and then deleting it would be another O(n), so ultimately, if we used the RAM model to evaluate the algorithm, we would find that the fastest growing term would be 2n.
59 | ## 6.3 What is a Hashing Data Structure
60 | It turns out that there is a way for us to make working with linear data structures more efficient. When we were talking about the fast operations of an array and list, we mentioned that getting a value at a specific index will always be O(1), but the problem with this is that we would need to know the index of the value that looking for, so we will end up working with an O(n) search in order to make use of the O(1) access.
61 |
62 | This is where hashing comes in. Hashing takes a value, performs some operations on the value and returns an index where the value can be stored in an array.
63 |
64 | This hashing operations basically serves as our search, but since it will be some constant time calculation to find the index, we will have an O(1) search before being able to make use of the O(1) access of the array.
65 |
66 | ### 6.4 Creating a hashing data structure
67 | A hashing data structure is made up of two main parts, the internal array that will store the values and the hash function that is responsible for transforming the value into an index before it can be stored in the internal array.
68 |
69 | #### 6.4.1 Internal Array
70 | In most cases, we will use an actual array of a fixed size as our internal array, this is important as part of our hash function, we need to consider the maximum size of the array so that we can get indexes that will fall into our array size, we don't want to have a situation where we get an index of 20 in an array of 10 items.
71 |
72 | #### 6.4.2 Hash Function
73 | This is the function that will convert our value into an index for the internal array. The algorithm that is used for the hash is up to you as the programmer, but the final output should be an integer that can be used to reference the internal array.
74 |
75 | #### 6.4.3 Implementing a Hashing Data Structure
76 | The first steps to creating a hashing data structure is creating the internal array and determining our strategy for hashing our inputs.
77 |
78 | #### 6.4.3.1 Simple Hashing
79 | Given the following list of string values, ["apple", "orange", "banana", "grape"], we can take the following approach to hash them.
80 |
81 | 1. Create an internal array of size 4
82 | 2. Knowing that we need to generate a number from the strings in our hash function, get the ASCII value of each character and perform a calculation from there (yes technically this will be O(n), but there are other more advanced techniques for hashing strings, we will pretend like this is efficient for this example).
83 |
84 | [ASCII TABLE](https://www.asciitable.com/)
85 |
86 | 
87 | - Get the input value
88 | - Add up the ASCII values of each character
89 | - a = 97, p = 112, l = 108, e = 101
90 | - 97 + 112 + 112 + 108 + 101 = 530
91 | - Use the modulo operator on the sum of the characters
92 | - 530%4 = 2
93 | - The result will be the index in our array
94 | - insert the value to the index in the array
95 |
96 | We can carry on the same process for the rest of the items:
97 | 
98 |
99 | 
100 |
101 | 
102 |
103 |
104 |
105 | #### 6.4.4 Handling Collisions
106 | As you can imagine, there will be a point where the value we get from our hash function has already been taken in our internal array, this is referred to as a hash collision.
107 |
108 | A hash collision occurs when two or more values return the same result from our hashing function. Finding an algorithm that minimises the chances of a hash collision is the biggest challenge that you will encounter when building a hashing data structure from scratch, it's important that you know the values that might be stored as this can guide you in creating your function.
109 |
110 | Another technique that would help reduce hash collisions would be to increase the size of the internal array, as we saw previously, we will use use the modulo operator against the length of the internal array. If we increase the size of the internal array, we are reducing the chances of two values landing on the same spot.
111 |
112 | Although we can minimise the chances of hash collisions, we can never be 100% sure that our algorithm completely rules out the possibility of collisions taking place, for this reason, we need to put measures in place to make sure that collisions are resolved.
113 |
114 | To resolve collisions, there are two main approaches that we can take, Open Addressing and Closed Addressing.
115 |
116 | #### 6.4.4.1 Open Addressing (Closed Hashing)
117 | With open addressing, when we have a collision, we will look for another open lot within our internal array using some approach.
118 |
119 | Some common approaches for open addressing include:
120 | - Linear Probing
121 | - Quadratic Probing
122 | - Double Hashing
123 |
124 | Linear probing is the most popular approach and it involves finding the next open slot to the right of where there is a collision.
125 |
126 | ![[Pasted image 20240601154738.png]]
127 | If we get to a point where there are no values to the right, we will wrap around to the start of the array and find an open slot from there.
128 |
129 | **Pros of Open Addressing**
130 | - We are able to use up all of the open memory slots in our internal array
131 |
132 | **Cons of Open Addressing**
133 | - If two values collide early, one of them will take the position of another value, leading to a higher possibility of further collisions.
134 |
135 | #### 6.4.4.2 Closed Addressing (Open Hashing)
136 | This approach is often referred to as chaining, the process involves storing any values that have collisions within a list (typically a linked list) at their correct index. Unlike Closed addressing, chaining guarantees that the values will be at their correct index in the internal array.
137 |
138 | ![[Pasted image 20240601155938.png]]
139 |
140 | **Pros of Closed Addressing**
141 | It reduces the possibility of having cascading collisions as every value will be at it's correct index in the internal array.
142 |
143 | **Cons**
144 | This approach will use more memory than open addressing as a new object is created every time there is a collision. It will also result in a lot of open slots in our internal array
145 |
146 |
147 | #### 6.4.5 Memory Allocation
148 | Since we are working with a fixed size internal array, we are likely to run out of free slots within our internal array especially when we are working with open addressing, we need a way to handle this.
149 |
150 | To make sure that our hash data structure never runs out of open slots, we can resize the array. Before we go any further, you might be thinking that this is the point where we bring lists into the equation, but the truth is that lists have no real place in hashing data structures. Because we are not able to manually set an index when we add a value, the list would not be feasible.
151 |
152 | ##### 6.4.5.1 Loading Factor
153 | When resizing our array, we usually include an attribute known as the loading factor, the loading factor is a value between 0 - 1 that will let us know when to resize our array based on the percentage of space being used.
154 |
155 | ##### 6.4.5.2 Resizing
156 | Resizing an array can be an intense process, if you think back to the algorithm being used, it's dependent on the size of the array, changing the size of our array will mean that the old hashes would be wrong, so we would need to rehash all of the values so that they can be correct in the resized array.
157 |
158 | We can resize our arrays when the percentage of slots in use are equal to or greater than the loading factor.
159 | ##### 6.4.5.3 Open Addressing vs Closed Addressing
160 | As you can imagine, we are more likely to run into situations where we need to resize our array when working with open addressing, unlike closed addressing where we can continue adding values even if we have run out of open slots, open addressing demands that a new array be created.
161 |
162 | But keep in mind that not resizing a closed addressing approach would result in a lot of O(n) operations.
163 |
164 | ### 6.5 Findings
165 | If you have been thinking about the time complexity of a hash table or hash set being O(1) throughout this chapter, you might be a little bit confused as to how a data structure that can potentially have O(n) operations is considered O(1)?
166 |
167 | The truth about hashing data structures is that they have an average case complexity of O(1), so most of the operations that are performed will be O(1), but there is a worst case of O(n) when we run into collisions, and when we need to resize the array.
168 |
169 | We generally use the average case in this instance since a good algorithm will heavily reduce the number of collisions that might occur.
170 |
171 | #### 6.5.1 Creating a Hashing Data Structure
172 | Lets take a look at how can create our own hashing data structure using linear probing.
173 |
174 | *For the examples, we will be creating a hash set, to create a hash table, you would just need to take in an additional argument as the value to be stored alongside the key (can you store the values in a tuple within the array)*
175 | ```python
176 | class HashSet:
177 | def __init__(self, size: int, load_factor: float) -> None:
178 | self.__size = size
179 | self.__filled_spaces = 0
180 | self.__load_factor = 1 if load_factor > 1 else load_factor
181 | self.__internal_array = [None] * size
182 |
183 | def add(self, value: str):
184 | self.__resize_array()
185 |
186 | index = hash
187 | self.__internal_array[index] = value
188 | self.__filled_spaces += 1
189 |
190 |
191 |
192 | def __resize_array(self):
193 | filled_percentage = self.__filled_spaces / self.__size
194 |
195 | if filled_percentage < self.__load_factor:
196 | return
197 |
198 | old_values = [value for value in self.__internal_array if value is not None]
199 |
200 | self.__size = self.__size * 2
201 | self.__internal_array = [None] * self.__size
202 |
203 | for value in old_values:
204 | self.add(value)
205 |
206 | def contains(self, value: str):
207 | index = self.__hash(value)
208 | index = self.__linear_probing_search(index, value)
209 | return index > -1
210 |
211 | def __linear_probing_search(self, index, value, count=0):
212 | if self.__internal_array[index] == value:
213 | return index
214 |
215 | if count == self.__size:
216 | return -1
217 |
218 | if index == self.__size - 1:
219 | index = -1
220 |
221 | return self.__linear_probing_search(index + 1, value, count + 1)
222 |
223 |
224 | def __hash(self, value: str):
225 | ascii_values = sum([ord(char) for char in value])
226 | return ascii_values % self.__size
227 |
228 | def __linear_probing_insertion(self, index):
229 | if self.__internal_array[index] is None:
230 | return index
231 |
232 | print("colision")
233 |
234 | if (index == self.__size - 1):
235 | index = -1
236 |
237 | return self.__linear_probing_insertion(index + 1)
238 |
239 |
240 |
241 |
242 | def print_internal_array(self):
243 | return print(self.__internal_array)
244 | ```
245 |
246 | ## 6.6 Further Reading and Resources
247 | 1. Additional learning
248 | - [CS3 Data Structures and Algorithms - OpenDSA](https://opendsa-server.cs.vt.edu/ODSA/Books/CS3/html/index.html)
249 | - [Introduction to Hash Tables and Dictionaries](https://www.youtube.com/watch?v=sfWyugl4JWA)
250 |
251 | 2. Online Courses
252 | - "Algorithms, Part I" and "Algorithms, Part II" by Princeton University on Coursera 🎓
253 | - "Data Structures and Algorithms" Specialization by University of California San Diego on Coursera 🎓
254 | - "Algorithms and Data Structures" by MIT OpenCourseWare 🎓
255 |
256 | 3. Websites and Blogs
257 | - [GeeksforGeeks](https://www.geeksforgeeks.org/)🌐
258 | - [LeetCode](https://leetcode.com/)💻
259 | - [HackerRank](https://www.hackerrank.com/)💻
260 | - [The Algorithms - Python](https://github.com/TheAlgorithms/Python) 🐍
261 |
262 | These resources offer in-depth explanations, coding examples, and practice problems to help you further enhance your understanding of computational complexity and algorithm optimization. 📚
263 |
264 | Remember, the field of algorithms is vast and constantly evolving. Keep exploring, learning, and challenging yourself to become a proficient and efficient problem solver. 🌟
265 |
266 | Happy learning, and may your algorithms be forever optimal! 😄
267 |
--------------------------------------------------------------------------------
/Textbook/Chapter 8 - Persistent Storage/assets/image-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Textbook/Chapter 8 - Persistent Storage/assets/image-1.png
--------------------------------------------------------------------------------
/Textbook/Chapter 8 - Persistent Storage/assets/image-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Textbook/Chapter 8 - Persistent Storage/assets/image-2.png
--------------------------------------------------------------------------------
/Textbook/Chapter 8 - Persistent Storage/assets/image-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Textbook/Chapter 8 - Persistent Storage/assets/image-3.png
--------------------------------------------------------------------------------
/Textbook/Chapter 8 - Persistent Storage/assets/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Textbook/Chapter 8 - Persistent Storage/assets/image.png
--------------------------------------------------------------------------------
/Textbook/Chapter 9 - Web Applications/assets/image-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Textbook/Chapter 9 - Web Applications/assets/image-1.png
--------------------------------------------------------------------------------
/Textbook/Chapter 9 - Web Applications/assets/image-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Textbook/Chapter 9 - Web Applications/assets/image-2.png
--------------------------------------------------------------------------------
/Textbook/Chapter 9 - Web Applications/assets/image-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Textbook/Chapter 9 - Web Applications/assets/image-3.png
--------------------------------------------------------------------------------
/Textbook/Chapter 9 - Web Applications/assets/image-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Textbook/Chapter 9 - Web Applications/assets/image-4.png
--------------------------------------------------------------------------------
/Textbook/Chapter 9 - Web Applications/assets/image-5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Textbook/Chapter 9 - Web Applications/assets/image-5.png
--------------------------------------------------------------------------------
/Textbook/Chapter 9 - Web Applications/assets/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Textbook/Chapter 9 - Web Applications/assets/image.png
--------------------------------------------------------------------------------
/Textbook/Chapter 9 - Web Applications/assets/image1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skills-cogrammar/Technical-Interview-Preperation/7a4d2fa4d50f30d9e7ad2a1e96ca9a47a5cce025/Textbook/Chapter 9 - Web Applications/assets/image1.png
--------------------------------------------------------------------------------