<jupyter_start><jupyter_text>Problem 1 Given the class "Vehicle"<jupyter_code>class Vehicle(object):
    def __init__(self, name, km = 0, num_wheels = None):
        self.name = name
        self.km = km
        self.num_wheels = num_wheels
    
    def add_km(self,*args):
        if any(type(arg) is not float for arg in args) or any(type(arg) is not int for arg in args):
            raise TypeError
        summation_km = sum(arg for arg in args)
        self.km += summation_km
    
    def __str__(self):
        return f"Car: {self.name}, kilometers travelled: {self.km}"<jupyter_output><empty_output><jupyter_text>Step 1 Modify the class so to - include a metod to accumulate travelled kilometres. The method can receive as input an arbitrary number or arguments to be added;- define __ str __ () to print on screen the vehicle's name and travelled kilometers.- define a few vehicles to test the class<jupyter_code>punto = Vehicle("Punto",km=10,num_wheels=4)
moto = Vehicle("Honda",km=100,num_wheels=2)
print(punto)
print(moto)<jupyter_output>Car: Punto, kilometers travelled: 10
Car: Honda, kilometers travelled: 100<jupyter_text>Step 2 Define the class "Car" extending the class "Vehicle". For the class "Car"- add a mandatory attribute plate- add a mandatory attribute for the list of owners (initially empty)- add the optional attributes year (defalt: None) and fuel (default: None)- add a method for adding an owner- override __ str __ () so to print as well the list of ownersDefine a few cars to test the class<jupyter_code>class Car(Vehicle):
    """
    For the class "Car"

        add a mandatory attribute plate
        add a mandatory attribute for the list of owners (initially empty)
        add the optional attributes year (defalt: None) and fuel (default: None)
        add a method for adding an owner
        override __ str __ () so to print as well the list of owners
    """
    def __init__(self,name,plate,owners,km = 0, num_wheels = None,year=None,fuel=None ):
        super().__init__(name,km,num_wheels)
        self.plate = plate
        self.owners = []
        self.year = year
        self.fuel = fuel
    
    def add_owner(self,owner: str):
        if len(owner) == 0:
            raise ValueError
        self.owners.append(owner)
    
    def __str__(self):
        string = super().__str__()
        string += "\nList of owners: \n"
        for owner in self.owners:
            string += f"\t{owner}"
        return string
punto = Car("Punto",4,[],km=10,num_wheels=4)
print(punto)<jupyter_output>Car: Punto, kilometers travelled: 10
List of owners:<jupyter_text>Step 3 Define the class "Bicycle" extending the class "Vehicle".For the class "Bicycle":- fix the number of wheels to 2- add a method to print on the screen if the bicycle is new (0 km), used but still good (01000 km).Define a few bikes to test the class<jupyter_code>class Bicycle(Vehicle):
    """
    For the class "Car"

        fix the number of wheels to 2
        add a method to print on the screen if the bicycle is new (0 km), used but still good (0<x<1000 km) or to be dismissed (>1000 km).
    """
    def __init__(self,name,km = 0):
        super().__init__(name,km,num_wheels=2)
    
    def is_new(self):
        if self.km == 0:
            print("The bycicle is new")
            return
        print("The bycicle has been already used")

honda = Bicycle("Honda",km=0)
honda.is_new()Bycicle<jupyter_output>The bycicle is new<jupyter_text>Problem 2 Given the class "Point", which represents a point in an n-dimensional space<jupyter_code>class Point(object):
    
    def __init__(self, *args, label=''):
        self.coords = [x for x in args]
        self.label = label
        
    def __str__(self):
        return " ".join(str(x) for x in self.coords)
    
    def __len__(self):
        return len(self.coords)<jupyter_output><empty_output><jupyter_text>Step 1 Define the class "Vector" extending the class "Point".For the class "Vector"- define a method to compute the module of the vector (euclidean distance from the origin). Hint: from math library import sqrt to use the square root function.- overload the operator " < " to know if a vector has a smaller module then other. - overload the operator " + " to compute the vector sum of two vectors.Note: it make sense to compare and sum only vectors having same dimensional space.Define a few vectors to test the class<jupyter_code>from math import sqrt
class Vector(Point):

    def module(self):
        """
            module: Compute the euclidean distance from the origin
        """
        return sqrt(sum([coordinate**2 for coordinate in self.coords]))
    
    def __lt__(self, other):
        if not isinstance(other,Vector): raise TypeError
        if len(self) != len(other): raise ValueError("Different dimension of other vector")
        return self.module() < other.module()
    
    def __add__(self, other): 
        if not isinstance(other,Vector): raise TypeError
        if len(self) != len(other): raise ValueError("Different dimension of other vector")
        return Vector([coordinate_1 + coordinate_2 for (coordinate_1,coordinate_2) in zip(self.coords, other.coords)],label=f"{self.label}+{other.label}")

# Define two vectors (same dimension)
A = Vector(2, 0, 0, label='A')
B = Vector(1, 0, 0, label='B')

# Compare their modules
print("A has a smaller module then B:", A < B)

# and compute the sum
C = A + B
print("A + B =", C)<jupyter_output>A has a smaller module then B: False
A + B = [3, 0, 0]<jupyter_text>Problem 3  Step 1 Define the class "Bot". It must include:- a mandatory attribute for the name;- an attribute for the position in the room. (two coordinates, default: 0 0)- define __ str __ () in order to print the bot name and position.<jupyter_code>class Bot:
    
    def __init__(self, name, coordinates = [0,0]):
      self.name = name
      self.coordinates = coordinates
    
    def __str__(self):
        return f"The Bot {self.name} is in position: {self.coordinates}"<jupyter_output><empty_output><jupyter_text>Step 2 Extend the class "Bot" in order to define "MovingBot". A moving bot is able to modify its position. - define a method to make a movement. It receives two arguments which indicate the correspondent movent in the x and in the y axes. If no arguments are passed, the moving bot takes a random movement (in the range of -5, 5 for each coordinate). Hint: from random library import randint(a, b) to get a random integer from a to b.<jupyter_code>from random import randint
class MovingBot(Bot):
    
    def movement(self, x = randint(-5,5), y = randint(-5,5)):
        old_coordinates = self.coordinates
        self.coordinates = [self.coordinates[0]+x,self.coordinates[1]+y]
        print(f"Robot move: from {old_coordinates} to {self.coordinates}")<jupyter_output><empty_output><jupyter_text>Step 3 Extend the class "Bot" in order to define "TalkingBot". A talking bot is able to say random sentences.- define a method to print a random sentence from its list (initially empty)- define a method to add a new sentence;<jupyter_code>from random import randint
class TalkingBot(Bot):
    
    def __init__(self, name, coordinates = [0,0]):
      super().__init__(name, coordinates)
      self._sentences = []
    
    @property
    def sentences(self):
      return self._sentences
    
    def add_sentence(sentence: str):
      self.sentence.append(sentence)
      
    def talk(self):
      if len(self.sentences) <= 1: 
        print("Robot says:...")
        return
      print(f"Robot says: {self.sentences[randint(0,len(self.sentences)-1)]}")<jupyter_output><empty_output><jupyter_text>Step 4 Define a "CoolBot", extending the classes "MovingBot" and "TalkingBot". - add a method "action" to perform a couple of a random movement (print it) and a random talk.<jupyter_code>class CoolBot(MovingBot, TalkingBot):
    
    def action(self):
        if randint(0,1) == 1: 
            self.movement()
            return
        self.talk()

emilio = CoolBot(name="Emilio")
for i in range(5):
    emilio.action()<jupyter_output>Robot move: from [0, 0] to [-3, -2]
Robot move: from [-3, -2] to [-6, -4]
Robot says:...
Robot move: from [-6, -4] to [-9, -6]
Robot says:...
{'fraction_non_alphanumeric': 0.10233633487466537, 'fraction_numerical': 0.012290094913604284, 'mean_word_length': 3.3053954950235727, 'pattern_counts': {'":': 1, '<': 42, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '10', 'dir': 'jupyter-structured-clean-dedup', 'id': '323051', 'license': 'MIT', 'n_tokens_mistral': 2583, 'n_tokens_neox': 2464, 'n_words': 938, 'path': 'Ex 6/ex6.ipynb', 'repo_name': 'christiandimaio/Programming-For-DataScience', 'size': '8218'}