ACM
انجمن جهانی ACM ، قدیمی ترین و معتبر ترین انجمن تخصصی در زمینه کامپیوتر است. این انجمن فعالیتهای گوناگونی برای ترویج و توسعه علوم و مهندسی کامپیوتر و فناوری اطلاعات و ارتباطات اعم از انتشار نشریات تخصصی، برگزاری همایشها، برگزاری مسابقات برنامه نویسی و غیره انجام میدهد.
این انجمن با هدف شناسایی و تشویق استعدادهای برجسته در زمینه طراحی الگوریتم و برنامه نویسی، همه ساله مسابقهای با نام (ICPC (International Collegiate Programming Contest در سطح جهان برگزار میکند. این مسابقه یک مسابقه دانشجویی است که تیمهای برنامه نویسی از دانشگاههای سراسر دنیا در آن شرکت میکنند.این مسابقه در دو مرحله برگزار می شود. تیم ها ابتدا در مسابقات منطقه ای با هم مبارزه می کنند و تیم های برتر هر منطقه به مسابقات فینال جهانی راه پیدا می کنند و در آنجا برترین تیمهای برنامه نویسی دانشجویی جهان مشخص میشوند. این مسابقات در قالب تیمهای 3 نفره برگزار میشود. حامی مسابقات شرکت IBM است.
چند نمونه سوال از مسابقات ACM
مسئله لیوان های وارونه
n لیوان رو میزی قرار دارن که تعدادی از اونها به صورت وارونه هستن. ما هر بار اجازه داریم وضعیت سه لیوان رو هم زمان عوض کنیم. یعنی اگه وارونه بودن درستشون کنیم و اگه درست بودن وارونه کنیم. شما باید برنامه ای بنویسید که مشخص کنه آیا با این شرایط امکان داره همه لیوانها رو تو وضعیت درست قرار داد؟ اگه جواب مثبته ، چطور؟
سطر اول فایل ورودی n رو نشون می ده که از 4 کمتر نیست. سطر بعدی شماره لیوانهایی رو مشخص می کنه که وارونه هستن. انتهای شماره ها با صفر مشخص می شه.
هر سطر فایل خروجی یه مرحله از کار رو نشون می ده. یعنی شماره سه لیوانی رو که تغییر وضعیت می دن.
از مثال زیر هم می تونید کمک بگیرید:
ورودی مسئله
4
2 4 0
خروجی مسئله
1 2 3
1 3 4
مسئله شاسی برق
تو یه اتاق m تا شاسی برق داریم که به n چراغ متصل هستن. ممکنه بعضی شاسی ها به چند چراغ متصل باشن. هر بار فشار دادن یه شاسی باعث می شه که وضعیت چراغهای متصل به اون تغییر پیدا کنه. یعنی چراغهای روشن خاموش می شن و بالعکس. در ابتدای کار بعضی از چراغها روشن هستن. می خوایم ببینیم آیا می شه با فشار دادن تعدادی از این شاسی ها همه چراغها رو روشن کنیم؟
سطر اول فایل ورودی به ترتیب اعداد n و m رو نشون می ده. m سطر بعدی با شماره چراغهایی که به شاسی ها متصل هستن پر می شه. مثلا سطر اول نشون می ده که کدوم چراغها به شاسی شماره 1 متصل هستن و ... آخر این سطرها با صفر مشخص می شه. و در آخر سطری قرار داره که شماره چراغهای روشن رو مشخص می کنه. این سطر هم با صفر تموم می شه.
هر سطر فایل خروجی شامل یه شماره شاسی خواهد بود که باید فشار داده بشه. اگه امکان روشن کردن تمامی چراغها نبود ، عبارت No Solution توی فایل خروجی نوشته بشه. مثلا:
ورودی مسئله
6 4
1 3 4 0
2 6 0
3 4 5 0
5 6 0
2 3 4 6 0
خروجی مسئله
1
3
مسئله بست اعشاری اعداد
همونطور که می دونید هر عدد به فرم کسری رو می شه به فرم اعشاری نوشت. اما بعضی کسرها فرم اعشاری نامتناهی دارن که اصطلاحا بهشون گفته می شه کسر با بسط متناوب (توجه داشته باشید که امکان نداره بسط اعشاری یه کسر غیرمتناوب باشه). حالا باید برنامه ای بنویسید که فرم کسری عدد رو دریافت کنه و فرم اعشاری رو چاپ کنه.
سطر اول فایل ورودی عدد n رو مشخص می کنه که تعداد ورودیهاست. n سطر بعدی رو n عدد کسری تشکیل می دن که صورت و مخرج اونها با فضای خالی از هم جدا شدن. توجه داشته باشید که قدرمطلق مقادیر صورت و مخرج بیشتر از ۶۰۰۰۰ نیست.
هر سطر فایل خروجی بسط اعشاری یه عدد ورودی رو مشخص می کنه. قسمت متناوب عدد باید داخل کروشه قرار بگیره. مثلا:
ورودی مسئله:
3
89 250
356 999
353 990
خروجی مسئله:
0.365
0.[365]
مساله عدد دراماتیک:
به یه عدد صحیح مثبت n_دراماتیک گفته می شه ، اگه حاصلضرب اون عدد در n ، از یکبار چرخش ارقامش به سمت راست حاصل بشه. مثلا اعداد 102564 و 128205 اگه در 4 ضرب بشن ، جواب بصورت 410256 و 512820 در می یاد. پس هر دو عدد 4_دراماتیک هستن.
حالا شما باید برنامه ای بنویسید که اعداد تک رقمی و غیر صفر n و k رو بگیره ، و کوچکترین عدد مثبت n_دراماتیک رو که رقم یکانش k هست پیدا کنه! اگر همچین عددی موجود نبود ، صفر رو نتیجه بده.
سطر اول فایل ورودی برنامه تعداد موارد آزمایشی رو مشخص می کنه ، و در سطرهای بعدی زوج اعداد n و k قرار می گیرن. مثلا اگه فایل ورودی به صورت زیر باشه:
2
4 5
2 1
فایل خروجی باید اینطور باشه:
128205
0
مسئله 4
هر فرمول ترتیبی از یک رقم غیر منفی و عملگرهای + و - میباشد. هیچ فاصلهای(Space) بین کاراکترهای فرمول قرار ندارد. فرض کنید که فرمولها به طریق صحیح نوشته شده اند. وظیفه شما خیلی ساده است: هر فرمول را ارزیابی کرده و نتیجه را بنویسید!
ورودی مسئله:
ورودی شامل چندی نمونه آزمایشی(Test Case) میباشد. هر Test Case در یک خط قرار می گیرد و هر خط شامل چندین Test Case می باشد که بوسیله Space از هم جدا شده اند.آخرین خط فایل ورودی تنها شامل # می باشد.
جروجی مساله:
برای هر Test Case فرمول را ارزیابی کرده و نتیجه را در یک خط فایل خروجی بنویسید. نتایج فرمولهایی که در یک خط قرار دارند را با یک Space از هم جدا کنید.
مثال ورودی:
1+3+5+7-4 1-2+2
1 6-2 2 1+2
مثال خروجی:
12 1
1 4 2 3
خوب به هر حال یک موضوع جدید برای بحث پیدا کردم . امرور میخوام روی یک مساله جالب بحث کنیم و جواب بگیریم .
اول طرح سوال : یک فایل متنی داریم که تمامش از حروف و ارقام تشکیل شده . میخواهیم ظرفیت این فایل را به کمترین مقدار لازم برسانیم . چقدر میتوانیم کم کنیم . چگونه به آن مقدار کم کنیم .
خوب این برنامه یکی از حالت های ساده فشرده سازی ( Zip ) کردنه . خوب البته اینجا همه چیز نیاز به اثبات داره .
اول بهتره اینو بدونیم که هر کاراکتر در فایل 8 بیت یا به عبارتی 1 بایت فضا اشغال میکنه . میدونیم که تو هر بایت میتونیم 256 نوع کاراکتر جا بدیم . ( حروف کد اسکی ) اما ما در اینجا فقط از 10 کاراکتر استفاده میکنیم پس میتوانیم مطمئن باشیم کلی فضا به هدر میرود . خوب میخواهیم این فضا را به صورت کامل استفاده کنیم . چه کنیم . خوب یک فکر که سریع به ذهن ما می رسه اینه که اعداد 0 تا 255 را با یک کاراکتر میشه نوشت . کافیه کد اسکی اون عدد رو سیو کنیم . یعنی به ازای 126 میتوانیم کاراکتر 126می کد اسکی را جایگزین کنیم . حال باید ببینیم برای اعداد بزرگتر چه باید بکنیم . خوب الگوریتمی که من به ذهنم برای حل این مساله رسید این بود که اعداد را به مبنای دو ببریم . خوب مطمئنا تعداد ارقام زیاد میشود . حال هر هشت رقم را از سمت راست جدا میکنیم و به جای آن عددش را مینویسیم . این اعداد بین 0 تا 255 هستند و با کنار هم قرار دادن این اعداد ( کد اسکی آنها ) در فایل متنی جدید آن را ذخیره میکنیم .
مثال : عدد 23564789 را فشرده کنید .
حل : این عدد 8 بایت فضا اشغال میکند . اما به روش ما اول به مبنای دو میبریم -- > 1011001111001000111110101
بعد هر 8 رقم را جدا میکنیم --> 11110101 و 10010001 و 01100111 و 1 . حالا این اعداد را به مبنای ده می آوریم --> 245 و 145 و 103 و 1 و حالا کد اسکی آنها را جایگزین میکنیم --> "_" و "و" و "g" و "Ǽ" . خوب یک کلمه چهار حرفی داریم که برگشت پذیره و میتونیم از اون عدد رو بدست بیاریم .
اما باید ثابت کنیم با این کار به کمترین ظرفیت میرسیم . چون تابع یک به یک است میتونیم ثابت کنیم ظرفیت کمتر از نمی شه فرض میکنیم بشه . خوب پس یک عدد با حروف کمتر به این نسبت داده شده و عدد ماهم به یک کتن دیگر نسبت داده شده و اون متن هم به یک عدد دیگر نسبت داده شده یک گراف دو بخشی به وجود میاد که یک طرف اعداد هستند و یک طرف متنها و از یک طرف با فرمول فشرده سازی ما میریم تو و یک جا با اون فرمول فشرده سازی فرضی برمیگردیم . حال چون گراف دور داره ( 2nتا راس داره ) نتیجه میگیریم فرمول ما یک به یک نیست که این خلاف واقعیته .