Skip to content

Instantly share code, notes, and snippets.

@huseyin
Last active November 14, 2015 10:32
Show Gist options
  • Save huseyin/72f92bf96eb98b2a9763 to your computer and use it in GitHub Desktop.
Save huseyin/72f92bf96eb98b2a9763 to your computer and use it in GitHub Desktop.
Veri yapıları - Ödev (Egzersiz-3)
# -*- 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))
@huseyin
Copy link
Author

huseyin commented Nov 13, 2015

Biraz aceleye geldiği için burada bahsedeyim. Fraction sınıfı, her daim parametreye ihtiyaç duymaz. Örneğin,

fr = Fraction()

dediğimizde bir kesirli ifade döndürür. Bu kesirli ifade:

print fr    # 0

ş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ı olay 3/1, 17/1, -2/1 için de geçerlidir. Gizli payda görülmek istenirse,

print repr(fr)    # Fraction(0, 1)

repr() fonksiyonu bize yardımcı olacaktır.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment