我真的很喜欢Ruby,我想做得更好。如有任何意见,我们将不胜感激。
该程序提示用户输入一个字符串,该字符串是凯撒密码给定(英文)明文和范围0,25上的密钥所产生的密文。然后,该程序使用英文字符频率表执行简单的密码分析,以确定前5种最可能的移位密钥,并在这些密钥用于解密密文时显示所产生的明文。
还应该指出的是,唯一需要输入的是字母和空格,但我认为它适用于大多数标点符号。
代码:
class Cryptanalysis
def initialize
@alphabet = ('A'..'Z').to_a.join
@english_frequency = { :A => 0.080, :B => 0.015, :C => 0.030,
:D => 0.040, :E => 0.130, :F => 0.020,
:G => 0.015, :H => 0.060, :I => 0.065,
:J => 0.005, :K => 0.005, :L => 0.035,
:M => 0.030, :N => 0.070, :O => 0.080,
:P => 0.020, :Q => 0.002, :R => 0.065,
:S => 0.060, :T => 0.090, :U => 0.030,
:V => 0.010, :W => 0.015, :X => 0.005,
:Y => 0.020, :Z => 0.002 }
end
def decrypt_caesar(ciphertext, shift)
i = shift % @alphabet.size
decrypt = @alphabet
encrypt = @alphabet[i..-1] + @alphabet[0...i]
ciphertext.tr(encrypt, decrypt)
end
def analyze(ciphertext)
chars = ciphertext.gsub(/[^A-Z]/i, '').split(//)
ciphertext_frequency = character_frequency(chars)
correlation_of_frequency = Hash.new
alphabet = @alphabet.split(//)
(0..25).each { |i|
sum = 0.0
alphabet.each { |c|
e = alphabet.index(c)
sum += ciphertext_frequency[c.to_sym] * @english_frequency[alphabet[(26 + e - i) % 26].to_sym]
}
correlation_of_frequency[i] = sum
}
correlation_of_frequency.sort_by { |_, v| -v }.take(5).to_h
end
def character_frequency(chars)
frequency = Hash.new
inc = 1.0 / chars.size
@alphabet.each_char { |c| frequency[c.to_sym] = 0.0 }
chars.each { |c| frequency[c.to_sym] += inc }
frequency
end
end
crypt = Cryptanalysis.new
puts 'Enter a string to analyze'
text = gets.chomp.upcase
result = crypt.analyze(text)
puts 'Top 5 possible shifts: '
choice = 1
result.each do |k, v|
puts '%10s) Shift amount: %2s Correlation: %%%.4f Result: %s' % [choice, k, v, crypt.decrypt_caesar(text, k)]
choice += 1
end发布于 2016-02-27 06:34:11
干得好。您可以通过以下方法获得一些简单的改进:
crypt_instance.analyze的操作。重写:
module Cryptanalysis
ALPHABET = ('A'..'Z').to_a
ENGLISH_FREQUENCY = { :A => 0.080, :B => 0.015, :C => 0.030,
:D => 0.040, :E => 0.130, :F => 0.020,
:G => 0.015, :H => 0.060, :I => 0.065,
:J => 0.005, :K => 0.005, :L => 0.035,
:M => 0.030, :N => 0.070, :O => 0.080,
:P => 0.020, :Q => 0.002, :R => 0.065,
:S => 0.060, :T => 0.090, :U => 0.030,
:V => 0.010, :W => 0.015, :X => 0.005,
:Y => 0.020, :Z => 0.002 }
def self.decrypt_caesar(ciphertext, shift)
decrypt = ALPHABET
encrypt = ALPHABET.rotate(shift)
ciphertext.tr(encrypt, decrypt)
end
def self.analyze(ciphertext)
freqs = frequencies(clean(ciphertext))
(0..ALPHABET.size)
.map{|i| [i, score(freqs, i)]}
.sort_by { |x| -x[1] }
.take(5)
.to_h
end
def self.clean(text)
text.upcase.gsub(/[^A-Z]/i, '')
end
def self.score(freqs, shift)
ENGLISH_FREQUENCY
.values
.rotate(shift)
.zip(freqs.values)
.map{|x| x.first * x.last}
.reduce(:+)
end
def self.frequencies(text)
ENGLISH_FREQUENCY
.keys
.map {|k| [k.to_sym, text.count(k.to_s) / text.size.to_f]}
.to_h
end
end
text = "the quick brown fox jumps over the lazy dog"
puts 'Top 5 possible shifts: '
puts Cryptanalysis.analyze(text)https://codereview.stackexchange.com/questions/121150
复制相似问题