├── 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 | ![alt text](assets/image.png) 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 | ![alt text](assets/image-2.png) 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 | ![alt text](assets/image-4.png) 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 | 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 | ![alt text](image-1.png) 6 | 7 | #### 2 - Select "load from file" 8 | ![alt text](image-2.png) 9 | 10 | #### 3 - Navigate to the directory and select the `Planning.excalidraw` file 11 | ![alt text](image-3.png) -------------------------------------------------------------------------------- /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 | ![alt text](image-1.png) 6 | 7 | #### 2 - Select "load from file" 8 | ![alt text](image-2.png) 9 | 10 | #### 3 - Navigate to the directory and select the `Planning.excalidraw` file 11 | ![alt text](image-3.png) -------------------------------------------------------------------------------- /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 | ![alt text](./assests/image-1.png) 6 | 7 | #### 2 - Select "load from file" 8 | ![alt text](./assests/image-2.png) 9 | 10 | #### 3 - Navigate to the directory and select the `Planning.excalidraw` file 11 | ![alt text](./assests/image-3.png) 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 | ![alt text](./assets/image-1.png) 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 | ![alt text](./assets/image-2.png) 98 | 99 | ![alt text](./assets/image-3.png) 100 | 101 | ![alt text](./assets/image-4.png) 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 --------------------------------------------------------------------------------