Problem 59

import Prelude
import Data.List
import Data.Char
toBin =reverse. unfoldr f
where f  = Nothing
f n =let (q,r) = divMod n 2 in Just(r,q)
toDigit = foldl1 f
where f a b = 2*a+b
xor ::Int->Int->Int
xor x y | len == = toDigit.zipWith xor' (toBin x) $toBin y
| len >  = toDigit.zipWith xor' (toBin x) $replicate len  ++ toBin y
| len <  = toDigit.zipWith xor' (toBin y) $replicate (-len) ++ toBin x
where len = (length.toBin)x - (length.toBin)y
xor' a b = if a == b then  else 1
decode xs key = map chr.zipWith xor xs .cycle .map ord $key
findKey xs = find (g.decode xs) [[a,b,c]|a<-keys,b<-keys,c<-keys]
where keys = "abcdefghijklmopqrstuvwxyz"
g ys =all (flip isInfixOf ys)["and ","is "]
main = do f <-readFile "cipher1.txt"
let plain = read $"["++f++"]" ::[Int]
--          print.findKey$plain
putStrLn.show.sum.map ord.flip decode "god"$ plain

鍵があれってのがいいね。始めは空白を考慮に入れていなかったので、鍵がなかなか見つからなかった。

Problem 60

import Number
import Control.Monad
lim = 10000
concatPrime 1 = map return .takeWhile(<lim) $ primes
concatPrime (n+1)=do
ps <- concatPrime n
q<-takeWhile(<lim).dropWhile(<=(last ps))$primes
guard.all (isPrime.read) $map (show q++) (map show ps) ++map (++show q) (map show ps)
return$q:ps
main = print.sum.head.concatPrime$5

探索範囲をサボっているし、最小性のチェックを行っていないが、まあ、あっているでしょう・。

Problem 58

import Data.List
import Number
import Data.Maybe
spiral' s = take 4.tail.iterate (+s)
spiral = [1]:[spiral' ((+1).floor.sqrt.fromIntegral$i)i|i<-map last spiral]
p058 =g.floor.fst.fromJust.find((<0.1).uncurry (flip (/))).tail. zip [realToFrac$1+4*n|n<-[..]] .scanl1 (+).map (realToFrac.length.filter isPrime)$spiral
where g a = div (a-1) 2 + 1
main = print p058

なんかすごく長くなった。