Teorija brojeva u pythonu ⇨ implementacija funkcija

Ovdje je implementirano nekoliko dodatnih funkcija za lakši i brži rad u pythonu.

Funkcije se nalaze u datoteci DSTG.py.

In [1]:
from ipy_table import *
import numpy as np
import itertools as it

Funkcija ispis ispisuje objekt tako da se u jednom retku nalazi najviše br znakova.

In [2]:
def ispis(objekt,br):
    objekt=str(objekt)
    d=len(objekt)
    red=d // br
    ostatak=d % br
    za_ispis=""
    for k in range(red):
        za_ispis=za_ispis+objekt[k*br:(k+1)*br]+"\n"
    if ostatak == 0:
        za_ispis = za_ispis[:-1]
    else:
        za_ispis = za_ispis+objekt[red*br:]
    print(za_ispis)

Funkcija kvocijent daje kvocijent dva cijela broja prema definiciji s predavanja.

In [3]:
def kvocijent(a,b): 
    if b==0: return "Error: dijeljenje s nulom" 
    elif b>0: 
        return int(np.floor(a/b)) 
    else: 
        return int(np.ceil(a/b))

Funkcija ostatak daje ostatak dva cijela broja prema definiciji s predavanja.

In [4]:
def ostatak(a,b): 
    if b==0: return "Error: dijeljenje s nulom" 
    elif b>0: 
        return int(a-np.floor(a/b)*b) 
    else: 
        return int(a-np.ceil(a/b)*b)

Funkcija euklid_rucno daje rucni postupak za prošireni Euklidov algoritam, tj. za određivanje jednog cjelobrojnog rješenja jednadžbe $ax+by=M(a,b)$. Rješenje daje u obliku rječnika ili html tablice ovisno o vrijednosti varijable izlaz.

In [5]:
def euklid_rucno(a,b,izlaz='html'): 
    qi = []
    xi = [1,0]
    yi = [0,1] 
    ri = [a,b]
    while True:
        q = ri[-2] // ri[-1]
        r = ri[-2]-q*ri[-1]
        if r != 0:
            qi.append(q)
            xi.append(xi[-2]-q*xi[-1])
            yi.append(yi[-2]-q*yi[-1]) 
            ri.append(ri[-2]-q*ri[-1])
        else:
            break
    rjecnik = {}
    rjecnik['ri'] = ri
    rjecnik['qi'] = qi
    rjecnik['xi'] = xi
    rjecnik['yi'] = yi
    rjecnik['NZM'] = ri[-1]
    if izlaz == 'rjecnik':
        return rjecnik
    else:
        indeksi = list(map(lambda x: '${}$'.format(x), list(range(-1,len(qi)+1))))
        ri = list(map(lambda x: '${}$'.format(x), ri))
        qi = list(map(lambda x: '${}$'.format(x), qi))
        xi = list(map(lambda x: '${}$'.format(x), xi))
        yi = list(map(lambda x: '${}$'.format(x), yi))
        red1 = [' '] + indeksi
        red2 = ['$r_i$'] + ri
        red3 = ['$q_i$',' ',' '] + qi
        red4 = ['$x_i$'] + xi
        red5 = ['$y_i$'] + yi
        tablica = [red1,red2,red3,red4,red5]
        tablica = make_table(tablica)
        apply_theme('basic_both')
        set_global_style(align='center')
        return tablica

Funkcija lin_kong_rucno daje rucni postupak za rješavanje linearne kongruencije $ax\equiv b\!\pmod{n}$. Rješenje daje u obliku rječnika ili html tablice ovisno o vrijednosti varijable izlaz.

In [6]:
def lin_kong_rucno(a,b,n,izlaz='html'): 
    qi = [] 
    yi = [0,1] 
    n1,q,r1,d = a,n//a,n%a,a 
    while r1 != 0: 
        qi.append(q) 
        yi.append(yi[-2]-q*yi[-1]) 
        q = n1//r1 
        n1,r1 = r1,n1%r1 
        if r1 != 0: d=r1 
    if b%d != 0: return False 
    a1,b1,n1 = a//d,b//d,n//d 
    x1 = (yi[-1]*b1)%n1 
    rjesenja = [x1+k*n1 for k in range(d)]
    rjecnik = {}
    rjecnik['qi'] = qi
    rjecnik['yi'] = yi
    rjecnik['a1b1d1'] = [a1,b1,n1]
    rjecnik['rjesenja'] = rjesenja
    if izlaz == 'rjecnik':
        return rjecnik
    else:
        indeksi = list(map(lambda x: '${}$'.format(x), list(range(-1,len(qi)+1))))
        qi = list(map(lambda x: '${}$'.format(x), qi))
        yi = list(map(lambda x: '${}$'.format(x), yi))
        red1 = [' '] + indeksi + ['rjesenja']
        red2 = ['$q_i$',' ',' '] + qi + ['${}$'.format(rjesenja)]
        red3 = ['$y_i$'] + yi + ['$(a_1,b_1,n_1)=({},{},{})$'.format(a1,b1,n1)]
        tablica = [red1,red2,red3]
        tablica = make_table(tablica)
        apply_theme('basic_both')
        set_global_style(align='center')
        return tablica

Funkcija KTO_rucno daje rucni postupak za rješavanje sustava linearnih kongruencija bazirano na kineskom teoremu o ostacima. Rješenje daje u obliku rječnika ili html tablice ovisno o vrijednosti varijable izlaz. Pritom je A lista ostataka, a N lista pripadnih modula.

In [7]:
def KTO_rucno(A,N,izlaz='html'): 
    for t in it.combinations(N,2): 
        if np.gcd(t[0],t[1])!=1: return "Error: moduli nisu u parovima relativno prosti." 
    n=np.prod(N) 
    ki=list(map(lambda x: n//x,N))
    xi=[]
    for i in range(len(N)): 
        xi.append(lin_kong_rucno(ki[i],A[i],N[i],izlaz='rjecnik')['rjesenja'][0])
    x0=sum(list(map(lambda x: x[0]*x[1],zip(ki,xi))))
    x0mod=x0%n
    if izlaz == 'rjecnik':
        return dict(zip(['n','k_i','x_i','x0','x0_mod'],[n,ki,xi,x0,x0mod])) 
    else:
        indeksi = [' '] + list(map(lambda x: '${}$'.format(x), list(range(1,len(A)+1))))
        ki = ['$k_i$'] + list(map(lambda x: '${}$'.format(x), ki))
        xi = ['$x_i$'] + list(map(lambda x: '${}$'.format(x), xi))
        x0 = ['$x_0$', '${}$'.format(x0)] + [' ']*(len(A)-1)
        x0mod = ['$x_0$-mod', '${}$'.format(x0mod)] + [' ']*(len(A)-1)
        n = ['$n$', '${}$'.format(n)] + [' ']*(len(A)-1)
        tablica = [indeksi,ki,xi,x0,x0mod,n]
        tablica = make_table(tablica)
        apply_theme('basic_both')
        set_global_style(align='center')
        set_cell_style(3, 1, column_span=len(A))
        set_cell_style(4, 1, column_span=len(A))
        set_cell_style(5, 1, column_span=len(A))
        return tablica
In [ ]: