Last active
November 14, 2015 10:32
-
-
Save huseyin/72f92bf96eb98b2a9763 to your computer and use it in GitHub Desktop.
Veri yapıları - Ödev (Egzersiz-3)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
""" Kesirli sayılar uzayı | |
from: Hüseyin Tekinaslan <[email protected]> | |
subject: Veri Yapıları - Egzersizler-3 | |
""" | |
import fractions as fr | |
# gcd (greatest common divisor): argüman olarak aldığı | |
# iki sayının kendi arasında en büyük ortak bölenini | |
# döndürür. | |
def gcd(a, b): | |
""" gcd(num1, num2) | |
""" | |
while b: | |
a, b = b, a % b | |
return a | |
# Argüman olarak gelen sayı integer tipinde mi? | |
def isint(value): | |
""" isint(value) | |
""" | |
try: | |
int(value) | |
return True | |
except: | |
return False | |
# Argüman olarak gelen sayı float tipinde mi? | |
def isfloat(value): | |
""" isfloat(value) | |
""" | |
try: | |
float(value) | |
return True | |
except: | |
return False | |
class Fraction: | |
def __init__(self, numerator=0, denominator=None): | |
""" Başlangıç | |
Kesirli ifade oluşturma kuralı: | |
* Klass örneklendiğinde her daim bir kesirli ifade ata. Öntanımlı (default) | |
0 / 1 ifadesi. | |
> instance = Fraction() | |
> print instance | |
> 0/1 #0 | |
* Klass durum olarak iki parametre kullanır. Payda parametresi default olarak | |
None değerine sahiptir. Bu demek oluyor ki tek argümanda kullanılabilir. | |
* Tek argüman verildiğinde sırası ile oluşacak olan durumlar, | |
""" | |
if denominator is None: | |
# Tek gelen argüman int tipinde ise, gelen argümanı pay olarak | |
# ata. Paydayı ise 1 olarak set et. | |
if isinstance(numerator, int): | |
self._numerator = numerator | |
self._denominator = 1 | |
# Tek gelen argüman float tipinde ise, gelen argümanını integer | |
# oranlarını (default olarak iki değer return eder) pay ve paydaya | |
# sırasıyla set et. | |
elif isinstance(numerator, float): | |
self._numerator, self._denominator = numerator.as_integer_ratio() | |
# Tek gelen argüman string tipinde ise, birkaç senaryoyu düşle. | |
# | |
# * Argüman içerisi tam sayı ise ('3' gibi) int tipine dönüştür | |
# ve sınıf parametrelerini ata. | |
# | |
# * Argüman içerisi gerçel sayı ise ('3.3' gibi) float tipine | |
# dönüştür ve sınıf parametrelerini ata. | |
# | |
# * Argüman bir Fraction örneği ise ('3/7' gibi) veriyi parse et. | |
# parsellerden yeni sınıf parametrelerini set et. | |
elif isinstance(numerator, str): | |
self._numerator, self._denominator = Fraction.as_str_ratio(numerator) | |
self.__pure() | |
else: | |
# Sınıf iki parametre alırsa, kesin kez kural olan her iki argümanın | |
# int tipinde olması uygulanır. | |
if isinstance(numerator, int) and \ | |
isinstance(denominator, int): | |
self._numerator = numerator | |
self._denominator = denominator | |
self.__pure() | |
else: | |
raise (TypeError('\'%s\': veri tipleri int olmalı!' % (type(self).__name__)) | |
if denominator == 0: | |
raise ZeroDivisionError( | |
'\'%s\': %s ifadesi gecersiz!' % (type(self).__name__, self) | |
) | |
def __str__(self): | |
""" str() | |
""" | |
if self._denominator == 1: | |
return str(self._numerator) | |
else: | |
return '%s/%s' % (self._numerator, self._denominator) | |
def __repr__(self): | |
""" repr() | |
""" | |
return ('Fraction(%s, %s)' % (self._numerator, self._denominator)) | |
# İki kesirli ifadeyi eşitlik yönünden birbiri ile karşılaştır. | |
# Eşitlerse True, değillerse False değerini döndür. | |
def __eq__(self, fraction): | |
""" eq(fraction) | |
""" | |
if self._numerator is fraction._numerator and \ | |
self._denominator is fraction._denominator: | |
return True | |
else: | |
return False | |
# İki kesri küçüklük yönünden karşılaştır. | |
def __lt__(self, fraction): | |
""" lt(fraction) | |
a < b | |
""" | |
ns, ds = self.__expand() | |
nf, df = fraction.__expand() | |
if fr.Fraction(ns, ds) < fr.Fraction(nf, df): | |
return True | |
else: | |
return False | |
# İki kesri büyüklük yönünden karşılaştır. | |
def __gt__(self, fraction): | |
""" gt(fraction) | |
a > b | |
""" | |
ns, ds = self.__expand() | |
nf, df = fraction.__expand() | |
if fr.Fraction(ns, ds) > fr.Fraction(nf, df): | |
return True | |
else: | |
return False | |
# İki kesri küçük-eşit lik yönünden karşılaştır. | |
def __le__(self, fraction): | |
""" le(fraction) | |
a <= b | |
""" | |
ns, ds = self.__expand() | |
nf, df = fraction.__expand() | |
if fr.Fraction(ns, ds) <= fr.Fraction(nf, df): | |
return True | |
else: | |
return False | |
# İki kesri büyük-eşit lik yönünden karşılaştır. | |
def __ge__(self, fraction): | |
""" ge(fraction) | |
a >= b | |
""" | |
ns, ds = self.__expand() | |
nf, df = fraction.__expand() | |
if fr.Fraction(ns, ds) >= fr.Fraction(nf, df): | |
return True | |
else: | |
return False | |
# Kesirli ifade sıfırı mı gösteriyor? | |
def __nonzero__(self, fraction): | |
""" nonzero() | |
a != 0 | |
""" | |
ns, ds = self.__expand() | |
nf, df = fraction.__expand() | |
if fr.Fraction(ns, ds) != fr.Fraction(nf, df): | |
return True | |
else: | |
return False | |
# İki ifadeyi topla. | |
def __add__(self, fraction): | |
""" add(fraction) | |
""" | |
if isinstance(fraction, int) or isinstance(fraction, float): | |
return Fraction(fraction) + self | |
else: | |
n = (self._numerator * fraction._denominator) +\ | |
(self._denominator * fraction._numerator) | |
d = self._denominator * fraction._denominator | |
return Fraction(n, d) | |
# İki ifadeyi çıkar. | |
def __sub__(self, fraction): | |
""" sub(fraction) | |
""" | |
if isinstance(fraction, int) or isinstance(fraction, float): | |
return self - Fraction(fraction) | |
else: | |
n = (self._numerator * fraction._denominator) -\ | |
(self._denominator * fraction._numerator) | |
d = self._denominator * fraction._denominator | |
return Fraction(n, d) | |
# İki ifadeyi çarp. | |
def __mul__(self, fraction): | |
""" mul(fraction) | |
""" | |
if isinstance(fraction, int) or isinstance(fraction, float): | |
return self * Fraction(fraction) | |
else: | |
n = self._numerator * fraction._numerator | |
d = self._denominator * fraction._denominator | |
return Fraction(n, d) | |
# İki ifadeyi böl. | |
def __div__(self, fraction): | |
""" div(fraction) | |
""" | |
if isinstance(fraction, int) or isinstance(fraction, float): | |
return self / Fraction(fraction) | |
else: | |
n = self._numerator * fraction._denominator | |
d = self._denominator * fraction._numerator | |
return Fraction(n, d) | |
# Kesirli bir ifadenin üssünü al. | |
def __pow__(self, value): | |
""" pow(value) | |
""" | |
n = pow(self._numerator, value) | |
d = pow(self._denominator, value) | |
return Fraction(n, d) | |
# Kesirli ifadelerin modunu al. | |
def __mod__(self, fraction): | |
""" mod(fraction) | |
""" | |
ns, ds = self._numerator, self._denominator | |
nf, df = fraction._numerator, fraction._denominator | |
return fr.Fraction(ns, ds) % fr.Fraction(nf, df) | |
# Bir kesirli ifade diğer iki kesirli ifadenin arasında mı? | |
def between(self, fr1, fr2): | |
""" between(fr1, fr2) | |
""" | |
if fr1 >= fr2: | |
mnf, mjf = fr2, fr1 | |
else: | |
mnf, mjf = fr1, fr2 | |
if self >= mnf and self <= mjf: | |
return True | |
else: | |
return False | |
# Kesirli ifadenin payını döndür. | |
def numerator(self): | |
""" numerator() | |
""" | |
return self._numerator | |
# Kersirli ifadenin paydasını döndür. | |
def denominator(self): | |
""" denominator() | |
""" | |
return self._denominator | |
# Kesirli ifadeyi insan konuşma dilinde göster. | |
def humanize(self): | |
""" humanize() | |
""" | |
n, d = self._numerator, self._denominator | |
if n > d: | |
w = n / d # whole | |
r = n % d # residual | |
return '%s tam %s bölü %s' % (w, r, d) | |
else: | |
return '%s bölü %s' % (n, d) | |
@classmethod | |
def isfraction(cls, fraction): | |
""" isfloat(cls, fraction) | |
""" | |
if isinstance(fraction, type(Fraction())): | |
return cls(True) | |
else: | |
return cls(False) | |
@classmethod | |
def as_str_ratio(cls, strnum): | |
""" as_str_ratio(strnum) | |
Dikkat: Üç adımlık bir parse işlemi mevcuttur. | |
* '17' gibi stringler (17, 1) şeklinde parse et, | |
* '1.5' gibi stringler (3, 2) şeklinde parse et, | |
* '3/14' gibi stringler (3, 14) şeklinde parse et. | |
""" | |
num, denom = None, None | |
if '/' not in strnum: | |
if isint(strnum): | |
n, d = int(strnum), 1 | |
elif isfloat(strnum): | |
n, d = float(strnum).as_integer_ratio() | |
else: | |
raise ValueError('\'%s\': tip hatası: %s' | |
%(type(strnum).__name__, self)) | |
else: | |
parse = strnum.split('/') | |
if len(parse) == 2: | |
arglist = [] # pay ve paydayı burada tut. | |
for value in parse: | |
if isint(value): | |
arglist.append(int(value)) | |
elif isfloat(item): | |
arglist.append(float(value)) | |
else: | |
raise() | |
n, d = arglist | |
else: | |
raise ValueError('\'%s\': geçersiz argüman: %s' | |
%(type(strnum).__name__, self)) | |
return n, d | |
# Kesirli ifadeyi sadeleştir. | |
def __pure(self): | |
""" pure(self) | |
Private method | |
""" | |
gcdv = gcd(self._numerator, self._denominator) | |
self._numerator /= gcdv | |
self._denominator /= gcdv | |
# Kesirli ifadenin payını ve paydasını döndür. | |
def __expand(self): | |
""" expand() | |
Private method | |
""" | |
return self._numerator, self._denominator | |
if __name__ == '__main__': | |
""" Test kodları için hatırlatma | |
Betiği kabukta doğrudan çalıştırırsanız çıktılarda bilmeniz gereken | |
bir ayrıntı mevcut: | |
* Çıktıların en sağında yer alan Boolean değerler beklenen çıktı | |
ile üretilen değerlerin karşılaştırmasıdır. False değerindeki | |
ifadeler beklenenin aksi bir çıktı üretmiştir. Bunlar her şekilde | |
kırmızı renkle belirtilir. | |
""" | |
def unittest(expr1, expr2): | |
return True if expr1 == expr2 else False | |
def tprint(*args): | |
buffer = '' | |
for st in args: | |
if str(st) == 'False': | |
# Hatalı yerleri belirginleştir. | |
buffer += '\033[38;5;198m%s\t\033[0m' %st | |
else: | |
buffer += '%s\t' %st | |
print buffer | |
# İfadeleri ilkle. | |
f1 = Fraction(1, 2) | |
f2 = Fraction(5) | |
f3 = Fraction(2.5) | |
f4 = Fraction('3/4') | |
f5 = Fraction('1.5') | |
f6 = Fraction('7') | |
# Kesir gösterimleri | |
tprint(f1, '-', unittest(f2, Fraction(5, 1))) | |
tprint(f2, '-', unittest(f2, Fraction('5'))) | |
tprint(f5, '-', unittest(f5, Fraction(3, 2))) | |
tprint(f6, '-', unittest(f6, Fraction(7, 1))) | |
# Kesirlerle işlemler | |
tprint(f1 + f2, '-', unittest(f1 + f2, Fraction(11, 2))) | |
tprint(f5 - f4, '-', unittest(f5 - f4, Fraction(3, 4))) | |
tprint(f3 * f6, '-', unittest(f3 * f6, Fraction(35, 2))) | |
tprint(f5 / f4, '-', unittest(f5 / f4, Fraction(2, 1))) | |
tprint(f2**3, '-', unittest(f2**3, Fraction(125))) | |
# Karşılaştırma işlemleri | |
tprint('f1 > f2', '-', unittest(f1 > f2, False)) | |
tprint('f3 < f6', '-', unittest(f3 < f6, True)) | |
# Diğer... | |
tprint(f1, '-', f1.humanize()) | |
tprint(f3, '-', f3.humanize()) | |
tprint(f1, '-', f1.numerator()) | |
tprint(f1, '-', f1.denominator()) | |
tprint(f3, '-', f3.between(f4, f2)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Biraz aceleye geldiği için burada bahsedeyim.
Fraction
sınıfı, her daim parametreye ihtiyaç duymaz. Örneğin,dediğimizde bir kesirli ifade döndürür. Bu kesirli ifade:
şeklindedir. Göründüğü üzere
0
değerini döner. Ama dikkat ki bu da bir kesirli ifadedir.0/1
gibi durumlarda gizli paydayı yazmaya ihtiyaç duyulmaz. Aynı olay3/1
,17/1
,-2/1
için de geçerlidir. Gizli payda görülmek istenirse,repr()
fonksiyonu bize yardımcı olacaktır.