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.


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

def initialize(selected_reflector, start_position = 0)
  @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) ⇒ Object


143
144
145
146
# File 'lib/rotor_machine/reflector.rb', line 143

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.


131
132
133
# File 'lib/rotor_machine/reflector.rb', line 131

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.


123
124
125
# File 'lib/rotor_machine/reflector.rb', line 123

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:


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

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:


114
115
116
117
# File 'lib/rotor_machine/reflector.rb', line 114

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.


139
140
141
# File 'lib/rotor_machine/reflector.rb', line 139

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