Skip to content

Instantly share code, notes, and snippets.

@tmaeda
Created January 28, 2010 15:58
Show Gist options
  • Save tmaeda/288860 to your computer and use it in GitHub Desktop.
Save tmaeda/288860 to your computer and use it in GitHub Desktop.
-- プログラミングHaskell 5章
import Data.Char
let2int :: Char -> Int
let2int c = ord c - ord 'a'
int2let :: Int -> Char
int2let n = chr (ord 'a' + n)
shift :: Int -> Char -> Char
shift n c | isLower c = int2let ((let2int c + n) `mod` 26)
| otherwise = c
encode :: Int -> String -> String
encode n xs = [shift n x | x <- xs]
positions :: Eq a => a -> [a] -> [Int]
positions x xs = [i | (x', i) <- zip xs [0..n], x == x']
where n = length xs - 1
lowers :: String -> Int
lowers xs = length [x | x <- xs, isLower x]
count :: Char -> String -> Int
count x xs = length [x' | x' <- xs, x == x']
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]
percent :: Int -> Int -> Float
percent n m = (fromIntegral n / fromIntegral m) * 100
freqs :: String -> [Float]
freqs xs = [percent (count x xs) n | x <- ['a'..'z']]
where n = lowers 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
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
require 'rubygems'
require 'activesupport'
def let2int(c)
c.ord - ?a
end
def int2let(n)
('a'.ord + n).chr
end
def shift(n, c)
/[a-z]/ =~ c ? int2let(let2int(c) + n) % 26 : c
end
def encode(n, str)
str.chars.map{|c| shift(n,c)}.join
end
def positions(x, xs)
xs.zip((0..xs.size-1).to_a).select{|x_, i| x_ == x }.map{|x_, i| i}
end
class String
def lowers
self.count('a-z')
end
end
$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]
def percent(n, m)
n.to_f / m.to_f * 100
end
def freqs(str)
('a'..'z').to_a.map do |c|
percent(str.count(c), str.lowers)
end
end
def chisqr(os, es)
os.zip(es).map{|o,e| ((o - e) ** 2) / e.to_f}.sum
end
def rotate(n, xs)
return xs if n < 1
xs[n..-1] + xs[0..n-1]
end
def crack(str)
table_ = freqs(str)
chitab = (0..25).to_a.map{|n| chisqr(rotate(n, table_), $table)}
factor = positions(chitab.min, chitab)[0]
encode(-factor, str)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment