Skip to content

Instantly share code, notes, and snippets.

@avescodes
Created October 21, 2009 03:30
Show Gist options
  • Save avescodes/214831 to your computer and use it in GitHub Desktop.
Save avescodes/214831 to your computer and use it in GitHub Desktop.
#!/usr/bin/env ruby
# Open up the String class and give it an alpha? check
class String
def alpha?
self =~ /^[A-Za-z]$/
end
end
# Run across each alpha character in string and tally letter occurances
# This returns something like [ 1, 2, <24 0's>] for "ABB"
def frequencies(string)
prob = string.upcase.each_char.inject(Array.new(26,0)) do |array,char|
if char.alpha?
array[char[0] - ?A] += 1
end
array
end
end
# This method defines a new enumerator. One can simply all every_x_letters
# on a piece of text and in the block expect to be passed sets of every X
# letters.
#
# Eg. "ABCABCABC", 3 would yield
# "AAA"
# "BBB"
# "CCC"
#
# Then method returns an array of results
def every_x_letters(string,m)
string.
split(/\s|\n/).
map {|word| word.split('')}.
flatten.
each_slice(m).to_a.
map {|slice| slice << nil until slice.length == m; slice }.
transpose.map(&:compact).
map(&:join).map do |every_x|
yield every_x
end
end
# Calculate the index of coincidence for a string given key length m
def index_of_coincidence(string,m=1)
every_x_letters(string,m) do |substring|
frequency = frequencies(substring)
total = frequency.inject(&:+).to_f
i_o_c = 0.upto(25).inject(0) do |ioc, i|
ioc + frequency[i] * (frequency[i] - 1)
end
i_o_c /= total * (total - 1)
end
end
# Drive the program
if __FILE__ == $0
begin
string = File.read(ARGV.shift)
m = ARGV.length != 0 ? ARGV.shift.to_i : 1
i_o_c = index_of_coincidence(string,m)
puts "I_c(x) = #{i_o_c.inspect}"
rescue
puts "ruby IOC.rb <text file> <key length (m)>"
end
end
#!/usr/bin/env ruby
require 'IOC.rb'
# English Language Frequencies - Page 26 of book
ELF = [82,15,28,43,127,22,20,61,70,2,8,40,24,67,75,19,1,60,63,91,28,10,23,1,20,1].map {|p| p / 1000.0}
# Method to calculate the M_g table for a given string and key length
# Present version prints the actual table instead of returning a hash
def m_g_table(string,m)
s = 0
every_x_letters(string,m) do |subtext|
printf "Subtext #{s+1}: "
f = frequencies(subtext)
n = f.inject(&:+).to_f
# Formula Summation
(0..25).to_a.each do |g|
# For each value of G
m_g = (0..25).inject(0) do |sum,i|
sum + (ELF[i]*f[(i+g)%26])/n
end
printf("%0.4f ",m_g+0.00005)
end
printf "\n\n"
s += 1
end
end
# Vroom, vroom
if __FILE__ == $0
begin
cipher = File.read(ARGV.shift)
m = ARGV.shift.to_i
m_g_table(cipher,m)
rescue
puts "ruby M_g.rb <text file> <key length (m)>"
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment