1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
|
#include <iostream>
#include <array>
using namespace std;
const int SIDE = 10; // Matrix width and height
typedef array<array<char,SIDE>, SIDE> Mat; // Helpful alias
// Add '#' to end for a total string size of SIDE*SIDE
void RightPad(string& input)
{
int diff = SIDE*SIDE - input.size();
if (diff <= 0)
return;
input = input + string(diff, '#');
}
// Converts the input to the blocky matrix format
void ConvertInputToMatrix(const string& input, Mat& a)
{
if (input.size() < SIDE*SIDE)
return;
for (int r=0; r<SIDE; ++r)
for (int c=0; c<SIDE; ++c)
a[r][c] = input[r*SIDE + c];
}
// Source (r,c) pairs which correspond to first elements
// of each destination row
array<pair<int,int>, SIDE> GenerateSeeds()
{
array<pair<int,int>, SIDE> seeds;
for (int i=0, r=0, c=0, inc=2; i<SIDE; ++i, inc+=1)
{
seeds[i] = make_pair(r,c);
c += inc;
if (c>=SIDE)
{
r += 1;
c %= SIDE;
}
}
return seeds;
}
// Pattern of differences across elements within a row
array<int,SIDE> GenerateDiffs()
{
array<int, SIDE> diffs;
for (int i=0; i<SIDE; ++i)
{
diffs[i] = i+1;
}
diffs[SIDE-1] = SIDE-1;
return diffs;
}
// Returns new transposed matrix with characters arranged
// right to left, diagonally downward
Mat CipherTranspose(const Mat& a)
{
Mat m;
auto seeds = GenerateSeeds();
auto diffs = GenerateDiffs();
int src_r, src_c;
int di; // Index for diffs
bool increasing; // Whether to increase or decrease di
for (int r=0; r<SIDE; ++r)
{
src_r = seeds[r].first;
src_c = seeds[r].second;
m[r][0] = a[src_r][src_c];
di = r;
increasing = true;
for (int c=1; c<SIDE; ++c)
{
src_c += diffs[di];
if (src_c >= SIDE)
{
src_r += src_c/SIDE;
src_c %= SIDE;
}
m[r][c] = a[src_r][src_c];
if (increasing)
{
di += 1;
if (di == SIDE)
{
di = SIDE-3;
increasing = false;
}
}
else
{
di -= 1;
if (di == -1)
{
// Currently unused since it happens on the
// last element, but might matter for rects
di = 1;
increasing = true;
}
}
}
}
return m;
}
void Show(const Mat& a)
{
for (int r=0; r<SIDE; ++r)
{
for (int c=0; c<SIDE; ++c)
cout << a[r][c] << ' ';
cout << endl;
}
cout << endl << endl;
}
int main()
{
string input("ONE OF THE EARLIEST KNOWN USES OF "
"TRANSPOSITION CODES WAS DESIGNED BY THE SPARTANS");
RightPad(input);
Mat mat;
ConvertInputToMatrix(input, mat);
Show(mat);
Mat encrypted = CipherTranspose(mat);
Show(encrypted);
return 0;
}
|