Project Euler 59

http://projecteuler.net/index.php?section=problems&id=59


3分割して、それぞれ最頻の数を選んで、それはスペースだとみて、キーを作る。

import Data.List

split [c] = [[c]]
split (c:cs) | c == ','  = []:(split cs)
             | otherwise = ([c] ++ s2):cs2
                    where (s2:cs2) = split cs

divide a m k | k == m    = []
divide a m k | otherwise = (f b):(divide a m (k + 1)) where
                b = zip [0..] a
                f x = map (\(_,n) -> n) (filter (\(n,_) -> mod n m == k) x)

count [] d = 0
count (x:xs) d = (if x == d then 1 else 0) + (count xs d)

decrypt a =  sum(concat (map (\(k,c) -> map (\e -> xor k e) c) (zip keys b)))
    where
        b = (divide (map read (split a)) 3 0)
        freq 128 a = []
        freq d a = (d, count a d):(freq (d + 1) a)
        max_freq b = foldr (\x y -> if snd x >= snd y then x else y) (0, 0) b
        keys = map ((xor 32) . fst . max_freq . (freq 0)) b

bin n 0 = []
bin n k = (mod n 2):(bin (div n 2) (k - 1))
xor n m = foldr (\x y -> x + 2 * y) 0
                [ mod (a + b) 2 | (a, b) <- zip (bin n 8) (bin m 8) ]

main = do
    cs <- readFile "cipher1.txt"
    print (decrypt cs)