نیما که یک آدم بسیار پرکار است، همزمان هم درس میخواند و هم سر کار میرود. حالا او برای اینکه ساعتهایش را مدیریت کند نیاز به کمک شما دارد.
شبانهروز او مثل همهی ما ۲۴ ساعت دارد، از این ۲۴ ساعت، ساعت را مشغول کارهای شرکت است و ساعت را مشغول درسهای دانشگاه است و در نهایت هم ساعت برای استراحت دارد.
اما همچنان محاسبات ما درست در نمیآید. چرا که وقت خالی او بیشتر از چیزی که محاسبه میکنیم میشود. بنابراین فرض میکنیم او در ساعت روز دو کار را با هم انجام میدهد. یعنی هم مشغول درس خواندن است و هم مشغول کار مفید!
حالا از شما میخواهیم حساب کنید که نهایتا چند ساعت از روز را استراحت میکند؟ () را به دست آورید.
ورودی تنها شامل یک خط است که در آن سه عدد حسابی و و با فاصله از هم آمده اند.
همچنین میدانیم که مجموع و از شبانهروز بیشتر نیست.
و البته مقدار از هر یک از درس و کار کمتر یا مساوی است.
در خروجی فقط یک عدد را چاپ کنید که نشان دهندهی تعداد ساعتهای خالی نیما در روز است.
در این مثال نیما ۱۰ ساعت مشغول کارهای دانشگاه و ۱۱ ساعت مشغول کارهای شرکت بوده است. ۲ ساعت از روز را نیز مشغول هر دو کار بوده است.
پس میتوان گفت ۱۹ ساعت جمعا برای دانشگاه و شرکت وقت گذاشته و ۵ ساعت هم وقت آزاد دارد.
در این مثال نیما ۴ ساعت برای دانشگاه کار کرده و ۵ ساعت برای شرکت، حالا هر ۴ ساعت درس خواندن همزمان با کارهای شرکت بوده است پس در کل ۵ ساعت وقت گذاشته است و ۱۹ ساعت زمان خالی داشته.
برای مدیریت بهتر کتابهایمان به یک کتابخانه نیاز داریم. این کتابخانه مقداری ظرفیت دارد که بیشتر از آن نمیتواند کتاب در خود جا دهد.
این کتابخانه مشخصات زیر را دارد:
Golestan
و gOlEsTan
دقیقاً یک کتاب هستند.OK
داده میشود:تشخیص اینکه کدام ارور در چه زمان(ها)ی باید برگردانده شود بر عهدهی شماست.
پروژهی اولیه را از این لینک دانلود کنید. ساختار فایلهای پروژه به صورت زیر است:
در فایل main.go
چند تابع و متد وجود دارد که شما باید آنها را کامل کنید.
NewLibrary
🔗این تابع یک اشارهگر به یک شی از نوع کتابخانه برمیگرداند. در این تابع باید یک شی جدید بسازید و ساختار داخلی آن را مطابق آنچه خودتان تعریف کردهاید مقداردهی کنید.
AddBook
🔗در این متد شما اسم یک کتاب را گرفته و در صورتی که شرایط برقرار بود (مثلاً کتابخانه جا داشت و این کتاب قبلا در کتابخانه نبود) آن را اضافه میکنید و OK
بر میگردانید. در غیر این صورت بسته به مورد ارور مناسب را در قالب یک رشته برمیگردانید.
*راهنمایی: در صورتی که کتابخانه پر باشد و کتابی با نام تکراری وارد شود، خطای مربوط به کتاب تکراری (و نه پر بودن ظرفیت) باید برگردانده شود.*
BorrowBook
و ReturnBook
🔗در این دو متد یک نفر یک کتاب را امانت میگیرد و سپس آن را پس میدهد.
در مواردی نیز ممکن است خطا پیش آید مثلا کتابی که امانت گرفته شده را دوباره کسی بخواهد امانت بگیرد یا کسی کتابی که در حال حاضر امانت گرفته نشده را بخواهد پس دهد.
پس از پیادهسازی توابع خواسته شده، فایل main.go
را آپلود کنید.
حتما خودتان بهتر میدانید که ما برنامهنویسان فراموشکار، جزئیات و آرگومانهای دستورات را به راحتی یادمان میرود. برای این منظور خیلی اوقات صفحات manual دستورها یا همان man page
ها را چک میکنیم.
برای مثال با وارد کردن دستور man ls
میتوانیم مستندات رسمی ابزار ls
را در صفحهی دوست داشتنی ترمینالمان بخوانیم.
متاسفانه به جز فراموشکار، گاهی کمحوصله هم هستیم و دنبال کردن یک مستند رسمی طولانی میتواند جانفرسا باشد. مثلا man bash
که توضیحات پوستهی bash
را به ما نشان میدهد بسیار طولانی است و حدود پنج هزار خط است! برای حل این مشکل، مستندات غیر رسمیای تحت نام «طولانی بود نخوندم» یا "too long didn't read» یا به طور مخفف TLDR
توسط کاربران ایجاد شد که نسخهی خلاصه شده و کاربردی از مستندات است و با مثالها و توضیحات و ... میتواند بسیار در زمان صرفهجویی کند. برای آشنایی اولیه با این مستندات میتوانید از این لینک استفاده کنید.
اما استفاده از سایت شاید برای همهی کاربران گزینهی اول نباشد و بسیاری از ما دوست داریم یک برنامهی سمت کاربر داشته باشیم که به این شکل از آن استفاده کنیم: tldr bash
و خودش از صفحات آنلاین خوانده و اطلاعات را در اختیار ما بگذارد. البته تنها مشکل ما این نیست. به جز این مورد، با توجه به سرعت محدود اینترنت، ما دوست داریم با استفاده از حافظهی نهان (کش) در زمان و مصرف اینترنت نیز صرفهجویی کند، به این ترتیب صفحاتی که تا کنون بازدید شدهاند را در خود ذخیره کند و در زمان استفاده، صفحهی ذخیره شده را بازگرداند.
کلاینت اصلی این نرمافزار با زبان Javascript
و در محیط Node.js
توسعه داده شده اما کلاینتهای دیگری نیز برای آن وجود دارد که میتوانید لیستی از آنها را اینجا ملاحظه کنید. توصیه میشود یکی از آنها را نصب کنید و با آن کار کنید.
پروژهی اولیه را از این لینک دانلود کنید. ساختار فایلهای پروژه به صورت زیر است:
در فایل main.go
چند تابع و متد وجود دارد که شما باید آنها را کامل کنید.
در فایل tldr.go
یک اینترفیس وجود دارد که باید آن را پیادهسازی کنید. این اینترفیس دو متد دارد که در ادامه توضیح داده میشود.
در فایل main.go، یک استراکت وجود دارد که قرار است اینترفیس گفته شده را پیادهسازی کند. همچنین یک تابع سازنده داریم
در متد Retrieve، یک کلید که اسم همان ابزاری است که توضیحات بیشترش را میخواهیم به ما داده میشود و انتظار میرود توضیح و راهنمای کار با آن را به شکل یک رشته برگردانیم.
زمانی که یک کلید را دریافت میکنیم دو حالت دارد. حالت اول حالتی است که قبلا آن را دیدهایم و در کش ذخیره کردهایم، پس باید به سرعت و بدون معطلی از کش آن را خوانده و برگردانیم. حالت دوم حالتی است که تا به حال این کلید را ندیدهایم، در این حالت باید با کمک منبع بیرونی یا همان provider (که خودش مثلا اینترنت دادهها را میخواند) و هم در کش ذخیره کند و هم برگرداند.
این متد باید لیست تمام مطالبی که در provider وجود دارند را برگرداند. به بیان دیگر این لیست یک رشته برمیگرداند شامل اسم تمام ابزارهایی که در tldr
داکیومنت مربوط به آن وجود دارد. برای دسترسی به این لیست به سادگی میتوانید متد List
را در تامینکننده فراخوانی کنید.
تنها نکتهای که وجود دارد این است که ترتیب این لیست باید تا حدی عوض شود. تفاوت به این صورت است که بین تمام مواردی که در لیست قرار میگیرند، در لیست خروجی شما باید اول اسم ابزارهایی که صفحهی آنها در کش موجود است آورده شود و در ادامه باقی ابزارها بیایند. مثلا اگر ابزار zsh
تا کنون فراخوانی شده و در کش موجود است، اول این لیست zsh
وجود داشته باشد و باقی ابزارها مثل bash
قرار گیرند. ترتیب اعضایی که در کش هستند اهمیتی ندارد و ترتیب اعضایی که در کش نیستند نیز اهمیتی ندارد.
این سازنده یک شی تامین کننده از جنس همین اینترفیس میگیرد و یک شی از نوع TLDRDBCached
که به درستی مقداردهی کرده است برمیگرداند.
از آنجا که به فصل گرم سال نزدیک میشویم و ممکن است برق سیستم برود، نیاز داریم که این اطلاعات در یک پایگاهداده ذخیره شوند تا با خاموش و روشن شدن سیستم، همچنان دسترسی به اطلاعات از طریق دیتابیس موجود باشد. برای این منظور یک DBMS از نوع postgres
تدارک دیدهایم که میتوانید از آن استفاده کنید. همچنین یک رابطه شی-ارتباط به نام Gorm
هم برای شما تدارک دیده شده که می توانید برای سهولت بیشتر از آن استفاده کنید.
در فایل db.go
یک تابع به نام GetConnection
وجود دارد که یک شی از نوع *gorm.DB
میدهد و میتوانید با آن به دیتابیس و امکانات Gorm
دسترسی داشته باشید. در سیستم خودتان میتوانید اطلاعات اتصال به دیتابیس را مطابق سیستم خودتان بروز کنید ولی آن فایل را آپلود نخواهید کرد و سمت سرور فایل db.go
مطابق کانفیگ سمت سرور موجود است.
در فایل tldr.go
که قبلا بخشی از آن را دیدهایم، یک موجودیت نیز برای شما آورده شده است به نام TLDREntity
:
شما برای حل این سوال باید اطلاعات خود را در قالب شیای از این نوع در دیتابیس ذخیره کنید و حق تغییر در این شی را نیز ندارید.
پس دقت کنید که فقط اجازه دارید کش کردن داده را با استفاده از Gorm
انجام دهید.
توجه کنید که در تستها بررسی میشود که جدول متناظر با این شی به طور مناسب پر شده باشد.
Retrieve
هیچگاه کلیدی که سمت سرور وجود ندارد پاس داده نمیشود. TLDREntity
وجود دارد. GetConnection
یک پوینتر به یک شی معتبر از نوع gorm.DB
خواهد بود و با آن به شکل مناسب به دیتابیس دسترسی خواهید داشت. provider
حداقل داکیومنت مربوط به یک ابزار وجود دارد.پس از پیادهسازی توابع خواسته شده، فایل main.go
را آپلود کنید.
سال 1410 است و برای همه دانشگاهها ابلاغیه آمده که باید تابلوهای اعلانات خود را الکترونیکی کنند. در بازار برنامههای مختلفی برای کار با تابلوهای الکترونیکی وجود دارد ولی دانشگاه شما میخواهد از برنامه متفاوتی استفاده کند و شما را به عنوان برنامه نویس آن انتخاب کرده است.
نمونهای از تابلو اعلانات موجود رو میتونید اینجا ببینید
پروژهی اولیه را از این لینک دانلود کنید. ساختار فایلهای پروژه به صورت زیر است:
در فایل main.go
چند تابع و متد وجود دارد که شما باید آنها را کامل کنید.
از شما خواسته شده که نحوه اضافه کردن اعلامیه به تابلو و برداشتن آن از روی تابلو شبیه تابلوهای فیزیکی موجود باشد تا شکل و شمایل آشنای خود را حفظ کند. به این معنی که ممکن است اعلامیهها روی هم قرار بگیرند و اگر بخواهیم اعلامیه زیرین را از روی تابلو حذف کنیم، باید ابتدا اعلامیههای روی آن برای لحظهای برداشته شوند و سپس دوباره سر جایشان گذاشته شوند. همچنین تمام اعلانات یک عدد منحفصر به فرد (ID) دارند.
در وهله اول به شما اینترفیس تابلو و اعلانات روی آن داده شده است. (به توضیحات راجع به این توابع بعدا پرداخته خواهد شد)
همچنین نیاز است برای تابلو و اعلانات توابعی با امضاهای زیر تعریف کنید که به عنوان تابع سازنده (constructor) عمل میکنند. تضمین میشود در تستها از خروجی همین توابع استفاده خواهد شد.
تابع NewBoard
: این تابع تعداد ردیفها و تعداد ستونهای تابلو را به عنوان ورودی میگیرد و یک شی از نوع AnnouncementBoard برمیگرداند.
تابع NewPaper
: این تابع عرض (تعداد ستونهایی که روی تابلو اشغال میکند) و طول (تعداد ردیفهایی که روی تابلو اشغال میکند) و آیدی اعلان را به عنوان ورودی میگیرد و یک شی از نوع AnnouncementPaper برمیگرداند. تضمین میشود که عرض تمام اعلانات عددی فرد است.
تابع getAnnouncementIDsAt
: این تابع به ترتیب شماره یک ردیف و شماره یک ستون از تابلو را میگیرد و آیدی اعلانات موجود در این نقطه را به ترتیب از زیرترین اعلان به روترین آن برمیگرداند.
تابع addTo
: اعلامیه را به تابلویی که به عنوان ورودی میگیرد میچسباند. رو مقدار بعدی در ورودی به ترتیب ردیف و ستونی است که پونز در آن قرار خواهد گرفت. (ردیف و ستون اینجا از 0 شمرده میشوند. مثلا اگر در تابع NewBoard
تعداد ردیف را 5 داده باشیم، اینجا اگر بخواهیم پونز روی ردیف اول باشد عددش را 0 میدهیم و اگر بخواهیم روی ردیف آخر باشد عددش را 4 میدهیم.) موقعیت پونز روی کاغذ ستون وسط و بالاترین ردیف است. یعنی اگر عرض کاغذ 3 و طول آن 4 باشد، یعنی کاغذ 3 ستون و 4 ردیف از تابلو را اشغال کند، پونز روی ردیف اول (از بالا) و ستون دوم قرار میگیرد. (یادآوری: تضمین میشود عرض کاغذ عددی فرد است)
همچنین در این تابع باید چک کنید که نه پونز و نه خود کاغذ از تابلو بیرون نزنند و اگر زدند یک error
برگردانید (پیام درون ارور مهم نیست)
و دقت کنید که در تابع getAnnouncementIDsAt
فقط پونزهایی که در آن نقطه قرار دارند را نمیخواهیم. هر قسمتی از هر کاغذی در آن نقطه از تابلو قرار داشته باشند باید آیدیش در لیست خروجی آن تابع در جای درستش باشد.
همچنین تضمین میشود هر شی که از تابع NewPaper
برگردانده میشود، در هر لحظه فقط و فقط به یک تابلو وصل خواهد شد. البته میتوان از روی یک تابلو آن را برداشت و سپس روی تابلوی دیگری نصب کرد.
تابع removeAndGetIDsOnTop
: وقتی این تابع روی یک اعلان صدا میشود، آن اعلان و تمام اثراتش باید از روی تابلویی که در حال حاضر رویش قرار دارد حذف شود. همچنین باید این تابع لیستی از اعلاناتی که رویا این اعلان قرار دارند را برگرداند (همان داستان که میخواهیم مثل تابلوی فیزیکی اول اعلانات رویش را برداریم تا به ایت اعلان برسیم و بعد آن روییها را سر جایشان برگردانیم).
البته این تابع یک چالش دارد که اگر پیاده سازیش نکنید فقط بخشی از نمره اسن قسمت را میگیرید. آن هم این است که این اعلانات باید به ترتیب از روترین اعلان به زیرترین مرتب شود. برای اعلاناتی که باید برداشته شوند ولی به هم ارجعیتی ندارند (هیچکدام روی دیگری نیست)، مهم نیست با چه ترتیبی در خروجی قرار میگیرند.
برای مثال اگر یک اعلان با آیدی 200 را بخواهیم حذف کنیم، در حالی که یک اعلان با آیدی 150 روی گوشه راست بالای آن قرار دارد و اعلان با آیدی 250 روی گوشه سمت چپ آن، در حالی که 150 و 250 با هم هیچ هم پوشانی ندارند، مهم نیست خروجی [150 250] است یا [250 150]. ولی اگر 200 را بخواهیم حذف کنیم در حالیکه 150 روی گوشه راست بالای 200 قرار داشته باشد و 250 گوشه راست بالای 150، خروجی باید باشد [150 250]، یعنی خانه 0 آن 250 و خانه 1 آن 150 باشد.
پس از پیادهسازی توابع خواسته شده، فایل main.go
را آپلود کنید.
پیپ یا pip
یکی از بازیگران مهم دنیای پایتون است. این نرمافزار که سابقا نامش pyinstall
بود الان به نام pip
تغییر نام داده است. این نام همانند GNU
یک مخفف بازگشتی است. در واقعا pip
مخفف Pip Install Paackages
است. اطلاعات بیشتر در صفحهی ویکیپدیای پیپ در دسترس است.
از شما میخواهیم در ادامه، این پکیجمنیجر دوست داشتنی را با زبان گو و برای زبان گو پیادهسازی کنید. پس بدون معطلی فایلهای اولیهی پروژه را از این لینک دانلود کنید.
برای این سوال از شما میخواهیم به شکل Test Driven Development عمل کنید. در واقع آنچه باید پیادهسازی کنید، هرچیزی است که باعث پاس شدن تستهای نمونه که در اختیار شماست میشود. برای این سوال تستهای اصلی دقیقا همان تستهای نمونه هستند و به این ترتیب شما میتوانید با خواندن دقیق تستها متوجه جزئیات سوال شوید و کد خودتان را همراه با پیادهسازی تست کنید.
fs
و commands
را بببینیم. داخل این پوشهها فایلهای go
را قرار دهید.