Skip to content
Open
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
2 changes: 2 additions & 0 deletions Week01/info_furkan_cetiner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
student_id = "210316074"
full_name = "Furkan Çetiner"
4 changes: 4 additions & 0 deletions Week02/types_furkan_cetiner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
my_int = 20
my_float = 9.11
my_bool = True
my_complex = 1 + 6j
9 changes: 9 additions & 0 deletions Week03/pyramid_furkan_cetiner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
def calculate_pyramid_height(number_of_blocks):
height = 0
used_blocks = 0

while used_blocks + (height + 1) <= number_of_blocks:
height += 1
used_blocks += height

return height
26 changes: 26 additions & 0 deletions Week03/sequences_furkan_cetiner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
def remove_duplicates(seq: list) -> list:

result = []
for item in seq:
if item not in result:
result.append(item)
return result


def list_counts(seq: list) -> dict:

counts = {}
for item in seq:
if item in counts:
counts[item] += 1
else:
counts[item] = 1
return counts


def reverse_dict(d: dict) -> dict:

reversed_dict = {}
for key, value in d.items():
reversed_dict[value] = key
return reversed_dict
52 changes: 52 additions & 0 deletions Week04/decorators_furkan_cetiner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
from __future__ import annotations

import time
import tracemalloc
from functools import wraps
from typing import Any, Callable, TypeVar, cast

F = TypeVar("F", bound=Callable[..., Any])


def performance(func: F) -> F:

@wraps(func)
def wrapper(*args: Any, **kwargs: Any) -> Any:
# ensure stats exist
wrapper.counter += 1 # type: ignore[attr-defined]

# time
t0 = time.perf_counter()

# memory (tracemalloc)
tracing_already = tracemalloc.is_tracing()
if not tracing_already:
tracemalloc.start()

before_current, before_peak = tracemalloc.get_traced_memory()
try:
result = func(*args, **kwargs)
finally:
after_current, after_peak = tracemalloc.get_traced_memory()
dt = time.perf_counter() - t0

wrapper.total_time += dt # type: ignore[attr-defined]

# Use peak delta as "consumed" approximation for this call
delta_peak = after_peak - before_peak
if delta_peak < 0:
delta_peak = 0
wrapper.total_mem += int(delta_peak) # type: ignore[attr-defined]

# Don't disrupt global tracing if it was already enabled
if not tracing_already:
tracemalloc.stop()

return result

# required attributes
wrapper.counter = 0 # type: ignore[attr-defined]
wrapper.total_time = 0.0 # type: ignore[attr-defined]
wrapper.total_mem = 0 # type: ignore[attr-defined]

return cast(F, wrapper)
36 changes: 36 additions & 0 deletions Week04/functions_furkan_cetiner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from __future__ import annotations

import inspect
from typing import Any, Dict, Tuple


custom_power = lambda x=0, /, e=1: x**e


def custom_equation(x: int = 0, y: int = 0, /, a: int = 1, b: int = 1, *, c: int = 1) -> float:

return (x**a + y**b) / c


def fn_w_counter() -> Tuple[int, Dict[str, int]]:


if not hasattr(fn_w_counter, "_total"):
fn_w_counter._total = 0 # type: ignore[attr-defined]
if not hasattr(fn_w_counter, "_by_caller"):
fn_w_counter._by_caller = {} # type: ignore[attr-defined]


frame = inspect.currentframe()
caller_frame = frame.f_back if frame is not None else None
caller_name = "<unknown>"
if caller_frame is not None:
caller_name = str(caller_frame.f_globals.get("__name__", "<unknown>"))


fn_w_counter._total += 1 # type: ignore[attr-defined]
by_caller: Dict[str, int] = fn_w_counter._by_caller # type: ignore[attr-defined]
by_caller[caller_name] = by_caller.get(caller_name, 0) + 1


return int(fn_w_counter._total), dict(by_caller) # type: ignore[attr-defined]
43 changes: 43 additions & 0 deletions Week05/emails_furkan_cetiner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import re

class Emails(list):
"""
Emails class that extends list and validates email addresses.
"""
def __init__(self, email_list):
validated_data = self.validate(email_list)
super().__init__(validated_data)
self.data = list(validated_data)

@staticmethod
def validate(email_list):
"""
Validates that all items are strings and follow email format.
Removes duplicates while preserving order (or just unique set).
"""
seen = []
email_regex = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'

for email in email_list:
if not isinstance(email, str):
raise ValueError("All items must be strings.")

if not re.match(email_regex, email):
raise ValueError(f"Invalid email format: {email}")

if email not in seen:
seen.append(email)

return seen

def __repr__(self):
"""
Returns a string representation that can recreate the object.
"""
return f"Emails({list(self)})"

def __str__(self):
"""
Returns a user-friendly string representation.
"""
return f"Email List: {list(self)}"