اعداد یکتا


  • محدودیت زمان: ۰٫۵ ثانیه
  • محدودیت حافظه: ۶۴ مگابایت

دنباله‌ای به طول nn به فرم a1,a2,,ana_1, a_2, \dots, a_n \, از اعداد صحیح داریم. می‌دانیم هیچ عددی در این دنباله، بیش از ۲ بار ظاهر نشده است. برای مثال این دنباله می‌تواند به صورت 4,3,2,7,8,2,3,14, 3, 2, 7, 8, 2, 3, 1 باشد.

به یک عدد صحیح «یکتا» می‌گوییم اگر فقط یک‌بار در این دنباله ظاهر شده باشد. برای مثال، در دنباله بالا تنها اعداد 11، 44، 77 و 88 «یکتا» هستند.

از شما می‌خواهیم برنامه‌ای بنویسید که با دریافت اعداد موجود در این دنباله، ‍XOR اعداد «یکتا» آن را چاپ کند. اگر هیچ عدد «یکتا»یی در این دنباله نبود، صفر چاپ کنید.

اگر نمی‌دانید که XOR چیست، روی این قسمت کلیک کنید.

منظور از XOR (مخفف eXclusive OR) دو عدد صحیح و نامنفی مثل aa و bb که آن را به صورت aba \oplus b نیز نشان می‌دهند، این است که اگر دو عدد aa و bb را در مبنای دو زیرهم بنویسیم. (اگر یکی از این اعداد تعداد کمتری رقم دارد پشت آن صفر در نظر بگیرید.) سپس برای هر دو رقم زیرهم اگر یکسان باشند رقم متناظر حاصل، صفر و در غیر این صورت یک خواهد بود.

برای مثال برای محاسبه 12612 \oplus 6 ابتدا این دو عدد را در مبنای دو می‌نویسیم (باید پشت ۶ صفر اضافه کنیم تا تعداد ارقام برابر شود.) سپس به صورت رقم به رقم نگاه می‌کنیم و اگر ارقام متناظر در این دو عدد برابر بودند، ۰ و در غیر این‌صورت ۱ می‌گذاریم یعنی:

612=(0110)2(1100)2=(1010)2=106 \oplus 12 = (0110)_2 \oplus (1100)_2 = (1010)_2 = 10

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

اگر می‌خواهید درباره این عملگر بیشتر بدانید،‌ این پیوند را مطالعه کنید.

ورودی🔗

در خط اول ورودی، عدد طبیعی nn نوشته می‌شود.

1n1001 \leq n \leq 100

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

1ai1001 \leq a_i \leq 100

خروجی🔗

در تنها سطر خروجی، XOR اعداد «یکتا»ی این دنباله را چاپ کند. اگر هیچ عدد «یکتا»یی در این دنباله نبود، 00 چاپ کنید.


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

2
1 1
Plain text

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

0
Plain text

هیچ عدد یکتایی در دنباله 1,11, 1 وجود ندارد، بنابراین پاسخ این نمونه ۰ خواهد بود.


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

8
4 3 2 7 8 2 3 1
Plain text

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

10
Plain text

اعداد یکتای دنباله 4,3,2,7,8,2,3,14, 3, 2, 7, 8, 2, 3, 1 همان 11، 44، 77 و 88 هستند بنابراین پاسخ این نمونه برابر است با: 1478=101 \oplus 4 \oplus 7 \oplus 8 = 10


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

2
2 1
Plain text

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

3
Plain text

همه اعداد دنباله 1,21, 2، یکتا هستند. بنابراین پاسخ این نمونه برابر است با: 21=32 \oplus 1 = 3

دیجی‌رمز


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

سال ۱۴۹۹ است و دیجی‌کال‍ا از رمزارز خود با نام دیجی‌رمز رونمایی کرده است!

علی می‌خواهد از طریق سرمایه‌گذاری در این رمزارز، mm تومان پول کسب کند، اما در حال حاضر هیچ سرمایه‌ای ندارد. او می‌خواهد از دوستش پول قرض کند تا این سرمایه‌گذاری‌ها را انجام دهد.

در بازار دیجی‌رمز ، nn فرصت سرمایه‌گذاری وجود دارد که iiاُمین آن‌ها ابتدا به cic_i تومان پول برای شروع نیاز دارد و پس از سرمایه‌گذاری، هر روز pip_i تومان سود می‌دهد. علی در هر یک از این فرصت‌ها می‌تواند حداکثر یک بار سرمایه‌گذاری کند، اما او می‌تواند در هر چند فرصت مختلفی که بخواهد سرمایه‌گذاری کند.

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

به او بگویید کوتاه‌ترین زمان چند روز است.

ورودی🔗

در سطر اول ورودی دو عدد صحیح و مثبت nn و mm با فاصله از هم آمده است. 1n100 0001 \le n \le 100\ 000

1m1091 \le m \le 10^9

در nn سطر بعدی، در هر خط دو عدد pip_i و cic_i که با یک فاصله از هم جدا‌شده‌اند آمده است. 1pi,ci1091 \le p_i, c_i \le 10^9

خروجی🔗

در تنها سطر خروجی کمترین تعداد روزی که لازم است تا علی بعد از پس دادن پول دوستش mm تومان سود کند را چاپ کنید.

مثال‌ها🔗

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

2 5
4 10
10 15
Plain text

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

2
Plain text

اگر علی ۲ روز در فرصت سرمایه‌گذاری دوم سرمایه‌گذاری کند، به اندازه‌ی 2×1015=552 \times 10 - 15 = 5 \geq 5 سود می‌کند و به هدفش می‌رسد.


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

4 10
1 8
3 12
4 17
10 100
Plain text

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

6
Plain text

اگر علی ۶ روز در فرصت سرمایه‌گذاری دوم و سوم سرمایه‌گذاری کند، به اندازه‌ی (6×312)+(6×417)=6+7=1310(6 \times 3 - 12) + (6 \times 4 - 17) = 6 + 7 = 13 \geq 10 سود می‌کند و به هدفش می‌رسد.


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

3 5
4 1
9 10
6 3
Plain text

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

1
Plain text

اگر علی ۱ روز در فرصت سرمایه‌گذاری اول و سوم سرمایه‌گذاری‌کند، به اندازه‌ی (1×41)+(1×63)=3+3=65(1 \times 4 - 1) + (1 \times 6 - 3) = 3 + 3 = 6 \geq 5 سود می‌کند و به هدفش می‌رسد.

مترو


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

نقشه متروی تهران را در نظر بگیرید. (این عکس فقط برای دادن یک دید کلی به شماست و نیازی به خواندن کلمات آن نیست.)

توضیح تصویر

اسم تمام ایستگاه‌ها در این فایل در ۷ سطر آمده است. در سطر iiام، نام ایستگاه‌های خط iiام مترو به ترتیب و با فاصله آمده است. (توجه کنید نام یک ایستگاه شامل کاراکتر فاصله (space) نیست.)

  • زمان لازم تردد قطار بین دو ایستگاه ۲ دقیقه
  • زمان لازم برای ورود به ایستگاهی که قصد سوار شدن قطار را داریم، ۱۷ دقیقه
  • زمان لازم برای خارج شدن از ایستگاه که قصد پیاده زدن در آن را داریم، ۱۲ دقیقه.
  • زمان لازم برای تعویض خط نیاز داریم، نیز ۱۰ دقیقه است.

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

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

از شما می‌خواهیم برنامه‌ای بنویسید که کمترین زمانی که طول می‌کشد تا محسن به محل خرید برسد را محاسبه کنید.

ورودی🔗

در سطر اول ورودی عدد صحیح و مثبت qq آمده است. 1q16000 1 \leq q \leq 16000 در qq سطر بعدی در هر سطر دو رشته ss و ff آمده که نام ایستگاه شروع و پایان را نشان می‌دهد.

تضمین می‌شود این دو رشته در فایل ایستگاه‌ها موجوداند.

خروجی🔗

برای هر کدام از qq جفت ایستگاه ورودی داده شده، کمینه زمان لازم برای رسیدن از ایستگاه مبدا به ایستگاه مقصد را محاسبه کنید.

مثال🔗

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

5
Tajrish Gheytariyeh
Tajrish Gholhak
Tarasht Eram-e_Sabz
Aghdasiyeh Sohrevardi
Towhid Baharestan
Plain text

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

31
35
43
45
51
Plain text

سفر اول از «تجریش» به «قیطریه»:

  • ۱۷ دقیقه ورود و سوار قطار شدن در ایستگاه «تجریش» طول می‌کشد.
  • ۲ دقیقه طول می‌کشد تا در خط ۱، از ایستگاه «تجریش» به «قیطریه» برسد.
  • ۱۲ دقیقه طول می‌کشد تا از ایستگاه «قیطریه» خارج شود.

بنابراین مجموع زمان این سفر برابر است با: 17+2+12=3117 + 2 + 12 = 31


سفر دوم از «تجریش» به «قلهک»:

  • ۱۷ دقیقه ورود و سوار قطار شدن در ایستگاه «تجریش» طول می‌کشد.
  • ۶ دقیقه طول می‌کشد تا در خط ۱، از ایستگاه «تجریش» به «قلهک» برسد.
  • ۱۲ دقیقه طول می‌کشد تا از ایستگاه «قلهک» خارج شود.

بنابراین مجموع زمان این سفر برابر است با: 17+6+12=3517 + 6 + 12 = 35


سفر سوم از «طرشت» به «ارم سبز»:

  • ۱۷ دقیقه ورود و سوار قطار شدن در ایستگاه «طرشت» طول می‌کشد.
  • ۲ دقیقه طول می‌کشد تا در خط ۲، از ایستگاه «طرشت» به «تهران (صادقیه)» برسد.
  • ۱۰ دقیقه طول می‌کشد تا از خط از ۲ به ۵ در ایستگاه «تهران (صادقه)» تغییر مسیر بدهد.
  • ۲ دقیقه طول می‌کشد تا در خط ۵، از ایستگاه «تهران (صادقیه)» به «ارم سبز» برسد.
  • ۱۲ دقیقه طول می‌کشد تا از ایستگاه «ارم سبز» خارج شود.

بنابراین مجموع زمان این سفر برابر است با: 17+2+10+2+12=4317 + 2 + 10 + 2 + 12 = 43


سفر چهارم از «اقدیسه» به «سهروردی»:

  • ۱۷ دقیقه ورود و سوار قطار شدن در ایستگاه «اقدسیه» طول می‌کشد.
  • ۱۶ دقیقه طول می‌کشد تا در خط ۳، از ایستگاه «اقدسیه» به «سهروردی» برسد.
  • ۱۲ دقیقه طول می‌کشد تا از ایستگاه «سهروردی» خارج شود.

بنابراین مجموع زمان این سفر برابر است با: 17+16+12=4517 + 16 + 12 = 45


سفر پنجم از «توحید» به «بهارستان»:

  • ۱۷ دقیقه ورود و سوار قطار شدن در ایستگاه «توحید» طول می‌کشد.
  • ۱۰ دقیقه طول می‌کشد تا در خط ۴، از ایستگاه «توحید» به «دروازه شمیران» برسد.
  • ۱۰ دقیقه طول می‌کشد تا از خط از ۴ به ۲ در ایستگاه «دروازه شمیران» تغییر مسیر بدهد.
  • ۲ دقیقه طول می‌کشد تا در خط ۵، از ایستگاه «دروازه شمیران» به «بهارستان» برسد.
  • ۱۲ دقیقه طول می‌کشد تا از ایستگاه «بهارستان» خارج شود.

بنابراین مجموع زمان این سفر برابر است با: 17+10+10+2+12=5117 + 10 + 10 + 2 + 12 = 51

انبارگردانی


کوئری‌های شما باید روی آخرین نسخه‌ی MySQL قابل اجرا باشند.


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

از آن‌جایی که محمد فرصت نوشتن کوئری‌های مدنظرش را ندارد، از شما می‌خواهیم تا این کوئری‌ها را برایش بنویسید.

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

داده‌های اولیه برای تست نمونه را از این لینک دانلود کنید.

ساختار جداول به‌شرح زیر است:

جدول products: از این جدول برای نگه‌داری اطلاعات محصولات استفاده می‌شود. ساختار این جدول به‌صورت زیر است:

نام ستون نوع تعریف
id ‌BIGINT(20) شناسه‌ی محصول
name VARCHAR(255) نام محصول
description TEXT توضیحات محصول
price DECIMAL(15, 2) قیمت محصول
total_profit DECIMAL(15, 2) مجموع مبلغ فروش محصول
created_at TIMESTAMP زمان درج محصول

جدول orders: از این جدول برای نگه‌داری لیست سفارش‌ها استفاده می‌شود. ساختار این جدول به‌صورت زیر است:

نام ستون نوع تعریف
id ‌BIGINT(20) شناسه‌ی سفارش
user_id ‌BIGINT(20) شناسه‌ی کاربر سفارش‌دهنده
created_at TIMESTAMP زمان ایجاد سفارش

جدول order_details: از این جدول برای نگه‌داری اطلاعات اقلام موجود در سفارش‌ها استفاده می‌شود. ساختار این جدول به‌صورت زیر است:

نام ستون نوع تعریف
id ‌BIGINT(20) شناسه‌ی اطلاعات محصول در سفارش
order_id ‌BIGINT(20) شناسه‌ی سفارش
product_id ‌BIGINT(20) شناسه‌ی محصول
quantity ‌INT(11) تعداد سفارش‌داده‌شده‌ی محصول

جدول delivery_centers: از این جدول برای نگه‌داری اطلاعات مراکز ارسال استفاده می‌شود. ساختار این جدول به‌صورت زیر است:

نام ستون نوع تعریف
id ‌BIGINT(20) شناسه‌ی مرکز ارسال
name ‌VARCHAR(255) نام مرکز ارسال

جدول deliveries: از این جدول برای نگه‌داری اطلاعات تحویل سفارش‌ها استفاده می‌شود. ساختار این جدول به‌صورت زیر است:

نام ستون نوع تعریف
order_id ‌BIGINT(20) شناسه‌ی سفارش
delivery_center_id ‌BIGINT(20) شناسه‌ی مرکز ارسال
received_at ‌TIMESTAMP زمان دریافت محصولات سفارش از انبار
delivered_at ‌TIMESTAMP زمان تحویل سفارش به مشتری (در صورتی که سفارش هنوز تحویل داده نشده باشد، مقدار آن برابر با NULL خواهد بود.)

توجه داشته باشید که جدول کاربران صرفاً جهت سادگی در سؤال نیامده است. نیازی به اطلاعات چنین جدولی نیست.

مطلوبات🔗

کوئری‌های زیر را طوری بنویسید که خروجی خواسته‌شده به‌دست آید:

  1. محمد اکنون متوجه شده که یک باگ در بک‌اند برنامه‌اش وجود داشته و مقدار ستون total_profit در جدول products لزوماً مطابق با اطلاعات موجود در جداول orders و order_details نیست (در داده‌ها inconsistency وجود دارد). کوئری‌ای بنویسید که مقدار ستون total_profit جدول products را طبق مقادیر موجود در جداول orders و order_details به‌روزرسانی کند تا inconsistency در صورت وجود رفع شود.
  2. کوئری‌ای بنویسید که شناسه‌ی ۵ مرکز ارسال برتر از نظر چابک بودن را برگرداند. یک مرکز ارسال در صورتی چابک است که میانگین اختلاف زمانی بین دریافت محصول از انبار تا تحویل آن به مشتری در سفارش‌های تحویل‌داده‌شده‌اش کمتر از سایر مراکز ارسال باشد. نتایج را به‌ترتیب نزولی میزان چابک بودن مرتب کنید. تضمین می‌شود که میزان چابک بودن مراکز ارسال با یکدیگر متفاوت است. نام ستون خروجی اهمیتی ندارد.
  3. کوئری‌ای بنویسید که شناسه‌ی محصولاتی که تا ۷ روز پس از انتشارشان کمتر از ۱۰ فروش داشتند را دریافت کند. نام ستون خروجی اهمیتی ندارد.

نکات🔗

  • کوئری‌های شما باید روی آخرین نسخه‌ی MySQL قابل اجرا باشند.
  • کوئری هر بخش باید تنها شامل یک statement باشد.
  • هر کوئری امتیاز جداگانه دارد و اگر کوئری یک قسمت را نتوانستید بنویسید، کوئری‌هایی که حل کردید را بفرستید و قسمت آن کوئری را خالی بگذارید.
  • در تست نمونه‌ی این سؤال، فقط کوئری بخش اول تست می‌شود.

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

پس از طراحی کوئری‌ها، آن‌ها را در قالب زیر در یک فایل با پسوند .sql آپلود کنید.

-- Section1
    Your first query here
-- Section2
    Your second query here
-- Section3
    Your third query here
SQL

بهینه‌سازی جست‌وجو


کوئری‌های شما باید روی آخرین نسخه‌ی MySQL قابل اجرا باشند.


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

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

داده‌های اولیه برای تست نمونه را از این لینک دانلود کنید.

ساختار جداول به‌شرح زیر است:

جدول users: از این جدول برای نگه‌داری اطلاعات کاربران استفاده می‌شود. ساختار این جدول به‌صورت زیر است:

نام ستون نوع تعریف
id ‌BIGINT(20) شناسه‌ی کاربر
username ‌VARCHAR(255) نام کاربری
name ‌VARCHAR(255) نام کاربر
password ‌VARCHAR(255) رمز عبور
created_at TIMESTAMP زمان عضویت کاربر

جدول products: از این جدول برای نگه‌داری اطلاعات محصولات استفاده می‌شود. فرض می‌شود که هر محصول تنها متعلق به یک دسته‌بندی است! ساختار این جدول به‌صورت زیر است:

نام ستون نوع تعریف
id ‌BIGINT(20) شناسه‌ی محصول
category_id ‌BIGINT(20) شناسه‌ی دسته‌بندی محصول
name VARCHAR(255) نام محصول
description TEXT توضیحات محصول
price DECIMAL(15, 2) قیمت محصول
created_at TIMESTAMP زمان درج محصول

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

مطلوبات🔗

کوئری‌های خواسته‌شده از شما، موارد زیر است:

  1. کوئری ساخت ایندکس جهت بهینه‌سازی حداکثری سرعت دریافت شناسه‌ی کاربرانی که نام‌شان با یک رشته‌ی خاص آغاز می‌شود:
SELECT id
FROM users
WHERE name LIKE 'Ali%'
SQL
  1. کوئری ساخت ایندکس جهت بهینه‌سازی حداکثری سرعت دریافت شناسه، نام و قیمت محصولاتی که قیمت‌شان بین دو عدد مشخص است و مربوط به یک دسته‌ی خاص هستند:
SELECT id, name, price
FROM products
WHERE price > 25000 AND price < 50000000 AND category_id = 5
SQL

نکات🔗

  • کوئری‌های شما باید روی آخرین نسخه‌ی MySQL قابل اجرا باشند.
  • کوئری هر بخش باید تنها شامل یک statement باشد.
  • هر کوئری امتیاز جداگانه دارد و اگر کوئری یک قسمت را نتوانستید بنویسید، کوئری‌هایی که حل کردید را بفرستید و قسمت آن کوئری را خالی بگذارید.
  • در تست نمونه‌ی این سؤال، فقط کوئری بخش اول تست می‌شود.

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

پس از طراحی کوئری‌ها، آن‌ها را در قالب زیر در یک فایل با پسوند .sql آپلود کنید.

-- Section1
    Your first query here
-- Section2
    Your second query here
SQL

کوتاه‌کننده لینک


این سؤال تنها با زبان‌های PHP ، Python ، Go و JS (Node.js) قابل حل است.


دیجی‌کال‍ا قصد دارد برای بخش تحویل محصولات خود یک سامانه‌ی ساده‌ی ثبت پیشنهادات و انتقادات راه‌اندازی کند. از شما می‌خواهیم یک API برای این سامانه طراحی کنید.

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

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

در این سؤال، یک REST API شامل endpoint های زیر باید پیاده‌سازی شود:

آدرس عنوان
GET / بررسی up بودن سرویس
POST /signup ثبت‌نام
POST /login ورود به حساب کاربری
POST /urls کوتاه کردن لینک
GET /urls دریافت لیست لینک‌های کوتاه‌شده
GET /{slug} لینک کوتاه‌شده

در این API هر کاربر باید یک توکن داشته باشد. این توکن برای هر کاربر ثابت است.

endpoint های موردنیاز🔗

در همه‌ی endpoint ها، پاسخ باید به‌صورت JSON باشد.

اطلاعات ورودی به‌صورت application/x-www-form-urlencoded به endpoint ها ارسال می‌شوند.

بررسی up بودن سرویس🔗

پاسخ این endpoint باید به‌صورت زیر باشد:

  • کد وضعیت: 200
  • بدنه: {"ok":true}

ثبت‌نام🔗

دو پارامتر username و password باید به این endpoint ارسال شوند. در صورتی که حداقل یکی از این پارامترها ارسال نشده باشد یا برابر با رشته‌ی خالی باشد، پاسخ باید به‌صورت زیر باشد:

  • کد وضعیت: 400
  • بدنه: {"ok":false,"error":"no username or password provided"}

اگر کاربری با نام کاربری واردشده از قبل موجود باشد، پاسخ باید به‌صورت زیر باشد:

  • کد وضعیت: 400
  • بدنه: {"ok":false,"error":"user already exists"}

در غیر این‌صورت، کاربر باید ساخته شود، یک توکن یکتا برایش تولید شود و پاسخ به‌صورت زیر باشد:

  • کد وضعیت: 201
  • بدنه: {"ok":true,"token":"USER_TOKEN"}

ورود به حساب کاربری🔗

دو پارامتر username و password باید به این endpoint ارسال شوند. در صورتی که حداقل یکی از این پارامترها ارسال نشده باشد یا برابر با رشته‌ی خالی باشد، پاسخ باید به‌صورت زیر باشد:

  • کد وضعیت: 400
  • بدنه: {"ok":false,"error":"no username or password provided"}

اگر نام کاربری یا رمز عبور نادرست باشد، پاسخ باید به‌صورت زیر باشد:

  • کد وضعیت: 400
  • بدنه: {"ok":false,"error":"invalid username or password"}

در غیر این‌صورت، پاسخ باید به‌صورت زیر باشد:

  • کد وضعیت: 200
  • بدنه: {"ok":true,"token":"USER_TOKEN"}

کوتاه کردن لینک🔗

این endpoint نیازمند authentication است. در ریکوئست ارسالی مقدار هدر Authorization باید برابر با توکن کاربر باشد (بدون Bearer یا موارد مشابه).

پارامتر url (لینک) باید به این endpoint ارسال شود. در صورتی که این پارامتر ارسال نشده باشد یا برابر با رشته‌ی خالی باشد، پاسخ باید به‌صورت زیر باشد:

  • کد وضعیت: 400
  • بدنه: {"ok":false,"error":"no url provided"}

در غیر این‌صورت، لینک باید کوتاه شود و پاسخ به‌صورت زیر باشد (مقدار {slug} می‌تواند رندوم باشد):

  • کد وضعیت: 201
  • بدنه: {"ok":true,"url":"http://localhost/{slug}"}

دریافت لیست لینک‌های کوتاه‌شده🔗

این endpoint نیازمند authentication است. در ریکوئست ارسالی مقدار هدر Authorization باید برابر با توکن کاربر باشد (بدون Bearer یا موارد مشابه).

این endpoint باید لیست لینک‌های کوتاه‌شده‌ی کاربر به همراه تعداد بازدید هر کدام را در قالب یک لیست برگرداند.

  • کد وضعیت: 200
  • مثالی از پاسخ:
    [
      {
          "short_url": "http://localhost/SDas2",
          "url": "https://quera.org",
          "visits_count": 3
      },
      {
          "short_url": "http://localhost/zxcA54",
          "url": "https://google.com",
          "visits_count": 0
      }
    ]
    JSON

لینک کوتاه‌شده🔗

آدرس این درخواست به‌صورت /{slug} است که {slug} همان رشته‌ای است که به لینک کوتاه‌شده توسط برنامه تخصیص می‌یابد. اگر {slug} ورودی یافت نشود، پاسخ باید به‌صورت زیر باشد:

  • کد وضعیت: 404

در غیر این‌صورت، کاربر باید به لینک اصلی با کد پاسخ 301 هدایت شود.

نکات تکمیلی🔗

نصب نیازمندی‌ها و اجرا

برای حل این سؤال می‌توانید از هر زبان و هر تکنولوژی‌ای که می‌خواهید استفاده کنید. به‌صورتی که در یک پوشه به نام api کد برنامه را نوشته و در فایلی به نام runner.sh که توسط sh اجرا می‌شود، باید برنامه‌ی خود را اجرا کنید. توجه کنید که حتماً باید Dockerfile مربوط به پروژه‌ی خود را برای ما ارسال کنید.

در پروژه‌ی اولیه، ۴ داکرفایل برای php، python، golang و node قرار دادیم که می‌توانید از آن‌ها مستقیماً استفاده کنید. در صورتی که از یکی از این زبان‌ها برای حل سؤال استفاده می‌کنید، کافیست که Dockerfile مربوط به آن را در پوشه‌ی api کپی کنید و طبق توضیحات داده شده، سؤال را حل کنید. برای نصب نیازمندی‌های پایتون از requirements.txt، برای پی‌اچ‌پی از composer.json، برای گولنگ از go.mod و برای نودجی‌اس از package.json استفاده کنید.

در صورتی که زبان مورد استفاده‌ی شما، چیزی به جز این ۴ مورد است، باید خودتان داکرفایلی در پوشه‌ی api به‌شکلی بنویسید که بتواند نیازمندی‌های پروژه‌ی شما را نصب کرده و برنامه‌ی شما را مانند داکرفایل‌های موجود اجرا کند.

  • نیازی به persistent بودن داده‌ها نیست!
  • سیستم داوری docker-compose.yml زیر را خارج از فولدر api پاسخ شما قرار می‌دهد و با دستور docker-compose up --build آن را اجرا می‌کند.
extensionFromNamedocker-compose.yml
version: "3"

services:
  api:
    build: "./api"
    container_name: "api"
    ports:
      - "80:80"
YAML
  • شما مجاز به تغییر یا ارسال docker-compose.yml دلخواه نیستید.
  • سرویس شما باید روی پورت 80 آدرس localhost قابل دسترسی باشد.
  • توصیه می‌کنیم در runner.sh خود APIتان را روی 0.0.0.0:80 اجرا کنید.
تغییر Dockerfile

امکان تغییر فایل Dockerfile وجود ندارد، اما در اسکریپت runner.sh می‌توانید هر دستوری را اجرا کنید.

نحوه ارسال پاسخ🔗

شما می‌توانید تمامی محتوای موجود در پوشه‌ی api را تغییر دهید و هر فایلی که می‌خواهید اضافه یا کم کنید.

api
├──  api.py   # or main.go somefile.js anyfile.php name.any ...
├── Dockerfile
├── requirements.txt  # or go.mod package.json composer.json
└── runner.sh
Plain text

توجه کنید که نام فایل کد شما برای سیستم داوری اهمیتی ندارد و این خود شما هستید که در runner.sh از نام آن برای اجرای پروژه استفاده می‌کنید.

در نهایت این پوشه را zip کرده و ارسال کنید. توجه کنید که پس از extract کردن فایل zip شما، باید پوشه‌ی api را ببینیم که درون آن Dockerfile وجود دارد.