# -*- coding: utf-8 -*-
# python version 3.4 
import math 
 
from fractions import Fraction  # version python >= 2.6 
 
 
class MyError(Exception): 
    """Erreur custom""" 
 
    def __init__(self, value): 
        self.value = value 
 
    def __str__(self): 
        return repr(self.value) 
 
 
# ###Espaces vectoriels sur R ou Q avec produit scalaire et norme associée############## 
class VecteurKn: 
    """modélisation des vecteurs à n dimensions corps quelconque""" 
 
    def __init__(self, L): 
        """constructeur""" 
        self.V = L 
        self.n = len(L) 
 
    def __str__(self): 
        """représentation externe print, etc...""" 
        L = [str(x) for x in self.V] 
        return '(' + ",".join(L) + ')' 
 
    def __eq__(self, other): 
        """test d'égalité""" 
        return self.n == other.n and all(self.L[i] == other.L[i] for i in range(0, self.n)) 
 
    def __add__(self, other): 
        """addition des vecteurs""" 
        if self.n != other.n: 
            raise MyError("Tailles non concordantes") 
        else: 
            L = [self.V[i] + other.V[i] for i in range(0, self.n)] 
            return VecteurKn(L) 
 
    def __neg__(self): 
        """opposé d'un vecteur""" 
        return VecteurKn([-x for x in self.V]) 
 
    def __sub__(self, other): 
        """différence de deux vecteurs""" 
        return self + (-other) 
 
    def __rmul__(self, k): 
        """ produit par un scalaire """ 
        L = [k * x for x in self.V] 
        return VecteurKn(L) 
 
    def __mul__(self, other): 
        """produit scalaire""" 
        if self.n != other.n: 
            raise MyError("Tailles non concordantes") 
        return sum([self.V[i] * other.V[i] for i in range(0, self.n)]) 
 
    def norm(self): 
        """norme d'un vecteur""" 
        return math.sqrt(self * self) 
 
 
####fin de la définition des espaces vectoriels euclidiens############### 
 
###########Modélisation des espaces affines euclidiens################### 
class PointKn: 
    """modélisation des espaces affines K^n n et K quelconques""" 
 
    def __init__(self, L): 
        """constructeur""" 
        self.C = L  #coordonnées 
        self.n = len(L) 
 
    def __str__(self): 
        """représentation externe print, etc...""" 
        L = [str(x) for x in self.C] 
        return '(' + ",".join(L) + ')' 
 
    def __eq__(self, other): 
        """test d'égalité""" 
        return self.n == other.n and all(self.C[i] == other.C[i] for i in range(0, self.n)) 
 
    def __add__(self, vecteur): 
        """opération du groupe additif des vecteurs""" 
        if self.n != vecteur.n: 
            raise MyError("Tailles non concordantes") 
        else: 
            L = [self.C[i] + vecteur.V[i] for i in range(0, self.n)] 
            return PointKn(L) 
 
    def __sub__(self, other): 
        """vecteur différence de deux points""" 
        if self.n != other.n: 
            raise MyError("Tailles non concordantes") 
        else: 
            L = [self.C[i] - other.C[i] for i in range(0, self.n)] 
            return VecteurKn(L) 
 
    def dist(self, other): 
        """distance de deux points""" 
        V = other - self 
        return V.norm() 
 
 
###fin de la modélisation des espaces affines###################### 
 
 
def main(): 
    """programme de tests """ 
    U = VecteurKn([1, 2, 3]) 
    V = VecteurKn([1, 2, -1]) 
    print(U * V) 
    print(U.norm()) 
    A = PointKn([1, 2, 3]) 
    B = PointKn([4, 5, 6]) 
    print(A.dist(B)) 
 
 
if __name__ == '__main__': 
    main()