برای شروع، از شما میخواهیم به کسانی که بعد از شما وارد مسابقه میشوند خوشآمد بگویید. برای این منظور یک تابع با نام HelloCodeCup
تعریف کردهایم.
اما از آنجا که میخواهیم برنامه برای مسابقات بعدی کدکاپ نیز قابل استفاده باشد، از کاربر میخواهیم که شمارهی مسابقه را به تابع بدهد، سپس براساس آن، عبارت خوشآمدگویی مناسب را برگردانیم.
پروژهی اولیه را از این لینک دانلود کنید. ساختار فایلهای پروژه بهصورت زیر است:
در فایل main.go
تابعی با نام HelloCodeCup
تعریف شده که امضای آن بهصورت زیر است:
این تابع را طوری پیادهسازی کنید که به ازای ورودی n
، رشتهی Hello Codecup n
را برگرداند.
به ازای ورودی 6
، تابع باید چنین مقداری را برگرداند:
توجه: در این سؤال مجاز به استفاده از کتابخانههای شخص ثالث نیستید.
پس از پیادهسازی تابع HelloCodeCup
، فایل main.go
را آپلود کنید.
پس از کنکور سخت و طاقتفرسا، مهدی تصمیم گرفته سریال جدیدی را شروع کند.
برای این منظور، چند قسمت از آن سریال را دانلود کرده (ویدیوهایی با فرمت mkv
) و همچنین از آنجا که زبانش خوب نیست، یک سری زیرنویس (با فرمت srt
) هم برای برخی قسمتها دانلود کرده است.
او همهی فایلها را در یک پوشه ریخته، اما مشکلی که وجود دارد این است که برای این که زیرنویسها به درستی کنار ویدیوها پخش شوند، باید هر زیرنویس دقیقاً همنام فایل ویدیویی باشد، با این تفاوت که extension ها متفاوت است.
پروژهی اولیه را از این لینک دانلود کنید. ساختار فایلهای پروژه بهصورت زیر است:
مهدی میخواهد در فایل main.go
تابعی با نام Renamify
پیادهسازی کند که زیرنویسها را همنام با ویدیوها کند. این تابع آدرس یک دایرکتوری را دریافت کرده و باید عملیات تغییر نام را انجام دهد:
مثلاً پوشهی ورودی میتواند به این شکل باشد:
ولی میخواهیم زیرنویسها به ویدیوی متناظر خود تغییر نام داده شوند؛ مثلاً پوشهی نهایی چنین محتویاتی داشته باشد:
mkv
(ویدیوها) و فایلهای srt
(زیرنویسها) هیچ فایل دیگری در پوشه موجود نیست.S01E01
در خود دارد.main.go
هستید.پس از پیادهسازی تابع Renamify
، فایل main.go
را آپلود کنید.
یک هکر کلاهسفید قصد دارد سایتهای مختلف برای برای آسیبپذیری Log4jShell بررسی کند. همانطور که میدانید، این یک آسیبپذیری از نوع RCE است و میتواند بسیار مخرب باشد؛ بنابراین باید به سرعت تشخیص داده شود.
این هکر برای بررسی یک سایت، باید تمام مسیرهای ممکن آن را بررسی کند. برای این که از روی آدرس سایت تمام مسیرهای آن را پیدا کند، از HATEOAS استفاده میکند (فرض کنیم همهی سایتها HATEOAS دارند).
پروژهی اولیه را از این لینک دانلود کنید. ساختار فایلهای پروژه بهصورت زیر است:
هکر تاکنون یک تابع Retrieve
در فایل utils.go
نوشته که با دریافت آدرس یک مسیر، مسیرهای دیگری که از این مسیر امکان رفتن بهصورت مستقیم دارند را به او میدهد. مثلاً به ازای ورودی snapp.ir/
، آدرسهای زیر را برمیگرداند:
snapp.ir/blog
snapp.ir/contact
snapp.ir/about
و به ازای ورودی snapp.ir/blog
، آدرس های زیر را برمیگرداند:
snapp.ir/blog/post1
snapp.ir/blog/post2
نسخهی اصلی این تابع که هکر پیادهسازی کرده، به آدرس موردنظر درخواست HTTP ارسال میکند و نتیجه را پردازش کرده و لینک مسیرها را استخراج گرده و برمیگرداند. همانطور که حدس میزنید، هر بار اجرای این تابع با توجه به این که از شبکه استفاده میکند تا به سرور دسترسی پیدا کند، بسیار زمانبر است.
علاوه بر تابع Retrieve
، یک تابع به نام Hack
نوشته که قرار است به شکل بازگشتی، از ریشهی یک سایت شروع کرده و تمام مسیرهایی که به شکل مستقیم یا غیرمستقیم میتوان به آنها رسید را پیدا کند (به شکل بدون ترتیب). پیادهسازی اولیهای نیز از این تابع در اختیار ما قرار گرفته، اما متأسفانه با توجه به کندی تابع Retrieve
، بسیار کند است.
هکر کلاهسفید از شما خواسته تا بدون تغییر عملکرد و امضا، تابع Hack
را برایش سریعتر کنید. با توجه به این که تابع Retrieve
تابع ایمنی در مقابل همروندی است، میخواهیم از امکانات همروندی Go استفاده کنیم تا زمان اجرای تابع Hack
کمینه شود.
runtime
زبان Go را ندارید.Retrieve
را در فایل ارسالی قرار ندهید.main.go
هستید.main.go
تعریف کنید.پس از پیادهسازی موارد خواستهشده، فایل main.go
را آپلود کنید.
آرش قصد دارد یک وبسرویس خفن پیادهسازی کند، اما او میداند که از همان ابتدای کار، تعداد درخواستهای کاربران به endpoint هایی که بار پردازشی بالایی دارند بسیار زیاد خواهد بود. بنابراین او تصمیم گرفته که از rate limiter استفاده کند. از آنجایی که او نمیداند این rate limiter را چگونه پیادهسازی کند، از شما خواسته تا آن را برایش پیادهسازی کنید.
پروژهی اولیه را از این لینک دانلود کنید. ساختار فایلهای پروژه بهصورت زیر است:
وابستگی time/rate
در پروژه تعریف شده و برای پیادهسازی rate limiter باید از آن استفاده کنید.
در این پروژه از پایگاه دادهی PostgreSQL استفاده شده است. برنامه شامل جدولی با نام app_keys
است که شامل دو ستون id
از نوع BIGSERIAL
و key
از نوع VARCHAR(255)
است.
در پکیج db
تابعی با نام GetConnection
تعریف شده که باید از آن برای دریافت کانکشن دیتابیس استفاده کنید. میتوانید اطلاعات اتصال به دیتابیس را در این فایل تغییر دهید.
تنها یک روت با آدرس /
در برنامه تعریف شده است که میتوان rate limiter های مختلف را روی handler آن اعمال کرد.
ByIp
🔗این تابع بهترتیب شامل سه پارامتر زیر است:
next
از نوع http.Handler
: همان handler اصلی روت است.refillRate
از نوع rate.Limit
: میزان افزایش تعداد درخواستهای مجاز کاربر در هر ثانیه (برای مثال اگر مقدار آن برابر با ۳ باشد، در هر ثانیه، ۳ واحد به تعداد درخواستهای مجاز کاربر اضافه میشود، به شرطی که تعداد درخواستهای مجاز فعلیاش کوچکتر از tokenBucketSize
باشد.)tokenBucketSize
از نوع int
: سقف تعداد درخواستهای پیاپی کاربراین تابع را طوری پیادهسازی کنید که درخواستها را براساس آیپی محدود کند. در صورتی که کاربر با محدودیت مواجه نشده باشد، پردازش درخواست باید توسط next
صورت گیرد. در غیر اینصورت، کد پاسخ باید به 429
تغییر کند، مقدار هدر Content-Type
باید برابر با application/json
قرار داده شود و بدنهی پاسخ بهصورت زیر باشد:
ByAppKey
🔗امضای این تابع مشابه تابع ByIp
است.
این تابع را طوری پیادهسازی کنید که درخواستها را براساس مقدار هدر X-App-Key
موجود در درخواست محدود کند. اگر مقدار این هدر در جدول app_keys
وجود نداشته باشد، محدودیت نباید اعمال شود. در غیر اینصورت، محدودیت باید اعمال شود. اگر کاربر با محدودیت مواجه شده باشد، پاسخ باید مشابه پاسخ مورد انتظار برای تابع ByIp
باشد.
تضمین میشود که هنگام استفاده از این تابع، هدر X-App-Key
در درخواست موجود است.
ممکن است بخواهیم rate limiter ها را ترکیب کنیم. اگر از توابع ByIp
و ByAppKey
در کنار یکدیگر استفاده شود، محدودیت باید هم براساس آیپی و هم براساس مقدار هدر X-App-Key
اعمال شود. مثلاً اگر مقدار tokenBucketSize
برابر با ۵ باشد و ۵ درخواست پیاپی با آیپیهای مختلف، اما با X-App-Key
یکسان (بهطوری که در جدول app_keys
موجود باشد) ارسال کنیم، باید با محدودیت مواجه شویم. همچنین اگر این درخواستها را با آیپی یکسان، اما با X-App-Key
های متفاوت (بهطوری که در جدول app_keys
موجود باشند) ارسال کنیم، باز هم باید با محدودیت مواجه شویم.
limiters
هستید.limiters
تعریف کنید.پس از پیادهسازی موارد خواستهشده، پوشهی limiters
را زیپ کرده و آپلود کنید.