แบบฝึกหัด: โครงสร้างข้อมูล I#

โจทย์เรื่องลิสต์#

ข้อ 1. สลากกินแบ่ง#

เขียนฟังก์ชันเพื่อตรวจสอบว่าสลากกินแบ่ง (lottery) ที่มีอยู่ (อาจมีมากกว่า 1 ใบ) ถูกรางวัลทั้งหมดเท่าไร โดยที่ฟังก์ชันจะรับข้อมูล 3 อย่าง ได้แก่

  1. เลขสลากที่มีทั้งหมด (เป็นลิสต์ของสตริง) สลากแต่ละใบมีเลข 6 หลัก

  2. เลขรางวัลที่ 1 ที่ออก (เป็นสตริง) สลากจะถูกรางวัลที่ 1 เมื่อตัวเลขสลากตรงกับเลขรางวัลที่ 1 ที่ออก รางวัลละ 6,000,000 บาท

  3. เลขรางวัลเลขท้าย 2 ตัวที่ออก(เป็นสตริง) สลากจะถูกรางวัลเลขท้าย 2 ตัว เมื่อเลข 2 ตัวท้ายของสลาก ตรงกับเลขรางวัลเลขท้าย 2 ตัวที่ออก รางวัลละ 5,000 บาท

สลาก 1 เลข สามารถถูกทั้งรางวัลที่ 1 และรางวัลเลขท้าย 2 ตัวได้ เช่น ถ้าเลขรางวัลที่ 1 คือ 613728 และเลขท้าย 2 ตัวที่ออกคือ 28 สลากเลข 613728 จะได้รับรางวัล 6,000,000 + 5,000 = 6,005,000 บาท

ให้ฟังก์ชัน return ค่าเป็น list โดยที่ค่าแรกใน list เป็นจำนวนเงินที่ได้รับรางวัลทั้งหมด (เป็น int) และค่าต่อๆ ไปใน list เป็นเลขสลากที่ถูกรางวัล (เป็น string, อาจมีมากกว่า 1 เลขสลากได้ หรือไม่มีสลากที่ถูกรางวัลเลยก็ได้)

คำใบ้:

  • ไม่มีความจำเป็นที่จะต้องแปลงเลขสลาก เลขรางวัลที่ 1 เลขรางวัลเลขท้าย 2 ตัว จากสตริงเป็นเลข

  • ค่อยๆ แก้ทีละส่วนตามหลักการย่อยโจทย์ โจทย์ย่อย ๆ มีดังนี้ 2.1) คำนวณรางวัลที่ได้ 2.2) หาวิธีเก็บเลขสลากที่ถูกรางวัล 2.3) สร้างลิสต์สุดท้ายตามโจทย์กำหนด

  • อย่าลืมว่าสลากใบเดียวสามารถถูกได้สองรางวัล

def lottery_check(lottery_numbers, first, end2):
    """

	ตัวอย่าง
    >>> lottery_check(['613728'], '613728', '28')
    [6005000, '613728']

    >>> lottery_check(['382982', '428121'], '613728', '28')
    [0]

    >>> lottery_check(['382982', '417328', '012828'], '613728', '28')
    [10000, '417328', '012828']

    """
    return 0

ข้อ 2. ลิสต์อาหาร#

เพื่อนของคุณซึ่งเป็นผู้ชนะจากรายการ Master Top Iron Supercook Thailand ได้รับมอบหมายให้ไปทำอาหารให้เด็กนักเรียนโรงเรียน Sarasas Cadbury International แต่กลับโชคไม่ดีที่ว่าเด็กนักเรียนโรงเรียนนี้เป็นเด็กที่เลือกกินมาก เด็กแต่ละคนจะมี ลิสต์ของอาหารที่ตัวเองไม่กิน เพราะฉะนั้นเพื่อนของคุณจะต้องตรวจสอบวัตถุดิบของทุกจาน เพื่อเลือกสิ่งที่เด็กแต่ละคนไม่กินออก

จงเขียนฟังก์ชัน select_ingredients ซึ่งรับ input ดังนี้

  1. ลิสต์ของวัตถุดิบของอาหารที่เพื่อนของคุณจะทำ

  2. ลิสต์ของวัตถุดิบที่เด็กไม่กิน ฟังก์ชันนี้จะต้อง return ลิสต์ของวัตถุดิบที่เพื่อนของคุณสามารถใช้ได้

ตัวอย่าง

>>> ingredients = ['คะน้า', 'กระเทียม', 'น้ำมันหอย', 'หมูกรอบ', 'น้ำปลา', 'พริกไทย', 'ปลาเค็ม']
>>> prohibited = ['น้ำปลา', 'กระเทียม', 'ปลาเค็ม', 'มะนาว']
>>> select_ingredients(ingredients, prohibited)
['คะน้า', 'น้ำมันหอย', 'หมูกรอบ', 'พริกไทย'] 
def select_ingredients(list1, list2):
	return []

ข้อ 3. a/an#

เราเรียนกันมาแล้วว่า a ใช้นำหน้าคำที่ขึ้นต้นด้วยเสียงพยัญชนะ และ an ใช้นำหน้าคำที่ขึ้นต้นด้วยเสียงสระ

จงเขียนฟังก์ชันที่รับสตริงเป็น input และ return สตริงที่มีแก้การใช้ a/an โดยให้ assume ว่า

  • สตริงที่ได้มายังไม่ถูกตัดเป็นคำ และแต่ละคำถูกแบ่งได้ด้วย space

  • สตริงที่ได้มาไม่มีเครื่องหมายวรรคตอน (punctuation) หรือตัวเลขใดๆ

  • ถ้าคำนำหน้าด้วยพยัญชนะให้ใช้ a ถ้าคำนำหน้าด้วย aeiou ให้ใช้ an

  • ให้แก้ a–>an หรือ an–>a อย่างเดียว โดยไม่ต้องหาที่เติม a/an/the/ เข้าไปในจุดใดเลย

def correct_indefinite_article(sentence):
	"""
	ตัวอย่าง
	>>> correct_article('A elephant steps on an piece of wood in a forest')
	'An elephant steps on a piece of wood in a forest
	"""
	return ''

ข้อ 4. ทำความสะอาดข้อมูล#

เขียนฟังก์ชันที่รับสตริงประโยคภาษาอังกฤษ และ return ลิสต์ของคำในประโยคนั้น โดยไม่มีเครื่องหมายวรรคตอน (.,!?:)

คำใบ้

  1. ควรเอาเครื่องหมายวรรคตอนออกจากสตริงก่อน

  2. ใช้ method .split()

# Your code here
def str_to_clean_list(text):
	""" Turn English text into clean words
	
	Example:
	>>> str_to_clean_list("I will not give up on this. If I feel tired, I will take a rest.")
	['I','will','not','give','up','on','this','If','I','feel','tired','I','will','take','a','rest']
	"""
	return []

ข้อ 5. ความยาวเฉลี่ยของคำ#

เขียนฟังก์ชันหาความยาวเฉลี่ยของคำที่อยู่ในข้อความ โดยให้ใช้ฟังก์ชันจากข้อที่แล้วมาใช้ในการช่วยในการหาลิสต์ของคำทั้งหมดที่ไม่มีเครื่องหมายวรรคตอนอยู่เลย

คำใบ้: ใช้คำสั่ง sum() ในการหาผลรวมของตัวเลขที่อยู่ในลิสต์ทั้งหมด

def compute_mean_number_of_words(text):
    return 0

ข้อ 6. ตรวจข้อสอบ#

จงเขียนฟังก์ชันตรวจข้อสอบโดยรับค่า parameter 2 ตัว ได้แก่ ลิสต์ของเฉลยข้อสอบ และลิสต์ของคำตอบที่ต้องการตรวจในลำดับเดียวกัน ให้ข้อที่ถูกได้คะแนน 1 คะแนน หลังจากนั้นให้ฟังก์ชันคืนค่าเปอร์เซนต์ของข้อที่ตอบทั้งหมด

def grade_exam(correct_list, answer_list):
    """
    >>> check_exam(['a','b','d','a','c'], ['a','a','b','d','a'])
    (1, [1, 0, 0, 0, 0])
    >>> check_exam(['a','b','d','a','c'], ['a','b','d','a','c'])
    (5, [1, 1, 1, 1, 1])
    """
    return 0

ข้อ 7. เปลี่ยนตัว#

สมมติว่าเรามีลิสต์ของแขกที่จะมาร่วมงานวันเกิด แต่ว่าแขกมักจะมีการเปลี่ยนตัวกระทันหันเนื่องจากอาจจะติดธุระมาไม่ได้ จงเขียนฟังก์ชันที่รับ 3 พารามิเตอร์

  1. ลิสต์ของสตริงที่ชื่อแขกทั้งหมดอยู่

  2. ชื่อแขกที่มาไม่ได้แล้ว

  3. ชื่อแขกที่จะมาแทน ฟังก์ชันจะแก้ลิสต์ของแขกแต่ว่าจะไม่ return อะไรเลย

ตัวอย่าง

>>> name_list = ["Tony", "Elan", "Bee", "Bonus", "Jane"]
>>> sub_name("Bee", "Thomas", name_list)
>>> print(name_list)
["Tony", "Elan", "Thomas", "Bonus", "Jane"]
def sub_name(old_guest, new_guest, guest_list):
	pass

ข้อ 8. คำนวณสถิติ#

เขียนฟังก์ชันที่รับลิสต์ของตัวเลขเข้ามาเป็น input และคำนวณหาค่าต่ำสุด สูงสุด เรนจ์ (สูงสุด - ต่ำสุด) ค่ามัธยฐาน และค่าเฉลี่ย โดย print ออกมาและไม่ return ค่าใด ๆ และเพ่ือทำให้โจทย์นี้ง่ายลง เราสามารถ assume ได้ว่าจำนวนสมาชิกของลิสต์เป็นเลขคี่

>>> score_nlps = [6, 5, 10, 8, 7, 11, 5.5, 4, 8, 9, 11]
>>> stats_summary(score_nlps)
Min = 4
Max = 11
Range = 7
Median = 8
Mean = 7.68

คำใบ้: ควรใช้คำสั่ง sorted(x) ในการหามัธยฐาน

def stats_summary(number_list):
	print ('')

ข้อ 9. เลือกคำ#

จงเขียน function หาคำที่สนใจ โดยกำหนดให้ function รับ parameter เข้ามา 2 ตัว

  1. list ของประโยคที่ถูกตัดคำแล้ว เช่น [‘She’, ‘went’, ‘to’, ‘eat’, ‘pizza’, ‘at’, ‘Huahin’ ,’yesterday’]

  2. list ที่เป็นค่า 0 หรือ 1 เพื่อบอกว่าที่ตำแหน่งของคำนั้นเป็นคำที่เราสนใจหรือไม่ โดยที่ 0 คือไม่สนใจและ 1 คือสนใจ เช่น [0, 0, 0, 0, 1, 0, 1, 0]

และคืนค่าออกมาเป็น list ที่มีแต่คำที่สนใจเท่านั้น

def select_words_from_mask(word_list, mask_list):
    """ Select words from a list
    
    Example

    >>> tokenized_sentence = ['She', 'went', 'to', 'eat', 'pizza', 'at', 'Huahin' ,'yesterday']
    >>> mask = [0, 0, 0, 0, 1, 0, 1, 0]
    >>> select_words_from_mask(tokenized_sentence, mask)
    ['pizza', 'Huahin']
    """
    return []

โจทย์เรื่องดิกชันนารี#

ข้อ 1. ตัดเกรด#

เขียนฟังก์ชันที่ตัดเกรดให้กับนักเรียนโดยที่ดูจากคะแนนการสอบสองครั้งที่ผ่านมา คะแนนสอบแต่ละครั้งนั้นถูกเก็บในรูปของ dictionary ที่ key=ชื่อนักเรียน value=คะแนนสอบ 0-10 คะแนน ถ้านักเรียนไม่ได้เข้าสอบชื่อก็จะไม่ได้อยู่ใน dictionary เรามีเกณฑ์การตัดเกรดง่ายๆ ดังนี้

  • นักเรียนที่สอบผ่านทั้งสองครั้ง (คะแนน > 5 ทั้งสองครั้ง) จะได้ A

  • นักเรียนที่สอบผ่านแค่ครั้งเดียว จะได้ B

  • นักเรียนที่สอบไม่ผ่านเลย จะได้ C

  • นักเรียนที่เข้าสอบไม่ครบทั้งสองครั้งจะได้ M

Input: คะแนนสอบครั้งที่ 1 และ คะแนนสอบครั้งที่ 2 เป็น dictionary

Output: dictionary ที่ key=ชื่อนักเรียนที่เข้าสอบอย่างน้อยหนึ่งครั้ง value=เกรด string A, B,C หรือ M

ตัวอย่าง

>>> midterm = {'Rick': 5.5, 'Michonne': 2, 'Carol': 9, 'Daryl': 7}
>>> final = {'Rick': 6, 'Michonne': 5, 'Carol': 4}  
>>> assign_grades(midterm, final) 
{'Rick': 'A', 'Michonne':'C', 'Carol': 'B', 'Daryl': 'M'}
def assign_grades(midterm, final):
	return {}

ข้อ 2. Recode part 1#

หลายครั้งเวลาเราประมวลผลข้อมูลที่เป็นคำ เราต้องเปลี่ยนคำให้เป็นตัวเลข (เรียกว่า index) เพราะว่าตัวเลขกินพื้นที่น้อยกว่าและจัดเก็บได้ง่ายกว่าตัวหนังสือ จงเขียนฟังก์ชันที่เปลี่ยนคำใน list เป็น list of index โดยมองหา index จาก dictionary ที่กำหนดให้

dictionary จะมีลักษณะดังนี้คือ ถ้ามี key อยู่ 3 ตัว value จะเป็น 0, 1, 2 และจะไม่ซ้ำกันเช่น

{'cat': 0, 'mat':1, 'care': 2}

ถ้าคำนั้นไม่อยู่ใน dictionary ให้เติมคำใหม่เข้าไปและหา index ที่ไม่ซ้ำกับคำอื่น เช่น ถ้าเจอคำว่า ‘cow’ เราต้องเพิ่มคู่ key-value เข้าไปในดิกชันนารีและให้ index ใหม่ เป็น

{'cat': 0, 'mat':1, 'care': 2, 'cow':3}
def recode_word(word_list, word_to_index):
    """
    This function takes a list of words and a dictionary that maps word to index
    This function must return a tuple of (index list, updated dictionary)

    ตัวอย่าง
    >>> recode_word(['cat', 'mat', 'cat'], {'cat': 0, 'mat':1})
    ([0, 1, 0], {'cat': 0, 'mat':1})

    >>> recode_word(['cat', 'bat', 'mat', 'cat', 'eat'], {'cat': 0, 'mat':1})
    ([0, 2, 1, 0, 3], {'cat': 0, 'mat':1, 'bat': 2, 'eat': 3})
    """

ข้อ 3. Recode part 2#

เมื่อเวลาเราประมวลผลข้อมูลเสร็จแล้ว เราจะต้องการแปลงค่าที่เป็น index ของคำกลับไปเป็นคำเหมือนเดิม เช่น ถ้าดิกชันนารีจากคำไป index มีลักษณะดังนี้

{'cat': 0, 'mat':1, 'bat': 2, 'eat': 3}

และข้อมูลจัดเก็บอยู่ในลิสต์ดังนี้

[0, 2, 1, 0, 3]

เราต้องให้แปลงกลับไปเป็นคำเหมือนเดิม

['cat', 'bat', 'mat', 'cat', 'eat']

จงเขียนฟังก์ชันที่แปลงลิสต์ของ index ของคำมาเป็นลิสต์ของคำ โดยใช้ข้อมูลจากดิกชันนารี

คำใบ้ สังเกตว่าดิกชันนารีที่ให้มา key เป็นคำและ value เป็น index ทำให้เปิดหาได้ยาก เราจะต้องสร้างดิกอันใหม่ขึ้นมาหนึ่งอัน และนำ value มาเป็น key นำ key เป็น value โดยการวนซ้ำไปบน .items()

def inverse_recode(index_list, word_to_index):
    """
    ตัวอย่าง
    >>> inverse_recode([0, 2, 1, 0, 3], {'cat': 0, 'mat':1, 'bat': 2, 'eat': 3})
    ['cat', 'bat', 'mat', 'cat', 'eat']
    """
    return []

ข้อ 4.#

โนโน่เป็นคนชอบเขียนโปรแกรมและกินผลไม้มาก โนโน่เลยเก็บจำนวนผลไม้ที่มีในตู้เย็นไว้ใน python dictionary เช่น { "apple": 1, "banana": 2 } คือมีแอปเปิ้ล 1 ลูก กล้วย 2 ลูก ต่อมา โนโน่ซื้อตู้เย็นมาอีกตู้ จึงมี dictionary อีกอันหนึ่งไว้เก็บจำนวนผลไม้

โนโน่อยากรู้จำนวนผลไม้ที่มีทั้งหมด ช่วยโนโน่หน่อย เขียนฟังก์ชันที่รับ dictionary 2 ตัวเป็น parameters (คือ dictionary ที่แทนผลไม้ในตู้ที่ 1 และ 2 ตามลำดับ) และ return dictionary แสดงจำนวนผลไม้ทั้งหมด เช่น

>>> count_fruits({"apple": 1, "banana": 2}, {"apple": 3, "banana": 4})
{"apple": 4, "banana": 6}
>>> count_fruits({"apple": 5, "banana": 7, "papaya": 9}, {"apple": 3, "banana": 5, "papaya": 7}) 
{"apple": 8, "banana": 12, "papaya": 16}

เพื่อความง่าย ให้ถือว่าชนิดของผลไม้ที่โนโน่มีในตู้เย็นเหมือนกันทั้งสองตู้ (ถ้าตู้แรกมีแอปเปิ้ล ตู้ที่สองก็มีด้วย ถ้าตู้ที่สองมีองุ่น ตู้แรกก็มีด้วย)

def count_fruits(count1, count2):
    """
    ตัวอย่าง
    >>> count_fruits({"apple": 1, "banana": 2}, {"apple": 3, "banana": 4})
    {"apple": 4, "banana": 6}
    >>> count_fruits({"apple": 5, "banana": 7, "papaya": 9}, {"apple": 3, "banana": 5, "papaya": 7}) 
    {"apple": 8, "banana": 12, "papaya": 16}
    """
    return {}

ข้อ 5. สนุกกำลังสอง#

เขียนฟังก์ชันที่รับค่า n แล้ว return dictionary ที่มี key ตั้งแต่ 1 ถึง n โดย value ของแต่ละตัวคือ key ยกกำลังสอง เช่น

squared_dict(3)  
>>> { 1: 1, 2: 4, 3: 9 }
squared_dict(5) 
>>> { 1: 1, 2: 4, 3: 9, 4: 16, 5: 25 }
def squared_dict(num):
    return {}

ข้อ 6. สร้าง dictionary#

สมมติว่าเรามี list ของคำศัพท์ และ list ของคำแปล

english_list = ['computer', 'dog', 'floor']
thai_list = ['คอมพิวเตอร์', 'หมา', 'พื้น']

เขียนฟังก์ชันที่สร้าง dict ที่ key คือคำภาษาอังกฤษ และ value คือคำแปลภาษาไทย

>>> en_th_dict = make_en_th_dictionary(english_list, thai_list)
>>> en_th_dict['dog']
'หมา'
def make_en_th_dictionary(english_list, thai_list):
    return {}

ข้อ 7. Simplify#

สมมติว่าเราต้องการทำให้ข้อความเข้าใจง่ายขึ้นโดยการแทนที่คำยากด้วยคำง่าย โดยเราจะเก็บคู่ของคำยาก คำง่ายไว้ใน ใน dictionary ดังนี้

censor_dict = {
    'utilize': 'use',
    'eulogize': 'praise',
    'annihilate': 'destroy',
    'apprise': 'warn',
    'impending': 'upcoming'
}

เขียนฟังก์ชั่นที่เปลี่ยน string ภาษาอังกฤษ เป็น string ที่คำยากถูกแทนด้วยคำง่ายที่อยู่ใน dictionary

Hint:

  • เปลี่ยน text ให้เป็น list ก่อน

  • จากนั้นก็เช็คว่าคำในลิสต์อยู่ในดิกมั้ย ถ้าอยู่ก็แก้ไขลิสต์ตรงตำแหน่งนั้น (ใช้ for i in range(len(...)))

def simplify_eng(text):
    censor_dict = {
        'utilize': 'use',
        'eulogize': 'praise',
        'annihilate': 'destroy',
        'apprise': 'warn',
        'impending': 'upcoming'
    }
    
    return ''

โจทย์เรื่องเซ็ต#

ข้อ 1 - คำที่ไม่ซ้ำ#

จงเขียนฟังก์ชันที่รับสตริงที่เป็นประโยคภาษาอังกฤษแบบไม่มีเครื่องหมายวรรคตอนใด ๆ (ยกเว้นช่องว่าง) และเป็นตัวพิมพ์เล็กทั้งหมด ให้ฟังก์ชันนี้ return คำทั้งหมดที่เจอในสตริง เรียงตามลำดับตัวอักษรรวมกันเป็นสตริงเดียวไม่มีคำที่ซ้ำ (duplicate) แต่ละคำถูกคั่นด้วย |

def unique_words(text):
    """
    >>> unique_words('hello world and practice makes perfect and hello world again')
    'again|and|hello|makes|perfect|practice|world'
    """
    return ''

ข้อ 2 - ตัวอักษรที่ไม่ซ้ำ#

จงเขียนฟังก์ชันที่หาว่าสตริงที่ได้รับมามีตัวอักษรซ้ำกันบ้างหรือไม่

def is_all_distinct_characters(word):
    """
    Examples:
    >>> is_all_distinct_characters('abc')
    True    
    >>> is_all_distinct_characters('aA')
    True
    >>> is_all_distinct_characters('abca')
    False
    >>> is_all_distinct_characters('Alexander') # ตัว e ซ้ำ
    False
    """
    return ''

ข้อ 3 - สินค้าที่ร้านอื่นไม่มี#

เขียนฟังก์ชันที่เปรียบเทียบรายการสินค้าของร้าน A กับร้าน B โดยให้หาว่าอะไรบ้างที่ร้าน A ขายแต่ร้าน B ไม่ได้ขาย ฟังก์ชันนี้รับ list ของสตริงที่แสดงรายการสินค้าจากร้าน A และอีก list แสดงรายการสินค้าของร้าน B ฟังก์ชันนี้ต้อง return list ของสินค้า

def find_business_opportunities(storeA_items, storeB_items):
    """
    
    Examples:
    >>> list1 = ['razor blade', 'soap', 'shampoo', 'liquid detergent', 'toothbrush']
    >>> list2 = ['soap', 'conditioner', 'shampoo', 'toothpaste']
    >>> find_business_opportunities(list1, list2)
    ['razor blade', 'liquid detergent', 'toothbrush']
    """
    return []

ข้อ 4 - Out of vocabulary#

เขียนฟังก์ชันที่รับ list ของคำ (สตริง) และ vocabulary ซึ่งเป็นเซ็ตของสตริง ให้ฟังก์ชันนี้ return จำนวนคำในลิสต์ที่ไม่อยู่ใน vocabulary ได้รับมา

ข้อนี้ให้ลองแก้สองวิธี

  1. แบบใช้ for loop ลงไปบน word_list

  2. แปลง word_list ให้เป็นเซ็ต จากนั้นใช้เซ็ต operation แก้โจทย์

def count_oov_words(word_list, vocab_set):
    return 0

ข้อ 5 - Dinner#

เขียนฟังก์ชันชื่อ agree_dinner ที่รับ parameter เป็นชื่อ list จำนวน 3 list ซึ่งแต่ละ list จะเป็นประเภทของอาหารที่เพื่อนแต่ละคนอยากทาน ให้ฟังก์ชันนี้ return ค่าเป็น list ของประเภทอาหารที่ทุกคนอยากทาน โดยเรียงลำดับตามตัวอักษร เช่น

agree_dinner(
  ['thai', 'chinese', 'japanese', 'shabu'],
  ['shabu', 'japanese', 'yakiniku', 'italian'],
  ['greek', 'shabu', 'chinese', 'japanese']
)

ฟังก์ชันต้อง return ['japanese', 'shabu']

def agree_dinner(list1, list2, list3):
    return []