جمع دو عدد (آشنایی با داوری)


این سوال صرفاً برای آموزش کار با سیستم داوری است و هیچ تاثیری در نتیجه‌ی مسابقه ندارد.
  • محدودیت زمان: ۱ ثانیه
  • محدودیت حافظه: ۲۵۶ مگابایت

در این سوال به شما دو عدد صحیح مثل aa و bb داده می‌شود. از شما می‌خواهیم برنامه‌ای بنویسید که مقدار aa و bb را دریافت کند و a+ba + b را چاپ کند.

ورودی🔗

در تنها سطر ورودی، دو عدد صحیح aa و bb که با یک فاصله از هم جدا شده‌اند، داده می‌شود.

1a,b1001 \leq a, b \leq 100

خروجی🔗

در تنها سطر خروجی، مقدار a+ba + b را چاپ کنید.

مثال‌ها🔗

ورودی نمونه ۱🔗

3 5
Plain text

خروجی نمونه ۱🔗

8
Plain text

ورودی نمونه ۲🔗

1 1
Plain text

خروجی نمونه ۲🔗

2
Plain text
راه‌حل Php8
extensionFromNamecode.php
<?php
$line = readline();
[$a, $b] = explode(' ', $line);
echo $a + $b;
?>
PHP

اشتباهات متداول🔗

چک کردن شرایط ورودی

نیازی نیست بررسی کنید که ورودی داده شده مطابق شرایط گفته شده باشد. محدودیت‌ها تنها برای اطلاع شما از تست‌ها و محدودیت‌های مسئله هستند و در ورودی‌های داده شده به برنامه شما رعایت می‌شوند. بنابراین نیازی نیست کد زیر را بنویسید:

if ($n >= 1 && $n <= 100) {
    // Your Solution
} else {
    // echo 'Invalid Input'
}
PHP
ابتدا گرفتن تمام ورودی‌ها و سپس چاپ همه خروجی‌ها

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

چاپ پیام‌های اضافی برای دریافت ورودی

از چاپ پیام‌های اضافی مثل :please enter a number برای دریافت ورودی خودداری کنید. برای مثال در زبان PHP نباید کدی مانند زیر بنویسید:

echo 'please enter a number:';
PHP
نحوه‌ی دریافت ورودی و چاپ خروجی

برای اطلاعات بیشتر درباره نحوه دریافت ورودی و چاپ خروجی در PHP، می‌توانید به این لینک مراجعه کنید.

برچسب حروف (ورودی/خروجی)


  • محدودیت زمان: ۱ ثانیه
  • محدودیت حافظه: ۲۵۶ مگابایت

شرکت شبکه‌ی الکترونیکی پرداخت کارت که به شاپرک معروف است تصمیم گرفته جملات انگیزشی به زبان انگلیسی را روی دیوار شرکت بنویسد. این جملات باید با حروف بزرگ انگلیسی و بدون علائم نگارشی چاپ شوند.

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

برای بهتر متوجه شدن خواسته‌ی سوال به نمونه‌های پایین سوال توجه کنید.

ورودی🔗

در تنها سطر ورودی، یک رشته مثل ss در یک سطر داده می‌شود.

1s1000001 \leq |s| \leq 100 \, 000

خروجی🔗

در تنها سطر خروجی، ۲۶ عدد که با فاصله از هم جداشده‌اند، چاپ می‌شود. عدد iiام نشان دهنده‌ی تعداد کاراکترهای لازم برای چاپ iiامین حرف انگلیسی است.

مثال‌ها🔗

ورودی نمونه ۱🔗

Salam Be Hamegi! 
Plain text

خروجی نمونه ۱🔗

3 1 0 0 2 0 1 1 1 0 0 1 2 0 0 0 0 0 1 0 0 0 0 0 0 0 
Plain text

ورودی نمونه ۲🔗

Campus Technology Park, was established as the largest technology.
Plain text

خروجی نمونه ۲🔗

6 1 3 1 6 0 3 4 1 0 1 4 1 2 4 2 0 2 6 5 1 0 1 0 2 0 
Plain text

تقویم‌های فضایی (ورودی/خروجی)


  • محدودیت زمان: ۱ ثانیه
  • محدودیت حافظه: ۲۵۶ مگابایت

در کهکشانی که کیهان‌شناس‌ها آن را «پردیس» می‌نامند، سیستم تقویم همه‌ی سیاره‌های این کهکشان، به صورت (M,D)(M, D) است.

در تقویم (M,D)(M, D) هر سال از MDMD روز تشکیل می‌شود. اهالی این سیاره سال‌های خود را به MM ماه با شماره‌های ۱، ۲، ...، MM و در هر ماه DD روز با شماره‌های ۱، ۲، ...، DD قرار می‌دهند.

فیروز در سیاره‌ای از کهکشان «پردیس» زندگی می‌کند. در این سیاره سیستم تقویم (M1,D1)(M_1, D_1) است و فیروز متولد روز DsD_s از ماه MsM_s است. فیروز می‌خواهد به سیاره‌ای برود که در آن تقویم به سیستم (M2,D2)(M_2, D_2) است.

فیروز می‌خواهد بداند روز و ماه تولد او در سیاره‌ی جدید به چه صورت است. فرض کنید در سال تولد فیروز، روز ۱ از ماه ۱ در هر دو تقویم یکسان بوده است.

برای بهتر متوجه شدن سوال به نمونه‌ها دقت کنید.

ورودی🔗

در سطر اول ورودی، دو عدد D1D_1‌ و M1M_1 داده می‌شود. در سطر دوم ورودی، دو عدد D2D_2‌ و M2M_2 داده می‌شود. در سطر سوم ورودی، دو عدد DsD_s‌ و MsM_s داده می‌شود.

1MsM11001 \leq M_s \leq M_1 \leq 100 1DsD11001 \leq D_s \leq D_1 \leq 100 1M2,D21001 \leq M_2, D_2 \leq 100

خروجی🔗

در تنها سطر خروجی DsD'_s و MsM'_s را چاپ کنید که تاریخ تولد فیروز در تقویم دوم است.

مثال‌ها🔗

ورودی نمونه ۱🔗

30 12
15 24
27 8
Plain text

خروجی نمونه ۱🔗

12 16
Plain text

در این نمونه، تقویم اول دارای ۱۲ ماه است و هر ماه ۳۰ روز دارد. تقویم دوم دارای ۲۴ ماه است و هر ماه ۱۵ روز دارد. فیروز در روز ۲۷ از ماه ۸ در تقویم اول به دنیا آمده است. پس تولد او روز ۱۲ از ماه ۱۶ در تقویم دوم است.

ورودی نمونه ۲🔗

28 10
100 1
11 3
Plain text

خروجی نمونه ۲🔗

67 1
Plain text

در این نمونه، تقویم اول دارای ۱۰ ماه است و هر ماه ۲۸ روز دارد. تقویم دوم تنها یک ماه دارد که ۱۰۰ روز طول می‌کشد. فیروز در روز ۱۱ از ماه ۳ در تقویم اول به دنیا آمده است. پس تولد او روز ۶۷ از ماه ۱ در تقویم دوم است.

ورودی نمونه ۳🔗

30 12
10 10
24 12
Plain text

خروجی نمونه ۳🔗

4 6
Plain text

در این نمونه، تقویم اول دارای ۱۲ ماه است و هر ماه ۳۰ روز دارد. تقویم دوم دارای ۱۰ ماه است و هر ماه ۱۰ روز دارد. فیروز در روز ۲۴ از ماه ۱۲ در تقویم اول به دنیا آمده است. پس تولد او روز ۴ از ماه ۶ در تقویم دوم است.

جوایزوپیک (PHP)


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

جزئیات پروژه🔗

شما می‌توانید پروژه‌ی اولیه را از این لینک دانلود کنید.

تابعی با نام handleCeremony پیاده‌سازی کنید که آرایه‌ای از افراد را که کلاس Person نماینده‌ای از آن‌هاست را تحویل می‌گیرد و سپس این افراد را به صورت نزولی مرتب‌سازی می‌کند تا لیستی برای مراسم اهدای جوایز آماده شود.

توضیحات کلاس Person🔗

این کلاس نماینده‌ی افراد شرکت‌کننده در رویداد المپیک‌فناوری است. ساختار متد‌ها و ویژگی‌های کلاس به شکل زیر تعریف می‌شود:

<?php

class Person
{
    public function __construct(
        public string $personName,
        public int $bootcampScore,
        public int $onlineContestScore,
        public int $inpersonContestScore,
        public float $passionRate,
    ) {
    }

    public function calculateTotalScore(): float
    {
        return ($this->bootcampScore * 0.15) +
               ($this->onlineContestScore * 0.25) +
               ($this->inpersonContestScore * 0.5) +
               ($this->passionRate * 0.1);
    }

    public function displayInfo(): string
    {
        $result = "Person Name: " . $this->personName . "\n";
        $result .= "Bootcamp Score: " . $this->bootcampScore . "\n";
        $result .= "Online Contest Score: " . $this->onlineContestScore . "\n";
        $result .= "In-person Contest Score: " . $this->inpersonContestScore . "\n";
        $result .= "Passion Rate: " . $this->passionRate . "\n";
        $result .= "Total Weighted Score: " . $this->calculateTotalScore() . "\n";
        $result .= "- - - - - - - - - - - - -\n";

        return $result;
    }
}
PHP
  • ویژگی personName: این ویژگی به صورت رشته‌ای از نام فرد شرکت‌کننده در رویداد است.
  • ویژگی bootcampScore: این ویژگی به صورت عدد صحیح مثبت بیانگر امتیازی است که فرد در بوت‌کمپ‌های المپیک فناوری کسب کرده است. ضریب این ویژگی 0.150.15 است.
  • ویژگی onlineContestScore: این ویژگی به صورت عدد صحیح مثبت بیانگر امتیازی است که فرد در مسابقات مجازی المپیک فناوری کسب کرده است. ضریب این ویژگی 0.250.25 است.
  • ویژگی inpersonContestScore: این ویژگی به صورت عدد صحیح مثبت بیانگر امتیازی است که فرد در مسابقات حضوری المپیک فناوری کسب کرده است. ضریب این ویژگی 0.50.5 است.
  • ویژگی passionRate: این ویژگی به صورت عددی اعشاری بیانگر میزان شور و اشتیاق فرد است که توسط داوران مسابقه تعیین می‌شود و مقداری بین 00 تا 1010 دارد. ضریب این ویژگی 0.10.1 است.
  • متد calculateTotalScore: این متد مجموع وزن‌دار امتیاز فرد را با توجه به ضرایب ویژگی‌ها محاسبه می‌کند.
  • متد displayInfo: این متد اطلاعات شرکت‌کننده را چاپ می‌کند.

شما باید تابع handleCeremony را به صورتی پیاده سازی کنید که افراد را بر اساس مجموع وزن‌دار امتیازهایشان به صورت نزولی مرتب‌سازی کند. در این بین اگر مجموع وزن‌دار امتیاز دو فرد با یک‌دیگر برابر شد، اولویت در مقایسه و رتبه‌دهی بر اساس ویژگی با ضریب بیشتر است. یعنی اگر دو فرد در مجموع امتیاز یکسانی داشته باشند، فردی در مرتب‌سازی قبل‌تر ظاهر می‌شود که امتیازinpersonContestScore او بزرگ‌تر باشد. (در صورتی که این ویژگی نیز در هر دو فرد برابر بود به سراغ امتیاز onlineContestScore می‌رویم و به همین شکل...) پس از مرتب سازی صرفا باید اطلاعات 55 نفر برتر رویداد (55 نفر اول در مرتب‌سازی انجام شده) توسط فراخوانی متد displayInfo دریافت و در قالب یک رشته خروجی داده شود.

مقیاس‌بندی و اعتبار‌سنجی امتیاز افراد قبلا انجام شده است. همچنین تضمین می‌شود که تمام امتیاز‌های هیچ دو فردی با هم برابر نیست.

امضای تابع handleCeremony به‌صورت زیر خواهد بود:

function handleCeremony(array $personsArray): string
{
    // TODO: Implement
}
PHP

مثال🔗

<?php

class Person
{
    public function __construct(
        public string $personName,
        public int $bootcampScore,
        public int $onlineContestScore,
        public int $inpersonContestScore,
        public float $passionRate,
    ) {
    }

    public function calculateTotalScore(): float
    {
        return ($this->bootcampScore * 0.15) +
               ($this->onlineContestScore * 0.25) +
               ($this->inpersonContestScore * 0.5) +
               ($this->passionRate * 0.1);
    }

    public function displayInfo(): string
    {
        $result = "Person Name: " . $this->personName . "\n";
        $result .= "Bootcamp Score: " . $this->bootcampScore . "\n";
        $result .= "Online Contest Score: " . $this->onlineContestScore . "\n";
        $result .= "In-person Contest Score: " . $this->inpersonContestScore . "\n";
        $result .= "Passion Rate: " . $this->passionRate . "\n";
        $result .= "Total Weighted Score: " . $this->calculateTotalScore() . "\n";
        $result .= "- - - - - - - - - - - - -\n";

        return $result;
    }
}

function handleCeremony(array $personsArray): string
{
    // TODO: Implement
}

echo handleCeremony([
    new Person("Ali Gholi", 1000, 700, 700, 1.5),
    new Person("Gholi Ali", 12000, 200, 100, 3.8),
    new Person("Ali Phish", 9000, 900, 900, 9.9),
    new Person("Pish Ali", 8000, 900, 900, 8.9),
    new Person("Ali Reza", 100, 900, 900, 0.3),
    new Person("Reza Ali", 18000, 100, 0, 4.4),
    new Person("Ali Safar", 10000, 10000, 10000, 0),
    new Person("Safar Ali", 8000, 5000, 13100, 0)
]);
PHP

خروجی موردانتظار:

Person Name: Safar Ali        
Bootcamp Score: 8000
Online Contest Score: 5000    
In-person Contest Score: 13100
Passion Rate: 0
Total Weighted Score: 9000    
- - - - - - - - - - - - -     
Person Name: Ali Safar        
Bootcamp Score: 10000
Online Contest Score: 10000   
In-person Contest Score: 10000
Passion Rate: 0
Total Weighted Score: 9000    
- - - - - - - - - - - - -     
Person Name: Reza Ali
Bootcamp Score: 18000
Online Contest Score: 100     
In-person Contest Score: 0    
Passion Rate: 4.4
Total Weighted Score: 2725.44
- - - - - - - - - - - - -
Person Name: Ali Phish
Bootcamp Score: 9000
Online Contest Score: 900
In-person Contest Score: 900
Passion Rate: 9.9
Total Weighted Score: 2025.99
- - - - - - - - - - - - -
Person Name: Gholi Ali
Bootcamp Score: 12000
Online Contest Score: 200
In-person Contest Score: 100
Passion Rate: 3.8
Total Weighted Score: 1900.38
- - - - - - - - - - - - -
Plain text
  • همانطور که در خروجی مشاهده می‌کنید مجموع وزن‌دار امتیاز دو فرد Safar Ali و Ali Safar با هم برابر است اما چون امتیاز inpersonContestScore فردی با نام Safar Ali بیشتر است پس در رتبه‌بندی قبل از فردی با نام Ali Safar قرار می‌گیرد.

آن‌چه باید آپلود کنید🔗

یک فایل PHP که تابع handleCeremony در آن پیاده‌سازی شده است آپلود کنید.

کنکور پردیس (PHP)


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

جزئیات پروژه🔗

شما می‌توانید پروژه‌ی اولیه را از این لینک دانلود کنید.

تابعی با نام evaluateQuiz پیاده‌سازی کنید که آرایه‌ای از پاسخ‌های داوطلبان در کنکور چهار‌گزینه‌ای پردیس را همراه با آرایه‌ای از پاسخ‌های درست آزمون دریافت می‌کند و طبق قوانین و شرایط زیر نمرات هر شخص را مشخص کرده و در نهایت نمرات را همراه با گزارش کاملی از سوالات خروجی می‌دهد. همچنین شما باید کلاسی به نام FraudDetection را پیاده‌سازی کنید که متقلبین را شناسایی کند!

ورودی‌های تابع evaluateQuiz

ورودی‌های تابع evaluateQuiz🔗

  • در اولین ورودی، این تابع آرایه‌ای دو‌بعدی (آرایه‌ای از آرایه‌های) پاسخ‌های مختلف داوطلبان را دریافت می‌کند.
  • هر کدام از این آرایه‌های پاسخ، شامل مقادیری به صورت عدد صحیح و یا nullnull هستند. پاسخ‌های داوطلبان به سوالات کنکور پردیس به صورت چهار‌گزینه‌ای است، پس هر خانه از آرایه پاسخ داوطلب باید عددی بین 11 تا 44 و یا بی‌پاسخ (nullnull) باشد.
  • در دومین ورودی، این تابع آرایه‌ای از اعداد صحیح را دریافت می‌کند که هر خانه از آن مشخص‌کننده گزینه‌ی درست برای سوالی است که شماره‌اش با اندیس آن خانه از آرایه برابر است. توجه داشته باشید که هر سوال دقیقا یک گزینه‌ی درست دارد. تضمین می‌شود که این مقدار درست برای هر سوال، عدد صحیحی بین 11 تا 44 می‌باشد.
  • در سومین ورودی، این تابع یک نمونه از کلاس کشف تقلب FraudDetectionرا مطابق با توضیحات بخش این کلاس دریافت می‌کند تا در بدنه کلاس از آن جهت شناسایی افراد متقلب استفاده کند.
خروجی‌ تابع evaluateQuiz

خروجی‌ تابع evaluateQuiz🔗

خروجی تابع evaluateQuiz به صورت رشته ای با ساختار زیر خواهد بود:

{
    "scores": [],
    "reports": {
        "max_score": ,
        "min_score": ,
        "average_score": ,
        "questions_average": [],
        "questions_labels": [],
        "invalid_answersheets": [],
        "cheating_examiners": []
    }
}
JSON
  • خروجی تابع باید به شکل Json باشد. توجه کنید که خروجی شما حتما باید مطابق با ساختار بالا باشد و در مقادیری مثل کوچگ و بزرگ بودن حروف کلید‌ها نباید تغییری ایجاد شود.

توضیحات مقادیر خروجی به شکل زیر است:

  • کلید scores: آرایه‌ای است از نمراتی که برای کاربران محاسبه شده است. این مقادیر به شکل اعداد صحیح هستند که خانه ii-ام مشخص کننده نمره کسب شده توسط نفر ii-ام است. (در صورتی که برگه‌ی فرد خراب باشد، این مقدار nullnull خواهد بود)
  • کلیدreports: این کلید شامل گزارش‌های کمی و کیفی آزمون به شکل زیر است:
    • کلید max_score: مقدار این کلید برابر با بیشترین نمره کسب شده در آزمون است.
    • کلید min_score: مقدار این کلید برابر با کمترین نمره کسب شده در آزمون است.
    • کلید average_score: مقدار این کلید برابر با میانگین نمرات کسب شده در آزمون است. این مقدار به صورت عدد اعشاری با دو رقم اعشار به صورت گرد شده است. (این مورد باید با استفاده از تابع round پیاده‌سازی شود)
    • کلید questions_average: مقدار این کلید به صورت آرایه‌ای از اعداد اعشاری با دو رقم اعشار به صورت گرد (این مورد باید با استفاده از تابع round پیاده‌سازی شود) شده است که میانگین نمره‌ای است که افراد مختلف شرکت کننده توانستند از هر کدام از این سوالات کسب کنند. برای مثال اگر پاسخ‌های افراد به سوال اول به شکل گزینه‌های 1 1 1 3 باشد و پاسخ سوال گزینه 1 باشد، میانگین نمره‌ای که کاربران توانستند از این سوال کسب کنند مقدار 2 خواهد بود. (این مورد به صورت ((3 * 3) - 1) / 4 = 2 خواهد بود)
    • کلید questions_labels: مقدار این کلید به صورت آرایه‌ای از رشته‌ها است که سطح سوال را مشخص می‌کند.
    • کلید invalid_answersheets: مقدار این کلید به صورت آرایه‌ای از اندیس کاربرانی است که پاسخ‌برگ آن‌‌ها خراب است. در صورتی که هیچ فردی به این شکل یافت نشد، این مقدار برابر آرایه‌ای خالی خواهد بود.
    • کلید cheating_examiners: مقدار این کلید به صورت آرایه‌ای از اندیس تمام کاربرانی (هم شامل افرادی که مراقب آن‌ها را متقلب شناسایی کرده و هم شامل افرادی که الگوریتم کشف تقلب پیاده‌سازی شده، آن‌ها را متقلب شناسایی کرده) است که متقلب شناسایی شدند. در صورتی که هیچ فردی به این شکل یافت نشد، این مقدار برابر آرایه‌ای خالی خواهد بود.
قوانین و شرایط نمره‎دهی در تابع evaluateQuiz

قوانین و شرایط نمره‎دهی🔗

  • پاسخ صحیح به هر سوال +3+3 نمره و پاسخ غلط به هر سوال 1-1 نمره به همراه خواهد داشت. پاسخی صحیح است که برابر با پاسخی باشد که در آرایه پاسخ سوالات برای آن سوال مشخص شده است. تضمین می‌شود که هر فرد به حداکثر یک گزینه می‌تواند پاسخ دهد.
  • در صورتی که فرد به سوالی پاسخ نداده باشد (پاسخ او به این سوال nullnull باشد)، نمره‌ای برای او لحاظ نمی‌شود (نمره‌ی این سوال 00 لحاظ می‌گردد)
  • ممکن است به دلیل اشتباه دستگاه برگه‌خوان، مقدار پاسخ برای سوالی از بازه 11 تا 44 خارج باشد! برای مثال مقدار پاسخ فردی برای یک سوال مقدار 99 باشد. در این صورت حتی اگر این اتفاق برای یکی از پاسخ‌های یک فرد داوطلب رخ دهد، نمره‌ای برای او نباید محاسبه شود. نمره نهایی او به صورت nullnull لحاظ می‌شود تا بعدا مسئولین پارک پردیس، پاسخ‌برگ او را دوباره تصحیح کنند. به این پاسخ‌برگ‌ها پاسخ‌برگ‌های خراب گفته می‌شود.
  • پس از مشخص شدن افرادی که پاسخ‌برگ آنها خراب است، نوبت اجرای تابع checkResults برای یافتن افراد متقلب در آزمون است. این تابع باید مطابق با توضیحات داده شده در بخش پیاده‌سازی این کلاس، لیست افراد متقلب را شناسایی کند. پس از شناسایی افراد متقلب باید نمره نهایی آن‌ها نیز مانند پاسخ‌برگ‌های خراب nullnull در نظر گرقته شود.
  • افرادی با پاسخ‌برگ‌های خراب و یا افراد متقلب در گزارشات نهایی ارائه شده شرکت ندارند و آمار‌های بدست آمده از پاسخ‌های آن‌ها نباید در گزارش‌دهی نهایی محاسبه شوند.
  • سوالات در 44 سطح با توجه به نحوه پاسخ‌دهی داوطلبان به صورت زیر دسته‌بندی می‌شوند:
    • سطح Easy: بیش‌تر مساوی 7575 درصد شرکت‌کنندگان به آن سوال پاسخ درست داده‌اند.
    • سطح Medium: بین 2525 درصد تا 7575 درصد شرکت‌کنندگان به آن سوال پاسخ درست داده‌اند.
    • سطح Hard: کمتر مساوی 2525 درصد شرکت‌کنندگان به آن سوال پاسخ درست داده‌اند.
    • سطح Brilliant: هیچ فردی در آزمون به این سوال پاسخ درست نداده است.
  • اگر تمام پاسخ‌برگ‌ها خراب باشند و یا هیچ داده‌ای از پاسخ‌ها یافت نشود (پاسخ‌ها nullnull باشند) در این صورت مقادیر استفاده شده در گزارش مقدار 00 خواهند بود.
ساختار کلاس کشف تقلب FraudDetection

کلاس FraudDetection برای کشف تقلب‌های آزمون ساخته شده است. این کلاس در سازنده خود به ترتیب درصد حساسیت sensitivity_percentage را که عددی بین 00 و 100100 است را همراه با آرایه‌ای از اعداد صحیح که اندیس‌های افرادی هستند که مراقب آزمون، آن‌ها را متقلب شناسایی کرده است، دریافت می‌کند. همچنین این کلاس تابعی به نام checkResults دارد که با دریافت آرایه‌ای دو‌بعدی از پاسخ‌برگ‌های افراد مختلف، با برسی این پاسخ‌برگ‌ها، در صورتی که شخصی وجود داشته باشد که بیشتر مساوی درصد حساسیت مشخص شده از پاسخ‌هایش دقیقا با حداقل یگی از این افراد متقلب یکسان باشد، آن فرد نیز متقلب شناخته خواهد شد. تابع checkResults در نهایت آرایه‌ای از اعداد صحیح که اندیس تمامی افراد متقلب (هم شامل افرادی که مراقب آن‌ها را متقلب شناسایی کرده و هم شامل افرادی که الگوریتم کشف تقلب پیاده‌سازی شده، آن‌ها را متقلب شناسایی کرده) می‌باشد را خروجی می‌دهد.

  • کلاس FraudDetection به صورت تزریق وابستگی (Dependency Injection) به تابع نمره‌دهی evaluateQuiz به عنوان ورودی داده خواهد شد.

به مثال‌های زیر از شیوه کارکرد این کلاس، توجه کنید:

مثال نمونه ۱🔗

$fraud_detector = new FraudDetection(70, [1]);

$answers = [
    [1, 1, 1, 1],
    [1, 2, null, 2],
    [1, 9, 3, 4],
    [1, 2, 3, 2],
    [1, 2, 3, 1]
];

print_r($fraud_detector->checkResults($answers));
PHP
Array
(
    [0] => 1
    [1] => 3
)
Plain text
  • در این مثال درصد حساسیت برابر با 70 است و فردی که به عنوان متقلب شناخته شده است فردی با اندیس شماره 1 است. پس از فراخوانی تابع checkResults و انجام بررسی‌های لازم، به دلیل اینکه پاسخ فردی با اندیس شماره 3 با پاسخ [1, 2, 3, 2] در سه چهارم (یا به عبارتی در 75 درصد) پاسخ‌برگ با پاسخ فرد با اندیس 1 مشابهت دارد پس متقلب شناخته می‌شود.

مثال نمونه ۲🔗

$fraud_detector = new FraudDetection(90, [0]);

$answers = [
    [1, 2, 3, 4],
    [1, 2, 3, 2],
    [1, 2, 3, 1]
];

print_r($fraud_detector->checkResults($answers));
PHP
Array
(
    [0] => 0
)
Plain text
  • در مثال بالا به دلیل اینکه هیچ فردی وجود ندارد که در بیشتر مساوی 90 درصد پاسخ‌برگ با پاسخ‌برگ فرد مختلف با اندیس شماره 0 برابر باشد پس تنها فرد متقلب همان اندیس شماره 0 خواهد بود. (هر دو فرد دیگر در 75 درصد از پاسخ‌برگ‌هایشان با فرد متقلب مشابهت دارند که این مقدار از درصد حساسیت کمتر است)

امضای تابع evaluateQuiz به‌صورت زیر خواهد بود:

function evaluateQuiz(array $answers_array, array $key_array, FraudDetection $fraudDetector): string
{
    // TODO: Implement
}
PHP

امضای کلاس FraudDetection به صورت زیر خواهد بود:

class FraudDetection
{

    public function __construct()
    {
        // TODO: Implement
    }

    public function checkResults(array $answers_array): array
    {
        // TODO: Implement
    }

}
PHP
مثال و خروجی مورد انتظار (حتما مطالعه شود)

مثال🔗

<?php

class FraudDetection
{

    public function __construct()
    {
        // TODO: Implement
    }

    public function checkResults(array $answers_array): array
    {
        // TODO: Implement
    }

}

function evaluateQuiz(array $answers_array, array $key_array, FraudDetection $fraudDetector): string
{
    // TODO: Implement
}

$answers = [
    [1, 1, 1, 1],
    [1, 2, null, 2],
    [1, 9, 3, 4],
    [1, 2, 3, 2],
    [1, 2, 3, 1]
];

$keys = [1, 2, 3, 4];

echo evaluateQuiz($answers, $keys, new FraudDetection(70, [1]));
PHP

خروجی موردانتظار:

{
    "scores": [
        0,
        null,
        null,
        null,
        8
    ],
    "reports": {
        "max_score": 8,       
        "min_score": 0,       
        "average_score": 4,   
        "questions_average": [
            3,
            1,
            1,
            -1
        ],
        "questions_labels": [
            "Easy",
            "Medium",
            "Medium",
            "Brilliant"
        ],
        "invalid_answersheets": [
            2
        ],
        "cheating_examiners": [
            1,
            3
        ]
    }
}
Plain text
  • پاسخ‌برگ داوطلب با اندیس 22 به دلیل اینکه در یکی از سوالات پاسخی برابر با 99 دارد به عنوان پاسخ‌برگ خراب در نظر گرفته شده و در محاسبه آمار‌ها نیز سایر پاسخ‌های این فرد در نظر گرفته نشده است.

آن‌چه باید آپلود کنید🔗

یک فایل PHP که تابع evaluateQuiz و کلاس FraudDetection در آن پیاده‌سازی شده است آپلود کنید.

معینِ دوز و کلک (Laravel)


معین که پس از شکست در طراحی سوالات خوب برای مسابقات برنامه نویسی #المپیک‌فناوری از کار خود در کوئرا، بر‌کنار شده است و در حال حاضر مشغول دوز (Tic-tac-toe یا همان بازی ایکس-او خودمان) بازی است! معین که آدم پر دوز و کلکی است و هیچ کاری را مثل سایر افراد انجام نمی‌دهد، در دوز-بازی هم دوز و کلک جدیدی می‌زند. او بازی دوز را به این شکل تغییر می‌دهد که پس از انجام حرکت چهارم، اولین حرکتی که از هر کدام از بازیکن‌ها باقی مانده بود از بازی پاک می‌شود. معین برای معرفی این بازی به جهانیان قصد دارد تا نسخه‌ی برخطی از آن را با استفاده از لاراول پیاده سازی کند.

جزئیات پروژه🔗

پروژه‌ی اولیه را از این لینک دانلود کنید.

ساختار فایل‌ها
moeine-dooz-o-kalak
├── app
│   ├── Http
│   │   ├── Livewire
│   │   │   ├── XOGame.php
│   ├── Models
│   └── Providers
├── bootstrap
├── config
├── database
├── public
├── resources
│   ├── views
│   │   ├── livewire
│   │   │   └── x-o-game.blade.php
│   │   └── dooz.blade.php
│   └── css
├── routes
│   └── web.php
├── storage
├── tests
├── README.md
├── artisan
├── composer.json
├── composer.lock
├── package.json
├── phpunit.xml
└── vite.config.js
Plain text
راه‌اندازی پروژه

برای اجرای پروژه، باید php و composer را از قبل نصب کرده باشید.

  • ابتدا پروژه‌ی اولیه را دانلود و از حالت فشرده خارج کنید.
  • دستور composer install را در پوشه‌ی اصلی پروژه برای نصب نیازمندی‌ها اجرا کنید.
  • دستور npm install را در پوشه‌ی اصلی پروژه برای نصب نیازمندی‌ها اجرا کنید. (توجه کنید که این پروژه از Tailwindcss استفاده می‌کند)
  • دستور npm run dev را در مسیر پوشه اصلی پروژه اجرا کنید. در صورتی که این دستور را اجرا نکنید نمی‌توانید ویو‌های ساخته شده با Tailwindcss را مشاهده کنید.
  • برای اجرای تست‌های نمونه، می‌توانید از دستور php artisan test استفاده کنید.

پیاده‌سازی پروژه🔗

در این سوال قرار است شما به سراغ پیاده سازی این بازی هیجان‌انگیز با استفاده از Livewire3 بروید!

جزئیات دقیق‌تر و معرفی بازی جدید معینِ دوزُ کلک

جزئیات دقیق‌تر و معرفی بازی جدید معینِ دوزُ کلک🔗

همانطور که در بخش ابتدایی این سوال گفته شد، بازی معینِ دوزُ کلک یک نسخه خاصی از بازی دوز است که در آن پس از انجام حرکت چهارم، قدیمی‌ترین (ابتدایی‌ترین) حرکتی که همان فرد انجام داده است باید از صفحه بازی حذف شود! به مثال زیر توجه کنید که در آن پس از حرکت چهارم X، حرکت اول او از بازی حذف می‌شود و به این ترتیب جا برای حرکت‌های جدید باز می‌شود. همین شرایط برای بازیکن O و همچنین سایر حرکت‌ها هم صادق است.

  • برد بازی مانند یک دوز کلاسیک، زمانی اتفاق خواهد افتاد که یکی از بازکینان X یا O بتواند یک سطر، ستون و یا یکی از قطر‌های اصلی را با X یا O تماما پر کند.

پیش نمایش بازی

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

دموی بخش چلنجینگ بازی

در واقع این نسخه از بازی دوز، یک نسخه دارای حافظه می‌باشد! پس ترتیب حرکت‌های انجام شده هم علاوه بر ماهیت و مکان حرکت انجام شده اهمیت خواهد داشت زیرا این مورد در ترتیب حذف شدن حرکت‌های X یا O از صفحه و برد بازیکن نقش خواهد داشت.

جزئیات و ساختار Route و View بازی

برای دسترسی به این بازی در پروژه اولیه یک Route با آدرس /dooz به صورت پیشفرض تعریف شده است که به ویو dooz متصل شده است. در این مسیردهی و ویو تعریف شده نباید تغییری داده شود.

در فایل مربوط به ویو dooz شما باید کامپوننتی (Component) که از قبل در ساختار پروژه اولیه با نام x-o-game تعریف شده است را استفاده (Include) کنید. این کامپوننت همان بخش اصلی بازی دوز است که قرار است تا اجزای مختلف کامپوننتش را در بخش‌های بعدی این سوال پیاده‌سازی کنید تا در نهایت بازی به درستی اجرا شود.

extensionFromNamelaravel
<?php

use Illuminate\Support\Facades\Route;

Route::get('/dooz', function () {
    return view('dooz');
});
PHP
extensionFromNamelaravel
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>❌ Moeine Dooz O Kalak ⭕</title>
    @vite('resources/css/app.css')
    @livewireStyles
</head>
<body>

    {{--TODO: Include Laravel game component--}}

@livewireScripts
</body>
</html>
PHP

و در نهایت ساختار View مربوط به کامپوننت بازی که در مسیر resources/views/livewire/x-o-game.blade.php قرار گرفته است و باید در ویو dooz.blade.php از آن استفاده شود به شکل زیر است:

extensionFromNamelaravel
<div class="flex flex-col items-center justify-center min-h-screen bg-teal-700">
    <h1 class="text-6xl font-bold text-white mb-8">❌ Moeine Dooz O Kalak ⭕</h1>

    <!-- Input form for player names -->
    <div class="flex flex-col items-center space-y-4">
        <input type="text" placeholder="🏅First Player's name"
               class="px-4 py-2 rounded bg-white text-black text-xl focus:outline-none">
        <input type="text" placeholder="🏅Second Player's name"
               class="px-4 py-2 rounded bg-white text-black text-xl focus:outline-none">
        <button class="bg-cyan-500 text-white font-bold py-2 px-4 rounded hover:bg-cyan-600">
            Start Game 🎮
        </button>
    </div>
    <!-- Input form for player names -->

    <!-- Winner animation section -->
    <div class="absolute inset-0 flex items-start justify-center">
        <div class="confetti-container">
            @for ($i = 0; $i < 18; $i++)
                <div class="confetti-piece"></div>
            @endfor
        </div>
        <div class="text-white text-6xl font-bold animate-bounce scale-125 mt-12 z-50">
            🎉 Winner: [WinnerPlayerName]! 🎉
        </div>
    </div>
    <!-- Winner animation section -->

    <!-- Game board section -->
    <div class="grid grid-cols-3 gap-4 w-64">
            <button class="bg-teal-700 border-4 border-teal-500 aspect-square text-5xl font-bold flex items-center justify-center
                transition-transform transform hover:scale-105 hover:bg-teal-600 focus:outline-none focus:ring-2 focus:ring-yellow-300">
                    <span class="text-gray-300">X</span>
                    <span class="text-yellow-300">O</span>
            </button>
    </div>
    <!-- Game board section -->

    <!-- Current turn section -->
    <div class="mt-6 text-xl text-white">
        🕹 Current Turn:
        <span class="font-bold animate-pulse">[X] - [PlayerName]</span>
    </div>
    <!-- Current turn section -->

    <!-- Leaderboard to track wins -->
    <div class="mt-6 text-xl text-white">
        <div class="font-bold">📊 Leaderboard</div>
        <div>[Player1Name]: [NumberOfWinsPlayer1] win(s)</div>
        <div>[Player2Name]: [NumberOfWinsPlayer2] win(s)</div>
    </div>
    <!-- Leaderboard to track wins -->

</div>
PHP
  • این ساختار صرفا ساختار آماده مربوط به رابط گرافیکی بازی می‌باشد و منطق نمایش المان‌های مختلف آن باید توسط شما در این کامپوننت پیاده‌سازی شود.
ساختار بازی معینِ دوزُ کلک

ورود به بازی🔗

پس از اجرای مسیر /dooz در ابتدا شما با ساختاری مشابه ساختار زیر مواجه می‌شوید، که در آن دو Input از شما دو رشته را به عنوان نام بازیکنان دریافت می‌کنند. سپس پس از فشردن دکمه Start Game 🎮 باید برسی شود که در صورتی که هر دو نام وارد شده بودند بازی آغاز شود. نیازی به انجام هیچ اعتبارسنجی‌ای برای نام‌های ورودی نیست؛ صرفا این دو رشته نباید مقادیر خالی باشند.

تصویر اول سوال معین دوز و کلک

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

تصویر دوم سوال معین دوز و کلک

دموی بازی اول

پس از انجام بازی با هر تعداد مرحله، با توجه به موارد نوشته شده در بخش جزئیات دقیق‌تر و معرفی بازی ممکن است بازی برنده‌ای داشته باشد. در صورتی که فردی با انجام حرکتی موجب پیروزی شد، باید مطابق تصویر زیر، 🎉 Winner: [PlayerName]! 🎉 در بالای صفحه همراه با انیمیشن مورد نظر نمایش داده شده، جدول و وضعیت بازی ریست شده و همچنین به تعداد برد‌های فردی که برنده بازی شده یکی اضافه شود.

تصویر سوم سوال معین دوز و کلک

مورد قابل توجه این است که بازی را همیشه X شروع می‌کند اما بازیکنان هر دفعه به صورت یکی در میان نقش X و O را بر عهده می‌گیرند تا بازی عدالت بیشتری داشته باشد. همچنین بازی را فردی شروع می‌کند که نامش در ابتدای ورود به بازی به عنوان نام نفر اول وارد شده است. برای مثال، اگر دوین نام اول و معین نام دوم باشد، در بازی اول دوین X و معین O و در بازی دوم، معین X و دوین O خواهد بود و ترتیب چرخشی به همین صورت برای باقی بازی‌ها ادامه خواهد داشت. اما در تمامی حالات شروع کننده بازی X است و صرفا فرد شروع‌کننده تغییر خواهد کرد.

با توجه به موارد گفته شده در بخش‌های بالا، شما باید ساختار کامپوننت Livewire ای XOGame را که در ساختار پروژه اولیه در مسیر app/Livewire/XOGame.php قرار دارد را مطابق با ساختار زیر پیاده سازی کنید:

extensionFromNamelaravel
<?php

namespace App\Livewire;

use Livewire\Component;

class XOGame extends Component
{
    public $board = [];
    public $current_turn = 'X';
    public $last_winner = null;

    public $player1_name;
    public $player2_name;
    public $player1_wins = 0;
    public $player2_wins = 0;

    public $name_submitted = false;

    public function mount()
    {
        // TODO: Implement
    }

    public function submitNames()
    {
       // TODO: Implement 
    }

    public function resetBoard()
    {
        // TODO: Implement
    }

    public function makeMove($index)
    {
        // TODO: Implement
    }

    public function render()
    {
        // TODO: Implement
    }
}
PHP

توضیحات ساختار و ویژگی‌های این کامپوننت به شکل زیر است:

  • متغیر board: این متغیر همان‌طور که از اسمش پیداست ساختار جدول را در خود ذخیره می‌کند. هر کدام از خانه‌های این جدول می‌توانند یکی از مقادیر X، O و یا null باشند. این متغیر یک آرایه یک‌بعدی می‌باشد که اندیس‌های شماره 0 تا 8 اش نشان دهنده خانه‌های جدول بازی هستند.
  • متغیر current_turn: این متغیر نشان‌دهنده نوبت فعلی می‌باشد که می‌تواند یکی از مقادیر X و یا O را داشته باشد.
  • متغیر last_winner: این متغیر مشخص می‌کند که آخرین فردی که برنده بازی شده است چه کسی بوده است. این متغیر در ابتدا مقداری برابر با null دارد اما بلافاصله پس از بردن بازی توسط یکی از X و یا O مقدار آن را ذخیره‌سازی می‌کند.
  • متغیر‌های player1_name و player2_name: این دو متغیر نام دو بازیکن را دریافت و ذخیره‌سازی می‌کنند.
  • متغیرهای player1_wins و player2_wins: این دو متغیر تعداد برد هر کدام از بازیکن‌ها را مشخص می‌کنند. این مقدار باید پس از برد هر فرد بروزرسانی شود و به صورت زنده در صفحه بازی نمایش داده شود.
  • متغیر name_submitted: این متغیر یک متغیر بولی است که پس از وارد شدن نام بازیکنان مقدارش از false ابتدایی به true تغییر پیدا می‌کند.

توابعی که شما باید در این سوال پیاده‌سازی کنید به شکل زیر هستند:

  • تابع mount: این تابع در واقع همان تابع سازنده کامپوننت خواهد بود.
  • تابع submitNames: این تابع باید برسی کند که در صورتی که نام بازیکنان وارد شده بود، مقدار متغیر name_submitted را به true تغییر دهد. در ویو کامپوننت این مورد برسی شده و در صورتی که نام بازیکنان وارد شده بود دیگر بخش وارد کردن نام و شروع بازی نباید نمایش داده شود.
  • تابع resetBoard: این تابع وضعیت بازی را ریست می‌کند. توجه کنید که با ریست وضعیت بازی صرفا جدول و نوبت بازی X یا O ریست می‌شود و تغییری در امتیاز بازیکنان داده نمی‌شود. در واقع این تابع پس از مشخص شدن هر وضعیت برد اجرا خواهد شد تا بتوان بازی را به تعداد دلخواهی بار با شرایط گفته شده انجام داد.
  • تابع makeMove: این تابع در هر مرحله با فشردن بر روی یکی از خانه‌های جدول اجرا می‌شود. هر خانه که یکی از اندیس‌ها 0 تا 8 را داراست (خانه‌های جدول هر بار از سمت چپ به راست اندیس‌دهی می‌شوند، یعنی اندیس‌های سطر اول برابر با 0 1 2 و اندیس‌های سطر دوم برابر با 3 4 5 خواهند بود) مهره تعیین شده در current_turn در خانه مشخص شده از جدول جایگزین می‌شود.
  • تابع render: این تابع کامپوننت بازی را رندر می‌کند.

آن‌چه باید آپلود کنید🔗

  • توجه: شما می‌توانید هر تعداد تابع یا متغیر کمکی را در ساختار کامپوننت بازی (یا همان کلاس XOGame) پیاده‌سازی کنید، اما توابع و متغیر‌هایی که در مورد آن‌ها در سوال توضیح داده شده است نباید تغییری داشته باشند. تغییر در ساختار ورودی توابع یا نام توابع و متغیر‌های تعریف شده باعث عدم دریافت نمره از سمت داور خودکار خواهد شد.
  • توجه: تمامی موارد مربوط به استایل‌های بازی در پروژه اولیه از قبل قرار گرفته اند و شما نیازی به پیاده‌سازی هیچ‌گونه استایلی ندارید. در این سوال که از Tailwindcss برای طراحی رابط کاربری استفاده شده است، موارد مورد نیاز مربوط به کامپوننت بازی در مسیر View این کامپوننت در مسیر resources/views/livewire/x-o-game.blade.php قرار گرفته اند، اما شما نیاز پیدا خواهید کرد تا مانند ساختار گفته شده منطق نمایش آن‌ها را پیاده‌سازی کنید.
  • توجه: پیاده‌سازی منطق نمایش در ویو‌ی کامپوننت resources/views/livewire/x-o-game.blade.php در سیستم داوری مورد تست قرار خواهد گرفت، لذا از تغییر نام یا افرودن فواصل کمتر یا بیشتر در متن المان‌هایی که در اختیار شما قرار داده شده مانند دکمه‌ها و یا متن‌های نمایش داده شده اکیدا خودداری کنید. ایجاد تغییرات منجر‌ به عدم دریافت نمره از سیستم داوری خواهد شد.
  • توجه: پس از اعمال تغییرات، کل پروژه به غیر از پوشه‌ی vendorو node_modules را Zip کرده و آپلود کنید.
  • توجه: نام فایل ZIP اهمیتی ندارد.