راه
۶ کیو· متوسطمتوسطPYTHON۴ ثانیه · ۲۵۶ مگابایت

اسم‌فامیل

فایل esm_famil_data.csv را داور کنار کد تو می‌گذارد. درباره‌ی دو قانون امتیازدهی: قانون اول (۵ برای پاسخ تکراری، ۱۰ برای پاسخ منحصربه‌فرد) برای زمینه‌ای است که همه‌ی بازیکنان در آن پاسخی داده‌اند؛ قانون دوم (۱۰ و ۱۵) برای زمینه‌ای است که دست‌کم یک نفر آن را خالی گذاشته — همان‌طور که در راهنمایی نهایی آمده است.

سلیب که از تنهایی و خانه‌نشینی حوصله‌اش سر رفته، تصمیم گرفته که دوستانش را دعوت کند تا با آن‌ها اسم‌فامیل بازی کند. بعد از رسیدن دوستان سلیب آن‌ها بازی را شروع کردند، اما بعد از تمام شدن دست اول در امتیاز‌دهی دچار مشکل شده‌اند. هیچ‌کس کلمات دیگری را قبول نداشت؛ به همین دلیل نمره‌ی هر کلمه نامشخص بود.

سلیب و دوستانش برنامه‌نویس هستند و فقط به برنامه‌های کامپیوتری اعتماد دارند؛ بنابراین از شما می‌خواهند برایشان برنامه‌ای بنویسید که با دریافت فایل تمامی کلمات قابل‌قبول از نظر آن‌ها، طبق قوانین ذکر شده، بتواند به او و دوستانش نمره‌ای صحیح بدهد.


📂 فایل کلمات

دوستان سلیب برای این‌که در امتیازدهی به مشکل نخورند، یک فایل CSV آماده کردند که شامل همه‌ی کلماتی است که از نظر آن‌ها درست هستند. این فایل با نام esm_famil_data.csv به فرمت CSV در پروژه‌ی اولیه در اختیار شما قرار داده شده‌است.

نمونه‌ی محتوای فایل CSV:

text
esm,famil,keshvar,rang,ashia,ghaza
اب گوشت,استکان,ابی,المان,اسدی,اوا
اش,ایینه,اجری,البانی,ارمانی,ارزو
برنج خورشت,اره,ارغوانی,انگولا,اکبری,اتنا
باقالی پلو,اره برقی,ارکیده,اتریش,اعظمی,ارش
به پلو,اب پاش,البالویی,امریکا,امینی,امنه
باقلوا,بیل,بژ,ایتالیا,ازادی,ارمین
پیتزا,بمب,بنفش,ارژانتین,بابایی,ایدا

پیشنهاد می‌کنیم قبل از شروع پیاده‌سازی، یک بار این فایل را باز کنید و محتویات آن را ببینید (اگر با باز کردن این فایل مشکل داشتید می‌توانید از ابزار Google Sheets استفاده کنید).


🔧 پیاده‌سازی

شما باید سه تابع با نام‌های ready_up و add_participant و calculate_all را برای سلیب و دوستانش پیاده‌سازی کنید. غیر از این توابع، می‌توانید از متغیرهای global نیز برای به اشتراک گذاشتن اطلاعات بین توابع استفاده کنید.

به‌صورت کلی، ابتدا باید محتویاتِ فایلِ کلماتِ قابل‌قبول را بخوانید و ذخیره کنید، سپس پاسخ‌های بازیکنان را به بازی اضافه کنید و در نهایت شروع به امتیاز‌دهی کنید.


این تابع باید محتویات درون فایل CSV داده‌شده را خوانده و به شکل دلخواه شما ذخیره کند. فایل CSV با نام esm_famil_data.csv در کنار فایل پایتون شما قرار دارد. پیشنهاد می‌شود برای ذخیره‌سازی این اطلاعات از قابلیت‌های داده‌ساختارهای لیست و دیکشنری بهره ببرید.

💡 راهنمایی ۱: هنگام ذخیره کردن هر کلمه در دسته‌بندی مربوط به خودش، فاصله‌های درون و اطراف کلمه (یعنی کاراکتر ' ') را حذف کنید (با کاراکتر '' جایگزین کنید) تا بعداً تطبیق کلمات با پاسخ‌های بازیکنان آسان‌تر شود.


این تابع باید یک بازیکن و پاسخ‌هایش را به بازی اضافه کند. نحوه‌ی استفاده از این تابع به این صورت خواهد بود:

شما باید در این تابع، پاسخ‌های تک‌تک بازیکنان را نیز برای آن بازیکن ذخیره کنید. انتخاب نحوه‌ی ذخیره‌سازی بر عهده‌ی شما است. پیشنهاد می‌شود از قابلیت‌های دیکشنری‌ها برای این کار بهره ببرید.

💡 راهنمایی ۲: هنگام ذخیره کردن هریک از پاسخ‌های بازیکن، فاصله‌های درون و اطراف کلمه (یعنی کاراکتر ' ') را حذف کنید (با کاراکتر '' جایگزین کنید) تا بعداً تطبیق کلمات با کلمات موردقبول، آسان‌تر شود.

python
add_participant(participant='salib', answers={'esm': 'بردیا', 'famil': 'بابایی', 'keshvar': 'باربادوس', 'rang': 'بنفش', 'ashia': 'بمب', 'ghaza': 'باقالیپلو'})

این تابع هنگامی فراخوانی می‌شود که پاسخ‌های تمامی بازیکنان به برنامه داده شده‌است. وظیفه‌ی این تابع، محاسبه‌ی نمره‌ی همه‌ی افراد است. پس از محاسبه باید در قالب یک دیکشنری مشابه زیر، نتیجه‌ی بازی را برگردانید:

python
{'salib': 65, 'kianoush': 55, 'sajjad': 45, 'farhad': 40}

📋 قوانین امتیازدهی

در هر زمینه (برای مثال ghaza) دو حالت امتیازدهی زیر را داریم:

  • اگر بازیکن پاسخی ارائه کرده باشد که در لیست کلمات قابل‌قبول نیست، ۰ امتیاز می‌گیرد.
  • اگر بازیکن پاسخی تکراری داده باشد که در کلمات قابل‌قبول هست، ۵ امتیاز می‌گیرد؛ مثلاً اگر سه نفر پیتزا نوشته باشند، هرسه ۵ امتیاز می‌گیرند.
  • اگر بازیکن پاسخ منحصربه‌فردی داده باشد که در کلمات قابل‌قبول هست، ۱۰ امتیاز می‌گیرد؛ مثلاً اگر فقط یک نفر پاستا نوشته باشد، آن یک نفر ۱۰ امتیاز می‌گیرد.
  • اگر بازیکن پاسخی ارائه کرده باشد که در لیست کلمات قابل قبول نیست و یا پاسخی ارائه نکرده باشد، ۰ امتیاز می‌گیرد.
  • اگر بازیکن پاسخی تکراری داده باشد که در کلمات قابل‌قبول هست، ۱۰ امتیاز می‌گیرد؛ مثلاً اگر سه نفر پیتزا نوشته باشند، هرسه ۱۰ امتیاز می‌گیرند.
  • اگر بازیکن پاسخ منحصربه‌فردی داده باشد که در کلمات قابل‌قبول هست، ۱۵ امتیاز می‌گیرد؛ مثلاً اگر فقط یک نفر پاستا نوشته باشد، آن یک نفر ۱۵ امتیاز می‌گیرد.

💡 نکات مهم

  • ممکن است پاسخ‌های درست به شکل نگارشی دیگری در بازی وجود داشته باشند. فاصله‌ها در کلمات، در درست بودن یک کلمه تفاوتی ایجاد نمی‌کنند. مثلاً عدس پلو و عدسپلو باید معادل یکدیگر در نظر گرفته شوند.
  • ممکن است پاسخ خالی به‌صورت تعدادی کاراکتر فاصله، مثلاً " "، به شما داده شود.
  • تضمین می‌شود که پاسخ‌های بازیکنان و هم‌چنین کلمات قابل‌قبول درون فایل، شامل آ نیستند و تمامی الف‌ها به‌صورت ا خواهند بود.
  • تضمین می‌شود که تمامی پاسخ‌های بازیکنان با یک حرف شروع می‌شوند؛ مثلاً اگر بازی با حرف س باشد، پاسخ‌های تمامی شرکت‌کنندگان نیز با حرف س شروع می‌شود.
  • اگر یک بازیکن، کلمه‌ای را برای زمینه‌ی اشتباهی نوشت، نباید امتیاز آن را دریافت کند؛ مثلاً کلمه‌ی قیمه در زمینه‌ی اشیاء پذیرفته نیست.
  • ⚠️ توجه کنید که برخی کلمات ممکن است در دو زمینه‌ی مختلف معنی‌دار باشند. در این صورت اگر دو بازیکن چنین کلمه‌ای را در دو زمینه‌ی مختلف نوشته باشند، نباید به‌عنوان کلمه‌ی تکراری در نظر گرفته شود و امتیاز آن‌ها را کم کند؛ مثلاً کلمه‌ی عدسی می‌تواند هم در زمینه‌ی غذا و هم اشیاء استفاده شود.

🎯 نمونه

text
>>> 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) مناسب باز کنید. برای باز کردن فایل از دستور زیر استفاده کنید:

python
open('esm_famil_data.csv', 'r', encoding="utf-8")

⚠️ چگونه فایل CSV را بخوانم؟

برای خواندن فایل CSV نیازی به هیچ کتابخانه‌ی خاصی ندارید. محتوای این فایل را مشابه یک فایل متنی معمولی در نظر بگیرید و با ابزارها و توابع کار با فایل متنی و کار با رشته، کلمات موجود در هر خط را استخراج و ذخیره کنید.

البته در پایتون یک کتابخانه‌ی قدرتمند برای کار با فایل‌های CSV به نام csv وجود دارد که در صورت تمایل می‌توانید با جست‌وجو در وب و آشنایی با توابع آن، از آن استفاده کنید.

⚠️ چه کتابخانه‌های جانبی‌ای را باید استفاده کنم در فایل python_requirements.txt قرار دهم؟

استفاده از کتابخانه‌های جانبی برای حل این تمرین الزامی نیست و می‌توانید آن را بدون استفاده از کتابخانه‌های دیگر حل کنید.

⚠️ چرا کدم تست آخر را پاس نمی‌کند؟

به نکته‌ی آخر که در قسمت «نکات» گفته شده، دقت کنید. اگر یک نفر عدسی را به‌عنوان غذا بنویسد، نباید روی امتیاز کسی که عدسی را در زمینه‌ی اشیاء نوشته، تأثیر بگذارد.


💡 راهنمایی نهایی

ساختار کلی کد به این شکل است:

python
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_words
  • add_participant() ← ذخیره پاسخ‌های بازیکن در players
  • calculate_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}

برای نوشتن پاسخ و دریافت امتیاز، ابتدا وارد حساب شوید.

ورود