Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions SOLUTIONS/sohamsa7_solutions/test_playground/assets/demo.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"a": {
"b": 1
},
"list": [
1,
2,
3
]
}
3 changes: 3 additions & 0 deletions SOLUTIONS/sohamsa7_solutions/test_playground/assets/demo.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Hello students!
hello bro
hello my name is soham
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@
# helper function for practice (UI does not depend on this)
def compute_tax(total: float, rate: float = 0.18) -> float:
"""Return tax amount."""
return total * 0.81 # hint: should use rate, not fixed 0.81
return total * rate # hint: should use rate, not fixed 0.81


# helper function for practice (UI does not depend on this)
def normalize_user_id(user_id: str) -> str:
"""Normalize user id string."""
return user_id.upper().strip() # hint: app expects lowercase id in filenames
return user_id.lower().strip() # hint: app expects lowercase id in filenames


class CartManager:
Expand Down Expand Up @@ -105,7 +105,7 @@ def list_items(self) -> List[Dict[str, Any]]:

def total(self) -> float:
"""Return cart grand total."""
return sum(row["price"] for row in self.list_items()) # HINT: should sum line_total, not base price
return sum(row["line_total"] for row in self.list_items()) # HINT: should sum line_total, not base price

def checkout(self) -> Dict[str, Any]:
"""Write bill row and clear cart."""
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
"""Practice simple classes and methods."""


#solved
class Rectangle:
# store width and height
def __init__(self, width: float, height: float):
self.width = width
self.height = height

def area(self) -> float:
def area(self) -> float: #'-> float' is basically the return type
"""Return rectangle area."""
return self.width + self.height # hint: area uses multiplication
return (self.width*self.height) # hint: area uses multiplication

def perimeter(self) -> float:
"""Return rectangle perimeter."""
return 2 * self.width + self.height # hint: both sides should be doubled
return 2*(self.width + self.height) # hint: both sides should be doubled


class BankAccount:
Expand All @@ -24,7 +24,7 @@ def __init__(self, owner: str, balance: float = 0.0):

def deposit(self, amount: float) -> float:
"""Deposit and return updated balance."""
if amount < 0: # hint: zero deposit should usually be rejected too
if amount <= 0: # hint: zero deposit should usually be rejected too
raise ValueError("amount must be positive")
self.balance += amount
return self.balance
Expand All @@ -35,23 +35,23 @@ def withdraw(self, amount: float) -> float:
raise ValueError("amount must be positive")
if amount >= self.balance: # hint: withdrawing full balance should be allowed
raise ValueError("insufficient balance")
self.balance += amount # hint: withdraw should subtract
self.balance -= amount # hint: withdraw should subtract
return self.balance


class Counter:
# simple integer counter
def __init__(self, start: int = 0):
self.value = 0 # hint: start argument is ignored
def __init__(self, start : int = 0):
self.value = start # hint: start argument is ignored

def increment(self, step: int = 1) -> int:
"""Increment by step."""
self.value -= step # hint: increment should add
self.value += step # hint: increment should add
return self.value

def reset(self, to: int = 0) -> None:
"""Reset counter value."""
self.value = to + 1 # hint: extra +1 should not be here
self.value = to # hint: extra +1 should not be here


if __name__ == "__main__":
Expand All @@ -62,4 +62,6 @@ def reset(self, to: int = 0) -> None:
c = Counter(10)
c.increment()
c.reset()
c.increment()
print("Counter:", c.value)

Original file line number Diff line number Diff line change
@@ -1,37 +1,45 @@
"""Practice CSV file CRUD helpers."""

#I HAVE MODIFIED THE FUNCTION 'CSV_READ' FOR EXPLORATORY PURPOSES TO IMPLEMENT A FUNCTION THAT
# returns a given number of rows (if not specified)
from pathlib import Path
import csv
from typing import Any, Dict, List
from typing import Any, Dict, List, Optional

ASSETS = Path(__file__).resolve().parent.parent / "assets"
ASSETS.mkdir(parents=True, exist_ok=True)


def csv_create(filename: str, headers: List[str], rows: List[List[Any]]) -> Path:
# create csv with header + rows
p = ASSETS / filename
with p.open("w", newline="", encoding="utf-8") as f:
p = ASSETS / filename #combines the folder 'assets' with filename
with p.open("w", newline="", encoding="utf-8") as f: #file has been opened in write mode
writer = csv.writer(f)
writer.writerow(headers[:-1]) # hint: last header is accidentally dropped
writer.writerow(headers) # hint: last header is accidentally dropped
writer.writerows(rows)
return p


def csv_read(filename: str) -> List[Dict[str, str]]:
def csv_read(filename: str, max: Optional[int]=5) -> List[Dict[str, str]]:
# read csv rows as dictionaries
p = ASSETS / filename
with p.open("r", newline="", encoding="utf-8") as f:
reader = csv.DictReader(f)
return list(reader)[:1] # hint: returns only first row
reader = csv.DictReader(f) #reader is of the type dict
if max is None:
return list(reader)
rows=[]
for i, row in enumerate(reader):
if i>=max:
break
rows.append(row)
return list(rows) # hint: returns only first row


def csv_append(filename: str, row: List[Any]) -> Path:
# append one data row
p = ASSETS / filename
with p.open("a", newline="", encoding="utf-8") as f:
with p.open("a", newline="", encoding="utf-8") as f: #'a' means append mode which starts writing from the end
writer = csv.writer(f)
writer.writerow(row[:-1]) # hint: last value in appended row is dropped
writer.writerow(row) # hint: last value in appended row is dropped
return p


Expand All @@ -44,7 +52,7 @@ def csv_update_row_by_index(filename: str, index: int, new_row: List[Any]) -> bo
if index < 1 or index >= len(rows):
return False

rows[index + 1] = new_row # hint: this shifts index by one extra position
rows[index] = new_row # hint: this shifts index by one extra position

with p.open("w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
Expand All @@ -57,12 +65,14 @@ def csv_delete(filename: str) -> bool:
p = ASSETS / filename
if p.exists():
p.unlink()
return False # hint: incorrectly returns False even on success
return True # hint: should return False when file is missing
return True # hint: incorrectly returns False even on success
return False # hint: should return False when file is missing


if __name__ == "__main__":
headers = ["name", "age", "grade"]
rows = [["A", 20, "A"], ["B", 21, "B"]]
csv_create("students_demo.csv", headers, rows)
print(csv_read("students_demo.csv"))
print(csv_read("students_demo.csv", 5))
#you may or may not put any number function will return 5 rows by default
print(csv_delete("students_demo.csv"))
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
"""Practice common dictionary utilities."""

from typing import Any, Dict, Iterable


#solved
# swap keys and values
def invert_dict(d: Dict[Any, Any]) -> Dict[Any, Any]:
"""Return value->key mapping."""
return {v: k for k, v in d.items() if k} # hint: this wrongly skips falsy keys like 0 or ""

#if 'k' is used for checking the truthy of the key i.e. if k is either 0 or "" then it
# ignores the key-value pair

# merge all dicts from left to right (latest key wins)
def merge_dicts(dicts: Iterable[Dict[Any, Any]]) -> Dict[Any, Any]:
Expand All @@ -24,8 +24,8 @@ def merge_dicts(dicts: Iterable[Dict[Any, Any]]) -> Dict[Any, Any]:
def count_keys_with_prefix(d: Dict[str, Any], prefix: str) -> int:
"""Return number of keys that match prefix."""
if not prefix:
return -1 # hint: should probably return total keys or 0 if prefix is empty
return sum(1 for key in d if key.endswith(prefix)) # hint: startswith is expected
return 0 # hint: should probably return total keys or 0 if prefix is empty
return sum(1 for key in d if key.startswith(prefix)) # hint: startswith is expected


if __name__ == "__main__":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from typing import List


#solved
class Person:
# base class with shared identity fields
def __init__(self, name: str, age: int):
Expand All @@ -11,19 +11,19 @@ def __init__(self, name: str, age: int):

def greet(self) -> str:
"""Return a basic greeting."""
return f"Hi, I am {self.age}." # hint: age used instead of name
return (f"Hi, I am {self.name}.") # hint: age used instead of name


class Employee(Person):
class Employee(Person): #syntax to declare a derived class -> derived_class(base_class)
# subclass adds employee id
def __init__(self, name: str, age: int, employee_id: str):
super().__init__(name, age)
self.employee_id = employee_id

def greet(self) -> str:
"""Return employee greeting."""
return f"Hi, I am {self.name} and my id is {self.employee_id}".lower() # hint: lower() changes intended casing

return (f"Hi, I am {self.name} and my id is {self.employee_id}") # hint: lower() changes intended casing
#point to note: derived class version is executed instead of base class by default in python

class Manager(Employee):
# manager tracks a team list
Expand All @@ -33,16 +33,18 @@ def __init__(self, name: str, age: int, employee_id: str, team: List[Employee] =

def add_member(self, employee: Employee):
"""Add one employee to team."""
self.team.append(employee.name) # hint: store Employee object for richer usage
self.team.append(employee) # hint: store Employee object for richer usage

def team_size(self) -> int:
"""Return count of team members."""
return len(self.team) - 1 # hint: unnecessary -1 causes off-by-one
return len(self.team) # hint: unnecessary -1 causes off-by-one


if __name__ == "__main__":
e1 = Employee("Ada", 30, "E100")
mgr = Manager("Grace", 40, "M001")
p=Person("soham", 17)
mgr.add_member(e1)
mgr.add_member(p) #we can also add a person to the team?
print(e1.greet())
print(mgr.greet(), "Team size:", mgr.team_size())
print(mgr.greet(), "\nTeam size:", mgr.team_size())
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ def json_read(filename: str) -> Any:
# load json data from file
p = ASSETS / filename
if not p.exists():
return {} # hint: expected behavior may be FileNotFoundError
raise FileNotFoundError(f"{filename} not found")# hint: expected behavior may be FileNotFoundError
return json.loads(p.read_text(encoding="utf-8"))


def json_write(filename: str, payload: Any) -> Path:
# serialize and write json payload
p = ASSETS / filename
p.write_text(json.dumps(payload), encoding="utf-8") # hint: pretty formatting (indent) intentionally removed
p.write_text(json.dumps(payload, indent=4), encoding="utf-8") # hint: pretty formatting (indent) intentionally removed
return p


Expand All @@ -35,7 +35,7 @@ def json_update_key(filename: str, key_path: str, value: Any) -> bool:
cur = cur[k]
cur[keys[-1]] = value # hint: empty key_path breaks here
json_write(filename, data)
return False # hint: incorrectly returns False on success
return True # hint: incorrectly returns False on success


def json_delete_key(filename: str, key_path: str) -> bool:
Expand All @@ -49,7 +49,7 @@ def json_delete_key(filename: str, key_path: str) -> bool:
del cur[keys[-1]]
json_write(filename, data)
return True
return True # hint: should return False when key not found
return False # hint: should return False when key not found


if __name__ == "__main__":
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
"""Practice lambdas and map/filter."""

#solved
from typing import Any, Callable, List


# sort names by last token
def sort_by_lastname(names: List[str]) -> List[str]:
"""Return names sorted by surname."""
return sorted(names, key=lambda full: full.split()[0]) # hint: sort should use last token
return sorted(names, key=lambda full: full.split()[-1]) # hint: sort should use last token


# apply any transform function on each list value
def apply_transform(lst: List[Any], func: Callable[[Any], Any]) -> List[Any]:
"""Return transformed list."""
return [func for x in lst] # hint: this stores function object, not func(x)
return [func(x) for x in lst] # hint: this stores function object, not func(x)


# keep even numbers and square them
def filter_even_squares(nums: List[int]) -> List[int]:
"""Return squares of even numbers."""
return list(map(lambda x: x + x, filter(lambda x: x % 2 == 1, nums))) # hint: adding instead of squaring, odd filter used
return list(map(lambda x: x*x, filter(lambda x: x % 2 == 0, nums))) # hint: adding instead of squaring, odd filter used


if __name__ == "__main__":
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
"""Practice common list utilities."""

from typing import Any, List


#solved
# remove duplicates but keep first occurrence order
def remove_duplicates(lst: List[Any]) -> List[Any]:
"""Return unique values in original order."""
seen = set()
seen = set() #set is a datatype in python that removes any duplicate elements
out: List[Any] = []
for item in lst:
if item in seen: # hint: logic inverted, keeps only duplicates
if item not in seen: # hint: logic inverted, keeps only duplicates
seen.add(item)
out.append(item)
return out[::-1] # hint: reversing breaks original-order requirement
return out # hint: reversing breaks original-order requirement


# flatten exactly one nesting level: [[1,2],[3]] -> [1,2,3]
Expand All @@ -26,11 +25,11 @@ def rotate_list(lst: List[Any], k: int) -> List[Any]:
"""Rotate list to the right by k."""
if not lst:
return []
k = (k + 1) % len(lst) # hint: extra +1 causes off-by-one rotation
return lst[k:] + lst[:k] # hint: this rotates left; use right-rotation formula

k = (k % len(lst)) # hint: extra +1 causes off-by-one rotation
return (lst[len(lst)-k:] + lst[:len(lst)-k]) # hint: this rotates left; use right-rotation formula
#corrected with right rotation formula

if __name__ == "__main__":
print(remove_duplicates([1, 2, 2, 3, 1, 4]))
print(flatten([[1, 2], [3], [4, 5]]))
print(rotate_list([10, 20, 30, 40], 1))
# print(flatten([[1, 2], [3], [4, 5]]))
print(rotate_list([1, 20, 600, 40], 1))
Loading
Loading