#1. 標準モジュールの利用
次の関数群を定義せよ。
なおData.Ord
、Data.List
、Data.Map
を用いて良い。
また、非負整数を受け取る関数については負数を受け取った時の挙動を考慮しなくてよい。
sortByFrequency
: リストxs
を受け取り、xs
内の要素の出現数で降順ソートしたリストを返す関数
なお、出現頻度が同じ要素については、要素自体の昇順となるようにすることinitialMap
: 文字列のリストss
を受け取り、その文字から始まる文字列のリストへのMapを返す関数
ただし、空文字列が含まれる場合はその要素を無視することinfixPalindromicNumber
: 非負整数n
を受け取り、その数を文字列として含む最小の回文数を返す関数
なお、回文数とは「逆から数字を読んでも同じ数になる数」のことをいう
###例
> :t sortByFrequency
sortByFrequency :: Ord a => [a] -> [a]
> sortByFrequency "abaacdabddddb"
"dabc"
> sortByFrequency "bbaacccc"
"cab"
> sortByFrequency ["high", "low", "middle", "high", "high", "middle"]
["high","middle","low"]
> :t initialMap
initialMap :: [String] -> Map.Map Char [String]
> initialMap ["hoge", "fuga", "hogehoge", "piyo", "", "fugapiyo"]
fromList [('f',["fugapiyo","fuga"]),('h',["hogehoge","hoge"]),('p',["piyo"])]
> :t infixPalindromicNumber
infixPalindromicNumber :: Int -> Int
> infixPalindromicNumber 0
0
> infixPalindromicNumber 12
121
> infixPalindromicNumber 21
121
> infixPalindromicNumber 765
56765
#2. バーナム暗号
ビット毎の排他的論理和は、同じ演算を2回行うと元に戻る性質を持っている。
x `xor` y `xor` y == x
これを利用し、暗号と復号に同一の鍵を用いるのが バーナム暗号 である。
今、暗号化対象となる平文を数列[1,2,3]
、暗号化鍵を[2,3,2]
とする。
リストの各要素同士の排他的論理和を取ると
1 `xor` 2 == 3
2 `xor` 3 == 1
3 `xor` 2 == 1
となり、暗号文[3,1,1]
が得られる。
復号の際には、同様に暗号化鍵との排他的論理和を取って
3 `xor` 2 == 1
1 `xor` 3 == 2
1 `xor` 2 == 3
となり、平文[1,2,3]
を得る。
暗号鍵となる文字列k
と、暗号化対象となる平文の文字列s
を受け取り、暗号文の文字列を返す関数vernam
を定義せよ。
なお、k
の長さがs
より短い場合は、k
を繰り返して使用せよ。
ビットごとの排他的論理和はData.Bits
にxor
として定義されており、これを使って良い。
ただし、Char
はBits
のインスタンスではないため、直接xor
を適用できないことに注意すること。
必要ならばData.Char
モジュールの関数を使って良い。
> :t vernam
vernam :: String -> String -> String
> vernam "\NUL" "hogefuga"
"hogefuga"
> vernam "BIGHERO6" "Hello, I am Baymax."
"\n,+$*~o\DELb(*h\a36[#1i"
> vernam "BIGHERO6" "\n,+$*~o\DELb(*h\a36[#1i"
"Hello, I am Baymax."