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)))




ksywa:

tu wpisz cyfrę cztery: (to takie zabezpieczenie antyspamowe)

komentarze wulgarne albo co mi się nie spodobają będę kasował


powrot na strone glowna

RSS