Next Chapter: Example for recursive Programming: Towers of Hanoi
Turkish Time and Clock
Introduction
This chapter of our Python tutorial deals with turkish times. You will learn how to tell the time in turkish, but what is more him important: We will teach Python to tell the time in Turkish given the time numerically. Turkish grammar and sentence structures as well as vocabulary differ extremely from Indo-European languages like English and Persian, and also Semitic languages like Arabic and Hebrew and many other languages. So, telling the time in Turkish is also extremely difficult for speakers of English, German, French, Italian and many other languages. Fortunately, there are strict rules available. Rules which are so regular that it is easy to write a Python program to the job.
"Saat kaç?" means "What is the time?" in Turkish.
The task of hour program is to answer this question, given the time as string in the form "03:00" or "10:30".
We will need the words for the digits 0, 1, ... 9. We use a Pyhton list for this:
digits_list = ["bir", "iki", "üç",
"dört", "beş", "altı",
"yedi", "sekiz", "dokuz"]
The digits are not enough. We will need the words for the tens as well. The following list corresponds to the numbers "ten", "twenty", "thirty", "forty", and "fifty". We do not need more:
tens_list = ["on", "yirmi", "otuz", "kırk", "elli"]
def num2txt(min):
digits = min % 10
tens = min // 10
if digits > 0:
if tens:
return tens_list[tens-1] + " " + digits_list[digits-1]
else:
return digits_list[digits-1]
else:
return tens_list[tens-1]
for number in range(60):
print(number, num2txt(number), end=", ")
We will start now implementing the function translate_time
. This function will produce a reply to the question "Saat kaç?". It takes hours
and minutes
as parameters. We will only implement the funciton for full hours, because this is the easiest case.
def translate_time(hours, minutes=0):
if minutes == 0:
return "Saat " + num2txt(hours) + "."
else:
return "I still do not know how to say it!"
for hour in range(1, 13):
print(hour, translate_time(hour))
Easy, isn't it? What about "half past"? This is similar to English, if you consider that "buçuk" means "half". We extend our function:
def translate_time(hours, minutes=0):
if minutes == 0:
return "Saat " + num2txt(hours) + "."
elif minutes == 30:
return "Saat " + num2txt(hours) + " buçuk."
else:
return "I still do not know how to say it!"
for hour in range(1, 13):
print(hour, translate_time(hour, 30))
We want to go on with telling the time in Turkish, and teach our Python program to say "a quarter past" and a "quarter to". It is getter more complicated or interesting now. Our Python implementation needs to learn some grammar rules now. The Python program has to learn now how to produce the Dative and the Accusative in Turkish.
Turkish Dative
The dative case is formed by adding e
or a
as a suffix to the end of the word (not necessarily a noun).
If the last syllable of the word has one of the vowels 'a', 'ı', 'o' or 'u', an 'a' has to be added to the end of the word. If the last syllable of the word has one of the vowels 'e', 'i', 'ö', or 'ü', an 'e' has to be appended.
One more important thing: Turkish doesn't like to vowels beside of each other. Therefore, we will add a "y" in front ot the 'e' or 'a', if the last letter of the word is a vowel.
Now we are ready to implement the dative
function. It will suffix the dative ending to a given word. The dative
function needs a function last_vowel
which comes back with two values:
- the vowel in the last syllable
True
orFalse
to indicate if the word ends with a vowel
def last_vowel(word):
vowels = {'ı', 'a', 'e', 'i', 'o', 'u', 'ö', 'ü'}
ends_with_vowel = True
for char in word[::-1]:
if char in vowels:
return char, ends_with_vowel
ends_with_vowel = False
def dative(word):
lv, ends_with_vowel = last_vowel(word)
if lv in {'i', 'e', 'ö', 'ü'}:
ret_vowel = 'e'
elif lv in {'a', 'ı', 'o', 'u'}:
ret_vowel = 'a'
if ends_with_vowel:
return word + "y" + ret_vowel
else:
return word + ret_vowel
We can check the dative
function by calling it with the numbers in digits_list
:
for word in digits_list:
print(word, dative(word))
def accusative(word):
lv, ends_with_vowel = last_vowel(word)
if lv in {'ı', 'a'}:
ret_vowel = 'ı'
elif lv in {'e', 'i'}:
ret_vowel = 'i'
elif lv in {'o', 'u'}:
ret_vowel = 'u'
elif lv in {'ö', 'ü'}:
ret_vowel = 'ü'
if ends_with_vowel:
return word + "y" + ret_vowel
else:
return word + ret_vowel
Let us have a look at the dative and accusative together:
print(f"{'word':<20s} {'dative':<20s} {'accusative':<20s}")
for word in digits_list:
print(f"{word:<20s} {dative(word):<20s} {accusative(word):<20s}")
Now, we have programmed what we need to further extend the translate_time
function. We will add now the branches for "a quarter to" and "a quarter past". A "quarter" means "çeyrek" in Turkish. "to" and "past" are translated by adding "var" and "geçiyor" to the end. The verbal representation of the hour number has to be put into the dative in case of "var" and into the accusative form in case of "geçiyor".
def translate_time(hours, minutes=0):
if minutes == 0:
return "Saat " + num2txt(hours) + "."
elif minutes == 30:
return "Saat " + num2txt(hours) + " buçuk."
elif minutes == 15:
return "Saat " + accusative(num2txt(hours)) + " çeyrek geçiyor."
elif minutes == 45:
if hours == 12:
hours = 0
return "Saat " + dative(num2txt(hours+1)) + " çeyrek var."
else:
return "I still do not know how to say it!"
for hour in range(1, 13):
print(f"{hour:02d}:{15:02d} {translate_time(hour, 15):25s}")
print(f"{hour:02d}:{45:02d} {translate_time(hour, 45):25s}")
We can finish the translate_time
function now. We have to branches for the minutes.
def translate_time(hours, minutes=0):
if minutes == 0:
return "Saat " + num2txt(hours) + "."
elif minutes == 30:
return "Saat " + num2txt(hours) + " buçuk."
elif minutes == 15:
return "Saat " + accusative(num2txt(hours)) + " çeyrek geçiyor."
elif minutes == 45:
if hours == 12:
hours = 0
return "Saat " + dative(num2txt(hours+1)) + " çeyrek var."
elif minutes < 30:
return "Saat " + accusative(num2txt(hours)) + " " + num2txt(minutes) + " geçiyor."
elif minutes > 30:
minutes = 60 - minutes
if hours == 12:
hours = 0
hours = dative(num2txt(hours + 1))
mins = num2txt(minutes)
return "Saat " + hours + " " + mins + " var."
for hour in range(1, 13, 1):
for min in range(1, 60, 9):
print(f"{hour:02d}:{min:02d} {translate_time(hour, min):25s}")
digits_list = ["bir", "iki", "üç",
"dört", "beş", "altı",
"yedi", "sekiz", "dokuz"]
tens_list = ["on", "yirmi", "otuz", "kırk", "elli"]
def num2txt(min):
""" numbers are mapped into verbal representation """
digits = min % 10
tens = min // 10
if digits > 0:
if tens:
return tens_list[tens-1] + " " + digits_list[digits-1]
else:
return digits_list[digits-1]
else:
return tens_list[tens-1]
def last_vowel(word):
""" returns a tuple 'vowel', 'ends_with_vowel'
'vowel' is the last vowel of the word 'word'
'ends_with_vowel' is True if the word ends with a vowel
False otherwise
"""
vowels = {'ı', 'a', 'e', 'i', 'o', 'u', 'ö', 'ü'}
ends_with_vowel = True
for char in word[::-1]:
if char in vowels:
return char, ends_with_vowel
ends_with_vowel = False
def dative(word):
""" returns 'word' in dative form """
lv, ends_with_vowel = last_vowel(word)
if lv in {'i', 'e', 'ö', 'ü'}:
ret_vowel = 'e'
elif lv in {'a', 'ı', 'o', 'u'}:
ret_vowel = 'a'
if ends_with_vowel:
return word + "y" + ret_vowel
else:
return word + ret_vowel
def accusative(word):
""" return 'word' in accusative form """
lv, ends_with_vowel = last_vowel(word)
if lv in {'ı', 'a'}:
ret_vowel = 'ı'
elif lv in {'e', 'i'}:
ret_vowel = 'i'
elif lv in {'o', 'u'}:
ret_vowel = 'u'
elif lv in {'ö', 'ü'}:
ret_vowel = 'ü'
if ends_with_vowel:
return word + "y" + ret_vowel
else:
return word + ret_vowel
def translate_time(hours, minutes=0):
""" construes the verbal represention
of the time 'hours':'minutes
'"""
if minutes == 0:
return "Saat " + num2txt(hours) + "."
elif minutes == 30:
return "Saat " + num2txt(hours) + " buçuk."
elif minutes == 15:
return "Saat " + accusative(num2txt(hours)) + " çeyrek geçiyor."
elif minutes == 45:
if hours == 12:
hours = 0
return "Saat " + dative(num2txt(hours+1)) + " çeyrek var."
elif minutes < 30:
return "Saat " + accusative(num2txt(hours)) + " " + num2txt(minutes) + " geçiyor."
elif minutes > 30:
minutes = 60 - minutes
if hours == 12:
hours = 0
hours = dative(num2txt(hours + 1))
mins = num2txt(minutes)
return "Saat " + hours + " " + mins + " var."
Let us test the previous Python code with some times:
from turkish_time import translate_time
for hour, min in [(12, 47), (1, 23), (16, 9)]:
print(f"{hour:02d}:{min:02d} {translate_time(hour, min):25s}")
We implement in the following Python program a clock, which uses a graphical user interface. This clock shows the current time in a verbal representation. Of course, in Turkish:
import tkinter as tk
import datetime
from turkish_time import translate_time
def get_time():
now = datetime.datetime.now()
return now.hour, now.minute
def time_text_label(label):
def new_time():
now = datetime.datetime.now()
res = translate_time(now.hour, now.minute)
label.config(text=res)
label.after(1000, new_time)
new_time()
flag_img = "images/turkish_flag_clock_background.png"
root = tk.Tk()
root.option_add( "*font", "lucida 36 bold" )
root.title("Turkish Time")
flag_img = tk.PhotoImage(file=flag_img)
flag_img = flag_img.subsample(4, 4) # shrink image, divide by 4
flag_label = tk.Label(root, image=flag_img)
flag_label.pack(side=tk.LEFT)
label = tk.Label(root,
font = "Latin 18 bold italic",
fg="dark green")
label.pack(side=tk.RIGHT)
time_text_label(label)
button = tk.Button(root,
text='Stop',
font = "Latin 12 bold italic",
command=root.destroy)
button.pack(side=tk.RIGHT)
root.mainloop()
Next Chapter: Example for recursive Programming: Towers of Hanoi