Sayıların Okunuşu

sayıların okunuşu ile ilgili bir program yazmak istiyorum basamak sayısı arttıkça sıkıntı artıyor en
azından milyarlara kadar gitmeli
Aşağıdaki kodda 100 bin e kadar olan sayılar var ama sıkıntı şu şu haliyle sadece 5 basamaklıları okuyor.
eğer if blokları kurup str(sayının) uzunluğuna göre daha küçük basamaklı sayılarıda okutabilirim ama gereksiz kod kalabalığı olcağını, daha pratik bir yolunun olabilceğini düşünüyorum.
Birde basamak sayısı artıkça daha uygun olabilecek bir yöntem bulabilirmiyiz fikirlerinizi bekliyorum :slight_smile:

birler = ["", "Bir", "İki", "Üç", "Dört", "Beş", "Altı", "Yedi", "Sekiz", "Dokuz"]
onlar = ["", "On", "Yirmi", "Otuz", "Kırk", "Elli", "Altmış", "Yetmiş", "Seksen", "Doksan"]
yuzler=["", "yüz", "İkiyüz", "Üçyüz", "Dörtyüz", "Beşyüz", "Altıyüz", "Yediyüz", "Sekizyüz", "Dokuzyüz"]
binler=["", "Bin", "İkiBin", "ÜçBin", "DörtBin", "BeşBin", "AltıBin", "YediBin", "SekizBin", "DokuzBin"]
onbinler=["", "Onbin", "yirmibin", "otuzbin", "kırkbin", "ellibin", "altmışbin", "Yetmişbin", "Seksenbin", "Doksanbin"]


def okunus(sayı):
    str(sayı)
    birinci = int(str(sayı)[4])
    ikinci = int(str(sayı)[3])
    ucuncu=int(str(sayı)[2])
    dorduncu=int(str(sayı)[1])
    besinci=int(str(sayı)[0])
    if dorduncu==0:
        return onbinler[besinci]+binler[dorduncu]+yuzler[ucuncu]+onlar[ikinci] +birler[birinci]

    else:
        return  onlar[besinci]+binler[dorduncu]+yuzler[ucuncu]+onlar[ikinci] +birler[birinci]



sayı = int(input("Sayı:"))

print(okunus(sayı))
1 Beğeni

Ben bu programı basamak sınırı olmadan yazmıştım, bulursam atacağım.

1 Beğeni

Teşekkürler şimdiden ayrıca sınır olmadan nasıl yaptınız ayrıca merak ettim

Kodu açıklayabilecek durumda değilim ama çalışıyor :slightly_smiling_face:

def fonk(a):
       y = a//100
       o = (a-y*100)//10
       b = a-y*100-o*10
       b = basamak1[b]
       o = basamak2[o]
       if y == 0:
              y = ""                    
       elif y == 1:
               y = "yüz "      
       else:
              y = basamak1[y] + " yüz "
       k = y + o + " " + b
       return k

sayılar = ["1","2","3","4","5","6","7","8","9","0"]
basamak1 = [
"",
"bir",
"iki" ,
"üç" ,
"dört",
"beş",
"altı",
"yedi",
"sekiz",
"dokuz"]
basamak2 = [
"",
"on",
"yirmi",
"otuz",
"kırk",
"elli",
"altmış",
"yetmiş",
"seksen",
"doksan",
]
basamak3 = [
"",
"bin",
"milyon",
"milyar",
"trilyon",
"katrilyon",
"kentilyon",
"sekstilyon",
"septilyon",
"oktilyon",
"nonilyon",
"desilyon",
"andesilyon",
"dodesilyon",
"tredesilyon",
"katordesilyon",
"kendesilyon",
"seksdesilyon",
"septendesilyon",
"oktodesilyon",
"novemdesilyon",
"vicintilyon",
"anvicintilyon",
"dovicintilyon",
"trevicintilyon",
"katorvicintilyon",
"kenkavicintilyon",
"sesvicintilyon",
"septemvicintilyon",
"oktovicintilyon",
"novemvicintilyon",
"tricintilyon",
"antricintilyon",
]

while True:
       while True:
              a = 0
              sayı = input("Bir sayı giriniz.\n> ")
              for i in sayı:
                     if i not in sayılar:
                            print("Lütfen girdiniz pozitif bir tam sayı olsun.")
                            a = 1
                            break
              if len(sayı) > 99 and a == 0:
                     print("Lütfen en fazla 99 basamaklı bir sayı yazınız. Sizin girdiğiniz sayı {} basamaklıdır.".format(len(sayı)))
                     a = 1
              if a == 0:
                     sayı =int(sayı)
                     break
                            
       sayı_asıl = sayı

       basamaklar = []
       ilk_sayı = 1000**((len(str(sayı))-1)//3)
       for i in range(-1,(len(str(ilk_sayı))-1)//3):      
              basamaklar.append(sayı//ilk_sayı)
              sayı -= basamaklar[i+1]*ilk_sayı
              ilk_sayı = ilk_sayı//1000

       for i in basamaklar: 
              if i == 0:
                     basamaklar[basamaklar.index(i)] = ""

       for i in basamaklar:
              if i == 1:
                     if basamak3[len(basamaklar)-1 - basamaklar.index(i)] == "bin":
                            basamaklar[basamaklar.index(i)] = " bin "
                     else:
                            basamaklar[basamaklar.index(i)] = " bir " + basamak3[len(basamaklar)-1 - basamaklar.index(i)]
              elif i != "":
                     bas = fonk(basamaklar[basamaklar.index(i)])
                     basamaklar[basamaklar.index(i)] = " " + bas + " " + basamak3[len(basamaklar)-1 - basamaklar.index(i)]

       if sayı_asıl == 0:
              print("Girdiğiniz sayının okunuşu şudur:")
              print("sıfır")
       else:
              okunuş = ""
              for i in basamaklar:
                     okunuş += i
              print("Girdiğiniz sayının okunuşu şudur:")
              print(okunuş)

       

Kodda gereksiz uzattığım yerler olabilir, Python’u yeni öğrenirken yapmıştım. Şimdi bakınca gördüm ki değişken isimlendirmelerini de kötü yapmışım.

Sınır yoktan kastım basamakların okunuşunu gerekli listeye eklemenizin yetecek olması. Bunu da döngüler kullanarak yaptım.

Hatta başta ben de sizin gibi her basamak için teker teker işlem yapıyordum (ama kullandığım yöntem farklıydı), sonra böyle basamak sınırı arttırılamaz diyerek kodu bir döngüye dönüştürmüştüm. Program bittikten sonra koddaki asıl işi yapan bölüme bakınca da “Beynimiz ne kadar garip çalışıyor, bir sayıyı okurken bunları farkında olmadan yapıyoruz” diye düşünmüştüm :sweat_smile:

2 Beğeni

Ikiniz de algoritma cikartmadan mi yaptiniz bunu, hic beklemezdim…

Turkce sayilarin okunusu cok basit, uclu gruplara dayaniyor. Buraya yazacaktim da, matematik hocasina ve kodunu yazmis programciya birakip implement etmeyi denemeyi daha uygun gordum :slight_smile:

1 Beğeni

Dediğim gibi programlamayı öğrenmeye başlayalı çok olmamıştı bunu yazarken, algoritma daha basit hale getirilebilir büyük ihtimalle. Ama benim bunu yazarken bir amacım da yazım kurallarına uyup her sayı arasına birer boşluk bırakmaydı. Gerçi split ve join'den o zamanlar haberim olsa bu da kolay olurdu herhalde.

Üçlü gruplar halinde olduğunun farkındaydım ama algoritmasını tam olarak kuramadığım için yardım almak istedim

Of, benim de bekledigimden zor cikti, keske yazsaymisim.

Yarin toparlayayip yazayim buraya ama sagdan sola calisacak gibi duruyor.

Pek okunabilir yapamadim ama burada dursun:

import Data.List

ones = ["", "bir", "iki", "uc", "dort", "bes", "alti", "yedi", "sekiz", "dokuz"]
tens = ["", "on", "yirmi", "otuz", "kirk", "elli", "altmis", "yetmis", "seksen", "doksan"]
huns = ["", "yuz"] ++ map (++ " yuz") (drop 2 ones)

parse1   n = (ones !! n, 0)
parse10  n = (tens !! (n `div`  10), n `mod`  10)
parse100 n = (huns !! (n `div` 100), n `mod` 100)

pstrJoin    s1 s2 = s1 ++ (if (length s1 > 0) && (length s2 > 0) then " " else "") ++ s2
pstrJoinRev s1 s2 = s2 ++ (if (length s1 > 0) && (length s2 > 0) then " " else "") ++ s1

pbind    ps f = let (fstr, fnum) = f (snd ps) in ((fst ps) `pstrJoin`    fstr, fnum)
pbindRev ps f = let (fstr, fnum) = f (snd ps) in ((fst ps) `pstrJoinRev` fstr, fnum)

parse1k n = (parse100 n) `pbind` parse10 `pbind` parse1

parseGroup join label n = let (gstr, gnum) = parse1k (n `mod` 1000) in (join gstr label, n `div` 1000)

pstrLeftJoin s1 s2 = if (length s1 > 0) then s1 ++ " " ++ s2 else ""
pstrNot1Join s1 s2 = if (s1 == "bir") then s2 else pstrLeftJoin s1 s2

parse1M n = ((fst . parse1k) (n `mod` 1000), n `div` 1000) `pbindRev` (parseGroup pstrNot1Join "bin")
parseAllBut0 groups n = foldl' pbindRev (parse1M n) (map (parseGroup pstrLeftJoin) groups)
parse0 n = if n == 0 then ("sifir", 0) else ("", n)

parseAll groups n = (parse0 n) `pbind` (parseAllBut0 groups)

--

readNumber = fst . parseAll ["milyon", "milyar"]

checkEqual x y = putStrLn ((show x) ++ (if x == y then " \ESC[32m==\ESC[0m " else " \ESC[31m!=\ESC[0m ") ++ (show y))

main = do
  checkEqual (readNumber 0) "sifir"
  checkEqual (readNumber 1) "bir"
  checkEqual (readNumber 2) "iki"
  checkEqual (readNumber 10) "on"
  checkEqual (readNumber 11) "on bir"
  checkEqual (readNumber 19) "on dokuz"
  checkEqual (readNumber 40) "kirk"
  checkEqual (readNumber 42) "kirk iki"
  checkEqual (readNumber 100) "yuz"
  checkEqual (readNumber 109) "yuz dokuz"
  checkEqual (readNumber 110) "yuz on"
  checkEqual (readNumber 114) "yuz on dort"
  checkEqual (readNumber 140) "yuz kirk"
  checkEqual (readNumber 142) "yuz kirk iki"
  checkEqual (readNumber 400) "dort yuz"
  checkEqual (readNumber 405) "dort yuz bes"
  checkEqual (readNumber 440) "dort yuz kirk"
  checkEqual (readNumber 448) "dort yuz kirk sekiz"

  checkEqual (readNumber 1000) "bin"
  checkEqual (readNumber 1001) "bin bir"
  checkEqual (readNumber 1002) "bin iki"
  checkEqual (readNumber 1010) "bin on"
  checkEqual (readNumber 1011) "bin on bir"
  checkEqual (readNumber 1018) "bin on sekiz"
  checkEqual (readNumber 1040) "bin kirk"
  checkEqual (readNumber 1042) "bin kirk iki"
  checkEqual (readNumber 1100) "bin yuz"
  checkEqual (readNumber 1107) "bin yuz yedi"
  checkEqual (readNumber 1110) "bin yuz on"
  checkEqual (readNumber 1116) "bin yuz on alti"
  checkEqual (readNumber 1140) "bin yuz kirk"
  checkEqual (readNumber 1142) "bin yuz kirk iki"
  checkEqual (readNumber 1400) "bin dort yuz"
  checkEqual (readNumber 1405) "bin dort yuz bes"
  checkEqual (readNumber 1440) "bin dort yuz kirk"
  checkEqual (readNumber 1448) "bin dort yuz kirk sekiz"

  checkEqual (readNumber 3000) "uc bin"
  checkEqual (readNumber 3001) "uc bin bir"
  checkEqual (readNumber 3002) "uc bin iki"
  checkEqual (readNumber 3010) "uc bin on"
  checkEqual (readNumber 3011) "uc bin on bir"
  checkEqual (readNumber 3018) "uc bin on sekiz"
  checkEqual (readNumber 3040) "uc bin kirk"
  checkEqual (readNumber 3042) "uc bin kirk iki"
  checkEqual (readNumber 3100) "uc bin yuz"
  checkEqual (readNumber 3107) "uc bin yuz yedi"
  checkEqual (readNumber 3110) "uc bin yuz on"
  checkEqual (readNumber 3116) "uc bin yuz on alti"
  checkEqual (readNumber 3140) "uc bin yuz kirk"
  checkEqual (readNumber 3142) "uc bin yuz kirk iki"
  checkEqual (readNumber 3400) "uc bin dort yuz"
  checkEqual (readNumber 3405) "uc bin dort yuz bes"
  checkEqual (readNumber 3440) "uc bin dort yuz kirk"
  checkEqual (readNumber 3448) "uc bin dort yuz kirk sekiz"

  checkEqual (readNumber 1003000) "bir milyon uc bin"
  checkEqual (readNumber 1003001) "bir milyon uc bin bir"
  checkEqual (readNumber 1003002) "bir milyon uc bin iki"
  checkEqual (readNumber 1003010) "bir milyon uc bin on"
  checkEqual (readNumber 1003011) "bir milyon uc bin on bir"
  checkEqual (readNumber 1003018) "bir milyon uc bin on sekiz"
  checkEqual (readNumber 1003040) "bir milyon uc bin kirk"
  checkEqual (readNumber 1003042) "bir milyon uc bin kirk iki"
  checkEqual (readNumber 1003100) "bir milyon uc bin yuz"
  checkEqual (readNumber 1003107) "bir milyon uc bin yuz yedi"
  checkEqual (readNumber 1003110) "bir milyon uc bin yuz on"
  checkEqual (readNumber 1003116) "bir milyon uc bin yuz on alti"
  checkEqual (readNumber 1003140) "bir milyon uc bin yuz kirk"
  checkEqual (readNumber 1003142) "bir milyon uc bin yuz kirk iki"
  checkEqual (readNumber 1003400) "bir milyon uc bin dort yuz"
  checkEqual (readNumber 1003405) "bir milyon uc bin dort yuz bes"
  checkEqual (readNumber 1003440) "bir milyon uc bin dort yuz kirk"
  checkEqual (readNumber 1003448) "bir milyon uc bin dort yuz kirk sekiz"

  checkEqual (readNumber 42000456123) "kirk iki milyar dort yuz elli alti bin yuz yirmi uc"
  checkEqual (readNumber 42789000123) "kirk iki milyar yedi yuz seksen dokuz milyon yuz yirmi uc"
  checkEqual (readNumber 42789456000) "kirk iki milyar yedi yuz seksen dokuz milyon dort yuz elli alti bin"
  checkEqual (readNumber 42789456123) "kirk iki milyar yedi yuz seksen dokuz milyon dort yuz elli alti bin yuz yirmi uc"

Monadic parser’lara ozendim,
parse fonksiyonlari Int -> (String, Int)
pbind da (String, Int) -> (Int -> (String, Int)) -> (String, Int)

Fakat 1~1000 arasini (muhtemelen yazmaya dun basladigim icin) buyukten kucuge, uclu basamak gruplarini da kucukten buyuge isledigim icin iki adet bind gerekti (string’leri duz ve ters birlestiren; sayilari buyukten kucuge okuyoruz ama kucukten buyuge islemek zorundayiz)

Ilk uc basamak grubu, kendilerini ters (duz) yazdigim icin ozel. Ikinci uc basamak grubu, “bir bin” denilmedigi icin ozel. Geriye kalan butun gruplar ayni ve parser’larini tek bir fold ile kombine edebiliyoruz.

Okunabilirligi arttirmam lazim. Bir daha Haskell’im geldiginde donerim belki.

1 Beğeni

Evet, 1~1000 arasini duzeltince kod cok daha basitlesti:

ones = ["", "bir", "iki", "uc", "dort", "bes", "alti", "yedi", "sekiz", "dokuz"]
tens = ["", "on", "yirmi", "otuz", "kirk", "elli", "altmis", "yetmis", "seksen", "doksan"]
huns = ["", "yuz"] ++ map (++ " yuz") (drop 2 ones)

pcomp f g = \n -> let (fstr, fnum) = f n; (gstr, gnum) = g fnum in (gstr ++ fstr, gnum)

parseArr arr n = (filter (/= "") [arr !! (n `mod` 10)], n `div` 10)
parse1   = parseArr ones
parse10  = parseArr tens
parse100 = parseArr huns
parse1k = parse1 `pcomp` parse10 `pcomp` parse100
parse0 n = if n == 0 then (["sifir"], 0) else ([], n)

parseGroup label n = let (gstr, _) = parse1k (n `mod` 1000) in (gstr ++ (if null gstr then [] else [label]), n `div` 1000)
parseThousands   n = let (gstr, _) = parse1k (n `mod` 1000) in (if null gstr then [] else if gstr == ["bir"] then ["bin"] else (gstr ++ ["bin"]), n `div` 1000)

parseAll groups = foldl1 pcomp ([parse0, parse1k, parseThousands] ++ (map parseGroup groups))

--

readNumber = unwords . fst . parseAll ["milyon", "milyar", "trilyon"]

Monadik bind’dan (>>=) esinlenen pbind yerine Kleisli kompozisyonundan (>=>) esinlenen pcomp da tam (ve basit) bir parser combinator oldu.

2 Beğeni

İzninizle ben de yaptığım programı paylaşayım.

#!/usr/bin/python3
# -*- coding: utf-8 -*-

basamak_1 = {
    "1": "bir",
    "2": "iki",
    "3": "üç",
    "4": "dört",
    "5": "beş",
    "6": "altı",
    "7": "yedi",
    "8": "sekiz",
    "9": "dokuz"
}

basamak_2 = {
    "10": "on",
    "20": "yirmi",
    "30": "otuz",
    "40": "kırk",
    "50": "elli",
    "60": "altmış",
    "70": "yetmiş",
    "80": "seksen",
    "90": "doksan"
}


def basamak_olustur(
        basamak: int = 0, isim: str = "", sozluk: dict = {}
):
    result = {}
    if sozluk == basamak_1:
        if basamak >= 10 ** 6 and "yüz" not in isim:
            result.update(
                {
                    str(basamak * int(k)): v + isim
                    for k, v in sozluk.items()
                }
            )
        else:
            result.update({str(basamak): isim})
            result.update(
                {
                    str(basamak * int(k)): v + isim
                    for k, v in sozluk.items() if k != "1"
                }
            )
        return result
    elif sozluk == basamak_2:
        result.update({str(basamak): isim})
        result.update(
            {
                str(int(basamak * int(k) / 10)): v + isim[2:]
                for k, v in sozluk.items() if k != "10"
            }
        )
        return result


basamak_3 = basamak_olustur(
    basamak=10 ** 2,
    isim="yüz",
    sozluk=basamak_1
)
basamak_4 = basamak_olustur(
    basamak=10 ** 3,
    isim="bin",
    sozluk=basamak_1
)
basamak_5 = basamak_olustur(
    basamak=10 ** 4,
    isim="onbin",
    sozluk=basamak_2
)
basamak_6 = basamak_olustur(
    basamak=10 ** 5,
    isim="yüzbin",
    sozluk=basamak_1
)
basamak_7 = basamak_olustur(
    basamak=10 ** 6,
    isim="milyon",
    sozluk=basamak_1
)
basamak_8 = basamak_olustur(
    basamak=10 ** 7,
    isim="onmilyon",
    sozluk=basamak_2
)
basamak_9 = basamak_olustur(
    basamak=10 ** 8,
    isim="yüzmilyon",
    sozluk=basamak_1
)
basamak_10 = basamak_olustur(
    basamak=10 ** 9,
    isim="milyar",
    sozluk=basamak_1
)
basamak_11 = basamak_olustur(
    basamak=10 ** 10,
    isim="onmilyar",
    sozluk=basamak_2
)

basamak_12 = basamak_olustur(
    basamak=10 ** 11,
    isim="yüzmilyar",
    sozluk=basamak_1
)
# basamak_13 = basamak_olustur(
#     basamak=10 ** 12,
#     isim="trilyon",
#     sozluk=basamak_1
# )

tanimli_basamaklar = {
    k: v
    for k, v in globals().items()
    if k.startswith("basamak") and isinstance(v, dict)
}


def sayi_okunusu(sayi: int = 0):
    okunus = []

    def _sayi_okunusu(_sayi: int = sayi):
        _sayi = str(_sayi)
        basamak = "basamak_" + str(len(_sayi))
        if basamak in tanimli_basamaklar:
            try:
                okunus.append(
                    tanimli_basamaklar[basamak][
                        str(int(_sayi[0]) * (10 ** (len(_sayi) - 1)))
                    ]
                )
                try:
                    return _sayi_okunusu(int(_sayi[1:]))
                except ValueError:
                    pass
            except KeyError:
                return

    if not sayi:
        return "sıfır"
    _sayi_okunusu()
    binler = ""
    milyonlar = ""
    milyarlar = ""
    # trilyonlar = ""
    ortak = []
    for i in okunus:
        if i.endswith("bin"):
            ortak.append(i)
            binler += i.replace("bin", "")
        elif i.endswith("milyon"):
            ortak.append(i)
            milyonlar += i.replace("milyon", "")
        elif i.endswith("milyar"):
            ortak.append(i)
            milyarlar += i.replace("milyar", "")
        # elif i.endswith("trilyon"):
        #     ortak.append(i)
        #     trilyonlar += i.replace("trilyon", "")
    fark = [i for i in okunus if i not in ortak]
    if binler:
        binler += "bin"
    if milyonlar:
        milyonlar += "milyon"
    if milyarlar:
        milyarlar += "milyar"
    # if trilyonlar:
    #     trilyonlar += "trilyon"
    return {sayi: milyarlar + milyonlar + binler + "".join(fark)}


Deneme:

print(sayi_okunusu(812558786520))
{812558786520: 'sekizyüzonikimilyarbeşyüzellisekizmilyonyediyüzseksenaltıbinbeşyüzyirmi'}

2 Beğeni

bir tanede ben paylaşayım

birler = ["", "Bir", "İki", "Üç", "Dört", "Beş", "Altı", "Yedi", "Sekiz", "Dokuz"]
onlar = ["", "On", "Yirmi", "Otuz", "Kırk", "Elli", "Altmış", "Yetmiş", "Seksen", "Doksan"]
yuzler=["", "yüz", "İkiyüz", "Üçyüz", "Dörtyüz", "Beşyüz", "Altıyüz", "Yediyüz", "Sekizyüz", "Dokuzyüz"]

def sayı_okur(sayı):
    def sayıayırır(sayı):
        liste = []
        liste.append(str(sayı)[-3:])
        for i in range(1, (len(str(sayı)) // 3)):
            liste.append(str(sayı)[-3 * (i + 1):-3 * i])
        liste.append(str(sayı)[:-3 * (len(str(sayı)) // 3)])

        if '' in liste:
            liste.remove('')
        return liste

    def okunus(sayı):
        birinci = sayı % 10
        ikinci = (sayı %100)//10
        ucuncu=sayı//100

        return yuzler[ucuncu]+ onlar[ikinci] + birler[birinci]
    basamaklisteleri= [
        "",
        "bin",
        "milyon",
        "milyar",
        "trilyon",
        "katrilyon",
        "kentilyon",
        "sekstilyon",
        "septilyon",
        "oktilyon",
        "nonilyon",
        "desilyon",
        "andesilyon",
        "dodesilyon",
        "tredesilyon",
        "katordesilyon",
        "kendesilyon",
        "seksdesilyon",
        "septendesilyon",
        "oktodesilyon",
        "novemdesilyon",
        "vicintilyon",
        "anvicintilyon",
        "dovicintilyon",
        "trevicintilyon",
        "katorvicintilyon",
        "kenkavicintilyon",
        "sesvicintilyon",
        "septemvicintilyon",
        "oktovicintilyon",
        "novemvicintilyon",
        "tricintilyon",
        "antricintilyon"]

    okuma_listesi = []
    for i in sayıayırır(sayı):
        okuma_listesi.append(str(okunus(int(i))))

    yb=basamaklisteleri[:len(okuma_listesi)]
    yalancıbasamak=yb[::-1]
    yalancıokuma_listesi=okuma_listesi[::-1]
    boş=''
    for i in range(len(okuma_listesi)):
        if len(yalancıokuma_listesi)==2 and yalancıokuma_listesi[0]=='Bir':
            boş=yalancıbasamak[0]+yalancıokuma_listesi[1]
        elif yalancıokuma_listesi[i]=='':
            boş+=''
        else:boş+=yalancıokuma_listesi[i]+yalancıbasamak[i]
    print(boş)
sayı_okur(12345)
2 Beğeni

Basamak4, basamak5 gibi değişkenleri elle tanımlamanız basamak sayısını sınırlamıyor mu?

O direk code smell zaten. Obje veya tuple listesine donusturmek lazim.

Şöyle değiştireyim o zaman:

#!/usr/bin/python3
# -*- coding: utf-8 -*-

basamak_1 = {
    "1": "bir",
    "2": "iki",
    "3": "üç",
    "4": "dört",
    "5": "beş",
    "6": "altı",
    "7": "yedi",
    "8": "sekiz",
    "9": "dokuz"
}

basamak_2 = {
    "10": "on",
    "20": "yirmi",
    "30": "otuz",
    "40": "kırk",
    "50": "elli",
    "60": "altmış",
    "70": "yetmiş",
    "80": "seksen",
    "90": "doksan"
}


def basamak_olustur(
        basamak: int = 0, isim: str = "", sozluk: dict = {}
):
    result = {}
    if sozluk == basamak_1:
        if basamak >= 10 ** 6 and "yüz" not in isim:
            result.update(
                {
                    str(basamak * int(k)): v + isim
                    for k, v in sozluk.items()
                }
            )
        else:
            result.update({str(basamak): isim})
            result.update(
                {
                    str(basamak * int(k)): v + isim
                    for k, v in sozluk.items() if k != "1"
                }
            )
        return result
    elif sozluk == basamak_2:
        result.update({str(basamak): isim})
        result.update(
            {
                str(int(basamak * int(k) / 10)): v + isim[2:]
                for k, v in sozluk.items() if k != "10"
            }
        )
        return result


basamaklar = [
    "bin",
    "milyon",
    "milyar",
    "trilyon",
    "katrilyon",
    "kentilyon",
    "sekstilyon",
    "septilyon",
    "oktilyon",
    "nonilyon",
    "desilyon",
    "andesilyon",
    "dodesilyon",
    "tredesilyon",
    "katordesilyon",
    "kendesilyon",
    "seksdesilyon",
    "septendesilyon",
    "oktodesilyon",
    "novemdesilyon",
    "vicintilyon",
    "anvicintilyon",
    "dovicintilyon",
    "trevicintilyon",
    "katorvicintilyon",
    "kenkavicintilyon",
    "sesvicintilyon",
    "septemvicintilyon",
    "oktovicintilyon",
    "novemvicintilyon",
    "tricintilyon",
    "antricintilyon"
]

basamak_listesi = [
    basamak_1, basamak_2,
    basamak_olustur(
        basamak=10 ** 2,
        isim="yüz",
        sozluk=basamak_1
    )
]

count = 3
for _basamak in basamaklar:
    basamak_listesi.extend(
        [
            basamak_olustur(
                basamak=10 ** count,
                isim=_basamak,
                sozluk=basamak_1
            ),
            basamak_olustur(
                basamak=10 ** (count + 1),
                isim=f"on{_basamak}",
                sozluk=basamak_2
            ),
            basamak_olustur(
                basamak=10 ** (count + 2),
                isim=f"yüz{_basamak}",
                sozluk=basamak_1
            )
        ]
    )
    count += 3

def sayi_okunusu(sayi: int = 0):
    okunus = []

    def _sayi_okunusu(_sayi: int = sayi):
        _sayi = str(_sayi)
        for basamak_ in basamak_listesi:
            if str(int(_sayi[0]) * (10 ** (len(_sayi) - 1))) in basamak_:
                try:
                    okunus.append(
                        basamak_[
                            str(int(_sayi[0]) * (10 ** (len(_sayi) - 1)))
                        ]
                    )
                    try:
                        return _sayi_okunusu(int(_sayi[1:]))
                    except ValueError:
                        pass
                except KeyError:
                    return

    if not sayi:
        return "sıfır"

    _sayi_okunusu()
    string = {i: "" for i in basamaklar}
    ortak = []
    for i in okunus:
        for j in basamaklar[::-1]:
            if i.endswith(j):
                ortak.append(i)
                string[j] += i.replace(j, "")
                break
    fark = [i for i in okunus if i not in ortak]
    for i in string:
        if string[i]:
            string[i] += i
    return {
        sayi: "".join([string[i] for i in string if string[i]][::-1]) +
              "".join(fark)}

Deneme:

print(sayi_okunusu(1321181255878645021))
{1321181255878645021: 'birkentilyonüçyüzyirmibirkatrilyonyüzseksenbirtrilyonikiyüzellibeşmilyarsekizyüzyetmişsekizmilyonaltıyüzkırkbeşbinyirmibir'}

print(sayi_okunusu(12321181255878645021))
{12321181255878645021: 'onikikentilyonüçyüzyirmibirkatrilyonyüzseksenbirtrilyonikiyüzellibeşmilyarsekizyüzyetmişsekizmilyonaltıyüzkırkbeşbinyirmibir'}

print(sayi_okunusu(512321181255878645021))
{512321181255878645021: 'beşyüzonikikentilyonüçyüzyirmibirkatrilyonyüzseksenbirtrilyonikiyüzellibeşmilyarsekizyüzyetmişsekizmilyonaltıyüzkırkbeşbinyirmibir'}

print(sayi_okunusu(6512321181255878645021))
{6512321181255878645021: 'altısekstilyonbeşyüzonikikentilyonüçyüzyirmibirkatrilyonyüzseksenbirtrilyonikiyüzellibeşmilyarsekizyüzyetmişsekizmilyonaltıyüzkırkbeşbinyirmibir'}

Şöyle bir ifade gördüm:

Determining what is and is not a code smell is subjective

Kaynak: https://en.wikipedia.org/wiki/Code_smell

Siz de biliyorsunuz ki, programda bir değişiklik yapıldığı zaman, daha önce sorun oluşturmayan kısımlar birden sorun oluşturmaya başlayabilir. İlk tasarımda daha sonradan yapılacak bir değişiklikte oluşabilecek sorun henüz düşünülmemiş olabiliyor. Yeni kodlarda sorun oluşturabilecek kısımlar ortadan kaldırılabilir.

Daha önce de başıma geldi böyle şeyler. Programı hazır hale getiriyorsunuz, programı kullanan birisi başka bir özellik daha eklenmesini istiyor, mevcut haliyle program eklenecek yeni özelliğe uygun olmayabiliyor, programın diğer özelliklerine dokunmadan yeni özelliği kullanılabilir hale getirebileceğiniz yerlerde ufak değişiklikler yapıyorsunuz.

basamak: int = 0, ifadesi ile ne yapmaya çalışıyoruz. Anlamadım :slight_smile:

Bir parametrenin tipini ve ön-tanımlı değerini yazıyoruz. Zorunlu değil.

Ama şu kod neden çalışıyor

def foo(var: int =0):
       print(var)
foo("hı")

Neden çalışmasın ki, python’da verinin tipini zaten değiştirebiliyorsunuz. Yani böyle yaptığınız zaman kod çalışmayacak diye bir kural yok. Veri tipini burada kodu okuyan kişiye bilgi versin diye yazıyorsunuz.