2017.07.11 19:54
sortowalny zapis liczb wymiernych
Zastanawiałem się od kilku tygodni, czy dałoby sie znaleźć taki zapis liczb wymiernych, żeby jak się zapisze nim kilka liczb, to żeby ich posortowanie alfabetyczne (słownikowe) sortowało je od razu po wielkości. Na przykład że skoro "2 3/7" jest większe od "2 3/8", to żeby "2 3/7" zapisane moim zapisem było słownikowo większe niż "2 3/8" zapisane moim zapisem. Znalazłem taki zapis. Oto proof of concept w Pythonie:
Wersja uruchamialna: https://repl.it/JXIf/1
Kod:
# coding: utf-8
import logging
import sys
logger = logging.getLogger('zapisywacz')
ch = logging.StreamHandler(sys.stderr)
ch.setLevel(logging.DEBUG)
formatter = logging.Formatter('[%(message)s]')
ch.setFormatter(formatter)
logger.addHandler(ch)
# odkomentuj żeby włączyć logowanie:
#logger.setLevel(logging.DEBUG)
class Ulamek:
def __init__(self, licznik, mianownik):
self.licznik = licznik
self.mianownik = mianownik
def __cmp__(self, other):
return (self.licznik * other.mianownik).__cmp__(other.licznik * self.mianownik)
def __str__(self):
return str(self.licznik) + '/' + str(self.mianownik)
def str2ulamek(napis):
licznik, _, mianownik = napis.partition('/')
return Ulamek(int(licznik), int(mianownik))
def zapisz_wymierna(naturalna, ulamek):
zapis = zapisz_naturalna(naturalna) + zapisz_ulamek(ulamek)
logger.info('Na koniec liczby dopisuję E.')
return zapis + 'E'
def zapisz_naturalna(naturalna):
logger.info('Liczbę %d zapisuję jako ciąg %d liter D.' % (naturalna, naturalna))
return 'D' * naturalna
def zapisz_ulamek(ulamek):
assert ulamek.licznik < ulamek.mianownik
return zapisz_ulamek_z_zakresem(ulamek, Ulamek(0, 1))
def zapisz_ulamek_z_zakresem(ulamek, poczatek_zakresu):
nastepny = Ulamek(poczatek_zakresu.licznik + 1, poczatek_zakresu.mianownik + 1)
logger.info('Wiem, że badany ułamek %s leży między %s a %s. Ale gdzie w tym zakresie? Przed %s czy za nim?' % (str(ulamek), str(poczatek_zakresu), str(Ulamek(poczatek_zakresu.licznik + 1, poczatek_zakresu.mianownik)), str(nastepny)))
if ulamek == nastepny:
logger.info('A, on leży równo na %s. Więc do reprezentacji dopisuję B.' % (str(nastepny)))
return 'B'
if ulamek < nastepny:
logger.info('A, on leży przed %s. Więc do reprezentacji dopisuję A.' % (str(nastepny)))
return 'A' + zapisz_ulamek_z_zakresem(ulamek, Ulamek(nastepny.licznik - 1, nastepny.mianownik))
if ulamek > nastepny:
logger.info('A, on leży po %s. Więc do reprezentacji dopisuję C.' % (str(nastepny)))
return 'C' + zapisz_ulamek_z_zakresem(ulamek, nastepny)
print 'Podaj liczbę wymierną w formacie "3 2/7". W ułamku licznik musi być mniejszy od mianownika.'
napis = raw_input()
naturalna, _, ulamek = napis.partition(' ')
naturalna = int(naturalna)
licznik, _, mianownik = ulamek.partition('/')
ulamek = Ulamek(int(licznik), int(mianownik))
print 'Twoja liczba to %s %s.' % (str(naturalna), (ulamek))
print 'W zapisie dziesiętnym to %6.3f.' % (naturalna + float(licznik) / float(mianownik))
print 'W moim zapisie to %s' % zapisz_wymierna(naturalna, ulamek)
komentarze:
2017.07.11 20:00 Piotrek
Może kilka przykładów.
W moim zapisie "2 2/7" to "DDAACAABE".
W moim zapisie "3 2/7" to "DDDAACAABE".
W moim zapisie "3 2/6" to "DDDABE".
W moim zapisie "3 2/8" to "DDDAABE".
2017.07.22 11:45 Piotrek
A oto program w Haskellu, który konwertuje liczbę wymierną na ten zapis:
data Ulamek = Ulamek Integer Integer
instance Show Ulamek where
show (Ulamek a b) = (show a) ++ "/" ++ (show b)
instance Eq Ulamek where
(Ulamek a x) == (Ulamek b y) = (a * y) == (b * x)
instance Ord Ulamek where
(Ulamek a x) `compare` (Ulamek b y) = (a * y) `compare` (b * x)
data Wymierna = Wymierna Integer Ulamek
instance Show Wymierna where
show (Wymierna a b) = (show a) ++ " " ++ (show b)
nastepny (Ulamek a b) = Ulamek (a + 1) b
zapiszUlamekZZakresem ulamek poczatekZakresu
| ulamek == nastepny = "B"
| ulamek < nastepny = "A" ++ zapiszUlamekZZakresem ulamek (Ulamek x (y + 1))
| ulamek > nastepny = "C" ++ zapiszUlamekZZakresem ulamek nastepny
where (Ulamek a b) = ulamek
(Ulamek x y) = poczatekZakresu
nastepny = Ulamek (x + 1) (y + 1)
zapiszUlamek ulamek = zapiszUlamekZZakresem ulamek (Ulamek 0 1)
zapiszNaturalna 0 = ""
zapiszNaturalna x = "D" ++ (zapiszNaturalna (x - 1))
zapiszWymierna (Wymierna naturalna ulamek) = (zapiszNaturalna naturalna) ++ (zapiszUlamek ulamek) ++ "E"
-- oto przykład użycia tej funkcji dla liczby 5 3/4
main = do putStrLn (zapiszWymierna (Wymierna 5 (Ulamek 3 4)))
powrót na stronę główną
RSS