HW4.pdf

‫‪Haskell‬‬
‫نکات کلی‬
‫‪ ‬مهلت ارسال این تمرین تا ساعت ‪ ۹۵:۳۲‬روز ‪۷‬ام آذر ماه است‪ .‬درصورت ارسال با تاخیر به ازای هر‬
‫ساعت ‪ ٪۱‬ازنمره شما کسر خواهد شد‪.‬‬
‫‪ ‬جواب تمرینها را به آدرس ‪ [email protected]‬ارسال کنید‪ .‬برای این تمرین باید فایل‬
‫‪ HW4.hs‬که در اختیار شما داده شده است را کامل کنید و با فرمت ‪HW4_#STD1_#STD2.hs‬‬
‫ارسال کنید‪ .‬به هیچ عنوان اسم یا تایپهای مشخص داده شده را تغییر ندهید‪ .‬درصورت نیاز توابع خودتان‬
‫را به آن اضافه کنید‪ .‬عنوان ایمیل را نیز به صورت ‪ HW4_#STD1_#STD2‬بنویسید‪.‬‬
‫‪ ‬توابعی که به آنها احتماال نیاز پیدا خواهید کرد‪ ،‬در صفحه آخر‪ ،‬لیست شدهاند‪.‬‬
‫‪ ‬در نوشتن هریک از توابع ممکن است نیاز به نوشتن توابع کمکی نیز داشته باشید‪ .‬پیادهسازی توابع بیشتر‬
‫بالمانع است‪ ،‬گرچه تمامی توابع گفته شده‪ ،‬با همان نام و مشخصات توضیح داده شده‪ ،‬باید پیادهسازی‬
‫شده باشند‪ .‬عدم پیادهسازی هریک موجب کسر نمره شما خواهد شد‪.‬‬
‫‪ ‬سعی کنید کدتان باتوجه به ‪ styling guideline‬نوشته شده باشد‪.‬‬
‫‪ ‬کد شما بدون هیچ وارنینگی باید کامپایل شود‪ ( .‬به ‪ styling guideline‬مراجعه کنید‪).‬‬
‫‪ ‬تمرین در قالب گروههای دو نفره قابل انجام است‪.‬‬
‫‪ ‬با هرگونه تقلب به شدت برخورد خواهد شد‪.‬‬
‫‪ ‬هرگونه ابهام در صورت تمرین را حتما در گروه درس مطرح کنید‪ ،‬در هنگام تصحیح و یا تحویل تمارین‬
‫هیچ عذری مبنی بر گنگ بودن صورت تمرین قابل قبول نخواهد بود‪.‬‬
‫‪۱‬نوشته شده توسط عارف شفاعی با تشکر فراوان از آقای اللهوردی‪.‬‬
‫تمرین چهارم عملی‬
‫زبانهای برنامهنویسی‬
‫قسمت اول‪ :‬کدکردن پیام‬
‫پس از اینکه در تمرین قبل عباس آقا اخراج شد‪ ،‬افجی و هادی کلیه امور آقای لو را در درست گرفتند‪ .‬به دلیل‬
‫رونق کار آقای لو‪ ،‬وی شرکت گاز را تاسیس کرد‪ .‬مهندسین شرکت که میدانستند عباس ناراحت و به دنبال‬
‫انتقام گرفتن است‪ ،‬تصمیم به افزایش امنیت شرکت گرفتند‪ .‬به همین منظور روشی را برای کدکردن تمامی‬
‫پیامهای شرکت ابداع کردند‪.‬‬
‫الگوریتم استفاده شده‬
‫در روش ابداعی افجی و هادی که نامش را ‪ gazCrypt‬گذاشتند‪ ،‬مراحل زیر را برای کد کردن یک رشته باید‬
‫طی کنیم‪:‬‬
‫‪ .۱‬کلیه کاراکترهای موجود در رشته‪ ،‬به غیر از حروف انگلیسی و اعداد را از رشته حذف میکنیم‪.‬‬
‫‪ .2‬حروف انگلیسی را ‪ capitalize‬میکنیم‪.‬‬
‫‪ .3‬حروف انگلیسی را به یک مقدار ثابت (کلید) شیفت میدهیم‪.‬‬
‫برای مثال اگر رشته "!‪ "gaz‬را درنظر بگیریم‪ ،‬به ازای کلید ‪ ،۵‬کد خروجی "‪ "lfe‬میشود‪.‬‬
‫همچنین برای رمزگشایی یک رشته‪ ،‬کافی است با داشتن کلید‪ ،‬هر حرف را به همان مقدار شیفت برعکس بدهیم‪.‬‬
‫مراحل نوشتن برنامه‬
‫از آنجا که هادی دنبال پول بود و در ‪ ۵‬شرکت (عالوه بر شرکت گاز) به طور همزمان کار میکرد‪ ،‬وقتی برای‬
‫نوشتن برنامه نداشت‪ .‬افجی نیز مشغول سروکله زدن با علی برای پروژه کارشناسیاش بود‪ .‬البته وی مرام گذاشته‬
‫و نحوه نوشتن آنرا به ما در قالب چند تمرین گفت‪.‬‬
‫تمرین اول‪ :‬ابتدا تابعی را مینویسیم که با گرفتن رشتهای از اعداد‪ ،‬تعدادی از حروف اول آنرا گرفته و به انتهای‬
‫کلمه اضافه کند‪.‬‬
‫‪turn:: int -> String -> String‬‬
‫‪1‬‬
‫تمرین چهارم عملی‬
‫زبانهای برنامهنویسی‬
‫چند نمونه از اجرای این تابع‪:‬‬
‫"‪turn 2 "1234" == "3412‬‬
‫"‪turn 3 "ABCDEFG" == "DEFGABC‬‬
‫"‪turn 6 "1234" == "Exception: too large or too small‬‬
‫برای نمایش یک ‪ ،exception‬کافی است به صورت زیر عمل کنید‪:‬‬
‫"‪error "too large or too small‬‬
‫تمرین دوم‪ :‬حال با استفاده از تابع تمرین قبل‪ ،‬تابعی بنویسید که با گرفتن کلید‪ ،‬کلیه تبدیل حروف در‬
‫‪ gazCrypt‬را بدهد‪.‬‬
‫])‪KeyList :: Int -> [(Char, Char‬‬
‫برای مثال‪:‬‬
‫== ‪KeyList 5‬‬
‫)'‪[('A','F'),('B','G'),('C','H'),('D','I'),('E','J'),('F','K'),('G','L‬‬
‫)'‪,('H','M'),('I','N'),('J','O'),('K','P'),('L','Q'),('M','R'),('N','S‬‬
‫)'‪,('O','T'),('P','U'),('Q','V'),('R','W'),('S','X'),('T','Y'),('U','Z‬‬
‫])'‪,('V','A'),('W','B'),('X','C'),('Y','D'),('Z','E‬‬
‫همه حروف باید بزرگ باشند و تکراری وجود نداشته باشد‪ .‬برای نوشتن این تمرین ابتدا باید حروف الفبای انگلیسی‬
‫را تعریف کنید‪.‬‬
‫تمرین سوم‪ :‬حال که لیست حروف معادل را داریم‪ ،‬تابعی بنویسید که با گرفتن یک حرف و لیستی از تبدیل‬
‫حروف‪ ،‬حرف معادل آنرا بدهد‪ .‬درصورتی که این حرف در لیست داده شده وجود نداشت‪ ،‬خود آن حرف را‬
‫بازگردانید‪.‬‬
‫‪getValue :: Char -> [(Char, Char)] -> Char‬‬
‫چند نمونه از اجرای این تابع‪:‬‬
‫'‪getValue 'B' [('C','H'), ('W','B'),('B','G')] == 'G‬‬
‫'‪getValue '4' [('C','H'), ('W','B'),('B','G')] == '4‬‬
‫'‪getValue 'G' [('C','H'), ('W','B'),('B','G')] == 'A‬‬
‫‪2‬‬
‫تمرین چهارم عملی‬
‫زبانهای برنامهنویسی‬
‫تمرین چهارم‪ :‬با استفاده از توابع تمرین ‪ 2‬و‪ ،3‬تابعی بنویسید که با گرفتن کلید و یک حرف‪ ،‬معادل آنرا بدهد‪.‬‬
‫‪shift:: Int -> Char -> Char‬‬
‫چند نمونه از اجرای این تابع‪:‬‬
‫'‪shift 5 'B' == 'G‬‬
‫'‪shift 7 'Q' == 'X‬‬
‫تمرین پنجم‪ :‬تابعی بنویسید که با گرفتن یک رشته‪ ،‬کلیه کاراکترهای غیر از عدد و حروف انگلیسی را حذف‬
‫کرده و حروف انگلیسی را بزرگ کند‪.‬‬
‫‪capitalize:: String -> String‬‬
‫چند نمونه از اجرای این تابع‪:‬‬
‫"‪capitalize "This is confidential!!1" == "THISISCONFIDENTIAL1‬‬
‫"‪capitalize "abbas?!hah??" == "ABBASHAH‬‬
‫تمرین ششم‪ :‬حال میتوانیم با استفاده از توابع قبلی‪ encodeGazCrypt ،‬را بنویسیم‪ .‬ابتدا باید تابع تمرین ‪۵‬‬
‫را بر روی حروف صدا زده و سپس آنها را ‪ shift‬دهید‪.‬‬
‫‪encodeGazCrypt:: Int -> String -> String‬‬
‫چند نمونه از اجرای این تابع‪:‬‬
‫"‪encodeGazCrypt 3 "This is hidden!!1" == "WKLVLVKLGGHQ1‬‬
‫"‪encodeGazCrypt 25 "abbas?!hah??" == "ZAAZRGZG‬‬
‫‪3‬‬
‫تمرین چهارم عملی‬
‫زبانهای برنامهنویسی‬
‫قسمت دوم‪ :‬رمزگشایی پیامها‬
‫بعد از رمز کردن پیامها‪ ،‬مهندسین عزیز شرکت آقای لو به انجام کارهای شخصی پرداختند‪ .‬بجستان که تازه از‬
‫بجستان برگشته بود و از اخراج عباس خبر نداشت‪ ،‬برای دیدن دوستش به شرکت گاز رفت‪ .‬آقای لو درهمین حین‬
‫به صندوق پیامهای شرکت سر زد و متوجه شد که همه پیامها کد شدهاند و پنیک کرد‪ .‬او که میدانست بجستان‬
‫دانش اندکی از ‪ Haskell‬دارد‪ ،‬از وی خواست تا برایش پیامها را رمزگشایی کند‪ .‬وی پس از چانه زدن فراوان‪ ،‬به‬
‫ازای پول زیاد‪ ،‬حاضر به توضیح دادن نحوه نوشتن برنامه رمز گشایی به ما شد‪.‬‬
‫آقای لو فکر میکرد از آنجا که بجستان کلید استفاده شده در رمزگشایی را ندارد‪ ،‬نمیتواند این پیامها را رمزگشایی‬
‫کند‪.‬‬
‫تمرین هفتم‪ :‬ابتدا تابعی را بنویسید که لیستی شامل تاپلهایی از دو حرف انگلیسی گرفته و آنها را برعکس‬
‫کند‪ .‬در ادامه از این تابع برای برگرداندن معادل حروف انگلیسی در ‪ gazCrypt‬استفاده خواهیم کرد‪.‬‬
‫])‪getReverseValue:: [(Char, Char)] -> [(Char, Char‬‬
‫برای مثال‪:‬‬
‫])'‪getReverseValue [('A','G'),('B','H'),('C','I‬‬
‫])'‪== [('G','A'), ('H','B'), ('I ','C‬‬
‫تمرین هشتم‪ :‬حال با استفاده از توابع تمرینهای قبل‪ ،‬ابتدا ‪ decodeGazCryptChar‬را پیادهسازی کنید که‬
‫با گرفتن کلید و یک حرف‪ ،‬آنرا رمزگشایی میکند سپس با استفاده از آن تابعی برای رمزگشایی یک رشته بنویسید‪.‬‬
‫‪decodeGazCryptChar :: Int -> Char -> Char‬‬
‫‪decodeGazCrypt :: Int -> String -> String‬‬
‫"‪decodeGazCrypt 25 "ZAAZRGZG" == "ABBASHAH‬‬
‫‪4‬‬
‫تمرین چهارم عملی‬
‫زبانهای برنامهنویسی‬
‫قسمت سوم‪ :‬شکستن رمز‬
‫بجستان پس از گرفتن پول خود از آقای لو‪ ،‬راهی خوابگاه شد‪ .‬وی پس از تالش فراوان عباس آقا را درحال بازی‬
‫دوتا‪ 2‬دید‪ .‬بجستان قضیه اخراج شدن عباس را از وی پرسید و او نیز با خشم فراوان شروع به بدگویی از آقای لو‬
‫کرد و گفت که چند ماهی است که درحال یافتن راهی برای انتقام است‪ .‬بجستان داستان رمزکردن پیامها را به‬
‫عباس گفت و به وی گفت میتواند راهی برای شکستن این رمز ارائه دهد‪.‬‬
‫تمرین نهم‪ :‬برای بازگشایی رمز‪ ،‬از ‪ brute-force attack‬استفاده میکنیم‪ .‬به این صورت که تابعی مینویسیم‬
‫که رشته پیام رمزشده را گرفته و با هر ‪ 2۲‬کلید آنرا رمز گشایی میکنیم‪ .‬از آنجا که آقای لو در پیامهای خود از‬
‫واژه ‪ THE‬و ‪ AND‬زیاد استفاده میکند‪ ،‬رشتههایی را برمیگردانیم که حداقل یکی از این لغتها را دارند‪ .‬همچنین‬
‫کلید آنها را نیز برمیگردانیم‪.‬‬
‫])‪candidateMessages :: String -> [(Int, String‬‬
‫چند نمونه از اجرای این تابع‪:‬‬
‫== "‪candidateMessages "DGGADBCOOCZYMJHZYVMTOJOCZHVS‬‬
‫‪[(5,"YBBVYWXJJXUTHECUTQHOJEJXUCQN"),‬‬
‫‪(14,"PSSMPNOAAOLKYVTLKHYFAVAOLTHE"),‬‬
‫])"‪(21,"ILLFIGHTTHEDROMEDARYTOTHEMAX‬‬
‫برای این تمرین نیاز به استفاده از تابع ‪ contains‬که در تمرین قبل پیادهسازی کردید‪ ،‬خواهید داشت‪.‬‬
‫‪5‬‬
‫تمرین چهارم عملی‬
‫زبانهای برنامهنویسی‬
‫قسمت چهارم‪ :‬بهتر کردن رمز‬
‫مهندسین شرکت پس از بازگشت به شرکت متوجه اشتباه آقای لو شدند و تصمیم به بهتر کردن نحوه رمز گذاری‬
‫پیامها کردند‪ .‬برای اینکار‪ ،‬آنها تصمیم گرفتند به شیوه زیر عمل کنند‪:‬‬
‫ابتدا با استفاده از ‪ encodeGazCrypt‬پیام را رمز میکنیم‪.‬‬
‫‪ .۱‬رشته بدست آمده را تبدیل به لیستی از رشتههای به طول ‪ ۴‬میکنیم‪( .‬درصورتی که رشته آخر کمتر از‬
‫‪۴‬حرف شد‪ ،‬به انتهای آن ’‪ ‘z‬اضافه میکنیم‪(.‬‬
‫‪ .2‬بر روی لیست بدست آمده تابع ‪ transpose‬از کتابخانه ‪ Data.list‬را صدا میزنیم‪ .‬این تابع سطرها و‬
‫ستونهای یک لیست را جابهجا میکند‪.‬‬
‫‪ .3‬سپس لیست بدست آمده را کنار هم قرار داده و یک رشته رمز شده بدست میآوریم‪.‬‬
‫تمرین دهم‪ :‬برای پیاده سازی روش باال‪ ،‬ابتدا تابعی را تعریف کنید که رشتهای از حروف گرفته و آنرا به لیستی‬
‫از رشتههای به طول ‪ ۴‬تبدیل میکند‪ ( .‬درصورتی که عضو آخر رشتهای با طول کمتر از ‪ ۴‬بود‪ ،‬به انتهای آن به‬
‫تعدادی که طولش ‪ ۴‬شود‪ ‘z’ ،‬اضافه کنید‪).‬‬
‫]‪splitString :: String -> [String‬‬
‫چند نمونه از اجرای این تابع‪:‬‬
‫]"‪splitString "SALAM CHE KHABAR?"== ["SALA","M CH","E KH","ABAR","?ZZZ‬‬
‫]"‪splitString "" == ["ZZZZ‬‬
‫تمرین یازدهم‪ :‬حال تابعی پیادهسازی کنید که ابتدا ‪ encodeGazCrypt‬را صدا زده و سپس خروجی آنرا به‬
‫‪ splitString‬بدهید و در نهایت این لیست از رشتهها را به یک رشته تبدیل کنید‪.‬‬
‫‪encodeGazCryptAdv :: Int -> String -> String‬‬
‫"‪encodeGazCryptAdv 3 "This is hidden!!1" == "WLG1KVGZLKHZVLQZ‬‬
‫"‪encodeGazCryptAdv 25 "abbas?!hah??" == "ZRAGAZZG‬‬
‫‪6‬‬
‫تمرین چهارم عملی‬
‫زبانهای برنامهنویسی‬
‫لیست توابع‬
‫ این لیست‬.‫ این توابع کافی میباشند و نیاز به استفاده از توابع دیگری نخواهید داشت‬،‫برای نوشتن کلیه قسمتها‬
.‫تنها برای کمک به شما و صرفه جویی در وقتتان است‬
‫تابع‬
‫نحوه استفاده‬
‫مثال‬
isAlpha
isAlpha :: Char -> Bool
isAlpha ’3’ == False
isAlpha ’x’ == True
isDigit
isDigit :: Char -> Bool
isDigit ’3’ == True
isDigit ’x’ == False
isUpper
isUpper :: Char -> Bool
isUpper ’X’ == True
isUpper ’x’ == False
isLower
isLower :: Char -> Bool
isLower ’3’ == False
isLower ’x’ == True
toUpper
toUpper :: Char -> Char
toUpper ’x’ == ’X’
toUpper ’3’ == ’3’
isPrefixOf
isPrefixOf :: String -> String -> Bool
isPrefixOf “has”
“hasit” = True
Error
error :: String -> a
-
drop
drop :: Int -> [a] -> [a]
drop 6 “Hello world!”
== “world!”
Take
take :: Int -> [a] -> [a]
take 5 “hello world!”
= “hello”
head
head :: [a] -> a
head [1,2] = 1
length
length :: [a] -> Int
length [1,2] = 2
zip
zip :: [a] -> [b] -> [(a, b)]
-
concat
concat :: [[a]] -> [a]
concat [“sa”, “lam”]
= “salam”
replicate
replicate :: Int -> a -> [a]
replicate 3 “Z” =
[“Z”, “Z”, “Z”]
repeat
repeat :: a -> [a]
repeat “Z” = infinite
list of repeated “Z”
(i
7