حمید پس از نوشتن صورت جلساتش در *اسنپ* به زبان انگلیسی، متوجه شده که همهی اعداد را شمارشی نوشته، اما باید ترتیبی باشند! برای مثال، بهجای `1` باید مینوشته `1st` و بهجای `22` باید مینوشته `22nd`. از آنجایی که تعداد صورت جلسات حمید بسیار زیاد است، او از شما خواسته تا این تبدیل را بهصورت خودکار برایش انجام دهید.
# ورودی
در تعدادی خط از ورودی استاندارد (*stdin*) که **تعدادشان نامشخص است**، یکی از صورت جلسات حمید وارد میشود که ممکن است شامل اعداد مختلفی باشد. اعداد حداکثر ۷ رقمی هستند.
# خروجی
متن صورت جلسه را پس از تغییر اعداد به اعداد ترتیبی چاپ کنید.
# مثال
## ورودی نمونه ۱
```
This is the 1 text. I'm writing this text in my 23 daily.
s12napp
```
## خروجی نمونه ۱
```
This is the 1st text. I'm writing this text in my 23rd daily.
s12thnapp
```
## ورودی نمونه ۲
```
1, we should pay attention to the 2 point!
2, we should pay attention to the 1 point!
And finally, we should pay attention to the 3 point!
```
## خروجی نمونه ۲
```
1st, we should pay attention to the 2nd point!
2nd, we should pay attention to the 1st point!
And finally, we should pay attention to the 3rd point!
```
صورت جلسه
برنامهنویسان در شرکت *اسنپ* عادت دارند برای تشخیص اینکه ارور برگرداندهشده از متد چیست، کدهایی مثل کد زیر مینویسند:
```go
n, err := f.Read(data)
if err != nil {
if err == io.EOF {
break
}
fmt.Println(err)
return
}
```
در نتیجه انتظار دارند پکیج مربوطه، همه ارورهایی که ممکن است برگردانده شوند را به شکل فیلد در خود داشته باشد.
متاسفانه یا خوشبختانه یک کتابخانهی فوقالعاده مفید به دست تیم فنی *اسنپ* رسیده است. این کتابخانه اگرچه بسیار مفید است و کارهای آنها را راحت میکند، اما این قاعده در آن برقرار نیست.
حالا برنامهنویسان *اسنپ* میخواهند برخلاف عادت خود عمل نکنند، بنابراین نیاز به یک پکیج کمکی برای پکیج اصلی دارند که ارورها را در خودش داشته باشد.
خوشبختانه این کتابخانه، سورسکد قابل خواندن (و نه تغییر) دارد و میتوان از آن به منظور توسعهی پکیج کمکی استفاده کرد.
# جزئیات پروژه
+ سورسکد فعلی شرکت را از [این لینک](/contest/assignments/33300/download_problem_initial_project/113523/) دانلود کنید.
+ فایل `helper.go` در پکیج `helper` را به گونهای تغییر دهید تا فیلدهای ارورها در آن مقداردهی شوند.
+ باید با تغییرات جزئی در کتابخانه، برنامه شما دچار مشکل نشود. مثلا متن ارورها ممکن است تغییرات جزئی بکند.
+ در پکیج `helper` میتوانید به صورت زیر از کتابخانهی `the_lib` استفاده کنید.
```go
package helper
import (
"snapp/the_lib"
)
// the_lib.LoadData()
```
# آنچه باید آپلود کنید
فایل `helper.go` تغییریافتهی خود را آپلود کنید.
اروررررر
*اسنپ* برای افزایش کارایی کد در سرورهای خود، میخواهد از تکنیک **[SIMD](https://en.wikipedia.org/wiki/SIMD)** استفاده کند. این تکنیک به این صورت عمل میکند که به جای اینکه در آن واحد یک عملیات روی دیتای ۳۲ بیتی انجام شود، ۴ عملیات روی ۴ دیتای ۸ بیتی بدون علامت انجام میشود. به این ترتیب به Parallelism دست پیدا میکنیم. اما نکته مهم اینکه اینجا به جای استفاده از قابلیت سختافزاری پردازندهها برای SIMD، از امکانات همروندی زبان گو استفاده میکنیم.
# جزئیات پروژه
پروژه اولیه را از [این لینک](/contest/assignments/33300/download_problem_initial_project/113525/) دانلود کنید.
در این سوال شما باید تابع `Simd` را پیاده سازی کنید. تابع شما ورودیهای زیر را دارد:
+ یک تابع به عنوان عملیات
+ یک `uint32` به عنوان ورودی
+ یک `uint32` به عنوان خروجی محاسبات
# آنچه باید آپلود کنید
پس از پیادهسازی موارد خواسته شده، فایل `main.go` را آپلود کنید. در صورتی که از _dependency_ خاصی استفاده کردهاید، فایلهای `go.mod` و `go.sum` را بههمراه فایل `main.go` زیپ کرده و آن را آپلود کنید.
SIMD
یکی از کارمندان شرکت *اسنپ* ، در آخرین دقیقه از آخرین ساعت از آخرین روز کاری خود قبل از مرخصی تابستانه خود، متوجه یک باگ در سیستم اعمال تخفیف *اسنپ* میشود. او که چند ثانیه بیشتر زمان نداشته یک گزارش ناقص از باگ مینویسد و در سامانه ثبت میکند و برای همیشه خارج میشود.
گزارش وی به شرح زیر است:
> فوری فوری
>
> باگ در ماژول تخفیف
>
> این باگ میتواند منجر به ضرر شرکت شود
همانطور که میبینید، این باگ اهمیت زیادی دارد. او از شما خواسته شده که هرچه سریعتر با بررسی سورسکد، آن را پیدا و رفع کنید.
سورسکد باگدار (اولیه) را از [این لینک](/contest/assignments/33300/download_problem_initial_project/113521/) دانلود کنید.
# نکات
+ در حین برطرف کردن ایرادها، امضای متدهای پابلیک را عوض نکنید.
+ فیلدهای پابلیک *ساختار*ها را نیز تغییر ندهید.
+ امکان حذف و تغییر و اضافه کردن متدهای پرایوت را دارید.
+ فقط یک باگ در ماژول وجود دارد و شما باید فقط همان را برطرف کنید.
+ شی `SnappSystem` از سمت سرور میآید و دیتای آن حتما صحیح است.
+ شی `TripRequest` را سیستم کاربر ارسال میکند و مستقیم به این متد میرسد.
+ مبدا مختصات را همان بالا چپ فرض کنید.
+ باگ در سیستم بررسی تاریخ است.
# آنچه باید آپلود کنید
پس از پیادهسازی موارد خواسته شده، فایل `main.go` را آپلود کنید.
باگ در تخفیفها
تیم فنی *اسنپ* قصد دارد تا سیستم جدیدی برای مدیریت دستاوردهای کاربران و دادن امتیاز به آنها با بهرهگیری از *gamification* پیادهسازی کند، اما به دلیل درخواست این تیم برای جذب نیروی فنی، آنها این تسک را به برخی از افرادی سپردهاند که در مرحلهی اول مصاحبهی *اسنپ* قبول شدهاند. مهدی که سرش شلوغ است، اما میخواهد در *اسنپ* استخدام شود، از شما میخواهد تا این تسک را برایش انجام دهید. نسخهی اولیهی این سیستم قرار است یک *API* ساده باشد.
# جزئیات پروژه
پروژهی اولیه را از [این لینک](/contest/assignments/33300/download_problem_initial_project/113526/) دانلود کنید. ساختار فایلهای پروژه بهصورت زیر است:
```
snapp_baz
├── achievements
│ └── achievements.go
├── db
│ └── connection.go
├── handlers
│ └── achievements.go
├── test
│ └── achievements_sample_test.go
├── go.mod
├── go.sum
└── main.go
```
## پایگاه داده
در این پروژه از پایگاه دادهی *PostgreSQL* استفاده شده است. برنامه شامل جداول زیر است:
1. کاربران (`users`):
| نام ستون | نوع | تعریف | ملاحضات |
|:-------|:-------------|-------------:|:--------------|
| `id` | `BIGSERIAL` | شناسهی کاربر | `PRIMARY KEY` |
| `name` | `VARCHAR(255)` | نام | |
| `phone` | `VARCHAR(255)` | شماره تلفن | |
2. دستاوردها (`achievements`):
| نام ستون | نوع | تعریف | ملاحظات |
|:-------------|:-------------|--------------------------------:|:-------------------------------------|
| `id` | `BIGSERIAL` | شناسهی دستاورد | `PRIMARY KEY` |
| `title` | `VARCHAR(255)` | عنوان دستاورد | |
3. دستاوردهای کاربران (`user_achievements`):
| نام ستون | نوع | تعریف |
| :--------------- | :------- | -------------: |
| `user_id` | `BIGINT` | شناسهی کاربر |
| `achievement_id` | `BIGINT` | شناسهی دستاورد |
دسترسی به پایگاه داده از طریق تابع `db.GetConnection` صورت میگیرد که به شکل *singleton* پیادهسازی شده است.
## منطق کسب دستاوردها
یک `map[int](func(int) bool)` به شکل *singleton* در برنامه تعریف شده که از طریق تابع `achievements.GetMap` قابل دسترسی است. این مپ، نگاشتی از شناسهی دستاوردها به توابعی است که با دریافت شناسهی یک کاربر، مشخص میکنند که آیا آن دستاورد توسط کاربر کسب شده است یا خیر.
## روتها
نسخهی اولیهی این *API* شامل روتهای زیر است:
- `/is_achieved`: این روت به تابع `handlers.IsAchieved` مپ شده است که با دریافت یک `user_id` و یک `achievement_id` از *query string*، مشخص میکند که آیا دستاورد توسط کاربر ذکرشده کسب شده است یا خیر.
- اگر پارامتر `user_id` مقداردهی نشده باشد، کد پاسخ باید `400` و بدنهی پاسخ باید `{"error": "no user id provided"}` باشد.
- اگر پارامتر `user_id` مقداردهی شده باشد، اما پارامتر `achievement_id` مقداردهی نشده باشد، کد پاسخ باید `400` و بدنهی پاسخ باید `{"error": "no achievement id provided"}` باشد.
- اگر مقدار پارامتر `user_id` عددی نباشد، کد پاسخ باید `400` و بدنهی پاسخ باید `{"error": "invalid user id"}` باشد.
- اگر مقدار پارامتر `user_id` عددی باشد، اما مقدار پارامتر `achievement_id` عددی نباشد، کد پاسخ باید `400` و بدنهی پاسخ باید `{"error": "invalid achievement id"}` باشد.
- اگر کاربری با شناسهی `user_id` در جدول `users` موجود نباشد، کد پاسخ باید `404` و بدنهی پاسخ باید `{"error": "user not found"}` باشد.
- اگر کاربری با شناسهی `user_id` در جدول `users` موجود باشد، اما دستاوردی با شناسهی `achievement_id` در جدول `achievements` موجود نباشد، کد پاسخ باید `404` و بدنهی پاسخ باید `{"error": "achievement not found"}` باشد.
- اگر هیچ یک از شرایط فوق برقرار نباشد، کد پاسخ باید `200` و بدنهی پاسخ باید `{"is_achieved": true}` یا `{"is_achieved": false}` باشد (بسته به این که کاربر دستاورد را کسب کرده است یا خیر).
- `/get_achievements`: این روت به تابع `handlers.GetAchievements` مپ شده است که با دریافت یک `user_id` از *query string*، لیست دستاوردهای کاربر را برمیگرداند.
- اگر پارامتر `user_id` مقداردهی نشده باشد، کد پاسخ باید `400` و بدنهی پاسخ باید `{"error": "no user id provided"}` باشد.
- اگر مقدار پارامتر `user_id` عددی نباشد، کد پاسخ باید `400` و بدنهی پاسخ باید `{"error": "invalid user id"}` باشد.
- اگر کاربری با شناسهی `user_id` در جدول `users` موجود نباشد، کد پاسخ باید `404` و بدنهی پاسخ باید `{"error": "user not found"}` باشد.
- اگر هیچ یک از شرایط فوق برقرار نباشد، کد پاسخ باید `200` و بدنهی پاسخ باید به فرم `{"achievements": ["achievement 1 name", "achievement 2 name"]}` باشد (نام دستاوردها باید بهترتیب صعودی شناسهشان باشد).
- `/refresh_achievements`: این روت به تابع `handlers.RefreshAchievements` مپ شده است که با دریافت یک `user_id` از *query_string*، لیست دستاوردهای کاربر را بهروز میکند. در واقع، دستاوردهایی که تاکنون توسط کاربر کسب نشدهاند باید مجدداً بررسی شوند و در صورتی که دستاورد جدیدی کسب شده بود، در جدول `user_achievements` درج شود.
- کد و بدنهی پاسخ این روت باید مشابه روت `/get_achievements` باشد، با این تفاوت که دستاوردهای کسبنشده مجدداً بررسی میشوند.
**توجه:** مقدار هدر `Content-Type` در پاسخ همهی درخواستها باید برابر با `application/json` قرار داده شود.
# آنچه باید آپلود کنید
پس از پیادهسازی برنامه، یک فایل زیپ آپلود کنید که وقتی آن را باز میکنیم، با ساختار زیر مواجه شویم:
```
snapp_baz
├── handlers
│ └── achievements.go
├── go.mod (Optional)
└── go.sum (Optional)
```
اسنپباز
**کوئریهای شما باید روی *PostgreSQL 13* قابل اجرا باشد.**
---
طاها قصد دارد تا تصمیمهایش را از این پس به شکل دادهمحور بگیرد و صرفاً شهودی عمل نکند. برای این کار، او نیاز به اطلاعات مختلفی از کاربران *اسنپ* دارد؛ اما چون او *SQL* بلد نیست، از شما خواسته تا کوئریهای مربوط به اطلاعات موردنیازش را بنویسید.
# جزئیات پروژه
ساختار جداول بهصورت زیر است:
1. کاربران (`users`):
| نام ستون | نوع | تعریف | ملاحضات |
|:-------|:-------------|-------------:|:--------------|
| `id` | `BIGSERIAL` | شناسهی کاربر | `PRIMARY KEY` |
| `name` | `VARCHAR(255)` | نام | |
| `phone` | `VARCHAR(255)` | شماره تلفن | |
2. سفرها (`trips`):
| نام ستون | نوع | تعریف | ملاحظات |
|:-------------|:-------------|--------------------------------:|:-------------------------------------|
| `id` | `BIGSERIAL` | شناسهی سفر | `PRIMARY KEY` |
| `user_id` | `BIGINT` | شناسهی مسافر | |
| `driver_id` | `BIGINT` | شناسهی سفیر (جدول سفیران در این مسئله وجود ندارد) | |
| `started_at` | `TIMESTAMP` | زمان شروع سفر | |
| `finished_at` | `TIMESTAMP` | زمان پایان سفر | |
3. دعوت کاربران به اپلیکیشن (`invitations`):
| نام ستون | نوع | تعریف | ملاحظات |
|:-------------|:-------------|------------------------------------------:|:--------------|
| `id` | `BIGSERIAL` | شناسهی دعوت | `PRIMARY KEY` |
| `inviter_user_id` | `BIGINT` | شناسهی کاربر دعوتکننده | |
| `invitee_user_id` | `BIGINT` | شناسهی کاربر دعوتشده | |
| `invited_at` | `TIMESTAMP` | زمان دعوت | |
# مطلوبات
کوئریهای *SQL* خواستهشده از شما موارد زیر است (توجه کنید که هر کوئری امتیازی جداگانه دارد و اگر کوئری یک قسمت را نتوانستید بنویسید، کوئریهایی که حل کردید را بفرستید و قسمت مربوط به آن کوئری را خالی بگذارید):
1. شناسهی کاربرانی که شمارهی آنها شامل زیررشتهی `1400` است، بهترتیب صعودی برحسب شناسه
2. شناسهی سفرهایی که زمان شروعشان بین ساعت ۲۲ تا ۱ بامداد است، بهترتیب صعودی برحسب شناسه
3. شناسه، نام، شماره موبایل و جزء صحیح تعداد ساعات سفرهای کاربران (مجموع اختلاف زمان شروع و پایان سفرهایشان)، بهترتیب نزولی برحسب تعداد ساعات (اگر تعداد ساعات دو کاربر یکسان باشد، کاربری باید زودتر بیاید که شناسهاش کوچکتر است.)
4. شناسه و شماره تلفن افرادی که حداقل در سه ماه مختلف میلادی، در هر یک از این ماهها حداقل سه نفر را به *اسنپ* دعوت کردهاند، بهترتیب صعودی برحسب شناسه
**نکته:** نام ستونهای خروجی مهم نیست، اما ترتیب آنها مهم است.
# آنچه باید آپلود کنید
کوئریهای خود را در قالب زیر، در یک فایل با پسوند `.sql` قرار داده و آن را ارسال کنید (فایل را زیپ نکنید):
```sql
-- Section1
your 1st query here
-- Section2
your 2nd query here
-- Section3
your 3rd query here
-- Section4
your 4th query here
```