Life Goes On

まあまあだけど楽しんでる方です

59問目

http://projecteuler.net/index.php?section=problems&id=59
XOR関数によって暗号化された文章がある。キーには英語の小文字3文字を繰り返した文字列を用いている。この文章を復号化し(元の文章は一般的な英単語から成っている)、そのASCIIコードの和を求める。
一般的な英単語というのがどこまでを指すのか(記号をどこまで含むのか)、確かめるのに手間取りました。
元のテクストが何かというのが気になっていたのですが、複合化してみると、なるほど、これしかないなというものでした。
もしやと思ってキーの文字列も確認してみたら…ああ、やっぱりそうか。

import Data.Bits
import Data.Char
import Data.List

main = do
    cipher1 <- readFile "cipher1.txt"
    print $ sum $ euler059 $ read $ "[" ++ cipher1 ++ "]"

euler059 :: [Int] -> [Int]
euler059 message = head $ filter (all (isCommon . chr)) $
    [ zipWith xor message (cycle password) |
        password <- perm 3 [(ord 'a')..(ord 'z')] ]

isCommon :: Char -> Bool
isCommon c = isAlpha c || isAlphaNum c || isSeparator c || isPunctuation c

perm :: Eq a => Int -> [a] -> [[a]]
perm 0 _ = [[]]
perm n s = [x : xs | x <- s, xs <- perm (n - 1) (delete x s)]