Code: Alles auswählen
import re
try:
from itertools import izip as zip
except ImportError:
def enumerate(seq):
return zip(xrange(len(seq)),seq)
from operator import add
def sum(seq):
return reduce(add,seq,0)
def makeBruchLines(lines):
b=Bruch()
return [[b*num for num in line] for line in lines]
def makeBruchMatrix(matrix):
if not isinstance(matrix,Matrix):
raise TypeError,"Matrix als Argument erwartet"
return Matrix(*makeBruchLines(matrix.getlines()))
class Bruch(object):
__slots__=["_float_regex","z","n"]
_float_regex=re.compile('(\d*)\.(\d*)e?([\+-]?)(\d{0,3})')
def __init__(self,z=1,n=1):
if isinstance(z,Bruch) or isinstance(n,Bruch):
z,n=(z/n).gettuple()
else:
z,n=map(int,(z,n))
if n>=0:
self.z,self.n=z,n
else:
self.z,self.n=[-z,-n]
t = self._ggt(self.z,self.n)
self.z,self.n=self.z/t,self.n/t
if self.n==0:
raise ZeroDivisionError, "integer division or modulo by zero"
def gettuple(self):
"""Gibt das Tupel (Zaehler,Nenner) zureuck"""
return self.z,self.n
def _forceBruch(self,wert):
if isinstance(wert,Bruch):
return wert
elif (type(wert) in (int,long)) or (wert % 1 == 0):
return Bruch(wert,1)
elif type(wert) == float:
temp=self._float_regex.match(repr(wert)).groups()
z=long(temp[0])*(10L**len(temp[1]))+long(temp[1])
n=10L**len(temp[1])
if temp[2]=='+':
z*=10L**long(temp[3])
if temp[2]=='-':
n*=10L**long(temp[3])
return Bruch(z,n)
else:
raise TypeError,"no compatiple type for operation"
def _ggt(self,x,y):
while y > 0:
x,y=y,x%y
return x
def _kgv(self,x,y):
return (x/self._ggt(x,y))*y
def __add__(self,other):
other = self._forceBruch(other)
return Bruch(self.z * other.n + other.z * self.n, self.n * other.n)
def __cmp__(self,other):
try:
other = self._forceBruch(other)
except TypeError:
return cmp(id(self),id(other))
else:
kgv=self._kgv(self.n,other.n)
zself=self.z*(kgv/self.n)
zother=other.z*(kgv/other.n)
return cmp(zself,zother)
def __div__(self,other):
other = self._forceBruch(other)
if other.z==0L:
raise ZeroDivisionError, "integer division or modulo by zero"
return Bruch(self.z * other.n, self.n * other.z)
def __divmod__(self,other):
other = self._forceBruch(other)
return (self.__div__(other),self.__mod__(other))
def __mod__(self,other):
other = self._forceBruch(other)
if other.z==0:
raise ZeroDivisionError, "integer division or modulo by zero"
ns=self._kgv(self.n,other.n)
zself=self.z*(ns/self.n)
zother=other.z*(ns/other.n)
return Bruch(zself%zother,ns)
def __mul__(self,other):
other = self._forceBruch(other)
if other.n==0L:
raise ZeroDivisionError, "integer division or modulo by zero"
return Bruch(self.z * other.z, self.n * other.n)
def __pow__(self,other,z=None):
if (other%1)==0:
other = self._forceBruch(other)
if other.z>=0:
erg=Bruch(self.z**other.z,self.n**other.z)
else:
erg=Bruch(self.n**(-other.z),self.z**(-other.z))
else:
tempself=float(self)
tempother=float(other)
erg=self._forceBruch(tempself**tempother)
if z==None:
return erg
else:
return erg%z
def __radd__(self,other):
return self.__add__(other)
def __rdiv__(self,other):
other = self._forceBruch(other)
if self.z==0L:
raise ZeroDivisionError, "integer division or modulo by zero"
return Bruch(other.z * self.n, other.n * self.z)
def __rdivmod__(self,other):
return (self.__rdiv__(other),self.__rmod__(other))
def __rmod__(self,other):
other = self._forceBruch(other)
if self.z==0:
raise ZeroDivisionError, "integer division or modulo by zero"
ns=self._kgv(self.n,other.n)
zself=self.z*(ns/self.n)
zother=other.z*(ns/other.n)
return Bruch(zother%zself,ns)
def __rmul__(self,other):
return self.__mul__(other)
def __rpow__(self,other,z=None):
if z==None:
return other**float(self)
else:
return (other**float(self))%z
def __rsub__(self,other):
other = self._forceBruch(other)
return Bruch(other.z * self.n - self.z * other.n, other.n * self.n)
def __sub__(self,other):
other = self._forceBruch(other)
return Bruch(self.z * other.n - other.z * self.n, self.n * other.n)
def __abs__(self):
return Bruch(abs(self.z),abs(self.n))
def __float__(self):
return float(self.z)/float(self.n)
def __int__(self):
return int(self.__long__())
def __long__(self):
if self.n==1:
return long(self.z)
else:
return long(float(self.z)/float(self.n))
def __neg__(self):
return Bruch(-self.z,self.n)
def __pos__(self):
return Bruch(self.z,self.n)
def __repr__(self):
return "Bruch(%i,%i)"%(self.z,self.n)
def __str__(self):
return "(%i / %i)"%(self.z,self.n)
class Matrix(object):
__slots__=["lines","type"]
def __init__(self,*lines):
m=len(lines)
self.lines=[]
if m:
temp=[]
for line in lines:
line=tuple(line)
self.lines.append(line)
temp.append(len(line))
temp.sort()
if temp[0]!=temp[-1]:
raise TypeError,"keine gueltige Matrix"
n=temp[0]
del temp
else:
raise TypeError,"keine gueltige Matrix"
self.type=(m,n)
def copy(self):
return Matrix(self.lines)
def getspalte(self,i):
return [line[i] for line in self.lines]
def getzeile(self,j):
return self.lines[j]
def getlines(self):
return self.lines
def adjunkte(self,i,j):
untermat=[l[:j]+l[j+1:] for num,l in enumerate(self.lines) if num!=i]
return ((i+j)%2==0 or -1)*Matrix(*untermat).det()
def det(self):
m,n=self.type
if m!=n:
raise ValueError,"Matrix muss n-reihig sein"
if m==1:
return self.lines[0][0]
elif m==2:
(a,b),(c,d)=self.lines
return a*d-b*c
elif m==3:
(a,b,c),(d,e,f),(g,h,i)=self.lines
return a*e*i+b*f*g+c*d*h-c*e*g-b*d*i-a*f*h
else:
det=0
zeile1=self.lines[0]
for j in xrange(n):
det+=zeile1[j]*self.adjunkte(0,j)
return det
def invert(self):
m,n=self.type
if m!=n:
print m,n
raise ValueError,"Matrix muss n-reihig sein"
d=self.det()
if d==0:
raise ValueError,"Matrix nicht regulaer"
elif d==1:
pass
else:
d=1.0/d
return Matrix(*[[self.adjunkte(i,j) for j in xrange(n)] for i in xrange(n)]).transponiere() * d
def transponiere(self):
return Matrix(*zip(*self.lines))
def __add__(self,other):
if isinstance(other,Matrix):
m,n=self.type
m_o,n_o=other.type
if m!=m_o or n!=n_o:
raise ValueError,"Matrizen nicht verkettbar"
return Matrix(*[[self.lines[i][j]+other.lines[i][j] for j in xrange(n)] for i in xrange(m)])
else:
raise TypeError,"nicht rechenbar (Matrix und %s)"%type(other)
def __div__(self,other):
if isinstance(other,Matrix):
raise ValueError,"nicht durch Matrizen teilbar"
return self.__mul__(1.0/other)
def __mul__(self,other):
if isinstance(other,Matrix):
m,n=self.type
m_o,n_o=other.type
if n!=m_o:
raise ValueError,"Matrizen nicht verkettbar"
newmat=[]
for i in xrange(m):
newmatline=[]
for j in xrange(n_o):
newmatline.append(sum([self.lines[i][k]*other.lines[k][j] for k in xrange(n)]))
newmat.append(newmatline)
return Matrix(*newmat)
else:
return Matrix(*[tuple([element*other for element in line]) for line in self.lines])
def __pow__(self,other):
if other%1!=0:
raise ValueError,"nicht rechenbar (Exponent muss ganzzahlig sein)"
m,n=self.type
if m!=n:
raise ValueError,"Matrix muss n-reihig sein"
mat=Matrix(*[[int(i==j) for j in xrange(n)] for i in xrange(n)])
for i in xrange(abs(other)):
mat*=self
if other < 0:
mat=mat.invert()
return mat
def __rmul__(self,other):
assert not isinstance(other,Matrix)
return Matrix(*[tuple([element*other for element in line]) for line in self.lines])
def __sub__(self,other):
if isinstance(other,Matrix):
m,n=self.type
m_o,n_o=other.type
if m!=m_o or n!=n_o:
raise ValueError,"Matrizen nicht verkettbar"
return Matrix(*[[self.lines[i][j]-other.lines[i][j] for j in xrange(n)] for i in xrange(m)])
else:
raise TypeError,"nicht rechenbar (Matrix und %s)"%type(other)
def __neg__(self):
return -1 * self
def __pos__(self):
return self
def __repr__(self):
return "Matrix( %r )" % self.lines