Programming
Programming
Programming
Week 0
Theory
Unary – a simple system of using a single symbol to solve some problem, like counting the
number of people in a room.
Binary - is the system that computer use.
Bit – is just 0 and 1
ASCII – the American standard code for information interchange, its mapping for English.it can
store 226 characters
RGB – for every dot(pixels) on your screen a number is representing that.
Algorithm – step by step process for solving some problem
Pseudocode – out line for code
Data type –
o int - takes 32 bits and half of it negative and half of it is positive if you know that the
value is not going to be negative you can use unsigned int
o char – store 1 byte means 8 bits
o float – only have 32 bits to work with
o double – store real number store 64 bits
Array – is a way of storing a data back-to-back to back in a computer memory in such a way that
you can access each individually member easily,
String – when you type hello it is going to take 6 bits why coz it takes one extra bit to separate
the character from the next character
Encryption - convert plaintext into the ciphertext so that other can’t understand the text
Programming - Makes computer complete specific task without making mistakes.
IDE - A place to write, run, and debug code and convert it to machine code, ex - visual studio,
etc.
Console - Programmers keep track of their progress by looking at it, a text interface within the
computer that us programmers can use for a variety of purposes.
String - Another way of saying text, ex - "Hello World".
Algorithm - step by step instructions for solving some problem incarnated in the world of
computers by software.
Source code - Code which human being writes.
Machine code - Computer only understand binary numbers.
Compiler - Convert source code into machine code.
Const - means that thing would never change
To make a file, type: hello code hello[filename].py
To compile your code: python hello[filename].py.
Function: is some action that can easily be run by calling the function name.
Arguments are inputs that we pass into a function in order to manipulate its behavior.
Input, function: takes the input
Return values, function: return the input
Variables are just containers that store some value.
Operator, which helps you operate something, ex. "=", its assignment operator is will, which
means you want to assign from right to left whatever the return value is.
Comments: ignore the input in this thing; use # and even """ in the starting and """ in the ending
if you must write several lines of comments.
Positional parameters: "positional in the sense that the first thing you print gets printed first,
and the second thing you pass to print after a comma gets printed second.
Named parameters are optional, and you can pass them at the end of the print statement, but
you can also use them by their name. Example: Sep = separator; End = line ending.
F - string = if you want to specify the syntax inside the print, ex. print(f "hello, name"), then f
string would know that is some special function.
strip—remove the white space from the string.
capitalize: help you capitalize the first letter of the first word.
title: capitalize the first letter of every word in that string.
Int is just an integer. Take up 4 bytes of memory (32 bits, 8 bits memo byte). We split 32 bits into
negative and positive, getting half. Does not hold decimals
Symbols: +, -, *, /, %, ** (power)
Interactive mode: you can start writing Python code and immediately execute each of those
lines interactively.
floating Takes up 4 bytes of memory (32 bits). Can store decimals.
round: round the number to the nearest integer.
return – it returns the value
Exercises
#code format for, giving an input and returning a value.
#We are getting the input here and using strip (which would remove the white
space) and capitalize (capitalize the first letter of that word).
name = input("What's your name? ").strip().title()
#We are here splitting the value, you can take either first, last or both.
first, last = name.split(" ")
#We are using the f-string, which would specify this "{}" syntax.
print(f"hello, {name}")
# "name", is variable.
# “What’s your name?”, is an argument.
# "=” are operators.
# "input("")", are input functions.
# "print("hello, " + name)", is a return function.
def square(x):
return x * x
main()
Questions
#prompts the user for input and then outputs that same input, replacing each
space with "...".
x = str(input("What's the input? ")).strip()
y = ("...")
first, second, last = x.split(" ")
print(first+y+second+y+last)
#prompts the user for input and then outputs that same input in lowercase.
input = str(input("Type here? "))
x = (input.lower())
print(x)
# Implement a function called convert that accepts a str as input and returns
that same input with any :) converted to 🙂 and any :( converted to 🙁. all other
text should be returned unchanged. Then, implement a function called main that
prompts the user for input, calls convert on that input, and prints the result.
# "(x)" in def called parameters which comes handy in manipulating the value
inside it
# taking def as "x" which will give us input and would help us in replacing the
value
def convert(x):
z = x.replace(":)", "🙂").replace(":(", "🙁")
return z
def main():
y = (input("input here: "))
a = convert(y)
print(a)
if __name__ == "__main__":
main()
#it’s customary to leave a tip for your server after dining in a restaurant,
typically an amount equal to 15% or more of your meal’s cost.
def main():
dollars = float(input("How much was the meal? "))
percent = float(input("What percentage would you like to tip? "))
tip = dollars * (percent/100)
print(f"Leave ${tip:.2f}")
main()
Week 1
Theory
Conditionals: (>, <, <=, >=, =, ==, !=, or, and), use if, elif, and else statements.
Bool means yes or no, ex: if x < y:
Match – Similar to if, elif, and else statements, match statements can be used to conditionally
run code that matches certain values.
Types and format codes
o Number
int (%i) - integers
long (%li) - we will have longer value (we can store much more combination)
float (%f) - store decimal number
double (%f) - we can have twice as many bits to represent that information.
o Text
char (%c) - individual character
string (%s) - collection of characters
Data types and variable: -
o Int
Take up 4 bytes of memory (32bits, 8bits as per 1 bytes).
We split 32 bits into negative and positive getting half.
Does not hold decimal
Unsigned int
It modifies the data types of integers slightly, which doubles the positive range
of values so that you do not have to take any negative values.
we represent approximately 0 to 4 billion.
o Char
Store one character, takes up 1 bytes of memory(8bits).
o Floating
Takes up 4 bytes of memory (32bits).
Can store decimal.
o Double
They can fit 64bits of data, or eight bytes.
it is great when you are working with a lot of decimals
o Bool
Store one value, true or false.
Examples
#code format for, using match value.
name = input("What's your name? ")
match name:
case "Harry":
print("Gryffindor")
case "Hermione":
print("Gryffindor")
case "Ron":
print("Gryffindor")
case "Draco":
print("Slytherin")
case _:
print("Who?")
#Notice the use of the _ symbol in the last case. This will match with any input,
resulting in similar behavior as an else statement.
#code format for, defining the value and seeing if it is odd or even.
def main():
x = int(input("What's x? ")) #taking input in "x"
if y(x): #here we are assuming "x" value in "y"
print("Even") #if the "x" will return "true" then it will print "even".
else:
print("Odd") #if the "x" will return "false" then it will print "odd".
main()
if (x == "hello"):
print("$0")
elif (x[0] == "h"):
print("$20")
else:
print("$100")
if x.endswith("gif"):
print('image/gif')
elif x.endswith("jpg" or "jpeg"):
print('image/jpeg')
elif x.endswith("png"):
print('image/png')
elif x.endswith("pdf"):
print('application/pdf')
elif x.endswith("txt"):
print('text/plain')
elif x.endswith("zip"):
print('application/zip')
else:
print('application/octet-stream')
if y == ("+"):
print(float(x) + float(z))
elif y == ("-"):
print(float(x) - float(z))
elif y == ("*"):
print(float(x) * float(z))
elif y == ("/"):
print(float(x) / float(z))
else:
print("No")
week 2
Theory
loop - keeping things in loop
list – help you list item, use “[]” bracket
range – return a range of value, only takes int
len – would tell you the length
continue – will continue the loop forever
break – will break the loop
dict – dictionaries are a data structure that allows you to associate one value with
another, start and end with “{}”, there is keys and values inside dictionaries.
Sep – separator which separates the words
None – represent the absence of a value
end=”” - this end will end the space after the loop.
Examples
#code format for, while loop.
i = 0
while i < 3:
print("meow")
i += 1
# using a loop
for y in x:
# asking if y contains capital letter
if y.isupper():
# printing "_" and lowering that capital letter and again using end function so
that we can add the next print.
print("_" + y.lower(), end="")
else:
print(y, end="")
print()
while y != 50:
x = int(input("Insert Coin: "))
if x == 25 or 10 or 5:
y += x # add value of x unless y becomes 50
print("Amount Due: ", 50 - y)
else:
print("Invalid input. Please enter 5 or 10 or 25.")
print("Change Owed: 0")
# code format for, taking a input and returning the same but without vowel
x = input("Input: ").replace('A', '').replace('E', '').replace('I',
'').replace('O', '').replace('U', '').replace('a', '').replace('e',
'').replace('i', '').replace('o', '').replace('u', '')
print(x)
# code format for, input a name of a fruit and get its calories
x = input("Item: ")
if x == "Apple":
print("Calories: 130")
elif x == "Avocado":
print("Calories: 50")
elif x == "Banana":
print("Calories: 110")
elif x == "Cantaloupe":
print("Calories: 50")
elif x == "Grapefruit":
print("Calories: 60")
elif x == "Grapes":
print("Calories: 90")
elif x == "Honeydew Melon":
print("Calories: 50")
elif x == "kiwifruit":
print("Calories: 90")
elif x == "lemon":
print("Calories: 15")
elif x == "lime":
print("Calories: 20")
elif x == "Nectarine":
print("Calories: 60")
elif x == "Orange":
print("Calories: 80")
elif x == "Peach":
print("Calories: 60")
elif x == "Pear":
print("Calories: 100")
elif x == ("Pineapple"):
print("Calories: 50")
elif x == "Plums":
print("Calories: 70")
elif x == ("Strawberries"):
print("Calories: 50")
elif x == ("Sweet Cherries"):
print("Calories: 100")
elif x == ("Tangerine"):
print("Calories: 50")
elif x == ("Watermelon"):
print("Calories: 80")
else:
None
Week 3
Theory
ValueError - helps when a function receives an argument of the correct data type but
with an inappropriate value.
pass – means that we are going to loop again
break - used to stop or pause a program's execution.
Examples
# code format for, it would take a input and return the if it is right.
while True:
#"try" function comes use in trying things
try:
x = int(input("What the fuck is this"))
# if the "try" one is wrong then it would print except value
except ValueError:
print("x is not an integer")
# use else if nothing goes wrong
else:
break
# it would print the given if that "while" loop will break
print(f"x is {x}")
# code format for, it would take a input and return the if it is right.
#defining a function
def main():
# assining “cover function” to “x”
x = cover("What's x? ")
print(f"x is {x}")
#defining a function
def cover(prompt):
#asking question unless it gives true
while True:
#"try" function comes use in trying things
try:
#taking input and returing that
return int(input(prompt))
# if the "try" one is wrong then it would print except value
except ValueError:
#"pass" means not doing anything just simply passing the value
pass
#calling the main function
main()
Questions
#Fuel Gauge
while True:
#taking the input
fuel = (input("Fraction: "))
try:
#it will split the "input" in "x" and "y"
x, y= fuel.split("/")
#now we are denoting that x and y is int
new_numerator = int(x)
new_denominator = int(y)
#dividing the x and y
f = new_numerator / new_denominator
#if f is smaller than or equall to 1
if f <= 1:
break
except (ValueError, ZeroDivisionError):
pass
#multiplying the f with 100
p = int(f * 100)
# is p is smaller than or equal to 1
if p <= 1:
print("E")
elif p >= 99:
print("F")
else:
print(f"{p}%")
#fuel Gauge
food = {
"Baja Taco": 4.00,
"Burrito": 7.50,
"Bowl": 8.50,
"Nachos": 11.00,
"Quesadilla": 8.50,
"Super Burrito": 8.50,
"Super Quesadilla": 9.50,
"Taco": 3.00,
"Tortilla Salad": 8.00
}
# taking the input x and y
x = input("Item: ")
y = input("Item: ")
#made a dictionary
grocery = {}
while True:
try:
#prompt the user
x = input().upper()
#check if the dictionary contain the input if it does then increment the
value of that key and if it doesnt then put 1 in that value.
if x in grocery:
grocery[x] += 1
else:
grocery[x] = 1
except EOFError:
#sort the keys
for i in sorted(grocery.keys()):
#print value and keys
print(grocery[i], i.upper())
break
Week 4
Theory
Modules – Modules can be used to organize functions, classes, and other data together in a
structured way. All these modules are contained in a group called the Python standard library.
Import – you use import to call any library
Random.choice – output the result in the same probability
Sys.argv – argv stand for argument vector which describe - the list of all of the word that the
human typed in at their prompt before they hit inter. All of those are provided to you by python
in a variable called sys.argv
slices – take a slice of the list by specifying the start and the end you want
packages – third party library
pip – is a package manager allow you to install packages into your device
APIs – application programming interface 3rd party services that we can write code and talk to
Requests – allow you to make a web request
JSON – java script object notation which is standard text format used for exchanging data
between computers
Custom library – make your own library
__name__ = This allows you to determine if a module is being run as a standalone script or if it is
being imported as a module into another script.
examples
import random
coin = random.choice(["heads", "tails"])
print(coin)
#by doing this you no longer have to specify the random again and again you can
just call choice
from random import choice
coin = choice(["heads", "tails"])
print(coin)
import random
# taking an input
a = int(input("a: "))
b = int(input("b: "))
#outputing a random value btw a and b
coin = random.randint(a, b)
#printing coin
print(coin)
import random
#puting the value
x = ["jack", "queen", "king"]
#using shuffle to shuffle that value
random.shuffle(x)
#taking the each value at a time and then printing it
for i in x:
print(i)
# importing sys
import sys
#sys.argv will put something which we will type in terminal
print("hello, my name is", sys.argv[1])
import sys
# sys.exit will exit if the requirement meet
if len(sys.argv) < 2:
sys.exit("Too few arguments")
elif len(sys.argv) > 2:
sys.exit("Too many arguments")
import sys
if len(sys.argv) < 2:
sys.exit("Too few arguments")
# will slices the input
for arg in sys.argv[1:]:
print("hello, my name is", arg)
Questions
import emoji
x = input("Input: ")
y = emoji.emojize(x)
z = print(y)
import pyfiglet
import sys
x = input("Input: ")
while True:
try:
x = input("Name: ")
y = input("Name: ")
if y == "":
y = "NoName"
z = input("Name: ")
if z == "":
z = "NoName"
break
except EOFError:
break
import random
while True:
try:
x = int(input("Level: "))
if x > 0:
break
else:
pass
except ValueError:
pass
while True:
try:
y = int(input("Guess: "))
if y > 0:
break
else:
pass
except ValueError:
pass
z = random.randint(1, x)
if y == z:
print("just right!")
elif y > z:
print("Too small!")
elif y < z:
print("Too large!")
else:
pass
Week 5
Theory
assert = allow you to assert that something is true And if it is true then nothing happens but if it
is not true then you would see error.
pytest –will automate the testing of your code so you don’t have to write as many lines of code
yourself manually
raises – raising an exception
packages – python module that are organized inside a folder
Exercise
def main():
x = int(input("What's x? "))
print("x squared is", square(x))
def square(n):
return n * n
if __name__ == "__main__":
main()
from python import square
def test_positive():
assert square(2) == 4
assert square(3) == 9
def test_negative():
assert square(-2) == 4
assert square(-3) == 9
def test_zero():
assert square(0) == 0
def test_str():
with pytest.raises(TypeError):
square("cat")
Week 6
Theory
File I/O = store data so it won’t be deleted
Open – to open a file
With – open and automatically close some file
Sorted(name, key =None, reverse=False or True)
Csv (comma separated value) files – text format which separate texts with comma.
Key – where you can tell what key should be used In-order to sort some dictionaries
lambda - extracts the value
csv.reader – it will read csv file for you and deal with potential corner cases(ex- comma, quotes),
this returns a list
csv.DictReader – it will read csv file for you and deal with potential corner cases(ex- comma,
quotes), this returns a dictionary
binary file – just 0’s and 1’s and they can be laid our in any pattern you might want, particularly if
you want to store graphical or audio or video information as well.
Pill – allow you to navigate images files as well and to perform operations on images files.
Examples
# taking the input
name = input("What's your name? ")
# onening a file and w means want to write into
file = open("name.txt", "w")
# writing the file
file.write(name)
# closing and saving the file
file.close()
#making a list
name = []
#open and close the file
with open("names.txt") as file:
# go into the file line by line
for line in file:
# put all the line in name list
name.append(line.rstrip())
# now sort that list in descending order
for name in sorted(name, reverse = True):
# print the list
print(f"hello, {name}")
x = []
# The sorted() function is used to sort the list x based on the get_name()
function as the key. This means that the dictionaries in x will be sorted in
alphabetical order of the student names.
for y in sorted(x, key=get_name):
# Inside the loop, the student's name and house are printed
print(f"{y['name']} is in {y['house']}")
x = []
import csv
x = []
import csv
x = []
with open("students.csv") as file:
z = csv.DictReader(file)
for i in z:
x.append({"name": i["name"], "home": i["home"]})
import csv
x = []
import csv
x = []
#code file 2
# Say hello
#code file 1
import sys
if sys.argv[1] == "sicilian.csv":
with open("pizza.py", "r") as file:
lines = file.readlines()
for line in lines:
if "a" in line:
print(line)
#code file 2
from tabulate import tabulate
s = [
["Sicilian Pizza", "Small", "Large"],
["Cheese", "$25.50", "$39.95"],
["1 item", "$27.50", "$41.95"],
["2 item", "$29.50", "$43.95"],
["3 item", "$31.50", "$45.95"],
["Special", "$33.50", "$47.95"],
]
s_fmt = "grid"
a = tabulate(s, headers="firstrow", tablefmt=s_fmt)
print(a)
r = [
["Regular Pizza", "Small", "Large"],
["Cheese", "$13.50", "$18.95"],
["1 topping", "$14.75", "$20.95"],
["2 toppings", "$15.95", "$22.95"],
["3 toppings", "$16.95", "$24.95"],
["Special", "$18.50", "$26.95"],
]
r_fmt = "grid"
b = tabulate(r, headers="firstrow", tablefmt=r_fmt)
print(b)
#code 1
import sys
x = []
if len(sys.argv) < 4:
sys.exit("Too few command-line arguments")
elif len(sys.argv) != 4:
sys.exit("Too many command-line arguments")
elif sys.argv[1] == "invalid_file.csv":
sys.exit("Could not read invalid_file.csv")
#code 2
name,house
"Abbott, Hannah",Hufflepuff
"Bell, Katie",Gryffindor
"Bones, Susan",Hufflepuff
"Boot, Terry",Ravenclaw
"Brown, Lavender",Gryffindor
"Bulstrode, Millicent",Slytherin
"Chang, Cho",Ravenclaw
"Clearwater, Penelope",Ravenclaw
"Crabbe, Vincent",Slytherin
"Creevey, Colin",Gryffindor
"Creevey, Dennis",Gryffindor
"Diggory, Cedric",Hufflepuff
"Edgecombe, Marietta",Ravenclaw
"Finch-Fletchley, Justin",Hufflepuff
"Finnigan, Seamus",Gryffindor
"Goldstein, Anthony",Ravenclaw
"Goyle, Gregory",Slytherin
"Granger, Hermione",Gryffindor
"Johnson, Angelina",Gryffindor
"Jordan, Lee",Gryffindor
"Longbottom, Neville",Gryffindor
"Lovegood, Luna",Ravenclaw
"Lupin, Remus",Gryffindor
"Malfoy, Draco",Slytherin
"Malfoy, Scorpius",Slytherin
"Macmillan, Ernie",Hufflepuff
"McGonagall, Minerva",Gryffindor
"Midgen, Eloise",Gryffindor
"McLaggen, Cormac",Gryffindor
"Montague, Graham",Slytherin
"Nott, Theodore",Slytherin
"Parkinson, Pansy",Slytherin
"Patil, Padma",Gryffindor
"Patil, Parvati",Gryffindor
"Potter, Harry",Gryffindor
"Riddle, Tom",Slytherin
"Robins, Demelza",Gryffindor
"Scamander, Newt",Hufflepuff
"Slughorn, Horace",Slytherin
"Smith, Zacharias",Hufflepuff
"Snape, Severus",Slytherin
"Spinnet, Alicia",Gryffindor
"Sprout, Pomona",Hufflepuff
"Thomas, Dean",Gryffindor
"Vane, Romilda",Gryffindor
"Warren, Myrtle",Ravenclaw
"Weasley, Fred",Gryffindor
"Weasley, George",Gryffindor
"Weasley, Ginny",Gryffindor
"Weasley, Percy",Gryffindor
"Weasley, Ron",Gryffindor
"Wood, Oliver",Gryffindor
"Zabini, Blaise",Slytherin
week 7
Theory
regexes – also known as regular expressions, its just a pattern that can be used to match some
kind of data often user input.
re – library for regular expression, here you can define, check and even replace pattern.
re.search(pattern, string, flags=0) function is used to search for a specified pattern within a
given string. Here's a breakdown of the function's parameters: pattern: This parameter
represents the regular expression pattern that you want to search for within the string. Regular
expressions provide a powerful and flexible way to match and manipulate strings. string: This
parameter specifies the actual string in which you want to search for the pattern. flags
(optional): Flags modify the behavior of the regular expression matching.
Some special symbol for the pattern –
o . - any character except a newline
o * - 0 or more character
o + - 1 or more character
o ? - 0 or 1 character
o {m} - number character
o {m, n} - if you want range of character number - other number
o \ = if you will type this and after this if you will type anything then it will take it as a
string
o r – raw means you want .edu as a string not as something else.
o ^ - matches the start of the string
o $ - matches the end of the string or just before the newline at the end of the string
o [] - set of characters (things you want to write)
o [^] - things you want to exclude
o [a-z] - if you want range of alphabets then you can just do this and f you want to do this
of capital letter also then do [a-zA-Z]
o \d – decimal digit
o \D – not a decimal digit
o \s – whitespace characters
o \S – not a whitespace character
o \w – word character… as well as number and the underscore
o \W – not a word character
o A|B – either A or B
o (...) – a group
o (?:…) – non-capturing version
Some flags
o re.IGNORECASE – ignore the case
o re.MULTILINE – match the multiline
o re.DOTALL – you can recognize any character except new line
re.match(pattern, string, flag=0) – matches the beginning of the input string.
re.fullmatch(pattern, string, flog=0) – matches the beginning and the end of the input string.
:= - walrus operator allow you to assign a value from right to left, and ask a Boolean question
about it
re.sub(pattern, repl, string, count=0, flags=0) – sub is substitute, repl is replace, how many
times you want to do.
removeprefix – prefix is a string that comes at the start.
Examples
import re
#The re.search() function is used to search for a match between the regular
expression pattern and the email address.
email = input("What's the email? ").strip()
#^ asserts the start of the string.
#\w+ matches one or more word characters (alphanumeric or underscore).
#@ matches the "@" symbol.
#(\w+\.)? matches an optional group consisting of one or more word characters
followed by a dot.
#\w+ matches one or more word characters.
#\. matches a dot.
#edu matches the literal characters "edu".
#$ asserts the end of the string.
#re.IGNORECASE allows both uppercase and lowercase letters to be valid in the
email address.
if re.search(r"^\w+@(\w+\.)?\w+\.edu$", email, re.IGNORECASE):
print("Valid")
else:
print("Invalid")
import re
name = input("What's the email? ").strip()
#r"^(.+), (.+)$" is used to match the "Last Name, First Name".
#^ asserts the start of the string.
#(.+) captures one or more characters (except newline) greedily and saves it as a
group.
#, matches a comma followed by a space.
#(.+) captures one or more characters greedily and saves it as a group.
#$ asserts the end of the string.
#The if matches: statement checks if the re.search() function found a match. If a
match is found, it means that the input name was in the "Last Name, First Name"
format.
#Inside the if statement, the name variable is updated by rearranging the last
name and first name using matches.group(2) (which retrieves the second captured
group, i.e., the first name) and matches.group(1) (which retrieves the first
captured group, i.e., the last name).
matches = re.search(r"^(.+), (.+)$", name)
if matches:
last = matches.group(1)
first = matches.group(2)
name = f"{first} {last}"
print(f"hello, {name}")
import re
x = input("IPv4 Address:")
if re.search(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$", x):
y = x.split('.')
for i in y:
if 0 <= int(i) <= 255:
print("Valid")
break
else:
print("Invalid")
else:
print("Invalid format")
Week 8
Theory
methods are functions that operate on the attributes of a specific instance of a class.
Variables that have different values for different instances of the same class are called instance
variables,
Object oriented programming - a flexible, powerful paradigm where classes represent
and define concepts, while objects are instances of classes. Almost everything in Python is an
object, all of the numbers, strings, lists, and dictionaries etc. And each of them was an instance
of a class representing a concept. concept of object-oriented programming comes down to
attributes and methods associated with a type.
Attributes are the characteristics associated to a type,
methods are the functions associated to a type.
dir function- This gets the Interpreter to print to the screen a list of all the attributes
and methods.
help function – would tell you how to use those attributes and methods When we use the help
function on any variable or value, we're showing all the documentation for the corresponding
class.
Dot notation - lets you access any of the abilities that the object might have, called methods or
information that it might store called attributes
tuple – collection of values, it is immutable means you cannot change the value of variable
classes – you can create your own data type and can give them a name. but anytime you use a
class you are creating objects. Classes also comes with method that you can define and they just
behave in a special.
Objects - any time when you use class you are creating objects
__init__ - if you want to initialize the content of a object from a classes then you define this
method
Methods – classes come’s with certain methods that you can define and they just behave in a
special way these functions allow you to determine behavior in a standard way.
raise – you can create your own exceptions when something just really goes wrong not wrong
enough that you want to quit and exit the whole program but enough that you need to
somehow alert the programmer that there has been an error and them try to catch it.
properties – is just attributes that we have more control over, @properties, you can save form
having any changes.
decorators – function that can modify the behavior of other functions
getter – is a function in some class that sets some value you write @<name>.setter in starting
setter – is a function in some class that gets some value you write @property in starting
class type
o class int(x, base=10) – this will return you object of int
o class str(object=’’) – this will return you object of str
o str.lower()
o str.strip([chars])
o class list([iterable])
o list.append(x)
type(60) – would tell you the type of that variable
class methods – sometimes it’s not really necessary or sensible to associate a function with
object of a class, but rather with the class itself, use @classmethod
STR method- which returns the string that we want to print.
A docstring is a brief text that explains what something does.
Inheritance - let's a programmer build relationships between concepts and group them
together. this allows us to reduce code duplication by generalizing our code.
Examples
class Flower:
color = 'unknown'
rose = Flower()
rose.color = "red"
violet = Flower()
violet.color = "blue"
class Piglet:
name = "piglet"
def speak(self):
print("oink! I'm {}! oink!".format(self.name))
hamlet = Piglet()
hamlet.name = "Hamlet"
hamlet.speak()
petunia = Piglet()
petunia.name = "petunia"
petunia.speak()
class Piglet:
years = 0
def pig_years(self):
return self.years * 18
piggy = Piglet()
piggy.years = 2
print(piggy.pig_years())
class Person:
def __init__(self, name):
self.name = name
def greeting(self):
# Should return "hi, my name is " followed by the name of the Person.
return "hi, my name is" + self.name
class Apple:
def __init__(self, color, flavor):
self.color = color
self.flavor = flavor
def __str__(self):
return "This apple is {} and its flavor is {}".format(self.color,
self.flavor)
class Fruit:
def __init__(self, color, flavor):
self.color = color
self.flavor = flavor
# class Apple(Fruit) this means that apple has the same function as fruit
class Apple(Fruit):
pass
class Grape(Fruit):
pass
class Animal:
sound = ""
def __init__(self, name):
self.name = name
def speak(self):
print("{sound} I'm {name}! {sound}".format(name=self.name,
sound=self.sound))
class Piglet(Animal):
sound = "Oink!"
hamlet = Piglet("Hamlet")
hamlet.speak()
class Clothing:
material = ""
def __init__(self,name):
self.name = name
def checkmaterial(self):
print("This {} is made of {}".format(self.name,self.material))
class Shirt(Clothing):
material="Cotton"
polo = Shirt("Polo")
polo.checkmaterial()
Week 9
Theory
Set – a collection of values where there are no duplicate if you want to add something in set you
don’t write append but rather you would use “add”
global – global that allows you to tell a function that, hey, this is not a variable that's local to you.
I mean it to be a global variable that I want you to edit.
constant - once you have set a value to them, you cannot change the value of that variable.
Type hints – you can provide hint to python
Docstring – tells how you should doc your strings
argparse – handle all the command line part so you can focus on cool things
unpacking – means other way of splitting the value
Examples
# it is type hint giving the hint that n is int
# -> means that the program is gona return str
# the middle comment is docstring.
print(total(*coins), "knuts")
print(total(**coins), "knuts")
CS basics
Questions:
1. Arrays
o Bare Minimum
https://www.geeksforgeeks.org/top-50-...
o Bonus
https://www.interviewbit.com/courses/...
https://leetcode.com/tag/array/
2. Strings
o Bare Minimum
https://www.interviewbit.com/courses/...
o Bonus
https://leetcode.com/tag/string/
https://www.hackerrank.com/domains/al...
3. Linked Lists
o Bare Minimum
https://www.interviewbit.com/courses/...
o Bonus
https://leetcode.com/tag/linked-list/
https://www.geeksforgeeks.org/top-20-...
4. Stacks and Queues
o Theory:
https://www.geeksforgeeks.org/stack-d...
https://www.geeksforgeeks.org/queue-s...
o Bare Minimum
https://www.interviewbit.com/courses/...
o Bonus
https://leetcode.com/tag/stack/
https://leetcode.com/tag/queue/
https://www.geeksforgeeks.org/queue-d...
https://www.geeksforgeeks.org/stack-d...
5. Tree-based data structures:
o Theory:
https://www.geeksforgeeks.org/binary-...
https://www.geeksforgeeks.org/binary-...
https://www.geeksforgeeks.org/trie-in...
https://www.geeksforgeeks.org/heap-da...
https://www.geeksforgeeks.org/hashing...
o Bare minimum:
https://www.interviewbit.com/courses/...
https://www.interviewbit.com/courses/...
https://www.interviewbit.com/courses/...
o Bonus
https://leetcode.com/tag/tree/
https://leetcode.com/tag/heap/
https://leetcode.com/tag/trie/
https://leetcode.com/tag/hash-table/
6. Graphs:
o Theory:
https://www.geeksforgeeks.org/graph-a...
o Standard Algos:
BFS - https://www.geeksforgeeks.org/breadth...
DFS - https://www.geeksforgeeks.org/depth-f...
Dijkstra - https://www.geeksforgeeks.org/dijkstr...
Prim's - https://www.geeksforgeeks.org/prims-m...
Kruskal - https://www.geeksforgeeks.org/kruskal...
Floyd-Warshall - https://www.geeksforgeeks.org/floyd-w...
Union Find - https://www.geeksforgeeks.org/union-f...
o Bare Minimum:
https://leetcode.com/tag/graph/ (Easy and Medium)
o Bonus:
https://www.interviewbit.com/courses/...
o
7. Dynamic Programming:
o Video lectures:
Lec 1 - • Lecture 19: Dynam...
Lec 2 - • Lecture 20: Dynam...
Lec 3 - • Lecture 21: Dynam...
o Bare minimum (Standard problems):
https://www.geeksforgeeks.org/program...
https://www.geeksforgeeks.org/0-1-kna...
https://www.geeksforgeeks.org/coin-ch...
https://www.geeksforgeeks.org/compute...
https://www.geeksforgeeks.org/longest...
https://www.geeksforgeeks.org/longest...
https://www.geeksforgeeks.org/longest...
o Bonus:
https://www.interviewbit.com/courses/...
https://leetcode.com/tag/dynamic-prog...
Space Complexity - measuring how much space it takes for the machine to finish the task. How much
space increase as the input increase so we can say it is Big O(n)
Time complexity - measuring how much time it takes for the machine to finish the task. How much Time
increase as the input increase so we can say it is Big O(n)
Big O notation - Big O notation is used to analyze the efficiency of an algorithm as its input approaches
infinity, which means that as the size of the input to the algorithm grows, how drastically do the space or
time requirements grow with it? For example, let's say that we have a dentist, and she takes 30 minutes
to treat one patient. As her line of patients increases, the time that it takes for her to treat all of the
patients will scale linearly with the number of patients waiting in line. With this in mind, we can
categorize her efficiency as being linear. Or, as we would say in Big O terms, - big O(n), where n is equal
to the number of patients in Big O.
Growth hierarchy - we have a growth hierarchy, form best to worst case when determining the efficiency
of an algorithm, we only care about the worst case so if in a code there is more than one algorithm, we
will only take the worst in consideration.
Constant - constant is any step that doesn't scale with the input to the function. like we use big O of n to
describe linear functions. We also have a big O name for constant algorithms, which is big O(1).
O(n^2) - Nested loops to iterate through each box in the grid, performing a certain action, such as
drawing a square, on each box. The first loop iterates through the rows, while the second loop iterates
through the columns. This nested loop structure gives the code a time complexity of O(n2), where n
represents the number of rows or columns in the grid. The code draws a total of n2 squares as it
traverses each row and column once. We say that the code has a "time complexity" of O(n2), and n is
equal to the number of rows or columns because the number of operations it performs is proportional
to the square of the grid size.
O(n^3) - The cube function is a special function that makes a big cube out of smaller cubes. The size of
the cube depends on the input number. For example, if we use the number 4, the cube will be made up
of 4 smaller cubes in each direction (length, width, and height). That means it will have a total of 64
small cubes. To build the cube, the function uses loops. Loops are like instructions that tell the function
to repeat certain actions. In this case, there are three nested loops. The outer loop determines how
many times we repeat the other two loops, which create rows of cubes. Each loop goes around the same
number of times as the input number. By using these loops, the function places the small cubes one by
one to build the big cube. The number of small cubes in the big cube is equal to the input number
multiplied by itself three times (n * n * n). This is called the volume of the cube. When we say the
function is O(n3), it means that if we give it a number n, it will take n cubed steps to build the cube. In
our example, 4 cubes equal 64, which is the volume of the cube.
O(log n) Recursive – Imagine you have a big pile of blocks. Now, you want to know how many times you
can divide that pile in half until you end up with just one block. Let's say you have 8 blocks in the pile.
You start by splitting the pile in half. In this case, you were able to divide the pile 3 times until you ended
up with just one block. This is similar to what we call "logarithm base 2^8 = 3 or 2*2*2 = 8." It means
that if you keep dividing the number 8 in half, you can do it 3 times until you get down to 1. So, when we
say that something has a time complexity of O(log n).
O(log n) Non- recursive/Iterative - Imagine you have a toy box with 8 toys in it. We want to count how
many toys are in the box. We have a special machine that can divide the toys in half. so, we start by
dividing the toys in half and we get 4 toys in one group and 4 toys in another group. Then we divide each
group in half again and we have 2 toys in each group. We do it one more time, and now we have 1 toy in
each group. So, after dividing the toys a few times, we end up with just 1 toy. We counted the toys by
dividing them in half multiple times. We needed to divide the toys 3 times before we got to 1. This is like
doing 1, 2, 3, which is the same as log base 2 of 8. This is what we mean by O(log n) complexity. It tells us
how many times we need to divide the toys (or any other problem) to solve it. In this case, we needed to
divide the toys log base 2 of 8 times, which is 3.
O(log n) Binary Search - In a long list of numbers, binary search is a faster method to find a specific
number. By comparing the middle number with the desired number, you can determine if it's on
the left or right side of the middle number. If it's smaller, it's on the left side, and if it's larger, it's
on the right side. Then, you can ignore the other side of the list and focus on the side where 100
could be. This process cuts the list in half, allowing you to focus on the side you want. This method
is more efficient than traditional guessing, as it requires an ordered list. In summary, binary search
is a clever way to find a specific number in a long list by comparing the middle number, dividing the
list in half, and ultimately finding the desired number.
#binary search
query = int(input("input the number: "))
cards = [9, 7, 6, 4, 3, 2, 1]
low = 0
high = len(cards) - 1
while low <= high:
mid = (low + high) // 2
if query == cards[mid]:
print("Found at index", mid)
break
elif query < cards[mid]:
high = mid - 1
else:
low = mid + 1
else:
print("Card not found")
Linear search – iterating through each of the value, its not O(log n).
# linear search
query = int(input("input the number: "))
cards = [13, 11, 10, 7, 6]
def locate_card(cards, query):
for i in range(len(cards)):
if query == cards[i]:
print(i)
break
else:
print("cards not found")
locate_card(cards, query)
O(n log n) - Suppose we have a list of 8 elements that we want to sort. In the first step of Merge Sort, we
divide the list into two halves, each containing 4 elements. We then recursively sort each half, which
involves further dividing them into smaller halves until we reach lists of size 1. After sorting the smaller
sublists, we start merging them back together. In this merging process, we compare elements from the
two sublists and arrange them in the correct order. Since each sublist is already sorted, merging them
takes a linear amount of time. For our example with 8 elements, the merge sort process would look
something like this:
3. Continue dividing: [7] | [2] | [5] | [1] | [6] | [4] | [3] | [8]
4. Start merging and sorting the sublists: [2, 7] | [1, 5] | [4, 6] | [3, 8]
The time complexity of the Merge Sort algorithm in this case is O(n log n), which is 8 * 3 = 24.
Let's imagine we have a special function called "fibonacci" that can calculate numbers in a special
sequence. If we ask the function to calculate a number in the sequence, let's say the 4th number, it will
start calculating by using two previous numbers. In this case, it will need to calculate the 3rd and 2nd
numbers. To calculate the 3rd number, the function will need to calculate the 2nd and 1st numbers. To
calculate the 2nd number, it will need to calculate the 1st and 0th numbers. Finally, to calculate the 1st
number, it will just return 1. And to calculate the 0th number, it will return 0. Finally, it will return the
values and add them together to get the 4th number. The problem is that this recursive function grows
very quickly as we increase the input number. Each call to the function creates more calls, and the
number of calls increases exponentially. This means that if we ask the function to calculate a large
number, it will take a very long time to finish. In simple terms, the function is like a tree that keeps
branching out, with more and more branches at each level. The number of branches grows very fast, and
that's why the function takes a long time to compute large numbers. So, to summarize, the "fibonacci"
function works by adding the two previous numbers in the sequence. But because it uses recursion, it
can become very slow when the numbers get bigger, and that's why we say it has exponential time
complexity.
O(n!)
Let's imagine you have a special machine that can do some calculations. This machine has a function
called "F" that takes a number as input. Now, imagine you have a number, let's say 3, and you want to
use this machine to do something with that number. Here's what happens:
1. First, the machine checks if the number is 0. If it is, it prints some stars and stops.
2. If the number is not 0 (like our 3), then the machine starts a loop. It will repeat a certain action for
each number starting from 0 up to the given number (3 in our case).
3. Inside the loop, the machine does something special. It calls itself again, but this time with a smaller
number. For example, instead of 3, it calls itself with 2.
4. This process continues. The machine calls itself again and again, each time with a smaller number,
until it eventually reaches 0.
5. When the machine reaches 0, it does the special action of printing stars and stops.
6. And this whole process happens many times, creating a big tree-like structure of calls to the machine.
Now, let's count how many times the machine performs its special action of printing stars. When we
started with the number 3, we went through the loop 3 times: once for 0, once for 1, and once for 2. And
for each of those loop iterations, the machine called itself with a smaller number until it reached 0. So, in
total, the machine did its special action 6 times. It printed stars 6 times. And that's what we mean by
"factorial time complexity. “It’s called "factorial" because we multiply all the numbers from the given
number down to 1. In our case, it was 3 times 2 times 1, which equals 6.
Jason Ku defines a function as a binary relation with exactly one output for every input.
An algorithm is described as a procedure or plan that takes input and produces output.
Verifying algorithm correctness can be done by running it on sample inputs and checking the
expected output.
Induction is a technique used to prove the correctness of algorithms for large inputs by looping,
recursing, or repeating code.
Understanding and proving the correctness of algorithms require knowledge of proofs, inductive
reasoning, and discrete mathematics.
Base Case
- We start by looking at the simplest example of a problem. We check if the thing
we want to prove is true for this example.
- Identify the simplest instance of the problem you're trying to solve, known as
the base case.
- Verify that the desired property holds true for the base case.
Inductive Hypothesis
- We make an assumption that if the thing we want to prove is true for one
example, it will also be true for the next example.
- Formulate an inductive hypothesis that assumes the desired property holds for a
certain value (K) of the problem.
- This assumption serves as the basis for proving the property for larger values.
Inductive Step
- We take a look at the next example and break it down into smaller parts. We
show that if the thing we want to prove is true for the smaller parts, it will also
be true for the next example.
- Consider the next case, which is K+1, and break it down into sub-cases:
- If the property holds true for the first K instances, show that it implies the
property holds for the (K+1)th instance as well.
- If the property doesn't hold for the first K instances, explain what needs to be
done to establish it for the (K+1)th instance.
Repeat the Inductive Step
- We keep doing the same thing, looking at each example and showing that if the
thing we want to prove is true for one example, it will also be true for the next
example.
- Apply the inductive step repeatedly, moving from one case to the next, until you
reach the desired value.
- Each time, demonstrate that if the property holds for K instances, it also holds
for K+1 instances.
Conclusion
- After we have done this for all the examples, we can say that the thing we
wanted to prove is true for all examples of the problem. We can say that the
thing we wanted to prove works for any situation we might encounter.
- After completing the inductive step for all values up to the desired value (n),
conclude that the property holds true for all instances of the problem.
- Emphasize that the inductive proof demonstrates the validity of the desired
property for any valid input of the problem.
Pointers
a pointer is a variable that stores memory address of another variable. Pointers are used to
directly manipulate memory, access and modify data, and enable more efficient memory
management.
Data Structure
Abstract data
An abstract data type is an abstraction of a data structure which provides only the
interface to which a data structure must adhere to, it only say how data structure should
behave and what methods it should have, but not the details like how those methods
are implemented