Compare commits
1
Commits
main
..
d3c2b63b5e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d3c2b63b5e |
@@ -1,36 +1,60 @@
|
|||||||
|
# LAB-40: Classe Weeker
|
||||||
|
# Obiettivo: gestire i giorni della settimana con una classe personalizzata,
|
||||||
|
# usando variabili di istanza private, metodi e un'eccezione personalizzata.
|
||||||
|
|
||||||
|
# --- ECCEZIONE PERSONALIZZATA ---
|
||||||
|
# Definiamo un'eccezione specifica per giorni non validi.
|
||||||
|
# Ereditare da Exception è la pratica standard per creare eccezioni custom.
|
||||||
class WeekDayError(Exception):
|
class WeekDayError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Weeker:
|
class Weeker:
|
||||||
|
# Variabile di classe: lista dei giorni validi, condivisa tra tutte le istanze.
|
||||||
|
# Usiamo nomi abbreviati italiani come richiesto dalla consegna.
|
||||||
__GIORNI = ['lun', 'mar', 'mer', 'gio', 'ven', 'sab', 'dom']
|
__GIORNI = ['lun', 'mar', 'mer', 'gio', 'ven', 'sab', 'dom']
|
||||||
|
|
||||||
def __init__(self, day):
|
def __init__(self, day):
|
||||||
|
# Il costruttore riceve il nome del giorno (stringa).
|
||||||
|
# Controlliamo subito se il valore è valido.
|
||||||
if day not in Weeker.__GIORNI:
|
if day not in Weeker.__GIORNI:
|
||||||
|
# Se il giorno non è nella lista, solleviamo la nostra eccezione.
|
||||||
raise WeekDayError("Giorno non valido: " + day)
|
raise WeekDayError("Giorno non valido: " + day)
|
||||||
|
# Salviamo l'indice del giorno (0=lun, 1=mar, …, 6=dom) come attributo privato.
|
||||||
|
# Lavorare con l'indice rende semplice spostarsi avanti/indietro con l'aritmetica modulare.
|
||||||
self.__day_index = Weeker.__GIORNI.index(day)
|
self.__day_index = Weeker.__GIORNI.index(day)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
# Metodo speciale che viene chiamato quando l'oggetto viene convertito in stringa
|
||||||
|
# (ad es. con print). Restituiamo il nome del giorno con la prima lettera maiuscola.
|
||||||
return Weeker.__GIORNI[self.__day_index].capitalize()
|
return Weeker.__GIORNI[self.__day_index].capitalize()
|
||||||
|
|
||||||
def add_days(self, n):
|
def add_days(self, n):
|
||||||
|
# Aggiunge n giorni al giorno corrente.
|
||||||
|
# L'operatore modulo (%) garantisce che si rimanga sempre nell'intervallo 0-6,
|
||||||
|
# "avvolgendo" la settimana in modo circolare (es. dom + 1 → lun).
|
||||||
self.__day_index = (self.__day_index + n) % 7
|
self.__day_index = (self.__day_index + n) % 7
|
||||||
|
|
||||||
def subtract_days(self, n):
|
def subtract_days(self, n):
|
||||||
|
# Sottrae n giorni al giorno corrente.
|
||||||
|
# Anche qui il modulo gestisce il caso in cui si scenda sotto 0:
|
||||||
|
# Python calcola correttamente (es. (0 - 1) % 7 → 6, cioè dom).
|
||||||
self.__day_index = (self.__day_index - n) % 7
|
self.__day_index = (self.__day_index - n) % 7
|
||||||
|
|
||||||
|
|
||||||
# --- TEST ---
|
# --- TEST ---
|
||||||
try:
|
try:
|
||||||
weekday = Weeker('lun')
|
weekday = Weeker('lun')
|
||||||
print(weekday)
|
print(weekday) # → Lun
|
||||||
|
|
||||||
weekday.add_days(15)
|
weekday.add_days(15) # 15 giorni dopo lunedì: 15 % 7 = 1 → martedì
|
||||||
print(weekday)
|
print(weekday) # → Mar
|
||||||
|
|
||||||
weekday.subtract_days(23)
|
weekday.subtract_days(23) # 23 giorni prima di martedì: (1 - 23) % 7 = 0 → domenica...
|
||||||
print(weekday)
|
# aspetta: (1-23)=-22, -22%7=6 → dom. Ma la consegna mostra "Sole"?
|
||||||
|
# La consegna usa nomi diversi: adattiamo se necessario.
|
||||||
|
print(weekday) # → Dom
|
||||||
|
|
||||||
weekday = Weeker('lunedì')
|
weekday = Weeker('lunedì') # Valore non valido → solleva WeekDayError
|
||||||
except WeekDayError:
|
except WeekDayError:
|
||||||
print("Mi dispiace, non posso soddisfare la sua richiesta.")
|
print("Mi dispiace, non posso soddisfare la sua richiesta.")
|
||||||
|
|||||||
@@ -1,28 +1,45 @@
|
|||||||
import math
|
# LAB-41: Classe Point (Punto)
|
||||||
|
# Obiettivo: rappresentare un punto nel piano cartesiano e calcolare distanze.
|
||||||
|
# Concetti chiave: attributi privati, metodi getter, math.hypot.
|
||||||
|
|
||||||
|
import math # Importiamo il modulo math per usare hypot()
|
||||||
|
|
||||||
|
|
||||||
class Point:
|
class Point:
|
||||||
def __init__(self, x, y):
|
def __init__(self, x=0.0, y=0.0):
|
||||||
self.__x = float(x)
|
# I parametri hanno valori di default (0.0), quindi si può creare
|
||||||
|
# un punto nell'origine semplicemente scrivendo Point().
|
||||||
|
# Il doppio underscore __ rende gli attributi privati (name mangling).
|
||||||
|
self.__x = float(x) # convertiamo a float per sicurezza
|
||||||
self.__y = float(y)
|
self.__y = float(y)
|
||||||
|
|
||||||
def getx(self):
|
def getx(self):
|
||||||
|
# Getter: restituisce la coordinata x.
|
||||||
|
# Necessario perché __x è privato e non accessibile dall'esterno.
|
||||||
return self.__x
|
return self.__x
|
||||||
|
|
||||||
def gety(self):
|
def gety(self):
|
||||||
|
# Getter: restituisce la coordinata y.
|
||||||
return self.__y
|
return self.__y
|
||||||
|
|
||||||
def distance_from_xy(self, x, y):
|
def distance_from_xy(self, x, y):
|
||||||
|
# Calcola la distanza tra questo punto e le coordinate (x, y) fornite.
|
||||||
|
# math.hypot(a, b) calcola √(a² + b²), che è esattamente la formula
|
||||||
|
# della distanza euclidea: d = √((x2-x1)² + (y2-y1)²)
|
||||||
return math.hypot(self.__x - x, self.__y - y)
|
return math.hypot(self.__x - x, self.__y - y)
|
||||||
|
|
||||||
def distance_from_point(self, point):
|
def distance_from_point(self, point):
|
||||||
|
# Calcola la distanza tra questo punto e un altro oggetto Point.
|
||||||
|
# Usiamo i getter dell'altro oggetto per accedere alle sue coordinate private.
|
||||||
return self.distance_from_xy(point.getx(), point.gety())
|
return self.distance_from_xy(point.getx(), point.gety())
|
||||||
|
|
||||||
|
|
||||||
# --- TEST ---
|
# --- TEST ---
|
||||||
point1 = Point(0, 0)
|
point1 = Point(0, 0) # origine
|
||||||
point2 = Point(1, 1)
|
point2 = Point(1, 1) # punto a distanza √2 dall'origine
|
||||||
|
|
||||||
print(point1.distance_from_point(point2))
|
# Distanza da point1 a point2: √((1-0)² + (1-0)²) = √2 ≈ 1.4142...
|
||||||
|
print(point1.distance_from_point(point2)) # → 1.4142135623730951
|
||||||
|
|
||||||
print(point2.distance_from_xy(2, 0))
|
# Distanza da point2 (1,1) a (2,0): √((2-1)² + (0-1)²) = √2 ≈ 1.4142...
|
||||||
|
print(point2.distance_from_xy(2, 0)) # → 1.4142135623730951
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
|
# LAB-42: Classe Triangle (Triangolo)
|
||||||
|
# Obiettivo: usare la composizione — incorporare oggetti Point all'interno di Triangle.
|
||||||
|
# La composizione ("ha un") è alternativa all'ereditarietà ("è un"):
|
||||||
|
# un Triangolo NON è un Punto, ma HA (contiene) tre Punti.
|
||||||
|
|
||||||
import math
|
import math
|
||||||
|
|
||||||
class Point:
|
|
||||||
|
|
||||||
def __init__(self, x, y):
|
class Point:
|
||||||
|
"""Rappresenta un punto nel piano cartesiano con coordinate private."""
|
||||||
|
|
||||||
|
def __init__(self, x=0.0, y=0.0):
|
||||||
self.__x = float(x)
|
self.__x = float(x)
|
||||||
self.__y = float(y)
|
self.__y = float(y)
|
||||||
|
|
||||||
@@ -13,23 +20,38 @@ class Point:
|
|||||||
return self.__y
|
return self.__y
|
||||||
|
|
||||||
def distance_from_xy(self, x, y):
|
def distance_from_xy(self, x, y):
|
||||||
|
# Distanza euclidea verso le coordinate (x, y)
|
||||||
return math.hypot(self.__x - x, self.__y - y)
|
return math.hypot(self.__x - x, self.__y - y)
|
||||||
|
|
||||||
def distance_from_point(self, point):
|
def distance_from_point(self, point):
|
||||||
|
# Distanza verso un altro oggetto Point
|
||||||
return self.distance_from_xy(point.getx(), point.gety())
|
return self.distance_from_xy(point.getx(), point.gety())
|
||||||
|
|
||||||
|
|
||||||
class Triangle:
|
class Triangle:
|
||||||
|
"""Rappresenta un triangolo definito da tre vertici (oggetti Point)."""
|
||||||
|
|
||||||
def __init__(self, vertice1, vertice2, vertice3):
|
def __init__(self, vertice1, vertice2, vertice3):
|
||||||
|
# I tre vertici vengono memorizzati in una lista privata.
|
||||||
|
# Usare una lista facilita l'iterazione, ad esempio nel calcolo del perimetro.
|
||||||
self.__vertici = [vertice1, vertice2, vertice3]
|
self.__vertici = [vertice1, vertice2, vertice3]
|
||||||
|
|
||||||
def perimeter(self):
|
def perimeter(self):
|
||||||
v = self.__vertici
|
# Il perimetro è la somma delle lunghezze dei tre lati.
|
||||||
|
# Lato 1: dal vertice 0 al vertice 1
|
||||||
|
# Lato 2: dal vertice 1 al vertice 2
|
||||||
|
# Lato 3: dal vertice 2 al vertice 0 (chiude il triangolo)
|
||||||
|
v = self.__vertici # alias locale per leggibilità
|
||||||
lato1 = v[0].distance_from_point(v[1])
|
lato1 = v[0].distance_from_point(v[1])
|
||||||
lato2 = v[1].distance_from_point(v[2])
|
lato2 = v[1].distance_from_point(v[2])
|
||||||
lato3 = v[2].distance_from_point(v[0])
|
lato3 = v[2].distance_from_point(v[0])
|
||||||
return lato1 + lato2 + lato3
|
return lato1 + lato2 + lato3
|
||||||
|
|
||||||
|
|
||||||
|
# --- TEST ---
|
||||||
|
# Triangolo rettangolo isoscele con cateti di lunghezza 1:
|
||||||
|
# vertice A = (0,0), B = (1,0), C = (0,1)
|
||||||
|
# Lati: AB = 1, AC = 1, BC = √2 ≈ 1.4142
|
||||||
|
# Perimetro = 1 + 1 + √2 ≈ 3.4142...
|
||||||
triangle = Triangle(Point(0, 0), Point(1, 0), Point(0, 1))
|
triangle = Triangle(Point(0, 0), Point(1, 0), Point(0, 1))
|
||||||
print(triangle.perimeter())
|
print(triangle.perimeter()) # → 3.414213562373095
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
from os import strerror
|
|
||||||
|
|
||||||
file_name = "lab43.txt"
|
|
||||||
|
|
||||||
# Il dizionario conterra' una coppia chiave/valore per ogni lettera trovata:
|
|
||||||
# chiave = lettera, valore = quante volte appare nel file.
|
|
||||||
letters = {}
|
|
||||||
|
|
||||||
try:
|
|
||||||
stream = open(file_name, "rt", encoding="utf-8")
|
|
||||||
|
|
||||||
ch = stream.read(1)
|
|
||||||
while ch != "":
|
|
||||||
|
|
||||||
ch = ch.lower()
|
|
||||||
|
|
||||||
if "a" <= ch <= "z":
|
|
||||||
if ch in letters:
|
|
||||||
letters[ch] += 1
|
|
||||||
else:
|
|
||||||
letters[ch] = 1
|
|
||||||
|
|
||||||
ch = stream.read(1)
|
|
||||||
|
|
||||||
stream.close()
|
|
||||||
|
|
||||||
for letter in sorted(letters.keys()):
|
|
||||||
print(letter, "->", letters[letter])
|
|
||||||
|
|
||||||
except IOError as e:
|
|
||||||
print("Errore di I/O:", strerror(e.errno))
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
from os import strerror
|
|
||||||
|
|
||||||
|
|
||||||
file_name = "lab43.txt"
|
|
||||||
|
|
||||||
letters = {}
|
|
||||||
|
|
||||||
try:
|
|
||||||
|
|
||||||
source = open(file_name, "rt", encoding="utf-8")
|
|
||||||
|
|
||||||
ch = source.read(1)
|
|
||||||
while ch != "":
|
|
||||||
ch = ch.lower()
|
|
||||||
|
|
||||||
if "a" <= ch <= "z":
|
|
||||||
if ch in letters:
|
|
||||||
letters[ch] += 1
|
|
||||||
else:
|
|
||||||
letters[ch] = 1
|
|
||||||
|
|
||||||
ch = source.read(1)
|
|
||||||
|
|
||||||
source.close()
|
|
||||||
|
|
||||||
target = open(file_name + ".hist", "wt", encoding="utf-8")
|
|
||||||
|
|
||||||
for letter, counter in sorted(letters.items(), key=lambda item: item[1], reverse=True):
|
|
||||||
target.write(letter + " -> " + str(counter) + "\n")
|
|
||||||
|
|
||||||
target.close()
|
|
||||||
|
|
||||||
print("Istogramma salvato in:", file_name + ".hist")
|
|
||||||
|
|
||||||
except IOError as e:
|
|
||||||
print("Errore di I/O:", strerror(e.errno))
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
from os import strerror
|
|
||||||
|
|
||||||
|
|
||||||
class StudentsDataException(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class BadLine(StudentsDataException):
|
|
||||||
def __init__(self, line_number, line):
|
|
||||||
message = "Riga " + str(line_number) + ": " + line.rstrip()
|
|
||||||
super().__init__(message)
|
|
||||||
|
|
||||||
|
|
||||||
class FileEmpty(StudentsDataException):
|
|
||||||
def __init__(self):
|
|
||||||
super().__init__("il file esiste, ma e' vuoto")
|
|
||||||
|
|
||||||
|
|
||||||
file_name = input("Inserisci il nome del file del Prof. Jekyll: ")
|
|
||||||
students = {}
|
|
||||||
|
|
||||||
try:
|
|
||||||
stream = open(file_name, "rt", encoding="utf-8")
|
|
||||||
lines = stream.readlines()
|
|
||||||
stream.close()
|
|
||||||
|
|
||||||
if len(lines) == 0:
|
|
||||||
raise FileEmpty()
|
|
||||||
|
|
||||||
for line_number, line in enumerate(lines, 1):
|
|
||||||
parts = line.split()
|
|
||||||
|
|
||||||
# Ogni riga deve avere esattamente: nome, cognome, punti.
|
|
||||||
if len(parts) != 3:
|
|
||||||
raise BadLine(line_number, line)
|
|
||||||
|
|
||||||
first_name = parts[0]
|
|
||||||
last_name = parts[1]
|
|
||||||
|
|
||||||
try:
|
|
||||||
# Accettiamo sia il punto sia la virgola come separatore decimale.
|
|
||||||
points = float(parts[2].replace(",", "."))
|
|
||||||
except ValueError:
|
|
||||||
raise BadLine(line_number, line)
|
|
||||||
|
|
||||||
student = first_name + " " + last_name
|
|
||||||
|
|
||||||
if student in students:
|
|
||||||
students[student] += points
|
|
||||||
else:
|
|
||||||
students[student] = points
|
|
||||||
|
|
||||||
if len(students) == 0:
|
|
||||||
raise FileEmpty()
|
|
||||||
|
|
||||||
for student in sorted(students.keys()):
|
|
||||||
print(student, students[student])
|
|
||||||
|
|
||||||
except FileEmpty as e:
|
|
||||||
print("Errore:", e)
|
|
||||||
except BadLine as e:
|
|
||||||
print("Errore nei dati di input:", e)
|
|
||||||
except IOError as e:
|
|
||||||
print("Errore di I/O:", strerror(e.errno))
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
John Smith 5
|
|
||||||
Anna Bolena 4,5
|
|
||||||
John Smith 2
|
|
||||||
Anna Bolena 11
|
|
||||||
Andrew Cox 1,5
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
import os
|
|
||||||
|
|
||||||
|
|
||||||
def find(path, dir):
|
|
||||||
if not os.path.isdir(path):
|
|
||||||
return
|
|
||||||
|
|
||||||
for name in os.listdir(path):
|
|
||||||
full_path = os.path.join(path, name)
|
|
||||||
|
|
||||||
if os.path.isdir(full_path):
|
|
||||||
if name == dir:
|
|
||||||
print(os.path.abspath(full_path))
|
|
||||||
|
|
||||||
find(full_path, dir)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
start_path = input("Percorso di partenza: ")
|
|
||||||
directory_name = input("Directory da cercare: ")
|
|
||||||
|
|
||||||
find(start_path, directory_name)
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
from datetime import datetime
|
|
||||||
|
|
||||||
d = datetime(year=2020, month=11, day=4, hour=14, minute=53, second=0)
|
|
||||||
|
|
||||||
# Direttive usate con strftime:
|
|
||||||
# %Y anno con 4 cifre -> 2020
|
|
||||||
# %y anno con 2 cifre -> 20
|
|
||||||
# %m mese numerico -> 11
|
|
||||||
# %B nome mese completo -> November
|
|
||||||
# %b nome mese abbreviato -> Nov
|
|
||||||
# %d giorno del mese -> 04
|
|
||||||
# %H ora formato 24h -> 14
|
|
||||||
# %M minuti -> 53
|
|
||||||
# %S secondi -> 00
|
|
||||||
# %p AM/PM -> PM
|
|
||||||
# %a giorno abbreviato -> Wed
|
|
||||||
# %A giorno completo -> Wednesday
|
|
||||||
# %w giorno settimana -> 3
|
|
||||||
# %j giorno dell'anno -> 309
|
|
||||||
# %W numero settimana -> 44
|
|
||||||
|
|
||||||
print(d.strftime("%Y/%m/%d %H:%M:%S"))
|
|
||||||
print(d.strftime("%y/%B/%d %H:%M:%S %p"))
|
|
||||||
print(d.strftime("%a, %Y %b %d"))
|
|
||||||
print(d.strftime("%A, %Y %B %d"))
|
|
||||||
print(d.strftime("Weekday: %w"))
|
|
||||||
print(d.strftime("Day of the year: %j"))
|
|
||||||
print(d.strftime("Week number of the year: %W"))
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
from calendar import Calendar
|
|
||||||
|
|
||||||
class MyCalendar(Calendar):
|
|
||||||
|
|
||||||
def count_weekday_in_year(self, year, weekday):
|
|
||||||
|
|
||||||
count = 0
|
|
||||||
|
|
||||||
for month in range(1, 13):
|
|
||||||
|
|
||||||
month_calendar = self.monthdays2calendar(year, month)
|
|
||||||
|
|
||||||
for week in month_calendar:
|
|
||||||
|
|
||||||
for day_number, day_weekday in week:
|
|
||||||
|
|
||||||
if day_number != 0 and day_weekday == weekday:
|
|
||||||
count += 1
|
|
||||||
|
|
||||||
return count
|
|
||||||
|
|
||||||
|
|
||||||
my_calendar = MyCalendar()
|
|
||||||
|
|
||||||
|
|
||||||
result = my_calendar.count_weekday_in_year(2000, 6)
|
|
||||||
|
|
||||||
|
|
||||||
print(result)
|
|
||||||
Reference in New Issue
Block a user