شرلوک هلمز در پی موریآرتی است و توانسته مکان اختفای او را کشف کند. خیابانهای لندن شلوغ است و او برای رسیدن به موریآرتی باید از ساختمان که به هم متصلاند گذر کند تا او را در پس آخرین ساختمان بیابد. نحوه حرکت شرلوک بدین شرح است که در هر ثانیه میتواند حداکثر مسافت متر به بالا، پایین یا جلو حرکت کند تا به ساختمان بعدی برسد. در صورتی که مسافت مانده تا رسیدن به سقف ساختمان بعدی یا زمین کمتر از متر باشد، این مسافت باقیمانده را نیز در یک ثانیه طی میکند. همچنین در ابتدا شرلوک و موریآرتی روی زمین (در ارتفاع صفر) هستند. عرض هر ساختمان نیز برابر با متر است؛ به این معنا که شرلوک عرض هر ساختمان را در یک ثانیه طی میکند. شما باید بگویید حداقل زمان مورد نیاز شرلوک برای رسیدن به موریآرتی چقدر است؟
ورودی شامل سه خط است. در خط اول، حداکثر مسافتی که هلمز میتواند در یک ثانیه طی کند، داده میشود. در خط دوم، عدد (تعداد ساختمانها) آمده است. در خط سوم ورودی، عدد آمده که نشاندهنده ارتفاع ساختمانهاست.
در خروجی مدت زمانی که طول میکشد تا هلمز در سریع ترین حالت به موریآرتی برسد را چاپ کنید.
در این مثال، شرلوک در تلاش برای عبور از پنج ساختمان است و حداکثر مسافتی که شرلوک در یک ثانیه میتواند طی کند، برابر سه متر است. همانطور که در تصویر این مثال مشخص شدهاست، مقدار زمانی که نیاز است تا شرلوک تمام ساختمانها را بپیماید، برابر تعداد بردارهای قرمز در تصویر، یعنی ۱۵ ثانیه میشود.
شرلوک نامهای از یکی از دوستانش دریافت میکند. متن نامه چنین میگوید: «شرلوک عزیز، امیدوارم این نامه به موقع به دستتان برسد. من در یک شهر کوچک واقع در سواحل آنتارکتیکا گیر کردهام. قبلا از مسیری گذشتهام و دوباره به این شهر رسیدهام. اکنون نمیدانم از چه مسیری عبور کنم و گم شدهام. لطفا سریعا به من کمک کنید. با تشکر، هالیس.»
شرلوک با بررسی دقیق متوجه میشود که بعضی از شهرهای آنتارکتیکا با یک جاده به هم متصل هستند و از هر شهر میتوان با طی کردن تعدادی جاده به هر شهر دیگر رفت. همچنین او یافته است شهری که هالیس در آن قرار دارد متعلق به یک دور در گراف آنتارکتیکا است. این گراف بدین گونه ساخته میشود: شهرهای آنتارکتیکا رئوس گراف هستند و اگر بین دو شهر جاده ای وجود داشته باشد بین رئوس متناظر آنها یال است.
اگر شهر هایی که روی دور قرار دارند را شهرهای حلقوی بنامیم (رئوسی که متعلق به دور هستند)، کوتاه ترین مسیر از شهر فعلی شرلوک به یک شهر حلقوی را چاپ کنید. اگر چند جواب برای مسئله وجود داشت، یکی از آنها را به دلخواه انتخاب کنید.
ورودی شامل خط است. در خط اول، ، شماره شهری که شرلوک در آن قرار دارد میآید. در خط دوم، که تعداد شهرها را نشان میدهد آمده است. در خط سوم عدد داده میشود. در خط بعدی، در هر خط دو عدد با فاصله از هم آمده است که شماره شهرهایی که بین آنها جاده وجود دارد آمده است.
در خروجی، کوتاه ترین مسیری که شرلوک را به یک شهر حلقوی میرساند چاپ کنید. در صورت وجود چند مسیر، یکی از آنها به دلخواه چاپ شود.
اگر گراف را رسم کنیم، میبینیم که یک دور با رئوس ۱، ۲ و ۳ داریم و کوتاهترین مسیر از رأسی که شرلوک روی آن قرار دارد (رأس ۵) به نزدیکترین رأس دور (رأس ۳) مسیر زیر میباشد:
اگر گراف را رسم کنیم، میبینیم که یک دور با رئوس ۱، ۲و ۳ و یک دور با رئوس ۴، ۷ و ۸ داریم و کوتاهترین مسیر از رأسی که شرلوک روی آن قرار دارد (رأس ۵) به نزدیکترین رأس نزدیکترین دور (رأس ۴) مسیر زیر میباشد:
کوتاهترین مسیر به دور دیگر طول ۲ دارد که از مسیر انتخابی ما که طول ۱ دارد بلندتر است پس انتخاب ما دور ۴، ۷ و ۸ میباشد.
شرلوک و موریآرتی پس از جنجالهای بسیار به این نتیجه رسیدند که تبهکاری و حل معما آخر عاقبت ندارد؛ بنابراین تصمیم گرفتند به اصفهان سفر کرده و در شرکت مهیمن مشغول به مهندسی نرمافزار شوند. مدیر تیم برای اینکه بتواند مسائل HRی که در آینده بین این دو به وجود میآید را کنترل کند، تصمیم گرفته که آنها را در یک بازی دونفره شرکت دهد و برنده را استخدام کند.
بازی بدین صورت است که جعبه داریم که در هرکدام از آنها مقداری گز وجود دارد. دو نفر با شروع از شرلوک به ترتیب بازی میکنند و هرکس در نوبت خود باید یک جعبه را انتخاب کند و تا گز از جعبه بردارد، به صورتی که را بتوان به صورت نوشت، که یک عدد اول و یک عدد حسابی است. کسی که در نوبت خود نتواند گزی بردارد، میبازد. میدانیم که هر دونفر به اندازه کافی باهوش هستند و هردو بهترین بازی خود را انجام میدهند، همچنین تضمین میشود بازی دقیقاً یک برنده دارد. شما باید بگویید که در نهایت چه کسی برنده بازی میشود.
در خط اول ورودی آمده که نشانگر تعداد تستها است. سپس در خط بعدی تست ها آمده اند. هر تست شامل دو خط است که در خط اول آن عدد طبیعی که نشاندهنده تعداد جعبههاست آمده و در خط دوم تا با فاصله از هم آمدهاند؛ نشاندهنده تعداد گزهای جعبه ام است.
در خروجی شما باید نام برنده را خروجی دهید، اگر شرلوک برنده بازی بود، Sherlock
و در صورتی که موریآرتی برنده بود، Moriarty
را چاپ کنید.
در تست اول، شرلوک میتواند در یک حرکت گز از تنها جعبه موجود بردارد و از آنجا که گزها تمام میشوند، دیگر موریآرتی نمیتواند حرکتی انجام دهد و شرلوک برنده بازی میشود.
در تست دوم شرلوک و موریآرتی هرکدام در نوبت خود باید یعنی یک گز از جعبهای بردارند، بنابراین پس از حرکت موریآرتی گزها تمام میشوند و دیگر شرلوک نمیتواند حرکتی انجام دهد و موریآرتی برنده بازی میشود.
Java, C#, C++
شرلوک پس از کشف راز قتل اندرسون توسط موریآرتی تصمیم میگیرد اسرار این جنایت مخوف را برای پلیس افشا کند به همین دلیل میخواهد نامهای برای بازرس لستراد بنویسد و این راز را برملا کند. موریآرتی در شبکه پست مزدورانی دارد که نامهها را به صورت مخفیانه بررسی میکنند؛ از آنجا که شرلوک نمیخواهد موریآرتی متوجه کشف این راز توسط او بشود، تصمیم میگیرد که نامه را به صورت رمزنگاری شده برای بازرس ارسال کند. در این سوال شما باید در رمزنگاری نامه به شرلوک کمک کنید!
ابتدا باید هر حرف در زبان انگلیسی را مستقل از بزرگ یا کوچک بودن، به یک عدد از 0 تا 25 نگاشت کنیم و در محاسبات رمزنگاری از آن عدد استفاده کنیم.
حرف | عدد |
---|---|
A | 0 |
B | 1 |
C | 2 |
D | 3 |
E | 4 |
F | 5 |
G | 6 |
H | 7 |
I | 8 |
J | 9 |
K | 10 |
L | 11 |
M | 12 |
N | 13 |
O | 14 |
P | 15 |
Q | 16 |
R | 17 |
S | 18 |
T | 19 |
U | 20 |
V | 21 |
W | 22 |
X | 23 |
Y | 24 |
Z | 25 |
برای تبدیل متن انگلیسی معنادار (plaintext
) به متن رمزشده (ciphertext
) میتوان از الگوریتمهای مختلفی استفاده کرد:
Additive Cipher
توضیح: در این روش، هر حرف متن اصلی با شیفت دادن به تعداد مشخصی از حروف در الفبا، به رمز تبدیل میشود.
پارامترها:
text
(متن اصلی)key
(کلید، که یک عدد صحیح است و مقدار شیفت را مشخص میکند)مثال:
text
: "hello"key
: 3رمزنگاری:
نتیجه رمز شده: "KHOOR"
دستور:
Multiplicative Cipher
توضیح: در این روش، هر حرف متن اصلی با ضرب در یک کلید به رمز تبدیل میشود.
پارامترها:
text
(متن اصلی)key
(کلید، که یک عدد صحیح است و با 26 نسبت به هم اولاند)مثال:
text
: "hello"key
: 3رمزنگاری:
نتیجه رمز شده: "VMHHQ"
دستور:
Affine Cipher
توضیح: این روش ترکیبی از رمزنگاری جمعی و ضربی است، به این صورت که هر حرف متن اصلی ضرب در یک کلید میشود و سپس به نتیجه کلید دوم اضافه میشود.
پارامترها:
text
(متن اصلی)a
(کلید ضربی، که یک عدد صحیح است و با 26 نسبت به هم اولاند)b
(کلید جمعی، که یک عدد صحیح است)مثال:
text
: "hello"a
: 5b
: 8رمزنگاری:
نتیجه رمز شده: "RCLLA"
دستور:
Mapping Cipher
توضیح: در این روش، هر حرف متن اصلی به یک حرف دیگر در الفبا مطابق با یک نگاشت از پیش تعریف شده تبدیل میشود.
پارامترها:
text
(متن اصلی)mapping
(نگاشت حروف، به صورت رشتهای که ترتیب جدید حروف الفبا را نشان میدهد)مثال:
text
: "hello"mapping
: "zyxwvutsrqponmlkjihgfedcba" (نگاشت معکوس الفبا)رمزنگاری:
نتیجه رمز شده: "SVOOL"
دستور:
همانطور که در مثالها آمده است، فرمت کلی هر دستور به شکل زیر است:
که در آن cipher-type
، نوع الگوریتم رمز و سایر موارد، پارامترهای آن الگوریتم رمز هستند. پارامترهایی که بین []
آمدهاند، بسته به الگوریتم رمزنگاری ممکن است در دستور وجود نداشته باشند.
ترتیب پارامترها میتواند متفاوت باشد. برای مثال دو دستور زیر معادل هستند:
فاصلههای اطراف متن معنادار نادیده گرفته میشوند و در متن رمزشده مشاهده نمیشوند. اما فاصلههای بین کلمات دقیقا در متن رمز شده میآید:
بزرگی یا کوچکی حروف در متن معنادار مهم نیست. بنابراین متن رمزشده برای دو متن معنادار hello
و Hello
یکسان خواهد بود.
ورودی شامل خط است. در خط اول ، تعداد دستورات میآید. در خط بعدی، در هر خط یک دستور رمزنگاری آمدهاست.
در خروجی به ازای هر دستور، نتیجه رمزنگاری را با حروف بزرگ در یک خط چاپ کنید.
در دستور اول، متن معنادار از نظر بزرگی یا کوچکی حروف فرقی نمیکند. بنابراین اگر help me
را بخواهیم با الگوریتم Additive Cipher
رمز کنیم، محاسبات به صورت زیر است:
key
برابر یک است. بنابراین هر کاراکتر در متن معنادار با عدد 1 جمع میشود. چون عدد حاصل باید بین 0 تا 25 باشد، باقیماندهی حاصل جمع را بر عدد 26 بدست میآوریم. سپس در جدول نگاشت حروف انگلیسی به اعداد، حرف انگلیسی متناظر عدد بدست آمده را به عنوان کاراکتر رمزشده درنظر میگیریم. کاراکتر فاصله بین کلمات نیز دقیقا در متن رمز شده میآید.
بنابراین متن رمز شده، IFMQ NF
خواهد بود.danger
را بخواهیم با الگوریتم Multiplicative Cipher
و کلید با مقدار 3 رمز کنیم، محاسبات به صورت زیر است: در دستور دوم، صرفا جای پارامترها عوض شده و محاسبات مانند دستور قبل است.در این مثال، محاسبات رمزنگاری به صورت زیر است:
در این مثال، پارامتر a
کلید ضربی و پارامتر b
کلید جمعی است. بنابراین حروف متن معنادار در a
ضرب و با b
جمع میشوند.
بنابراین متن رمز شده، WZ
خواهد بود.
در این مثال، mapping
داده شده برابر "zyxwvutsrqponmlkjihgfedcba"
است. به عبارت دیگر نگاشت حروف انگلیسی به متن رمز شده به صورت زیر است:
با توجه به نگاشت بالا، متن hello
به این صورت رمز میشود:
بنابراین متن رمز شده، SVOOL
خواهد بود.
Java, C#, C++
در خانهی مشهور شماره ۲۲۱ بیکر استریت، جاناتان کولمز، یک برنامهنویس با استعداد و دستیار وفادارش دکتر واتسون، به دنبال حل یک معمای جدید هستند. یک روز وقتی که جاناتان به دفترچهی پوشهدار خود مراجعه میکند، با اسنادی مرموز و عجیب مواجه میشود.
این اسناد به زبان انگلیسی نوشته شدهاند و به نظر میرسد برای نظریهپردازی دربارهی یک پروندهی مخفی تهیه شدهاند. جاناتان و دکتر واتسون، با تصمیم به حل این معما، به ساختن ابزاری سریع و قدرتمند میپردازند که به آنها کمک میکند تا اطلاعات مورد نیاز خود را از متون مرموز استخراج کرده و معمایی که پیش رویشان قرار دارد را حل نمایند.
اولین گام، پیشپردازش متون اسناد است. این پیادهسازی باید شامل موارد زیر باشد:
برای جلوگیری از مشکلات مربوط به حساسیت به بزرگی و کوچکی حروف، همه حروف موجود در متن باید به حروف کوچک تبدیل شوند.
برای مثال متن سند پیش از پردازش:
پس از این پردازش به متن زیر تبدیل خواهد شد:
هرگونه کاراکتر غیر از حروف انگلیسی و اعداد که برای جستجوی متنی اهمیتی ندارند، باید حذف شوند.
برای مثال متن سند پیش از پردازش:
پس از این پردازش به متن زیر تبدیل خواهد شد:
کلمات توقفی شامل موارد زیر هستند که در جستجوها نادیده گرفته میشوند و باید از متن حذف شوند:
برای مثال متن پیش از پردازش:
پس از این پردازش به متن زیر تبدیل خواهد شد:
نیاز است هرگونه فاصله اضافی بین کلمات حذف شود.
برای مثال متن پیش از پردازش:
پس از این پردازش به متن زیر تبدیل خواهد شد:
ساختار داده Inverted Index، ساختاری است که امکان نگهداری اطلاعات برای جستجوی سریع متنی را فراهم میکند. در ادامه با این ساختار داده بیشتر آشنا میشوید.
در این مرحله، باید تمامی کلمات موجود در هر سند را شناسایی کرده و لیستی از این کلمات ایجاد کنیم. این لیست، پایهای برای ساخت Inverted Index است.
برای مثال در سند زیر:
لیست کلمات به این شکل خواهد بود:
در این مرحله، یک دیکشنری ایجاد میشود که کلیدهای آن کلمات موجود در لیست کلمات هستند و مقادیر آنها لیستی از شماره اسنادی است که هر کلمه در آنها ظاهر شده است.
برای مثال دو سند پیشپردازش شده زیر را در نظر بگیرید:
بنابراین Inverted Index به این شکل خواهد بود:
همانطور که میبینید، کلمه halis
هم در سند 1 و هم در سند 2 وجود دارد؛ در حالی که کلمه please
تنها در سند 1 و کلمه code
تنها در سند 2 وجود دارند.
اکنون میتوانیم به کمک ساختار داده ایجاد شده، اسناد دلخواه را بازیابی کنیم.
برای مثال Inverted Index زیر را درنظر بگیرید:
میخواهیم بدانیم کلمات halis
و watson
همزمان در چه اسنادی آمدهاست. برای این منظور، کافی است اشتراک شماره اسناد برای این دو کلمه را بررسی کنیم:
همانطور که میبینید، میتوان نتیجه گرفت کلمات halis
و watson
همزمان در سند 1 آمده اند.
در این گام، کوئریهایی طراحی میشوند که به کمک آنها میتوان جستجوی متنی پیشرفته انجام داد و شماره اسناد مربوطه را بازیابی کرد. ساختار این کوئریها با فرمت JSON
است که در ادامه معرفی خواهند شد.
match
با استفاده از این کوئری، اسنادی که شامل یک عبارت مشخص هستند، بازیابی میشوند.
در مثال بالا، اسنادی که شامل عبارت john watson
هستند بازیابی میشوند؛ یعنی این دو کلمه پشت سر هم در متن پیش پردازش شده سند وجود داشته باشد.
all
با استفاده از این کوئری، اسنادی که شامل تمام عبارات هستند، بازیابی میشوند.
در مثال بالا، اسنادی که شامل هر دو عبارت moriarty
و john watson
هستند بازیابی میشوند.
any
با استفاده از این کوئری، اسنادی که شامل حداقل یکی از عبارات هستند، بازیابی میشوند.
در مثال بالا، اسنادی که شامل حداقل یکی از عبارتهای moriarty
یا john watson
باشند بازیابی میشوند.
and
با استفاده از این کوئری، اسنادی بازیابی میشوند که با تمام از کوئریهای فرزند به طور همزمان مطابقت دارند.
در مثال بالا، اسنادی بازیابی میشوند که شامل هر سه کلمهی rainy
، sherlock
و death
باشند.
یک نمونه کوئری دیگر شامل and
:
or
با استفاده از این کوئری، اسنادی بازیابی میشوند که با حداقل یکی از کوئریهای فرزند مطابقت داشته باشد.
در مثال بالا، اسنادی بازیابی میشوند که یا شامل عبارت rainy night
باشند، یا اینکه همه عبارات sherlock holmes
، dr john watson
و moriarty
در آن اسناد آمده باشد، و یا اینکه حداقل یکی از کلمات death
یا boold
در آن اسناد آمده باشد.
not
با استفاده از این کوئری، تمام اسنادی که با کوئری فرزند مطابقت نداشته باشند بازیابی میشوند.
در مثال بالا، اسنادی بازیابی میشوند که هر دو عبارت knife
و gun
همزمان در آن اسناد نیامده باشد.
کوئریهای والد، خود نیز میتوانند فرزند کوئری والد دیگری باشند.
در ریشه کوئری، ممکن است متغیر size
بیاید که نشان دهنده حداکثر تعداد اسنادی است که باید بازیابی شوند. درصورتی که اندازه مشخص نشده بود، همه نتایج بازیابی میشوند.
هدف این است که ابزاری ساخته شود تا متون اسناد را پیش پردازش کرده، سپس ساختار داده Inverted Index ایجاد شود. در نهایت به کمک این ساختار داده جهت افزایش سرعت جستجو، کوئریهایی با هدف بازیابی اسناد مختلف، پردازش شوند.
ورودی شامل خط است. در خط اول، تعداد سندها، داده میشود. در خط بعدی، در هر خط متن سند ام داده میشود. سپس، عدد (تعداد کوئریها) آمده است. در خط بعدی، در هر خط یک کوئری با فرمت JSONPath
میآید.
در خروجی به ازای هر کوئری، شماره اسنادی که بازیابی میشوند را به ترتیب شماره اسناد از کوچک به بزرگ با فاصله در یک خط چاپ کنید.
در صورتی که هیچ سندی در نتیجه اجرای کوئری پیدا نشد، عبارت NO RESULT
را چاپ کنید.
پس از مرحله پیشپردازش، اسناد به صورت زیر خواهند بود:
همچنین کوئریها پس از تبدیل به شکل زیر خواهند بود:
mystery
در آنها وجود دارد. این عبارت تنها در اسناد 2 و 3 آمده است.mystery
یا solution
در آن اسناد آمده است. عبارت mystery
در سند 2 و 3 و عبارت solution
در سند 1 آمده است.mystery
و clue
در آن اسناد آمده باشد. سند 3 هردوی این عبارات را دارا است.پس از مرحله پیشپردازش، اسناد به صورت زیر خواهند بود:
همچنین کوئریها پس از تبدیل به شکل زیر خواهند بود:
watson
یا holmes
در آن اسناد آمده است. عبارت watson
در همه اسناد به جز اسناد 6 و 7 آمده است. از طرفی عبارت holmes
در سند 6 و 7 هم دیده میشود. بنابراین همه اسناد بازیابی میشوند.size
برابر 6 است. بنابراین تنها 6 سند اول بازیابی میشوند.learn
در آن اسناد وجود داشته باشد، به علاوه اینکه حداقل یکی از عبارات watson
یا holmes
هم وجود داشته باشد. عبارت watson
و holmes
در کنار عبارت learn
تنها در سند 3 آمدهاند.پس از مرحله پیشپردازش، اسناد به صورت زیر خواهند بود:
همچنین کوئریها پس از تبدیل به شکل زیر خواهند بود:
little things
در آنها وجود دارد. کلمات little
و things
تنها در سند 2 پشت سر هم دیده میشوند.common rare
در هیچ سندی دیده نمیشود.