Sabtu, 02 April 2011

Terbilang (python version) part 1 -- satuan, puluhan dan belasan

Ada kalanya di dalam program kita membutuhkan sebuah fungsi untuk menghasilkan sebuah kalimat terbilang untuk angka yang dimasukkan (misalnya untuk mencetak kwitansi) pada postingan ini, saya akan membahas dan membuat sebuah fungsi pada python untuk menghasilkan kalimat terbilang sesuai dengan angka yang diinput.

satuan
Kita akan mulai dari yang paling mudah terlebih dahulu yaitu mengubah bilangan satuan menjadi terbilang. Contoh input dan output yang akan dihasilkan:
input 0 output nol, input 1 output satu, dan seterusnya sampai dengan input 9 output sembilan.

Potongan kode python untuk fungsi terbilang kita adalah:

satuan = ['nol', 'satu', 'dua', 'tiga', 'empat',
    'lima', 'enam', 'tujuh', 'delapan', 'sembilan']

def terbilang(angka):
    # satuan
    if angka < 10:
        return satuan[angka]

Cukup mudah untuk menghasilkan terbilang dari bilangan satuan. Untuk menggunakan fungsi ini langsung saja panggil fungsinya dengan memasukkan angka:

terbilang(2) --> dua
terbilang(9) -->  sembilan

puluhan
Berikutnya kita akan mengembangkan fungsi di atas untuk mengubah bilangan puluhan menjadi terbilang. Bilangan puluhan terdiri dari dua buah angka, angka pertama adalah puluhan dan angka kedua adalah satuan. Misalkan angka 25, diuraikan menjadi 2 (puluhan) 5 (satuan), dan ditulis sebagai "dua puluh lima".

Sebelum kita masuk ke kode python-nya, kita akan membahas dulu teknik yang digunakan untuk mengubah angka ini menjadi terbilang. Untuk mendapatkan terbilang dari bilangan puluhan, kita akan memisahkan masing-masing angka yang menjadi puluhan dan yang menjadi satuan. Caranya adalah dengan menggunakan operator bagi (/) dan operator modulus (%).
 
Untuk mendapatkan angka puluhan kita gunakan operator bagi:
    25 ==> 25 / 10 = 2

Kita membagi angka yang diinput dengan angka 10 untuk mendapatkan angka untuk puluhannya.
Sedangkan untuk angka satuan kita gunakan operator modulus:
    25 ==> 25 % 10 = 5

Kita menghitung sisa bagi angka yang diinput dengan angka 10 untuk mendapatkan angka satuannya. Setelah mendapatkan angka puluhan dan angka satuan, kita tinggal dapatkan terbilang untuk angka tersebut dan kemudian hasilnya disatukan menjadi terbilang yang lengkap.
    terbilang( angka / 10) + ' puluh ' + terbilang(angka % 10)

    terbilang(25 / 10) + ' puluh ' + terbilang(25 % 10) --> terbilang(2) + ' puluh ' + terbilang(5) = 'dua puluh lima'

tetapi bagaimana dengan bilangan yang satuannya nol? seperti 20, 30, atau 70?
    terbilang(20 / 10) + ' puluh ' + terbilang(angka % 10) --> terbilang(2) + ' puluh ' + terbilang(0) = 'dua puluh nol'

Hasilnya salah, harusnya 20 menghasilkan terbilang "dua puluh" bukan "dua puluh nol". Ini disebabkan karena kita memanggil fungsi terbilang lagi untuk 20 % 10 (0) yang menghasilkan terbilang nol. Untuk itu kita perlu tambahkan pengecekan pada hasil modulus untuk melihat apakah kita perlu menambahkan terbilang untuk satuan.

Kodenya:
    awalan = terbilang(angka / 10)
    akhiran = ''
    if angka % 10 > 0:
        satuan = terbilang(angka % 10)
    return awalan + ' puluh ' + akhiran

Kode lengkap untuk terbilang yang telah di-upgrade untuk puluhan adalah:
def terbilang(angka):
    # satuan
    if angka < 10:
        return satuan[angka]
    # puluhan
    elif angka >= 10 and angka <= 99:
        awalan = satuan[angka/10]
        akhiran = ''
        if angka % 10 > 0:
            akhiran = terbilang(angka % 10)
        return awalan + ' puluh ' + akhiran

Tapi tunggu, untuk angka 10 dan angka 19 ada yang aneh. Untuk angka 10 terbilang yang dihasilkan adalah satu puluh seharusnya adalah sepuluh dan untuk angka 19 seharusnya sembilan belas bukan satu puluh sembilan. Kita akan coba atasi masalah ini.

10, 100 dan 1000
Untuk angka 10, 100 dan 1000 biasanya kita akan tuliskan sebagai sepuluh, seratus dan seribu berbeda dengan angka 20, 500 dan 7000. Untuk menyelesaikan masalah ini kita akan memeriksa apakah awalan terbilang yang dihasilkan adalah 'satu' untuk puluhan, ratusan dan ribuan. Jika iya, ubah awalan tersebut menjadi 'se'.

def terbilang(angka):
    ...
    # puluhan
    elif angka >= 10 and angka <= 99:
        awalan = satuan[angka/10]
    if awalan == 'satu' and angka <= 1000:
        awalan = 'se'
    akhiran = ''
    if angka % 10 > 0:
        akhiran = terbilang(angka % 10)
    return awalan + ' puluh ' + akhiran

se puluh vs sepuluh
Hasil dari kode di atas sudah lebih baik sekarang, tetapi 10 menjadi 'se puluh' bukan 'sepuluh'. Permasalahan spasi ini juga cukup mengganggu estetika penulisan terbilang.
Kita akan menambahkan spasi antara awalan dan puluh apabila awalan bukan 'se' dan juga menambahkan spasi sebelum akhiran apabilan akhiran bukan ''.
Kita akan gunakan teknik string formating dan ekspresi if di dalam kode ini.

def terbilang(angka):
    ...
    # puluhan
    elif angka >= 10 and angka <= 99:
        ...
        if angka % 10 > 0:
            akhiran = terbilang(angka % 10)
        return '%s%s%s%s%s' % (awalan,
                               ' ' if awalan != 'se' else '',
                               'puluh',
                               ' ' if akhiran != '' else '',
                               akhiran)

Silahkan cobakan kode di atas. Kita akan mendapatkan terbilang yang lebih cantik sesuai dengan estetika penulisan. Berikutnya kita kita selesaikan masalah terbilang untuk bilangan belasan.

belasan
Sejauh ini kita sudah berhasil menghasilkan terbilang untuk satuan dan puluhan. Khusus untuk belasan, format penulisan berbeda dengan puluhan lainnya. Misalnya 19 terbilangnya adalah sembilan belas bukan sepuluh sembilan (apabila kita mengikuti aturan yang sama untuk angka 23 dsb). Yntuk belasan, angka satuannya akan disebutkan terlebih dahulu baru diikuti dengan akhiran belas. Cara kita mengatasi masalah ini adalah dengan menukar posisi satuan yang tadinya menjadi akhiran sekarang menjadi awalan.

def terbilang(angka):
    # satuan
    ...
    # belasan
    elif angka >= 11 and angka <= 19:
        awalan = satuan[angka%10]
        if awalan == 'satu': awalan = 'se'
        return '%s%s%s' % (awalan,
                           ' ' if awalan != 'se' else '',
                           'belas')
    # puluhan
    ...

Akhirnya terbilang yang dihasilkan sudah jauh lebih baik. Dengan menggunakan beberapa operasi sederhana (bagi dan modulus) dan string formatting pada python kita dapat membuat sebuah fungsi terbilang untuk bilangan satuan sampai dengan puluhan.

Kode lengkapnya:

def terbilang(angka):
    # satuan
    if angka < 10:
        return satuan[angka]
    # belasan
    elif angka >= 11 and angka <= 19:
        awalan = satuan[angka%10]
        if awalan == 'satu': awalan = 'se'
        return '%s%s%s' % (awalan,
                           ' ' if awalan != 'se' else '',
                           'belas')
    # puluhan
    elif angka >= 10 and angka <= 90:
        awalan = satuan[angka/10]
        if awalan == 'satu' and angka <= 1000:
            awalan = 'se'

        tengah = 'puluh'

        akhiran = ''
        if angka % 10 > 0:
            akhiran = terbilang(angka % 10)
        return '%s%s%s%s%s' % (awalan,
                             ' ' if awalan != 'se' else '',
                             tengah,
                             ' ' if akhiran != '' else '',
                             akhiran)


Fungsi terbilang yang saya bahas belum lengkap karena hanya mencakup bilangan satuan dan puluhan saja. Untuk bilangan yang lebih besar (ratusan, jutaan sampai tidak terhingga) akan saya bahas pada postingan berikutnya.

Happy Coding.