Class: RotorMachine::Reflector

Inherits:
Object
  • Object
show all
Defined in:
lib/rotor_machine/reflector.rb

Overview

Implementation of the Reflector rotor.

A Reflector behaves similarly to a Rotor, except that the Reflector did not rotate. Its purpose is to reflect the signal path back through the rotor stack in the opposite direction, thereby ensuring that the encryption algorithm is symmetric.

The module defines constants for the standard German Enigma reflectors, but you can create a reflector with any string of 26 alphabetic characters. However, you may not repeat a given letter more than once in your string, or else the symmetry of the encipherment algorithm will be broken.

Constant Summary collapse

REFLECTOR_A =

The letter mapping for the German “A” reflector.

"EJMZALYXVBWFCRQUONTSPIKHGD".freeze
REFLECTOR_B =

The letter mapping for the German “B” reflector.

"YRUHQSLDPXNGOKMIEBFZCWVJAT".freeze
REFLECTOR_C =

The letter mapping for the German “C” reflector.

"FVPJIAOYEDRZXWGCTKUQSBNMHL".freeze
REFLECTOR_B_THIN =

The letter mapping for the German “B Thin” reflector.

"ENKQAUYWJICOPBLMDXZVFTHRGS".freeze
REFLECTOR_C_THIN =

The letter mapping for the German “C Thin” reflector.

"RDOBJNTKVEHMLFCWZAXGYIPSUQ".freeze
REFLECTOR_ETW =

The letter mapping for the German “ETW” reflector.

"ABCDEFGHIJKLMNOPQRSTUVWXYZ".freeze
ALPHABET =

A letter mapping for a passthrough reflector; also used by the RSpec tests

"ABCDEFGHIJKLMNOPQRSTUVWXYZ".freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(selected_reflector, start_position = 0) ⇒ Reflector

Initialize a new RotorMachine::Reflector.

Parameters:

  • selected_reflector (String)

    The character sequqnece for the reflector. You can use one of the class constants which define the standard German reflectors, or pass a custom sequence of 26 letters.

  • start_position (Integer) (defaults to: 0)

    The start position of the reflector. Because the reflector does not rotate, this is essentially just an additional permutation factor for the encipherment.

Raises:

  • (ArgumentError)


60
61
62
63
64
65
66
# File 'lib/rotor_machine/reflector.rb', line 60

def initialize(selected_reflector, start_position = 0)
  raise ArgumentError, "Initialization string contains duplicate letters" unless selected_reflector.is_uniq?

  @letters = selected_reflector.chars.freeze
  @alphabet = ALPHABET.chars.freeze
  @position = start_position
end

Instance Attribute Details

#positionObject

Allow querying the numeric position (ie, the initial position) of the reflector.



20
21
22
# File 'lib/rotor_machine/reflector.rb', line 20

def position
  @position
end

Instance Method Details

#==(another_reflector) ⇒ Boolean

Compare this RotorMachine::Reflector to another one.

Returns True if the configuration of the supplied RotorMachine::Reflector matches this one, false otherwise.

to this one.

Parameters:

Returns:

  • (Boolean)

    True if the configurations match, false otherwise.



154
155
156
157
# File 'lib/rotor_machine/reflector.rb', line 154

def ==(another_reflector)
  self.letters == another_reflector.letters &&
  self.position == another_reflector.position
end

#current_letterString

Get the current letter position of the rotor.

Returns:

  • (String)

    The current letter position of the rotor.



133
134
135
# File 'lib/rotor_machine/reflector.rb', line 133

def current_letter
  @letters[self.position]
end

#lettersString

Return the sequence of letters on the reflector.

Returns:

  • (String)

    The sequence of letters on the reflector.



125
126
127
# File 'lib/rotor_machine/reflector.rb', line 125

def letters
  @letters.join("")
end

#reflect(input) ⇒ String

Feed a sequence of characters through the reflector, and return the results.

Any characters which are not present on the reflector will be passed through unchanged.

Parameters:

  • input (String)

    The string of characters to encipher.

Returns:



99
100
101
102
103
104
105
106
# File 'lib/rotor_machine/reflector.rb', line 99

def reflect(input)
  input.upcase.chars.each.collect { |c|
    if @alphabet.include?(c) then
      @letters[(@alphabet.index(c) + @position) % @alphabet.length]
    else
      c
    end }.join("")
end

#reflector_kind_nameSymbol

Return the reflector kind.

If the RotorMachine::Reflector is initialized with one of the provided rotor type constants (such as REFLECTOR_A), the name of the reflector will be returned as a symbol. If not, the symbol ‘:CUSTOM` will be returned..

Returns:



116
117
118
119
# File 'lib/rotor_machine/reflector.rb', line 116

def reflector_kind_name
  self.class.constants.each { |r| return r if (@letters.join("") == self.class.const_get(r)) }
  return :CUSTOM
end

#to_sString

Return a human-readable representation of the RotorMachine::Reflector

Returns:

  • (String)

    A description of the Reflector.



141
142
143
# File 'lib/rotor_machine/reflector.rb', line 141

def to_s
  "a RotorMachine::Reflector of type '#{self.reflector_kind_name.to_s}'"
end