School Commit Init

This commit is contained in:
2024-08-31 12:07:21 +03:00
commit 0b130ee18c
2801 changed files with 4720552 additions and 0 deletions
@@ -0,0 +1,129 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
.python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
@@ -0,0 +1,221 @@
# :computer: Assignment 06
## Requirements
- You will be given one of the problems below to solve
- In addition to **procedural programming**, also use **modular programming** by having a **UI** module, a **Functions** module and a **Start** module
- The **UI** module provides a command-based console user interface that accepts given commands **exactly** as stated
- Handle the case of incorrect user input by displaying error messages. The program must not crash regardless of user input.
- Use the built-in `list` or `dict` compound types to represent entities in the problem domain and access/modify them using *getter* and *setter* functions
- Use Python's [exception mechanism](https://docs.python.org/3/tutorial/errors.html) so that functions can signal that an exceptional situation, or error, has happened.
- Provide **specifications** for all non-UI functions (except getters and setters), and tests for all non-UI functions related to functionalities **(A)** and **(B)**
- Have at least 10 randomly generated items in your application at program startup
- Deadline for maximum grade is **week 8**, hard deadline is **week 11**.
## Problem Statements
### 1. Numerical List
A math teacher needs a program to help students test different properties of complex numbers, provided in the `a+bi` form (we assume `a` and `b` are integers for simplicity). Write a program that implements the functionalities exemplified below:
**(A) Add a number**\
`add <number>`\
`insert <number> at <position>`\
e.g.\
`add 4+2i` appends `4+2i` to the list\
`insert 1+1i at 1` insert number `1+i` at position `1` in the list (positions are numbered starting from `0`)
**(B) Modify numbers**\
`remove <position>`\
`remove <start position> to <end position>`\
`replace <old number> with <new number>`\
e.g.\
`remove 1` removes the number at position `1`\
`remove 1 to 3` removes the numbers at positions `1`,`2`, and `3`\
`replace 1+3i with 5-3i` replaces all occurrences of number `1+3i` with the number `5-3i`
**(C) Display numbers having different properties**\
`list`\
`list real <start position> to <end position>`\
`list modulo [ < | = | > ] <number>`\
e.g.\
`list` display all numbers\
`list real 1 to 5` display the real numbers (imaginary part `=0`) between positions `1` and `5`\
`list modulo < 10` display all numbers with modulo `<10`\
`list modulo = 5` display all numbers with modulo `=5`
**(D) Filter the list**\
`filter real`\
`filter modulo [ < | = | > ] <number>`\
e.g.\
`filter real` keep only numbers having imaginary part `=0`\
`filter modulo < 10` keep only numbers having modulo `<10`\
`filter modulo > 6` keep only those numbers having modulo `>6`
**(E) Undo**\
`undo` the last operation that modified program data is reversed. The user can undo all operations performed since program start by repeatedly calling this function.
---
### 2. Contest
During a programming contest, each contestant had to solve 3 problems (named `P1`, `P2` and `P3`). Afterwards, an evaluation committee graded the solutions to each of the problems using integers between `0` and `10`. The committee needs a program that will allow managing the list of scores and establishing the winners. Write a program that implements the functionalities exemplified below:
**(A) Add the result of a new participant**\
`add <P1 score> <P2 score> <P3 score>`\
`insert <P1 score> <P2 score> <P3 score> at <position>`\
e.g.\
`add 3 8 10` add a new participant with scores `3`,`8` and `10` (scores for `P1`, `P2`, `P3` respectively)\
`insert 10 10 9 at 5` insert scores `10`, `10` and `9` at position `5` in the list (positions numbered from `0`)
**(B) Modify scores**\
`remove <position>`\
`remove <start position> to <end position>`\
`replace <old score> <P1 | P2 | P3> with <new score>`\
e.g.\
`remove 1` set the scores of the participant at position `1` to `0`\
`remove 1 to 3` set the scores of participants at positions `1`, `2` and `3` to `0`\
`replace 4 P2 with 5` replace the score obtained by participant `4` at `P2` with `5`
**(C) Display participants whose score has different properties.**\
`list`\
`list sorted`\
`list [ < | = | > ] <score>`\
e.g.\
`list` display participants and all their scores\
`list < 4` display participants with an average score `<4`\
`list = 6` display participants with an average score `=6`\
`list sorted` display participants sorted in decreasing order of average score
**(D) Establish the podium**\
`top <number>`\
`top <number> <P1 | P2 | P3>`\
`remove [ < | = | > ] <score>`\
e.g.\
`top 3` display the 3 participants having the highest average score, in descending order of average score\
`top 4 P3` display the 4 participants who obtained the highest score for P3, sorted descending by that score\
`remove < 70` set the scores of participants having an average score `<70` to `0`\
`remove > 89` set the scores of participants having an average score `>89` to `0`
**(E) Undo**\
`undo` the last operation that modified program data is reversed. The user can undo all operations performed since program start by repeatedly calling this function.
---
### 3. Family Expenses
A family wants to manage their monthly expenses. They need an application to store, for a given month, all their expenses. Each expense will be stored using the following elements: `day` (*of the month in which it was made, between 1 and 30, for simplicity*), `amount of money` (positive integer) and `expense type` (one of: `housekeeping`, `food`, `transport`, `clothing`, `internet`, `others`). Write a program that implements the functionalities exemplified below:
**(A) Add a new expense**\
`add <sum> <category>`\
`insert <day> <sum> <category>`\
e.g.\
`add 10 internet` add to the current day an expense of `10 RON` for internet\
`insert 25 100 food` insert to day 25 an expense of `100 RON` for food
**(B) Modify expenses**\
`remove <day>`\
`remove <start day> to <end day>`\
`remove <category>`\
e.g.\
`remove 15` remove all expenses for day 15\
`remove 2 to 9` remove all expenses between days 2 and 9\
`remove food` remove all expenses for food
**(C) Display expenses with different properties**\
`list`\
`list <category>`\
`list <category> [ < | = | > ] <value>`\
e.g.\
`list` display all expenses\
`list food` display all the expenses for `food`\
`list food > 5` - display all `food` expenses with an amount of money `>5`\
`list internet = 44` - display all `internet` expenses with an amount of money `=44`
**(D) Filter expenses**\
`filter <category>`\
`filter <category> [ < | = | > ] <value>`\
e.g.\
`filter food` keep only expenses in category `food`\
`filter books < 100` keep only expenses in category books with amount of money `<100 RON`\
`filter clothing = 59` keep only expenses for clothing with amount of money `=59 RON`
**(E) Undo**\
`undo` the last operation that modified program data is reversed. The user can undo all operations performed since program start by repeatedly calling this function.
---
### 4. Bank Account
John wants to manage his bank account. To do this, he needs an application to store all the bank transactions performed on his account during a month. Each transaction is stored in the application using the following elements: `day` (of the month in which the transaction was made, between 1 and 30 for simplicity), `amount of money` (transferred, positive integer), `type` (`in` - into the account, `out` from the account), and `description`. Write a program that implements the functionalities exemplified below:
**(A) Add transaction**\
`add <value> <type> <description>`\
`insert <day> <value> <type> <description>`\
e.g.\
`add 100 out pizza` add to the current day an `out` transaction of `100 RON` with the *"pizza"* description\
`insert 25 100 in salary` insert to day 25 an `in` transaction of `100 RON` with the *“salary”* description
**(B) Modify transactions**\
`remove <day>`\
`remove <start day> to <end day>`\
`remove <type>`\
`replace <day> <type> <description> with <value>`\
e.g.\
`remove 15` remove all transactions from day 15\
`remove 5 to 10` remove all transactions between days 5 and 10\
`remove in` remove all `in` transactions\
`replace 12 in salary with 2000` replace the amount for the `in` transaction having the *“salary”* description from day 12 with `2000 RON`
**(C) Display transactions having different properties**\
`list`\
`list <type>`\
`list [ < | = | > ] <value>`\
`list balance <day>`\
e.g.\
`list` display all transactions\
`list in` display all `in` transactions\
`list > 100` - display all transactions having an amount of money `>100`\
`list = 67` - display all transactions having an amount of money `=67`\
`list balance 10` compute the accounts balance at the end of day 10. This is the sum of all `in` transactions, from which we subtract `out` transactions occurring before or on day 10
**(D) Filter**\
`filter <type>`\
`filter <type> <value>`\
e.g.\
`filter in` keep only `in` transactions\
`filter in 100` keep only `in` transactions having an amount of money smaller than `100 RON`
**(E) Undo**\
`undo` the last operation that modified program data is reversed. The user can undo all operations performed since program start by repeatedly calling this function.
---
### 5. Apartment Building Administrator
Jane is the administrator of an apartment building and she wants to manage the monthly expenses for each apartment. Each expense is stored using the following elements: `apartment` (*number of apartment, positive integer*), `amount` (*positive integer*), `type` (*from one of the predefined categories `water`, `heating`, `electricity`, `gas` and `other`*). Write a program that implements the functionalities exemplified below:
**(A) Add new transaction**\
`add <apartment> <type> <amount>`\
e.g.\
`add 25 gas 100` add to apartment 25 an expense for `gas` in amount of `100 RON`
**(B) Modify expenses**\
`remove <apartment>`\
`remove <start apartment> to <end apartment>`\
`remove <type>`\
`replace <apartment> <type> with <amount>`\
e.g.\
`remove 15` remove all expenses for apartment 15\
`remove 5 to 10` remove all expenses for apartments between 5 and 10\
`remove gas` remove all `gas` expenses from all apartments\
`replace 12 gas with 200` replace the amount of the expense with type `gas` for apartment 12 with `200 RON`
**(C) Display expenses having different properties**\
`list`\
`list <apartment>`\
`list [ < | = | > ] <amount>`\
e.g.\
`list` display all expenses\
`list 15` display all expenses for apartment 15\
`list > 100` - display all apartments having total expenses `>100 RON`\
`list = 17` - display all apartments having total expenses `=17 RON`
**(D) Filter**\
`filter <type>`\
`filter <value>`\
e.g.\
`filter gas` keep only expenses for `gas`\
`filter 300` keep only expenses having an amount of money smaller than 300 RON
**(E) Undo**\
`undo` the last operation that modified program data is reversed. The user can undo all operations performed since program start by repeatedly calling this function.
@@ -0,0 +1,174 @@
#
# The program's functions are implemented here. There is no user interaction in this file, therefore no input/print statements. Functions here
# communicate via function parameters, the return statement and raising of exceptions.
#
from list_repr import *
import random
def generate_list(contestants_list:list[list[int]],n:int)->None:
for i in range(n):
contestant=create_contestant(random.randint(0,10),random.randint(0,10),random.randint(0,10))
contestants_list.append(contestant)
def add_contestant(contestants_list:list[list[int]],grades:list[str])->None:
"""
:params: contestants_list - list[list[int,int]]
grades - list[str]
:return: None
The function checks the validity of the inputed data and throws exceptions accordingly.
Afterwares the function create a new contestant and add it to the contestants_list
:syntax:
add <P1 score> <P2 score> <P3 score>
"""
if len(grades)!=3:
raise ValueError("Invalid number of grades")
for grade in grades:
if not grade.isdecimal() or int(grade)>10 or int(grade)<0:
raise ValueError("Grades must be integers between 0 and 10")
contestant=create_contestant(int(grades[0]),int(grades[1]),int(grades[2]))
contestants_list.append(contestant)
def insert_contestant(contestants_list:list[list[int]],command_params:list[str]):
"""
:params: contestants_list - list[list[int,int]]
command_params - list[str]
:return: None
The function checks the validity of the inputed data and throws exceptions accordingly.
Afterwares the function create a new contestant and add it to the contestants_list at the position indicated by the command_params
:syntax: insert <P1 score> <P2 score> <P3 score> at <position>
"""
if len(command_params)!=5:
raise ValueError("Invalid number of parameters")
if command_params[3]!="at":
raise SyntaxError("Command must of format: \'insert <P1 score> <P2 score> <P3 score> at <position>\'")
for grade in command_params[:3]:
if not grade.isdecimal() or int(grade)>10 or int(grade)<0:
raise ValueError("Grades must be integers between 0 and 10")
if len(contestants_list) < int(command_params[4]):
raise ValueError("Position out of range")
contestant=create_contestant(int(command_params[0]),int(command_params[1]),int(command_params[2]))
contestants_list.insert(int(command_params[4]),contestant)
def list_contestants(contestants_list:list[list[int]],command_params:list[str]):
if command_params==[]:
return contestants_list
if command_params[0]=="sorted":
return sorted(contestants_list,key=get_average,reverse=True)
if len(command_params)!=2:
raise SyntaxError("Invalid number of parameters")
if not command_params[1].isdecimal() or int(command_params[1])>10 or int(command_params[1])<0:
raise ValueError("Grades must be integers between 0 and 10")
if command_params[0]=="<":
return list(filter(lambda x: get_average(x)<int(command_params[1]),contestants_list))
if command_params[0]=="=":
return list(filter(lambda x: get_average(x)==int(command_params[1]),contestants_list))
if command_params[0]==">":
return list(filter(lambda x: get_average(x)>int(command_params[1]),contestants_list))
raise SyntaxError("Invalid parameters for list command")
def top_contestants(contestants_list:list[list[int]],command_params:list[str]):
if not command_params[0].isdecimal() or len(contestants_list)<int(command_params[0]):
raise ValueError("Index of of range")
if len(command_params)==1:
return sorted(contestants_list,key=get_average,reverse=True)[:int(command_params[0])]
elif len(command_params)==2:
match command_params[1]:
case "P1":
return sorted(contestants_list,key=get_p1,reverse=True)[:int(command_params[0])]
case "P2":
return sorted(contestants_list,key=get_p2,reverse=True)[:int(command_params[0])]
case "P3":
return sorted(contestants_list,key=get_p3,reverse=True)[:int(command_params[0])]
case _:
raise ValueError("Argument does not match <P1 | P2 | P3>")
raise ValueError("Invalid number of parameters")
def replace_contestant(contestants_list:list[list[int]],command_params:list[str]):
"""
:params: contestants_list - list[list[int,int]]
command_params - list[str]
:return: None
The function checks the validity of the inputed data and throws exceptions accordingly.
Afterwares the function replaces the grades of the participant indicated by command_params with 0
:syntax:
replace <old score> <P1 | P2 | P3> with <new score>
"""
if len(command_params)!=4:
raise ValueError("Invalid number of parameters")
if command_params[2]!="with":
raise SyntaxError("Command must be of the form replace <old score> <P1 | P2 | P3> with <new score>")
if not command_params[0].isdecimal() or int(command_params[0])>=len(contestants_list) or not command_params[3].isdecimal() or int(command_params[3])>10 or int(command_params[3])<0:
raise ValueError("Grades must be integers between 0 and 10")
if int(command_params[0])>len(contestants_list)-1:
raise ValueError("Index out of range")
match command_params[1]:
case "P1":
set_p1(contestants_list[int(command_params[0])],int(command_params[3]))
case "P2":
set_p2(contestants_list[int(command_params[0])],int(command_params[3]))
case "P3":
set_p3(contestants_list[int(command_params[0])],int(command_params[3]))
case _:
raise ValueError("Argument does not match <P1 | P2 | P3>")
def remove_contestants(contestants_list:list[list[int]],command_params:list[str]):
"""
:params: contestants_list - list[list[int,int]]
command_params - list[str]
:return: None
The function checks the validity of the inputed data and throws exceptions accordingly.
Afterwares the function replaces the grades of the participant indicated by command_params with 0
:syntax:
remove <position>
remove <start position> to <end position>
remove [ < | = | > ] <score>
"""
match len(command_params):
case 1:
if command_params[0].isdecimal() and len(contestants_list)>int(command_params[0]):
set_p1(contestants_list[int(command_params[0])],0)
set_p2(contestants_list[int(command_params[0])],0)
set_p3(contestants_list[int(command_params[0])],0)
case 2:
if command_params[1].isdecimal() and int(command_params[1])<=10 and int(command_params[1])>=0:
match command_params[0]:
case "<":
for el in contestants_list:
if get_average(el)<int(command_params[1]):
set_p1(el,0)
set_p2(el,0)
set_p3(el,0)
case ">":
for el in contestants_list:
if get_average(el)>int(command_params[1]):
set_p1(el,0)
set_p2(el,0)
set_p3(el,0)
case "=":
for el in contestants_list:
if get_average(el)==int(command_params[1]):
set_p1(el,0)
set_p2(el,0)
set_p3(el,0)
case _:
raise SyntaxError("Invalid Syntax")
case 3:
if command_params[1]=="to":
if command_params[0].isdecimal() and command_params[2].isdecimal() and int(command_params[0])<len(contestants_list) and int(command_params[2])<len(contestants_list) and int(command_params[0])<int(command_params[2]):
for index in range(int(command_params[0]),int(command_params[2])+1):
set_p1(contestants_list[index],0)
set_p2(contestants_list[index],0)
set_p3(contestants_list[index],0)
else:
raise ValueError("Index out of range")
else:
raise SyntaxError("Invalid Syntax")
case _:
raise SyntaxError("Invalid number of parameters")
if __name__=="__main__":
from test import test_functions
test_functions()
@@ -0,0 +1,23 @@
def create_contestant(p1:int,p2:int,p3:int)->list[int]:
return [p1,p2,p3]
def get_p1(n:list[int])->int:
return n[0]
def get_p2(n:list[int])->int:
return n[1]
def get_p3(n:list[int])->int:
return n[2]
def set_p1(n:list[int],value:int)->None:
n[0]=value
def set_p2(n:list[int],value:int)->None:
n[1]=value
def set_p3(n:list[int],value:int)->None:
n[2]=value
def get_average(n:list[int])->float:
return sum(n)/3
@@ -0,0 +1,7 @@
#
# This module is used to invoke the program's UI and start it. It should not contain a lot of code.
#
from ui import UI
if __name__=="__main__":
UI()
@@ -0,0 +1,20 @@
from functions import *
def test_functions():
list=[]
add_contestant(list,["1","1","1"])
assert list==[[1,1,1]]
add_contestant(list,["2","2","2"])
assert list==[[1,1,1],[2,2,2]]
insert_contestant(list,["3","3","3","at","0"])
assert list==[[3,3,3],[1,1,1],[2,2,2]]
remove_contestants(list,["1"])
assert list==[[3,3,3],[0,0,0],[2,2,2]]
remove_contestants(list,['0','to','2'])
assert list==[[0,0,0],[0,0,0],[0,0,0]]
replace_contestant(list,["1","P2","with","10"])
assert list==[[0,0,0],[0,10,0],[0,0,0]]
print("All good")
if __name__=="__main__":
test_functions()
@@ -0,0 +1,70 @@
#Problem - 2
# This is the program's UI module. The user interface and all interaction with the user (print and input statements) are found here
#
import re
from functions import *
from copy import deepcopy
def parse_command(command:str)->list[str]:
command=command.strip()
command=re.split("\s+",command)
return command
def UI()->None:
contestants_list=[]
changes_stack=[]
generate_list(contestants_list,10)
while True:
command = input("> ")
command = parse_command(command)
match command[0]:
case "add":
try:
changes_stack.append(deepcopy(contestants_list))
add_contestant(contestants_list,command[1:])
except Exception as exception:
print(exception)
changes_stack.pop()
case "insert":
try:
changes_stack.append(deepcopy(contestants_list))
insert_contestant(contestants_list,command[1:])
except Exception as exception:
print(exception)
changes_stack.pop()
case "remove":
try:
changes_stack.append(deepcopy(contestants_list))
remove_contestants(contestants_list,command[1:])
except Exception as exception:
print(exception)
changes_stack.pop()
case "replace":
try:
changes_stack.append(deepcopy(contestants_list))
replace_contestant(contestants_list,command[1:])
except Exception as exception:
print(exception)
changes_stack.pop()
case "list":
try:
print(list_contestants(contestants_list,command[1:]))
except Exception as exception:
print(exception)
case "top":
try:
print(top_contestants(contestants_list,command[1:]))
except Exception as exception:
print(exception)
case "undo":
if changes_stack:
contestants_list=changes_stack.pop()
else:
print("No undo available")
case "exit":
break
case "":
continue
case _:
print("{} command does not exist".format(command[0]))