اسمفامیل
فایل
esm_famil_data.csvرا داور کنار کد تو میگذارد. دربارهی دو قانون امتیازدهی: قانون اول (۵ برای پاسخ تکراری، ۱۰ برای پاسخ منحصربهفرد) برای زمینهای است که همهی بازیکنان در آن پاسخی دادهاند؛ قانون دوم (۱۰ و ۱۵) برای زمینهای است که دستکم یک نفر آن را خالی گذاشته — همانطور که در راهنمایی نهایی آمده است.
سلیب که از تنهایی و خانهنشینی حوصلهاش سر رفته، تصمیم گرفته که دوستانش را دعوت کند تا با آنها اسمفامیل بازی کند. بعد از رسیدن دوستان سلیب آنها بازی را شروع کردند، اما بعد از تمام شدن دست اول در امتیازدهی دچار مشکل شدهاند. هیچکس کلمات دیگری را قبول نداشت؛ به همین دلیل نمرهی هر کلمه نامشخص بود.
سلیب و دوستانش برنامهنویس هستند و فقط به برنامههای کامپیوتری اعتماد دارند؛ بنابراین از شما میخواهند برایشان برنامهای بنویسید که با دریافت فایل تمامی کلمات قابلقبول از نظر آنها، طبق قوانین ذکر شده، بتواند به او و دوستانش نمرهای صحیح بدهد.
📂 فایل کلمات
دوستان سلیب برای اینکه در امتیازدهی به مشکل نخورند، یک فایل CSV آماده کردند که شامل همهی کلماتی است که از نظر آنها درست هستند. این فایل با نام esm_famil_data.csv به فرمت CSV در پروژهی اولیه در اختیار شما قرار داده شدهاست.
نمونهی محتوای فایل CSV:
esm,famil,keshvar,rang,ashia,ghaza
اب گوشت,استکان,ابی,المان,اسدی,اوا
اش,ایینه,اجری,البانی,ارمانی,ارزو
برنج خورشت,اره,ارغوانی,انگولا,اکبری,اتنا
باقالی پلو,اره برقی,ارکیده,اتریش,اعظمی,ارش
به پلو,اب پاش,البالویی,امریکا,امینی,امنه
باقلوا,بیل,بژ,ایتالیا,ازادی,ارمین
پیتزا,بمب,بنفش,ارژانتین,بابایی,ایدا
پیشنهاد میکنیم قبل از شروع پیادهسازی، یک بار این فایل را باز کنید و محتویات آن را ببینید (اگر با باز کردن این فایل مشکل داشتید میتوانید از ابزار Google Sheets استفاده کنید).
🔧 پیادهسازی
شما باید سه تابع با نامهای ready_up و add_participant و calculate_all را برای سلیب و دوستانش پیادهسازی کنید. غیر از این توابع، میتوانید از متغیرهای global نیز برای به اشتراک گذاشتن اطلاعات بین توابع استفاده کنید.
بهصورت کلی، ابتدا باید محتویاتِ فایلِ کلماتِ قابلقبول را بخوانید و ذخیره کنید، سپس پاسخهای بازیکنان را به بازی اضافه کنید و در نهایت شروع به امتیازدهی کنید.
این تابع باید محتویات درون فایل CSV دادهشده را خوانده و به شکل دلخواه شما ذخیره کند. فایل CSV با نام
esm_famil_data.csvدر کنار فایل پایتون شما قرار دارد. پیشنهاد میشود برای ذخیرهسازی این اطلاعات از قابلیتهای دادهساختارهای لیست و دیکشنری بهره ببرید.💡 راهنمایی ۱: هنگام ذخیره کردن هر کلمه در دستهبندی مربوط به خودش، فاصلههای درون و اطراف کلمه (یعنی کاراکتر ' ') را حذف کنید (با کاراکتر '' جایگزین کنید) تا بعداً تطبیق کلمات با پاسخهای بازیکنان آسانتر شود.
این تابع باید یک بازیکن و پاسخهایش را به بازی اضافه کند. نحوهی استفاده از این تابع به این صورت خواهد بود:
شما باید در این تابع، پاسخهای تکتک بازیکنان را نیز برای آن بازیکن ذخیره کنید. انتخاب نحوهی ذخیرهسازی بر عهدهی شما است. پیشنهاد میشود از قابلیتهای دیکشنریها برای این کار بهره ببرید.
💡 راهنمایی ۲: هنگام ذخیره کردن هریک از پاسخهای بازیکن، فاصلههای درون و اطراف کلمه (یعنی کاراکتر ' ') را حذف کنید (با کاراکتر '' جایگزین کنید) تا بعداً تطبیق کلمات با کلمات موردقبول، آسانتر شود.
add_participant(participant='salib', answers={'esm': 'بردیا', 'famil': 'بابایی', 'keshvar': 'باربادوس', 'rang': 'بنفش', 'ashia': 'بمب', 'ghaza': 'باقالیپلو'})
این تابع هنگامی فراخوانی میشود که پاسخهای تمامی بازیکنان به برنامه داده شدهاست. وظیفهی این تابع، محاسبهی نمرهی همهی افراد است. پس از محاسبه باید در قالب یک دیکشنری مشابه زیر، نتیجهی بازی را برگردانید:
{'salib': 65, 'kianoush': 55, 'sajjad': 45, 'farhad': 40}
📋 قوانین امتیازدهی
در هر زمینه (برای مثال ghaza) دو حالت امتیازدهی زیر را داریم:
- اگر بازیکن پاسخی ارائه کرده باشد که در لیست کلمات قابلقبول نیست، ۰ امتیاز میگیرد.
- اگر بازیکن پاسخی تکراری داده باشد که در کلمات قابلقبول هست، ۵ امتیاز میگیرد؛ مثلاً اگر سه نفر پیتزا نوشته باشند، هرسه ۵ امتیاز میگیرند.
- اگر بازیکن پاسخ منحصربهفردی داده باشد که در کلمات قابلقبول هست، ۱۰ امتیاز میگیرد؛ مثلاً اگر فقط یک نفر پاستا نوشته باشد، آن یک نفر ۱۰ امتیاز میگیرد.
- اگر بازیکن پاسخی ارائه کرده باشد که در لیست کلمات قابل قبول نیست و یا پاسخی ارائه نکرده باشد، ۰ امتیاز میگیرد.
- اگر بازیکن پاسخی تکراری داده باشد که در کلمات قابلقبول هست، ۱۰ امتیاز میگیرد؛ مثلاً اگر سه نفر پیتزا نوشته باشند، هرسه ۱۰ امتیاز میگیرند.
- اگر بازیکن پاسخ منحصربهفردی داده باشد که در کلمات قابلقبول هست، ۱۵ امتیاز میگیرد؛ مثلاً اگر فقط یک نفر پاستا نوشته باشد، آن یک نفر ۱۵ امتیاز میگیرد.
💡 نکات مهم
- ممکن است پاسخهای درست به شکل نگارشی دیگری در بازی وجود داشته باشند. فاصلهها در کلمات، در درست بودن یک کلمه تفاوتی ایجاد نمیکنند. مثلاً عدس پلو و عدسپلو باید معادل یکدیگر در نظر گرفته شوند.
- ممکن است پاسخ خالی بهصورت تعدادی کاراکتر فاصله، مثلاً
" "، به شما داده شود. - تضمین میشود که پاسخهای بازیکنان و همچنین کلمات قابلقبول درون فایل، شامل آ نیستند و تمامی الفها بهصورت ا خواهند بود.
- تضمین میشود که تمامی پاسخهای بازیکنان با یک حرف شروع میشوند؛ مثلاً اگر بازی با حرف س باشد، پاسخهای تمامی شرکتکنندگان نیز با حرف س شروع میشود.
- اگر یک بازیکن، کلمهای را برای زمینهی اشتباهی نوشت، نباید امتیاز آن را دریافت کند؛ مثلاً کلمهی قیمه در زمینهی اشیاء پذیرفته نیست.
- ⚠️ توجه کنید که برخی کلمات ممکن است در دو زمینهی مختلف معنیدار باشند. در این صورت اگر دو بازیکن چنین کلمهای را در دو زمینهی مختلف نوشته باشند، نباید بهعنوان کلمهی تکراری در نظر گرفته شود و امتیاز آنها را کم کند؛ مثلاً کلمهی عدسی میتواند هم در زمینهی غذا و هم اشیاء استفاده شود.
🎯 نمونه
>>> ready_up()
>>> add_participant(participant = 'salib', answers = {'esm': 'بردیا', 'famil': 'بابایی', 'keshvar': 'باربادوس', 'rang': 'بنفش', 'ashia': 'بمب', 'ghaza': 'باقالیپلو'})
>>> add_participant(participant = 'kianoush', answers = {'esm': 'بهرام', 'famil': 'بهرامی', 'keshvar': 'برزیل', 'rang': 'بلوطی', 'ashia': 'بیل', 'ghaza': 'به پلو'})
>>> add_participant(participant = 'sajjad', answers = {'esm': 'بابک', 'famil': 'بهشتی', 'keshvar': 'باهاما', 'rang': 'بژ', 'ashia': ' ', 'ghaza': 'برنج خورشت'})
>>> add_participant(participant = 'farhad', answers = {'esm': 'بهرام', 'famil': 'براتی', 'keshvar': 'بببببب', 'rang': 'بژ', 'ashia': 'بیل', 'ghaza': 'باقلوا'})
>>> calculate_all()
{'salib': 65, 'kianoush': 55, 'sajjad': 45, 'farhad': 40}
- بازیکن
salibبرای زمینهیghazaپاسخ باقالیپلو را نوشتهاست که معادل باقالی پلو در نظر گرفته میشود که در فایلesm_famil_data.csvوجود دارد.- بازیکن
kianoushبرای زمینهیghazaپاسخ به پلو را نوشته که معادل به پلو در نظر گرفته میشود که در فایل وجود دارد.- بازیکن
sajjadبرای زمینهیashiaپاسخ خالی دادهاست.
💡 چالشهای حل تمرین
⚠️ چگونه فایل کلمات قابلقبول را باز کنم؟
از آنجا که محتوای فایل به زبان فارسی نوشته شده، باید فایل را با رمزگذاری (encoding) مناسب باز کنید. برای باز کردن فایل از دستور زیر استفاده کنید:
open('esm_famil_data.csv', 'r', encoding="utf-8")
⚠️ چگونه فایل CSV را بخوانم؟
برای خواندن فایل CSV نیازی به هیچ کتابخانهی خاصی ندارید. محتوای این فایل را مشابه یک فایل متنی معمولی در نظر بگیرید و با ابزارها و توابع کار با فایل متنی و کار با رشته، کلمات موجود در هر خط را استخراج و ذخیره کنید.
البته در پایتون یک کتابخانهی قدرتمند برای کار با فایلهای CSV به نام
csvوجود دارد که در صورت تمایل میتوانید با جستوجو در وب و آشنایی با توابع آن، از آن استفاده کنید.
⚠️ چه کتابخانههای جانبیای را باید استفاده کنم در فایل python_requirements.txt قرار دهم؟
استفاده از کتابخانههای جانبی برای حل این تمرین الزامی نیست و میتوانید آن را بدون استفاده از کتابخانههای دیگر حل کنید.
⚠️ چرا کدم تست آخر را پاس نمیکند؟
به نکتهی آخر که در قسمت «نکات» گفته شده، دقت کنید. اگر یک نفر عدسی را بهعنوان غذا بنویسد، نباید روی امتیاز کسی که عدسی را در زمینهی اشیاء نوشته، تأثیر بگذارد.
💡 راهنمایی نهایی
ساختار کلی کد به این شکل است:
import csv
categories = ['esm', 'famil', 'keshvar', 'rang', 'ashia', 'ghaza']
valid_words = {cat: set() for cat in categories}
players = {}
def ready_up():
global valid_words
with open('esm_famil_data.csv', 'r', encoding='utf-8') as f:
reader = csv.reader(f)
header = next(reader)
for row in reader:
for i, cat in enumerate(categories):
word = row[i].replace(" ", "")
if word:
valid_words[cat].add(word)
def add_participant(participant, answers):
global players
players[participant] = {cat: ans.replace(" ", "") for cat, ans in answers.items()}
def calculate_all():
scores = {p: 0 for p in players}
for cat in categories:
answers = [players[p][cat] for p in players]
all_submitted = all(ans for ans in answers)
for p in players:
ans = players[p][cat]
if not ans or ans not in valid_words[cat]:
continue
count = sum(1 for a in answers if a == ans)
if all_submitted:
scores[p] += 5 if count > 1 else 10
else:
scores[p] += 10 if count > 1 else 15
return scores
valid_words← دیکشنری از مجموعهها (set) برای ذخیره کلمات قابلقبول در هر دستهplayers← دیکشنری برای ذخیره پاسخهای هر بازیکنready_up()← خواندن فایل CSV و ذخیره کلمات درvalid_wordsadd_participant()← ذخیره پاسخهای بازیکن درplayerscalculate_all()← محاسبه امتیاز بر اساس قوانین
✅ این تمرین را در ویرایشگر خود پیادهسازی کنید. به یاد داشته باشید که فایل
code.pyرا تکمیل و ارسال کنید.
نمونهها
ready_up()
add_participant(participant='salib', answers={'esm': 'بردیا', 'famil': 'بابایی', 'keshvar': 'باربادوس', 'rang': 'بنفش', 'ashia': 'بمب', 'ghaza': 'باقالیپلو'})
add_participant(participant='kianoush', answers={'esm': 'بهرام', 'famil': 'بهرامی', 'keshvar': 'برزیل', 'rang': 'بلوطی', 'ashia': 'بیل', 'ghaza': 'به پلو'})
add_participant(participant='sajjad', answers={'esm': 'بابک', 'famil': 'بهشتی', 'keshvar': 'باهاما', 'rang': 'بژ', 'ashia': ' ', 'ghaza': 'برنج خورشت'})
add_participant(participant='farhad', answers={'esm': 'بهرام', 'famil': 'براتی', 'keshvar': 'بببببب', 'rang': 'بژ', 'ashia': 'بیل', 'ghaza': 'باقلوا'})
calculate_all(){'farhad': 40, 'kianoush': 55, 'sajjad': 45, 'salib': 65}ready_up()
add_participant(participant='salib', answers={'esm': 'ایدا', 'famil': 'اسدی', 'keshvar': 'المان', 'rang': 'ابی', 'ashia': 'اره', 'ghaza': 'اش'})
add_participant(participant='kianoush', answers={'esm': 'امیر', 'famil': 'اکبری', 'keshvar': 'انگولا', 'rang': 'اجری', 'ashia': 'اره برقی', 'ghaza': 'اب گوشت'})
add_participant(participant='sajjad', answers={'esm': 'ارمان', 'famil': 'ارمانی', 'keshvar': 'ایتالیا', 'rang': 'ارغوانی', 'ashia': 'اب پاش', 'ghaza': 'اب گوشت'})
add_participant(participant='ali', answers={'esm': 'ارش', 'famil': 'اعظمی', 'keshvar': 'ارژانتین', 'rang': 'ارکیده', 'ashia': 'ایینه', 'ghaza': 'اب گوشت'})
add_participant(participant='mamad', answers={'esm': 'امنه', 'famil': 'ازادی', 'keshvar': 'ارمنستان', 'rang': 'البالویی', 'ashia': 'استکان', 'ghaza': 'اب گوشت'})
calculate_all(){'ali': 55, 'kianoush': 55, 'mamad': 55, 'sajjad': 55, 'salib': 60}ready_up()
add_participant(participant='a', answers={'esm': 'اوا', 'famil': 'اسدی', 'keshvar': 'المان', 'rang': 'ابی', 'ashia': 'استکان', 'ghaza': 'اش'})
add_participant(participant='b', answers={'esm': 'اوا', 'famil': 'اکبری', 'keshvar': 'ال مان', 'rang': 'اجری', 'ashia': 'اره', 'ghaza': 'اش'})
add_participant(participant='c', answers={'esm': 'ارش', 'famil': 'اعظمی', 'keshvar': 'اااا', 'rang': 'استکان', 'ashia': 'اره', 'ghaza': 'اب گوشت'})
calculate_all(){'a': 45, 'b': 40, 'c': 35}ready_up()
add_participant(participant='x', answers={'esm': 'بردیا', 'famil': 'بابایی', 'keshvar': 'افریقا', 'rang': 'بژ', 'ashia': 'بیل', 'ghaza': 'باقلوا'})
add_participant(participant='y', answers={'esm': 'بردیا', 'famil': 'باقری', 'keshvar': 'افریقا', 'rang': 'بنفش', 'ashia': ' ', 'ghaza': 'باقلوا'})
calculate_all(){'x': 50, 'y': 35}ready_up()
add_participant(participant='p1', answers={'esm': '', 'famil': 'کرمی', 'keshvar': '', 'rang': '', 'ashia': '', 'ghaza': ''})
add_participant(participant='p2', answers={'esm': '', 'famil': '', 'keshvar': '', 'rang': 'کرمی', 'ashia': '', 'ghaza': ''})
calculate_all(){'p1': 15, 'p2': 15}برای نوشتن پاسخ و دریافت امتیاز، ابتدا وارد حساب شوید.
ورود