def get_random_points(N):
    """
    Gibt eine Liste mit N zufaelligen Punkten [x,y] (x,y aus [0.,1.[) zurueck.
    """
    from random import random
    plist=[]
    for i in range(N):
        plist.append([random(),random()])
    return plist


def get_mean(a):
    """
    Gibt den Mittelwert von a zurueck
    """
    return sum(a)/float(len(a))


def get_sig(a):
    """
    Gibt die Standardabweichung des Mittelwertes von a zurueck
    """
    from math import sqrt
    sig=0.
    meana=get_mean(a)
    for val in a:
        sig+=(meana-val)**2
    return sqrt(sig)/float(len(a))


def gerade(x,a,b):
    """
    Gibt den y-Wert einer Geraden y=a*x+b zurueck
    """
    return a*x+b
    
def invgerade(y,a,b):
    """
    Gibt den x-Wert einer Geraden y=a*x+b zurueck
    """
    if a!=0.:
        return (y-b)/a
    else:
        return b

def get_pi(N,points=0):
    """
    Bestimmt den Wert von pi mithilfe der Monte Carlo Integration mit N Punkten
    und gibt den Wert zurueck.
    Wenn points gesetzt (!=0) ist werden die Punkte in- und ausserhalb
    des Kreises ebenfalls zurueck gegeben.
    """
    from math import sqrt
    p=get_random_points(N)
    incircp,outcircp=[],[]
    for val in p:
        if sqrt(val[0]**2+val[1]**2)<=1.:
            incircp.append(val)
        else:
            outcircp.append(val)
    if points:
        return 4*float(len(incircp))/float(N),incircp,outcircp
    else:
        return 4*float(len(incircp))/float(N)

def det_pi(NI,N0,points=0):
    """
    Bestimmt NI mal den Wert von pi anhand von N0 Punkten und gibt den
    Mittelwert und die Standardabweichung des Mittelwertes zurueck.
    """
    pilist=[]
    if points:
        pi,inp,outp=get_pi(N0,points)
        pilist.append(pi)
        NI-=1
    for i in range(NI):
        pilist.append(get_pi(N0))
    pi=get_mean(pilist)
    sigpi=get_sig(pilist)
    if points:
        return pi,sigpi,inp,outp
    else:
        return pi,sigpi

def det_area(N,param):
    """
    Bestimmt die Flaeche die von 4 Geraden eingesclossen wird.
    param -> [[a1,b1],[a2,b2],[a3,b3],[a4,b4]] definiert die 4
    einschliessenden Geraden a*x+b.
    Gibt die berechnete Flaeche sowie die Punkte die in- bzw.
    ausserhalb der Flaeche liegen zurueck.
    """
    p=get_random_points(N)
    inareap,outareap=[],[]
    for val in p:
        if gerade(val[0],param[0][0],param[0][1])<=val[1]:
            if gerade(val[0],param[1][0],param[1][1])>=val[1]:
                if invgerade(val[1],param[2][0],param[2][1])<=val[0]:
                    if invgerade(val[1],param[3][0],param[3][1])>=val[0]:
                        inareap.append(val)
                    else:
                        outareap.append(val)
                else:
                    outareap.append(val)
            else:
                outareap.append(val)
        else:
            outareap.append(val)
    return float(len(inareap))/float(N),inareap,outareap
