Class: EnigmaMachine

Inherits:
Object
  • Object
show all
Defined in:
lib/enigma_machine.rb,
lib/enigma_machine/rotor.rb,
lib/enigma_machine/version.rb,
lib/enigma_machine/plugboard.rb,
lib/enigma_machine/reflector.rb

Defined Under Namespace

Classes: ConfigurationError, Plugboard, Reflector, Rotor

Constant Summary collapse

ALPHABET =
('A'..'Z').to_a
VERSION =
"0.0.2"

Instance Method Summary collapse

Constructor Details

#initialize(config) ⇒ EnigmaMachine

Constructs an enigma machine with given reflector, rotors and plugboard settings.

Examples:

You can use the standard reflectors and rotors:

EnigmaMachine.new(
  :reflector => :B,
  :rotors => [[:i, 10], [:ii, 14], [:iii, 21]],
  :plug_pairs => %w(AP BR CM FZ GJ IL NT OV QS WX)
)

Or you can use custom reflector and rotor configurations:

EnigmaMachine.new(
  :reflector => %w(AF BV CP DJ EI GO HY KR LZ MX NW TQ SU),
  :rotors => [
    ['BDFHJLCPRTXVZNYEIWGAKMUSQO_V', 10],
    ['JPGVOUMFYQBENHZRDKASXLICTW_MZ', 14],
    ['ABCDEFGHIJKLMNOPQRSTUVWXYZ_AHT', 21]
  ],
  :plug_pairs => %w(AP BR CM FZ GJ IL NT OV QS WX)
)

When specifying a custom rotor, the letters after the _ indicate the notch positions.

Parameters:

  • config (Hash)

    A Hash of configuration params

Options Hash (config):

  • :reflector (Symbol, Array<String>)

    Which reflector to use. Reference one of the standard ones by Symbol, or pass in an array of letter pairs for a custom configuration.

  • :rotors (Array<Array>)

    Array of details for 3 or more rotors. Specified from left to right. Each one is specified as a tuple of the rotor spec, and ring setting. The rotor_spec can be one of the standard rotors referenced by Symbol, or a custom rotor described by a config string (see Examples).

  • :plug_pairs (Array<String>)

    an Optional array of letter pairs specifying the plugboard configuration. If omitted, no plugboard substitutions will be performed.

Raises:



45
46
47
48
49
50
51
52
# File 'lib/enigma_machine.rb', line 45

def initialize(config)
  @reflector = Reflector.new config[:reflector]
  @rotors = []
  config[:rotors].inject(@reflector) do |previous, rotor_config|
    Rotor.new(*rotor_config, previous).tap {|r| @rotors << r }
  end
  @plugboard = Plugboard.new(config[:plug_pairs] || [], @rotors.last)
end

Instance Method Details

#press_key(letter) ⇒ String

Simulates pressing a given key on the machine keyboard.

Advances the rotors, and then translates the letter

Parameters:

  • letter (String)

    the letter to be translated

Returns:

  • (String)

    the translated letter



72
73
74
75
# File 'lib/enigma_machine.rb', line 72

def press_key(letter)
  advance_rotors
  @plugboard.translate(letter)
end

#set_rotors(*positions) ⇒ void

This method returns an undefined value.

Set the rotors to the given positions.

Pass in Positions for the rotors from left to right

Parameters:

  • positions (List<String>)

    the positions to set the rotors to



60
61
62
63
64
# File 'lib/enigma_machine.rb', line 60

def set_rotors(*positions)
  positions.each_with_index do |position, i|
    @rotors[i].position = position
  end
end

#translate(message) ⇒ String

Translates the given message using the current settings

This will pass through space and - unmodified, and discard any other non-alpha characters.

Parameters:

  • message (String)

    the message to be translated

Returns:

  • (String)

    the translated message



83
84
85
86
87
88
89
90
91
92
# File 'lib/enigma_machine.rb', line 83

def translate(message)
  message.upcase.each_char.map do |letter|
    case letter
    when /[A-Z]/
      press_key(letter)
    when /[ -]/
      letter
    end
  end.join
end