HW3.pdf

‫‪Haskell‬‬
‫نکات کلی‬
‫‪ ‬مهلت ارسال این تمرین تا ساعت ‪ ۹۵:۳۲‬روز ‪۹۲‬ام آبان ماه است‪ .‬درصورت ارسال با تاخیر به ازای هر‬
‫ساعت ‪ ٪۱‬ازنمره شما کسر خواهد شد‪.‬‬
‫‪ ‬جواب تمرین ها را به آدرس ‪ [email protected]‬ارسال کنید‪ .‬برای این تمرین باید فایل‬
‫‪ HW3.hs‬که در اختیار شما داده شده است را کامل کنید و با فرمت ‪HW3_#STD1_#STD2.hs‬‬
‫ارسال کنید‪ .‬به هیچ عنوان اسم یا تایپهای مشخص داده شده را تغییر ندهید‪ .‬درصورت نیاز توابع خودتان‬
‫را به آن اضافه کنید‪ .‬عنوان ایمیل را نیز به صورت ‪ HW3_#STD1_#STD2‬بنویسید‪.‬‬
‫‪ ‬در نوشتن هریک از توابع ممکن است نیاز به نوشتن توابع کمکی نیز داشته باشید‪ .‬پیادهسازی توابع بیشتر‬
‫بالمانع است‪ ،‬گرچه تمامی توابع گفته شده‪ ،‬با همان نام و مشخصات توضیح داده شده‪ ،‬باید پیادهسازی‬
‫شده باشند‪ .‬عدم پیادهسازی هریک موجب کسر نمره شما خواهد شد‪.‬‬
‫‪ ‬سعی کنید کدتان باتوجه به ‪ styling guideline‬نوشته شده باشد‪.‬‬
‫‪ ‬کد شما بدون هیچ وارنینگی باید کامپایل شود‪ ( .‬به ‪ styling guideline‬مراجعه کنید‪).‬‬
‫‪ ‬تمرین در قالب گروههای دو نفره قابل انجام است‪.‬‬
‫‪ ‬با هرگونه تقلب به شدت برخورد خواهد شد‪.‬‬
‫‪ ‬هرگونه ابهام در صورت تمرین را حتما در گروه درس مطرح کنید‪ ،‬در هنگام تصحیح و یا تحویل تمارین‬
‫هیچ عذری مبنی بر گنگ بودن صورت تمرین قابل قبول نخواهد بود‪.‬‬
‫‪۱‬نوشته شده توسط عارف شفاعی با تشکر فراوان از آقای اللهوردی‪.‬‬
‫تمرین سوم عملی‬
‫زبانهای برنامهنویسی‬
‫قسمت اول‪ :‬تشخیص صحت کد ملی‬
‫جناب آقای لو به عباسآقا گفته است تا برایش وب سایتی بسازد‪ .‬او میخواهد با کمک این سایت بتواند آهنگ‬
‫های خود را با متقاضیان اشتراک بگذارد‪ .‬به طرز عجیبی‪ ،‬برای وی صحت ثبتنام کنندگان مهم است و از این‬
‫رو تصمیم گرفته تا در قسمت ثبتنام سایت‪ ،‬کدملی افراد را هم گرفته و صحت این کدملی را تایید کند‪.‬‬
‫عباسآقا که حوصله کد زدن نداشت‪ ،‬از ما خواست تا این بخش را برایش پیادهسازی کنیم‪.‬‬
‫درهمین حین افجی‪ 2‬به ما از مزایای ‪ Haskell‬گفت و ما را متقاعد کرد تا با این زبان‪ ،‬برنامه را بنویسیم‪ .‬وی‬
‫توضیحات زیر را برای ما فرستاد‪ ،‬تا بتوانیم این برنامه را پیادهسازی کنیم‪:‬‬
‫الگوریتم تشخیص کد ملی‬
‫‪3‬‬
‫کدملی یک رشته رقم به طول ‪ ۱۱‬میباشد‪ .‬رقم سمت راست این رشته‪ ،‬رقم کنترل نام دارد‪.‬‬
‫ساختار کد ملی‬
‫ارقام‬
‫رقم‬
‫کد‬
‫کنترل‬
‫موقعیت‬
‫‪۱‬‬
‫‪ ۹‬رقم سمت چپ کد ملی‬
‫‪2‬‬
‫‪3‬‬
‫‪4‬‬
‫‪5‬‬
‫‪۰‬‬
‫‪۲‬‬
‫‪8‬‬
‫‪۹‬‬
‫‪۱۱‬‬
‫برای تشخیص صحت کدملی کافیست‪:‬‬
‫‪ .۱‬هر رقم را در موقعیت آن ضرب کرده و حاصل ر ا باهم جمع کنیم‪.‬‬
‫‪ .2‬مجموع بدست آمده را بر ‪ ۱۱‬تقسیم کنیم‪.‬‬
‫‪ .3‬اگر باقیمانده کمتر از ‪ 2‬باشد‪ ،‬رقم کنترل باید برابر باقیمانده باشد در غیر اینصورت رقم کنترل باید برابر‬
‫یازده منهای باقیمانده باشد‪.‬‬
‫برای مثال‪ ،‬کدملی ‪ ۱۹2۱۹3۲۰۰۱‬را درنظر بگیرید‪ .‬رقم کنترل (با خط نشان داده شده است) برابر با صفر‬
‫است و حاصل مرحله اول ‪ 23۱‬میشود‪ .‬باقیمانده آن بر ‪ ۱۱‬صفر و کمتر از ‪ 2‬میباشد‪ .‬پس برای درست بودن‬
‫صحت آن باید رقم کنترل و باقیمانده برابر باشند که این چنین است‪ ،‬پس کدملی صحت دارد‪.‬‬
‫‪ 2 FJ‬متخصص در زمینه برنامهنویسی ‪ Functional‬و ‪open-GL‬‬
‫‪ 3‬برگرفته شده از‪ :‬تشخیص صحت کدملی‬
‫تمرین سوم عملی‬
‫زبانهای برنامهنویسی‬
‫مراحل نوشتن برنامه‬
‫از آنجا که آقای افجی میداند که این از اولین برنامههای ‪Haskell‬ای است که مینویسیم‪ ،‬ما را مرحله به مرحله‬
‫راهنمایی کرد‪.‬‬
‫تمرین اول‪ :‬ابتدا باید تابعی بنویسیم که یک رشته از حروف را گرفته و تشخیص دهد آیا عدد است یا خیر‪ .‬برای‬
‫اینکار تابع ‪ isNumeric‬را به صورت زیر تعریف میکنیم‪:‬‬
‫‪isNumerical :: String -> Bool‬‬
‫چند نمونه از اجرای این تابع‪:‬‬
‫‪isNumerical "1234" == True‬‬
‫‪== False‬‬
‫""‬
‫‪IsNumerical‬‬
‫‪isNumerical "0921937660" == True‬‬
‫‪isNumerical "12a" == False‬‬
‫برای تشخیص اینکه یک کاراکتر عدد است یا خیر میتوانید از تابع ‪ isDigit‬که در کتابخانه ‪ Data.Char‬است‪،‬‬
‫استفاده کنید‪.‬‬
‫تمرین دوم‪ :‬درادامه‪ ،‬تابعی مینویسیم که حاصل مرحله اول الگوریتم گفته شده و همچنین رقم کنترل را بدست‬
‫آورد‪.‬‬
‫)‪sumPositionalDigits :: String -> (Int, Int‬‬
‫چند نمونه از اجرای این تابع‪:‬‬
‫)‪sumPositionalDigits "" == (0, 0‬‬
‫)‪sumPositionalDigits "0921937660" == (231, 0‬‬
‫)‪sumPositionalDigits "0921937660" == (231, 0‬‬
‫برای تبدیل یک کاراکتر به عدد میتوانید از تابع ‪ digitToInt‬که در کتابخانه ‪ Data.Char‬است‪ ،‬استفاده کنید‪.‬‬
‫زبانهای برنامهنویسی‬
‫تمرین سوم عملی‬
‫تمرین سوم‪ :‬حال که رقم کنترل و حاصل جمع اعداد را داریم‪ ،‬کافی است تابعی برای اجرای مراحل ‪ 2‬و ‪3‬‬
‫الگوریتم بنویسیم‪:‬‬
‫‪ctrlCompare :: (Int, Int) -> Bool‬‬
‫چند نمونه از اجرای این تابع‪:‬‬
‫‪ctrlCompare (0, 0) == False‬‬
‫‪ctrlCompare (231, 0) == True‬‬
‫‪ctrlCompare (781, 0) == True‬‬
‫‪ctrlCompare (331, 0) == False‬‬
‫تمرین چهارم‪ :‬در نهایت با استفاده از توابع تعریف شده قبلی‪ ،‬میتوان تابع اصلی را نوشت‪ .‬که یک رشته گرفته‬
‫و صحت آنرا نشان میدهد‪.‬‬
‫‪validate :: String -> Bool‬‬
‫چند نمونه از اجرای این تابع‪:‬‬
‫‪validate "7731689951" == False‬‬
‫‪validate "0921937660" == True‬‬
‫‪validate "" == False‬‬
‫‪validate "aa3123" == False‬‬
‫تمرین سوم عملی‬
‫زبانهای برنامهنویسی‬
‫قسمت دوم‪ :‬یافتن کلمات در جدول‬
‫درحین اینکه شما درحال نوشتن برنامه تشخیص صحت کدملی بودید‪ ،‬اقای لو حوصلهاش سر رفت و مشغول حل‬
‫کردن جدول موجود در روزنامه شد‪ .‬از آنجا که ایشان کم حوصله میباشند به سرعت پس از نصفه گذاشتن جدول‬
‫عصبانی شده و از عباس آقا خواست تا به وی کمک کند‪.‬‬
‫عباس آقا پیشنهاد نوشتن برنامهای را داد که با گرفتن یک حرف خاص‪ ،‬جایگاه آن در کلمه‪ ،‬طول کلمه و لیستی‬
‫از کلمات‪ ،‬مشخص میکند که کدام کلمهها میتواند جواب باشند‪ .‬به عبارتی‪:‬‬
‫]‪findWords :: Char -> Int -> Int -> [String] -> [String‬‬
‫کلمههای جواب‬
‫کلیه کلمههای موجود‬
‫جواب‬
‫طول کلمه‬
‫در کلمه‬
‫جایگاه حرف‬
‫حرف موردنظر‬
‫چند نمونه از اجرای این تابع‪:‬‬
‫]"‪findWords 'f' 1 2 ["fj", "haskell", "party", "leu", "words"] == ["fj‬‬
‫]"‪findWords 'r' 3 5 ["fj", "party" , “leu”, “words”] == ["party", "words‬‬
‫][ == ]"‪findWords 'h' 3 5 ["fj", "haskell", "party" , "leu", "words‬‬
‫][ == ][ ‪findWords 'h' 3 5‬‬
‫افجی پس از بررسی سوال‪ ،‬تصمیم گرفت تا برای نشان دادن تواناییهای خود در زمینه ‪ Haskell‬به دو روش‬
‫این تابع را پیادهسازی کند‪.‬‬
‫تمرین پنجم‪ :‬این تابع را با استفاده از ‪ List Comprehension‬پیادهسازی کنید‪( .‬پیادهسازی آن به صورت بازگشتی‬
‫نمرهای دربر نخواهد داشت‪).‬‬
‫تمرین ششم‪ :‬این تابع را به صورت بازگشتی پیادهسازی کرده و نام آنرا ‪ findWordsRec‬بگذارید‪.‬‬
‫تمرین سوم عملی‬
‫زبانهای برنامهنویسی‬
‫قسمت سوم‪ :‬فیلتر کردن نظرات‬
‫در ادامه طراحی سایت‪ ،‬آقای لو‪ ،‬از عباسآقا خواست تا برایش سامانه نظرات را پیادهسازی کند‪ .‬اما عباس حواسش‬
‫به فیلتر کردن کلمات نامناسب نبود و چندی نگذشت که سایت آقای لو‪ ،‬به دلیل وجود محتوای غیراخالقی فیلتر‬
‫شد‪ .‬آقای لو پس از اخراج کردن عباسآقا‪ ،‬برای رفع فیلتر کردن سایتش مجبور به حذف همه نظرات شد‪.‬‬
‫وی که عالقه فراوانی به بخش نظرات داشت‪ ،‬برای احیای دوباره آن‪ ،‬آگهی استخدام برنامه نویس در سطح دانشگاه‬
‫پخش کرد‪ .‬وی از متقاضیان خواست برنامهای ایجاد کنند که تشخیص دهد یک نظر شامل کلمات غیراخالقی‬
‫هست و یا خیر‪ .‬هادی که دنبال پول بود‪ ،‬پس از دیدن آگهی‪ ،‬بالفاصله پیش آقای لو آمد و به ازای دریافت پول‬
‫اندک مشغول کار شد‪ .‬اما وی نیز همچون عباس‪ ،‬تنها نحوه پیادهسازی را به ما گفت و رفت‪.‬‬
‫تمرین هفتم‪ :‬ابتدا تابعی مینویسیم که با گرفتن دو رشته‪ ،‬مشخص کند که آیا رشته دوم در رشته اول هست یا‬
‫خیر‪.‬‬
‫‪contains :: String -> String -> Bool‬‬
‫‪contains "comment" "" == True‬‬
‫‪contains "" "FJ" == False‬‬
‫‪contains "salambejestan" "salam" == True‬‬
‫راهنمایی‪ :‬از تابع ‪ isPrefixOf‬و ‪ tail‬میتوانید استفاده کنید‬
‫تمرین هشتم‪ :‬حال کافیست با توجه به تابع تمرین قبل‪ ،‬تابعی بنویسیم که آنرا برروی لیستی از رشتهها اجرا‬
‫کند‪( .‬با این تابع میخواهیم کامنتهای خالی را نیز پاک کنیم)‬
‫‪hasBadWords :: String -> [String] -> Bool‬‬
‫‪hasBadWords "This comment has bad words" ["bad", "awful"] == True‬‬
‫‪hasBadWords "khodafez abbas" ["bad", "saamaane"] == False‬‬
‫‪hasBadWords "" ["word"] ==True‬‬
‫‪hasBadWords "this should be banned for badwords" ["bad"] == True‬‬
‫‪hasBadWords "this should not be banned for badwords" [] == False‬‬
‫‪hasBadWords "this should be banned for badwords" [""] == True‬‬