プログラミングHaskell 第5章の練習問題

import Data.Char

--2乗の和
sumsqr :: Int -> Int
sumsqr n = sum [i^2 | i <- [1..n]] 

--ある要素のみからなるリストを生成する
myReplicate :: Int -> a -> [a]
myReplicate n x = [x | i <- [1..n]]

--ピタゴラス数のリストを生成する
pyths :: Int -> [(Int, Int, Int)]
pyths n = [(x, y, z) | x <- [1..n], y <- [1..n], z <- [1..n], x^2 + y^2 == z^2] 

--自分自身以外の約数のリストを生成する
factors :: Int -> [Int]
factors n = [i | i <- [1..n-1], n `mod` i == 0]

--完全数のリストを生成する
perfects :: Int -> [Int]
perfects n = [i | i <- [1..n], sum (factors i) == i] 

--問題5
prob5 :: [a] -> [a] -> [(a, a)]
prob5 xs1 xs2 = concat [[(i, j) | j <- xs2] | i <- xs1]

--指定キーの値のリストを返す
find :: Eq a => a -> [(a, b)] -> [b]
find a b = [j | (i, j) <- b, i == a]

--リスト内の位置のリストを返す
positions :: Eq a => a -> [a] -> [Int]
positions a xs = find a (zip xs [0..n-1])
    where n = length xs -1 

--内積
scalarproduct :: [Int] -> [Int] -> Int
scalarproduct xs ys = sum [x * y | (x, y) <- zip xs ys]

--指定文字の個数を数える関数
count :: Char -> String -> Int
count c xs = length [c'| c' <- xs, toLower c' == c]

--文字を整数に変換する関数
let2int :: Char -> Int
let2int c = ord (toLower c) - ord 'a'

--整数を文字に変換する関数
int2let :: Int -> Char
int2let n = chr (ord 'a' + n)

--文字をシフト数だけずらす関数
shift :: Int -> Char -> Char
shift n c  |isAlpha c = int2let ((let2int c + n) `mod` 26)
           |otherwise = c

--シーザー暗号化する関数
encode :: Int -> String -> String
encode n xs = [shift n c | c <- xs]

--文字列中の文字の出現頻度を返す関数
persent :: Int -> Int -> Float
persent n m = (fromIntegral n / fromIntegral m) * 100

freqs :: String -> [Float]
freqs xs = [persent (count c xs) n | c <- ['a'..'z']]
           where n = length xs

--カイ二乗検定
chisqr :: [Float] -> [Float] -> Float
chisqr os es = sum [((o - e)^2) / e | (o, e) <- zip os es]

--リストの要素を左に回転させる関数
rotate :: Int -> [a] -> [a]
rotate n xs = drop n xs ++ take n xs

--アルファベットの出現頻度
table :: [Float]
table = [8.2, 1.5, 2.8, 4.3, 12.7, 2.2, 2.0, 6.1, 7.0, 0.2, 0.8, 4.0, 2.4, 6.7, 7.5, 1.9, 0.1, 6.0, 6.3, 9.1, 2.8, 1.0, 2.4, 0.2, 2.0, 0.1]

--シーザー暗号を復号する関数
crack :: String -> String
crack xs = encode (-factor) xs
    where
        factor = head (positions (minimum chitab) chitab)
        chitab = [chisqr (rotate n table') table | n <- [0..25]]
        table' = freqs xs