annotate enigma/plugboard.h @ 9:7362965f53b1

Added tests for the hill climbing functions in the plugboard class.
author Brian Neal <bgneal@gmail.com>
date Fri, 29 Jun 2012 21:19:00 -0500
parents f4e25e6b76c3
children 232dbe7a3fe0
rev   line source
bgneal@3 1 #ifndef CPP_ENIGMA_PLUGBOARD_H
bgneal@3 2 #define CPP_ENIGMA_PLUGBOARD_H
bgneal@3 3 // Copyright (C) 2012 by Brian Neal.
bgneal@3 4 // This file is part of Cpp-Enigma, the Enigma Machine simulation.
bgneal@3 5 // Cpp-Enigma is released under the MIT License (see License.txt).
bgneal@3 6 //
bgneal@3 7 // plugboard.h - This file contains the plugboard class.
bgneal@3 8
bgneal@3 9 #include <vector>
bgneal@3 10 #include <utility>
bgneal@3 11 #include <string>
bgneal@3 12 #include <cstddef>
bgneal@3 13 #include "enigma_types.h"
bgneal@3 14
bgneal@3 15 namespace enigma
bgneal@3 16 {
bgneal@3 17 class plugboard_error : public enigma_error
bgneal@3 18 {
bgneal@3 19 public:
bgneal@3 20 explicit plugboard_error(const std::string& what_arg)
bgneal@3 21 : enigma_error(what_arg)
bgneal@3 22 {}
bgneal@3 23 };
bgneal@3 24
bgneal@3 25 // The plugboard allows the operator to swap letters before and after the
bgneal@3 26 // entry wheel. This is accomplished by connecting cables between pairs of
bgneal@3 27 // plugs that are marked with letters (Heer & Luftwaffe models) or numbers
bgneal@3 28 // (Kriegsmarine). Ten cables were issued with each machine; thus up to 10 of
bgneal@3 29 // these swappings could be used as part of a machine setup.
bgneal@3 30
bgneal@3 31 // Each cable swaps both the input and output signals. Thus if A is connected
bgneal@3 32 // to B, A crosses to B in the keyboard to entry wheel direction and also in
bgneal@3 33 // the reverse entry wheel to lamp direction.
bgneal@3 34
bgneal@3 35 class plugboard
bgneal@3 36 {
bgneal@3 37 public:
bgneal@3 38 const static std::size_t max_pairs = 10;
bgneal@3 39
bgneal@3 40 typedef std::vector<std::pair<int, int>> pair_vector;
bgneal@3 41
bgneal@3 42 // Construct a plugboard with no connections:
bgneal@3 43 plugboard();
bgneal@3 44
bgneal@3 45 // Construct from a vector of integer pairs that describe the
bgneal@3 46 // connections. Each integer must be between [0-25], and the
bgneal@3 47 // vector can have no more than max_pairs pairs. Each plug should
bgneal@3 48 // be present at most once. A plugboard_error will be thrown if
bgneal@3 49 // the pair_vector is invalid.
bgneal@3 50
bgneal@3 51 explicit plugboard(const pair_vector& pairs);
bgneal@3 52
bgneal@3 53 // Configure the plugboard according to a settings string as you may
bgneal@3 54 // find on a key sheet.
bgneal@3 55 //
bgneal@3 56 // Two syntaxes are supported, the Heer/Luftwaffe and Kriegsmarine styles:
bgneal@3 57 //
bgneal@3 58 // In the Heer syntax, the settings are given as a string of
bgneal@3 59 // alphabetic pairs. For example: 'PO ML IU KJ NH YT GB VF RE DC'
bgneal@3 60 //
bgneal@3 61 // In the Kriegsmarine syntax, the settings are given as a string of number
bgneal@3 62 // pairs, separated by a '/'. Note that the numbering uses 1-26, inclusive.
bgneal@3 63 // For example: '18/26 17/4 21/6 3/16 19/14 22/7 8/1 12/25 5/9 10/15'
bgneal@3 64 //
bgneal@3 65 // To specify no plugboard connections, settings can be an empty string.
bgneal@3 66 //
bgneal@3 67 // A PlugboardError will be raised if the settings string is invalid, or if
bgneal@3 68 // it contains more than max_pairs pairs. Each plug should be present at
bgneal@3 69 // most once in the settings string.
bgneal@3 70
bgneal@3 71 explicit plugboard(const std::string& settings);
bgneal@3 72
bgneal@3 73 // Return the current settings as a vector of pairs:
bgneal@3 74 pair_vector get_pairs() const;
bgneal@3 75
bgneal@3 76 // Return the current settings as a string in Heer (army) format:
bgneal@3 77 std::string army_str() const;
bgneal@3 78
bgneal@3 79 // Return the current settings as a string in Kriegsmarine (navy) format:
bgneal@3 80 std::string navy_str() const;
bgneal@3 81
bgneal@3 82 // Simulate a signal entering the plugboard on wire n, where n must be
bgneal@3 83 // an integer between 0 and 25.
bgneal@3 84 //
bgneal@3 85 // Returns the wire number of the output signal (0-25).
bgneal@3 86 //
bgneal@3 87 // Note that since the plugboard always crosses pairs of wires, it doesn't
bgneal@3 88 // matter what direction (keyboard -> entry wheel or vice versa) the signal
bgneal@3 89 // is coming from.
bgneal@3 90
bgneal@3 91 int signal(int n) const
bgneal@3 92 {
bgneal@3 93 return wiring_map[n];
bgneal@3 94 }
bgneal@3 95
bgneal@3 96 //
bgneal@3 97 // Functions to support hill-climbing:
bgneal@3 98 //
bgneal@3 99
bgneal@3 100 // Return the internal state of the wiring:
bgneal@3 101 alpha_int_array get_wiring() const
bgneal@3 102 {
bgneal@3 103 return wiring_map;
bgneal@3 104 }
bgneal@3 105
bgneal@3 106 // Sets the internal state of the wiring:
bgneal@3 107 void set_wiring(const alpha_int_array& wiring)
bgneal@3 108 {
bgneal@3 109 wiring_map = wiring;
bgneal@3 110 }
bgneal@3 111
bgneal@3 112 // Returns true if connection n has a cable attached to it.
bgneal@3 113 // 0 <= n < 26
bgneal@3 114 bool is_wired(int n) const
bgneal@3 115 {
bgneal@3 116 return wiring_map[n] != n;
bgneal@3 117 }
bgneal@3 118
bgneal@3 119 // Returns true if connection n has no cable attached to it.
bgneal@3 120 // 0 <= n < 26
bgneal@3 121 bool is_free(int n) const
bgneal@3 122 {
bgneal@3 123 return wiring_map[n] == n;
bgneal@3 124 }
bgneal@3 125
bgneal@3 126 // Removes cable from plug number n [0-25].
bgneal@3 127 void disconnect(int n)
bgneal@3 128 {
bgneal@3 129 const int x = wiring_map[n];
bgneal@3 130 wiring_map[x] = x;
bgneal@3 131 wiring_map[n] = n;
bgneal@3 132 }
bgneal@3 133
bgneal@3 134 // Connects plug x to plug y, removing any existing connection first.
bgneal@3 135 // x & y must be in [0-25].
bgneal@3 136 void connect(int x, int y)
bgneal@3 137 {
bgneal@3 138 // disconnect any existing connections
bgneal@3 139 const int m = wiring_map[x];
bgneal@3 140 const int n = wiring_map[y];
bgneal@3 141 wiring_map[m] = m;
bgneal@3 142 wiring_map[n] = n;
bgneal@3 143
bgneal@3 144 wiring_map[x] = y;
bgneal@3 145 wiring_map[y] = x;
bgneal@3 146 }
bgneal@3 147
bgneal@3 148 // Returns true if plug x is connected to plug y.
bgneal@3 149 // x & y must be in [0-25].
bgneal@3 150 bool is_connected(int x, int y)
bgneal@3 151 {
bgneal@3 152 return wiring_map[x] == y && wiring_map[y] == x;
bgneal@3 153 }
bgneal@3 154
bgneal@3 155 private:
bgneal@3 156 alpha_int_array wiring_map;
bgneal@3 157
bgneal@3 158 // common constructor code:
bgneal@3 159 void construct_wiring(const pair_vector& pairs);
bgneal@3 160 };
bgneal@3 161
bgneal@3 162
bgneal@3 163 // This class can be used to save & restore the state of a plugboard
bgneal@3 164 // in RAII style:
bgneal@3 165
bgneal@3 166 class plugboard_state_saver
bgneal@3 167 {
bgneal@3 168 public:
bgneal@3 169 explicit plugboard_state_saver(plugboard& pb)
bgneal@3 170 : pb(pb)
bgneal@3 171 {
bgneal@3 172 state = pb.get_wiring();
bgneal@3 173 }
bgneal@3 174
bgneal@3 175 ~plugboard_state_saver()
bgneal@3 176 {
bgneal@3 177 pb.set_wiring(state);
bgneal@3 178 }
bgneal@3 179
bgneal@3 180 // disable copying & assignment
bgneal@3 181 plugboard_state_saver(const plugboard_state_saver&) = delete;
bgneal@3 182 plugboard_state_saver& operator=(const plugboard_state_saver&) = delete;
bgneal@3 183
bgneal@3 184 private:
bgneal@3 185 plugboard& pb;
bgneal@3 186 alpha_int_array state;
bgneal@3 187 };
bgneal@3 188
bgneal@3 189 }
bgneal@3 190
bgneal@3 191 #endif