Skip to content

exercise 1 work #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
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 Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ ARG env

RUN echo $env

ENV PYTHONPATH "${PYTHONPATH}:/usr/src/app"

WORKDIR /usr/src/app

COPY requirements.txt .
Expand Down
2 changes: 1 addition & 1 deletion Exercises/ex4_1.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
\[ [Index](index.md) | [Exercise 3.8](ex3_8.md) | [Exercise 4.2](ex4_2.md) \]
py\[ [Index](index.md) | [Exercise 3.8](ex3_8.md) | [Exercise 4.2](ex4_2.md) \]

# Exercise 4.1

Expand Down
Empty file added __init__.py
Empty file.
Empty file added dan_solutions/__init__.py
Empty file.
Empty file added dan_solutions/ex_1/__init__.py
Empty file.
15 changes: 15 additions & 0 deletions dan_solutions/ex_1/art.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import random
import sys

chars = "\\|/"


def draw(rows: int, columns: int):
for _ in range(rows):
print("".join(random.choice(chars) for _ in range(columns)))


if __name__ == "__main__":
if len(sys.argv) != 3:
raise SystemExit("Usage: art.py rows columns")
draw(int(sys.argv[1]), int(sys.argv[2]))
29 changes: 29 additions & 0 deletions dan_solutions/ex_1/pcost.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from dan_solutions.ex_1.stock import Stock


def read_file(path: str) -> list[Stock]:
stocks: list[Stock] = []
with open(path, "r") as f:
for line in f.readlines():
data = line.split()
name, number_of_shares, share_price = tuple(data)
try:
stock = Stock(
name=name,
number_of_shares=int(number_of_shares),
share_price=float(share_price),
)
stocks.append(stock)
except ValueError as ve:
print(f"WARNING: cannot parse {data}: {ve}")

return stocks


def portofolio_cost(path: str) -> float:
stocks = read_file(path)
return sum([stock.cost for stock in stocks])


if __name__ == "__main__":
print(f"portfolio total: ${portofolio_cost('Data/portfolio.dat'):.2f}")
12 changes: 12 additions & 0 deletions dan_solutions/ex_1/stock.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from dataclasses import dataclass


@dataclass
class Stock:
name: str
number_of_shares: int
share_price: float

@property
def cost(self) -> float:
return self.number_of_shares * self.share_price
71 changes: 71 additions & 0 deletions dan_solutions/ex_2/ex2_2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import csv
from collections import Counter, defaultdict


class Route:
__slots__ = ["number", "date", "daytype", "rides"]

def __init__(self, number: str, date: str, daytype: str, rides: int):
self.number = number
self.date = date
self.daytype = daytype
self.rides = rides


def read_data(file_name: str) -> list[Route]:
records: list[Route] = []
with open(file_name) as f:
rows = csv.reader(f)
_ = next(rows) # Skip headers
for row in rows:
route = Route(row[0], row[1], row[2], int(row[3]))
records.append(route)

return records


if __name__ == "__main__":
routes = read_data("Data/ctabus.csv")

unique_routes = {route.number for route in routes}
number_of_unique_routes = len(unique_routes)
print(f"1: {number_of_unique_routes=}")

target_day = "02/02/2011"
target_route = "22"
number_of_target_day_routes = sum(
[
route.rides
for route in routes
if route.number == target_route and route.date == target_day
]
)
print(f"2: {number_of_target_day_routes=} for {target_route} on {target_day}")

ride_counter = Counter[str]()
for route in routes:
ride_counter[route.number] = +route.rides
print(f"3: {ride_counter=}")

rides_by_year: dict[tuple[str, str], int] = defaultdict()
for route in routes:
rides_by_year[route.number, route.date[-4:]] = (
rides_by_year.get((route.number, route.date[-4:]), 0) + route.rides
)

growth_counter = Counter[str]()
for route in unique_routes:
for year in range(2011, 2001, -1):
if (route, str(year)) in rides_by_year:
current = rides_by_year[route, str(year)]

prev = 0
for prev_year in range(year - 1, 2001, -1):
if (route, str(prev_year)) in rides_by_year:
prev = rides_by_year[route, str(prev_year)]
break

change = current - prev
growth_counter[route] = change

print(f"4. {growth_counter.most_common(5)=}")
2 changes: 2 additions & 0 deletions dan_solutions/ex_2/ex2_3.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
>>> tracemalloc.get_traced_memory()
(102976, 132591)
66 changes: 66 additions & 0 deletions dan_solutions/ex_2/mutint.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# from dan_solutions.ex_2.mutint import MutInt


from functools import total_ordering
from typing import Any


@total_ordering
class MutInt:
__slots__ = ["value"]

def __init__(self, value: int):
self.value = value

def __str__(self):
return str(self.value)

def __repr__(self):
return f"MutInt({self.value!r})"

def __format__(self, fmt: str):
return format(self.value, fmt)

def __add__(self, other: Any):
if isinstance(other, MutInt):
return MutInt(self.value + other.value)
elif isinstance(other, int):
return MutInt(self.value + other)
else:
return NotImplemented

__radd__ = __add__ # Reversed operands

def __iadd__(self, other: Any):
if isinstance(other, MutInt):
self.value += other.value
return self
elif isinstance(other, int):
self.value += other
return self
else:
return NotImplemented

def __eq__(self, other: Any):
if isinstance(other, MutInt):
return self.value == other.value
elif isinstance(other, int):
return self.value == other
else:
return NotImplemented

def __lt__(self, other: Any):
if isinstance(other, MutInt):
return self.value < other.value
elif isinstance(other, int):
return self.value < other
else:
return NotImplemented

def __int__(self):
return self.value

def __float__(self):
return float(self.value)

__index__ = __int__ # Make indexing work
101 changes: 101 additions & 0 deletions dan_solutions/ex_2/readrides.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import csv
import typing
from dataclasses import dataclass


def read_rides_as_tuples(row: list[str]) -> tuple[str, str, str, int]:
route = row[0]
date = row[1]
daytype = row[2]
rides = int(row[3])
return (route, date, daytype, rides)


def read_rides_as_dict(row: list[str]) -> dict[str, str | int]:
return {
"route": row[0],
"date": row[1],
"daytype": row[2],
"rides": int(row[3]),
}


class Row:
def __init__(self, route: str, date: str, daytype: str, rides: int):
self.route = route
self.date = date
self.daytype = daytype
self.rides = rides


def read_rides_as_class(row: list[str]) -> Row:
return Row(row[0], row[1], row[2], int(row[3]))


class RowNamedTuple(typing.NamedTuple):
route: str
date: str
daytype: str
rides: int


def read_rides_as_named_tuple(row: list[str]) -> RowNamedTuple:
return RowNamedTuple(row[0], row[1], row[2], int(row[3]))


class RowWithSlots:
__slots__ = ["route", "date", "daytype", "rides"]

def __init__(self, route: str, date: str, daytype: str, rides: int):
self.route = route
self.date = date
self.daytype = daytype
self.rides = rides


def read_rides_as_class_with_slots(row: list[str]) -> RowWithSlots:
return RowWithSlots(row[0], row[1], row[2], int(row[3]))


def read_data(file_name: str, collector: typing.Callable[[list[str]], typing.Any]):
records: list[typing.Any] = []
with open(file_name) as f:
rows = csv.reader(f)
_ = next(rows) # Skip headers
for row in rows:
records.append(collector(row))

return records


@dataclass
class Result:
method: str
current: int
peak: int


if __name__ == "__main__":
import tracemalloc

test_methods = [
read_rides_as_tuples,
read_rides_as_dict,
read_rides_as_class,
read_rides_as_named_tuple,
read_rides_as_class_with_slots,
]

results: list[Result] = []
for test_method in test_methods:
tracemalloc.start()
rows = read_data("Data/ctabus.csv", test_method)
current, peak = tracemalloc.get_traced_memory()
results.append(Result(test_method.__name__, current, peak))
tracemalloc.reset_peak()

for result in results:
print(f"{result.method=}: {result.current=:,} / {result.peak=:,}")

min_result = min(results, key=lambda r: r.current)
print(f"most efficient: {min_result.method}")
31 changes: 31 additions & 0 deletions dan_solutions/ex_3/lenny.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from dataclasses import dataclass


@dataclass
class Gecko:
name: str
color: str

done = False
geckos: list[Gecko] = []
while done:
name = input("what is the gecko's name ? ")
color = input("what is the gecko's color ? ")
if name == "done":
done = True
else:
geckos.append(Gecko(name=name, color=color))

done = False
while done:
first_gecko_name = input("first gecko to marry")
if first_gecko_name == "done":
done = True
continue
second_gecko_name = input("second gecko to marry")

first_gecko_color = []
print(f"Their baby gecko's color is {} and {}")



14 changes: 14 additions & 0 deletions dan_solutions/ex_3/reader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import csv
from typing import TypeVar

TClass = TypeVar("TClass")


def read_csv_as_instances(filename: str, cls: TClass) -> list[TClass]:
records: list[TClass] = []
with open(filename) as f:
rows = csv.reader(f)
_ = next(rows)
for row in rows:
records.append(cls.from_row(row)) # type: ignore
return records
Loading