#include <bits/stdc++.h>
using namespace std;
 
string permute(string key, int arr[], int len) {
  string permutation_key = "";
  for (int i = 0; i < len; i++) {
    permutation_key = permutation_key + key[arr[i] - 1]; // arr[i] tidak zero indexed (1..n)
  }
  return permutation_key;
}
 
string hex_to_bin(string s) {
  char str[16 + 5] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
  string hex[16 + 5] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
  string ret = "";
  for (int i = 0; i < s.length(); i++) {
    for (int j = 0; j < 16; j++) {
      if (s[i] == str[j]) {
        ret = ret + hex[j];
        break;
      }
    }
  }
  return ret;
}
 
string bin_to_hex(string s) {
  char str[16 + 5] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
  string hex[16 + 5] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
  string ret = "";
  for (int i = 0; i < s.length(); i += 4) {
    string four_bits = "";
    for (int j = i; j < i + 4; j++) {
      four_bits = four_bits + s[j];
    }
    for (int j = 0; j < 16; j++) {
      if (four_bits == hex[j]) {
        ret = ret + str[j];
        break;
      }
    }
  }
  return ret;
}
 
int bin_to_dec(string s) {
  int decimal = 0;
  int power = 0;
  for (int i = s.length() - 1; i >= 0; i--) {
    if (s[i] == '1') {
      decimal += pow(2, power);
    }
    power++;
  }
  return decimal;
}
 
string dec_to_bin(int n) {
  string ret = "";
  while (n != 0) {
    if (n % 2 == 0) {
      ret = ret + "0";
    } else {
      ret = ret + "1";
    }
    n /= 2;
  }
  while (ret.length() < 4) {
    ret = ret + "0";
  }
  reverse(ret.begin(), ret.end());
  return ret;
}
 
string xor_f(string a, string b) {
  string ret = "";
  for (int i = 0; i < a.length(); i++) {
    if (a[i] == b[i]) {
      ret = ret + "0";
    } else {
      ret = ret + "1";
    }
  }
  return ret;
}
 
string generate_key() {
  srand(time({}));
  int range_ascii[] = {48, 57, 65, 70};
  string key = "";
  for (int i = 0; i < 16; i++) {
    char c = rand() % (range_ascii[3] + 1 - range_ascii[0]) + range_ascii[0];
    if (c > range_ascii[1] && c < range_ascii[2]) {
      i--;
      continue;
    }
    key = key + c;
  }
  return key;
}
 
string parity_bit_drop_key(string key) {
  int parity_table[] = {
    57, 49, 41, 33, 25, 17, 9,
    1, 58, 50, 42, 34, 26, 18,
    10, 2, 59, 51, 43, 35, 27,
    19, 11, 3, 60, 52, 44, 36,
    63, 55, 47, 39, 31, 23, 15,
    7, 62, 54, 46, 38, 30, 22,
    14, 6, 61, 53, 45, 37, 29,
    21, 13, 5, 28, 20, 12, 4
  };
  return (permute(key, parity_table, 56));
}
 
string compression_56_to_48(string key) {
  int compression_table[] = {
      14, 17, 11, 24, 1, 5,
			3, 28, 15, 6, 21, 10,
			23, 19, 12, 4, 26, 8,
			16, 7, 27, 20, 13, 2,
			41, 52, 31, 37, 47, 55,
			30, 40, 51, 45, 33, 48,
			44, 49, 39, 56, 34, 53,
			46, 42, 50, 36, 29, 32
  };
  return (permute(key, compression_table, 48));
}
 
void split_string(string str, string &left, string &right) {
  for (int i = 0; i < str.length() / 2; i++) {
    left = left + str[i];
    right = right + str[str.length() / 2 + i];
  }
}
 
string shift_left(string key, int n_shifts) {
  int shift_table[] = {
    1, 1, 2, 2,
    2, 2, 2, 2,
    1, 2, 2, 2,
    2, 2, 2, 1
  };
 
  string shifted_key = "";
  for (int i = 0; i < shift_table[n_shifts]; i++) {
    for (int j = 1; j < key.length(); j++) {
      shifted_key = shifted_key + key[j];
    }
    shifted_key = shifted_key + key[0];
    key = shifted_key;
    shifted_key = "";
  }
  return key;
}
 
struct round_keys {
  string random_hex;
  string round_keys_bin[16 + 5];
  string round_keys_hex[16 + 5];
};
 
round_keys generate_round_keys(string option, string key = "") {
  round_keys ret;
  if (option == "encryption_scheme") {
    ret.random_hex = "AABB09182736CCDD";
  } else {
    ret.random_hex = key;
  }
  string key_bin = hex_to_bin(ret.random_hex); 
  string key_bin_56 = parity_bit_drop_key(key_bin);
 
  string key_left;
  string key_right;
  split_string(key_bin_56, key_left, key_right);
 
  for (int i = 0; i < 16; i++) {
    key_left = shift_left(key_left, i);
    key_right = shift_left(key_right, i);
    string combined_key = key_left + key_right;
    string round_key = compression_56_to_48(combined_key);
    ret.round_keys_bin[i] = round_key;
    ret.round_keys_hex[i] = bin_to_hex(round_key);
  }
  return ret;
}
 
string initial_permutation(string text) {
  int IP_table[] = {
    58, 50, 42, 34, 26, 18, 10, 2,
    60, 52, 44, 36, 28, 20, 12, 4,
    62, 54, 46, 38, 30, 22, 14, 6,
    64, 56, 48, 40, 32, 24, 16, 8,
    57, 49, 41, 33, 25, 17, 9, 1,
    59, 51, 43, 35, 27, 19, 11, 3,
    61, 53, 45, 37, 29, 21, 13, 5,
    63, 55, 47, 39, 31, 23, 15, 7
  };
  return (permute(text, IP_table, 64));
}
 
string expansion(string text) {
  int expansion_table[] = {
    32, 1, 2, 3, 4, 5, 4, 5,
    6, 7, 8, 9, 8, 9, 10, 11,
    12, 13, 12, 13, 14, 15, 16, 17,
    16, 17, 18, 19, 20, 21, 20, 21,
    22, 23, 24, 25, 24, 25, 26, 27,
    28, 29, 28, 29, 30, 31, 32, 1
  };
  return (permute(text, expansion_table, 48));
}
 
string sbox_operation(string text) {
  int sbox[8 + 5][4 + 5][16 + 5] = {
    {
      {14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7},
      {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8},
      {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0},
      {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}
    },
 
    {
      {15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10},
      {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5},
      {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15},
      {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}
    },
 
    {
      {10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8},
      {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1},
      {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7},
      {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}
    },
 
    {
      {7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15},
      {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9},
      {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4},
      {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}
    },
 
    {
      {2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9},
      {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6},
      {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14},
      {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}
    },
 
    {
      {12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11},
      {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8},
      {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6},
      {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}
    },
 
    {
      {4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1},
      {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6},
      {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2},
      {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}
    },
 
    {
      {13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7},
      {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2},
      {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8},
      {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}
    }
  };
 
  string ret = "";
  for (int i = 0; i < 8; i++) {
    string outer = "";
    string inner = "";
    outer = outer + text[i * 6] + text[i * 6 + 5];
    inner = inner + text[i * 6 + 1] + text[i * 6 + 2] + text[i * 6 + 3] + text[i * 6 + 4];
    int val = sbox[i][bin_to_dec(outer)][bin_to_dec(inner)];
    ret = ret + dec_to_bin(val);
  }
  return ret;
}
 
string per(string text) {
  int per[] = {
    16, 7, 20, 21,
    29, 12, 28, 17,
    1, 15, 23, 26,
    5, 18, 31, 10,
    2, 8, 24, 14,
    32, 27, 3, 9,
    19, 13, 30, 6,
    22, 11, 4, 25
  };
  return permute(text, per, 32);
}
 
string final_permutation(string text) {
  int final_perm[] = {
    40, 8, 48, 16, 56, 24, 64, 32,
    39, 7, 47, 15, 55, 23, 63, 31,
    38, 6, 46, 14, 54, 22, 62, 30,
    37, 5, 45, 13, 53, 21, 61, 29,
    36, 4, 44, 12, 52, 20, 60, 28,
    35, 3, 43, 11, 51, 19, 59, 27,
    34, 2, 42, 10, 50, 18, 58, 26,
    33, 1, 41, 9, 49, 17, 57, 25
  };
  return permute(text, final_perm, 64);
}
 
string DES_encrypt(string plain_text, round_keys key) {
  plain_text = hex_to_bin(plain_text);
  plain_text = initial_permutation(plain_text);
 
  string chiper_left;
  string chiper_right;
 
  // THE FUNCTION
  split_string(plain_text, chiper_left, chiper_right);
 
  for (int i = 0; i < 16; i++) {
    string chiper_right_expanded = expansion(chiper_right);
 
    string first_xor = xor_f(chiper_right_expanded, key.round_keys_bin[i]);
 
    string sbox_str = sbox_operation(first_xor);
    sbox_str = per(sbox_str);
    string result = xor_f(chiper_left, sbox_str);
 
    chiper_left = result;
 
    if (i != 15) {
      swap(chiper_left, chiper_right);
    }
  }
  string chiper_text = chiper_left + chiper_right;
  chiper_text = final_permutation(chiper_text);
 
  cout << "Initial permutation  : " << bin_to_hex(plain_text) << "\n";
  cout << "Final chipper text   : " << bin_to_hex(chiper_text) << "\n";
 
  return bin_to_hex(chiper_text);
}
 
string DES_decrypt(string chiper_text, string key_hex) {
  round_keys key = generate_round_keys("decryption_scheme", key_hex);
  round_keys reversed_key;
  for (int i = 15; i >= 0; i--) {
    reversed_key.round_keys_bin[15 - i] = key.round_keys_bin[i];
    reversed_key.round_keys_hex[15 - i] = key.round_keys_hex[i];
  }
  return DES_encrypt(chiper_text, reversed_key);
}
 
vector<string> input_encrypt() { 
  // This function is used for converting literal string into hexadecimal
  string input_text;
  cout << "Input plain text:" << "\n";
  cout << ">> ";
  cin.ignore();
  getline(cin, input_text);
  vector<string> plain_text(1);
 
  int k = 0;
  for (int i = 0; i < input_text.length(); i++) {
    string character = "";
    for(int j = 7; j >= 0; j--) {
      bool is_set = input_text[i] & (1 << j);
      if (is_set == 1) {
        character = character + "1";
      } else {
        character = character + "0";
      }
    }
    string character_left, character_right;
    split_string(character, character_left, character_right);
    if (plain_text[k].length() == 16) {
      k++;
      plain_text.push_back("" );
    }
    plain_text[k] = plain_text[k] + bin_to_hex(character_left);
    plain_text[k] = plain_text[k] + bin_to_hex(character_right);
  }
 
  if (plain_text[k].length() != 16) {
    for (int i = plain_text[k].length(); i < 16; i++) {
      plain_text[k] = plain_text[k] + '0';
    }
  }
  return plain_text;
}
 
string output_decrypt(vector<string> plain_text_hex) {
  string ret = "";
  for (int i = 0; i < plain_text_hex.size(); i++) {
    for (int j = 0; j < 16; j += 2) {
      string two_hex = plain_text_hex[i].substr(j, 2);
      int value = stoi(two_hex, 0, 16);
      if (value != 0) {
        ret += (char)value;
      }
    }
  }
  return ret;
}
 
int main() {
  while (1) {
    int menu;
    cout << "||======================" << "||" << '\n';
    cout << "|| Wellcome to DES" << "\t" << "||" << '\n';
    cout << "|| Choose Menu:" << "\t\t" << "||" << '\n'; 
    cout << "|| 1: Encrypt Text" << "\t" << "||" << '\n';
    cout << "|| 2: Decrypt Text" << "\t" << "||" << '\n';
    cout << "|| 0: Exit" << "\t\t" << "||" << '\n';
    cout << "|| >> ";
    cin >> menu;
    cout << "||======================" << "||" << '\n' << '\n';
 
    if (menu == 1) {
      cout << "========================================================================================================================" << '\n';
      vector<string> plain_text = input_encrypt();
      const int message_size = plain_text.size();
      round_keys key = generate_round_keys("encryption_scheme");
      vector<string> chiper_text;
 
      cout << "\n" << "Encrypting plain text..." << "\n";  
      for (int i = 0; i < message_size; i++) {
        chiper_text.push_back(DES_encrypt(plain_text[i], key));
        cout << "Plain text encrypted [" << i + 1 << "/" << message_size << "]" << '\n' << '\n';
      }
      cout << "Key = " << key.random_hex << '\n';
      cout << "Chiper text = {" << '\n';
      for (int i = 0; i < message_size; i++) {
        cout << chiper_text[i];
      }
      cout << '\n' << "}" << '\n';
      cout << "========================================================================================================================" << '\n' << '\n';
    } else if (menu == 2) {  
      cout << "========================================================================================================================" << '\n';
      string key, chiper_text;
      vector<string> plain_text_hex;
      cout << "Input key:" << '\n' << ">> ";
      cin >> key;
      cout << "Input chiper text:" << '\n' << ">> ";
      cin >> chiper_text;
      const int message_size = chiper_text.length() / 16;
      cout << "\n" << "Decrypting chiper text..." << "\n";
      for (int i = 0; i < chiper_text.length(); i += 16) {
        string chiper_text_partition = chiper_text.substr(i, 16);
        plain_text_hex.push_back(DES_decrypt(chiper_text_partition, key));
        cout << "Chiper text decrypted [" << i / 16 + 1 << "/" << message_size << "]" << '\n' << '\n';
      }
      string plain_text = output_decrypt(plain_text_hex);
      cout << plain_text << '\n';
      cout << "========================================================================================================================" << '\n' << '\n';
    } else if (menu == 0) {
      break;
    } else {
      cout << "Invalid command" << '\n' << '\n';
    }
  }
 
  return 0;
}
				I2luY2x1ZGUgPGJpdHMvc3RkYysrLmg+CnVzaW5nIG5hbWVzcGFjZSBzdGQ7CgpzdHJpbmcgcGVybXV0ZShzdHJpbmcga2V5LCBpbnQgYXJyW10sIGludCBsZW4pIHsKICBzdHJpbmcgcGVybXV0YXRpb25fa2V5ID0gIiI7CiAgZm9yIChpbnQgaSA9IDA7IGkgPCBsZW47IGkrKykgewogICAgcGVybXV0YXRpb25fa2V5ID0gcGVybXV0YXRpb25fa2V5ICsga2V5W2FycltpXSAtIDFdOyAvLyBhcnJbaV0gdGlkYWsgemVybyBpbmRleGVkICgxLi5uKQogIH0KICByZXR1cm4gcGVybXV0YXRpb25fa2V5Owp9CgpzdHJpbmcgaGV4X3RvX2JpbihzdHJpbmcgcykgewogIGNoYXIgc3RyWzE2ICsgNV0gPSB7JzAnLCAnMScsICcyJywgJzMnLCAnNCcsICc1JywgJzYnLCAnNycsICc4JywgJzknLCAnQScsICdCJywgJ0MnLCAnRCcsICdFJywgJ0YnfTsKICBzdHJpbmcgaGV4WzE2ICsgNV0gPSB7IjAwMDAiLCAiMDAwMSIsICIwMDEwIiwgIjAwMTEiLCAiMDEwMCIsICIwMTAxIiwgIjAxMTAiLCAiMDExMSIsICIxMDAwIiwgIjEwMDEiLCAiMTAxMCIsICIxMDExIiwgIjExMDAiLCAiMTEwMSIsICIxMTEwIiwgIjExMTEifTsKICBzdHJpbmcgcmV0ID0gIiI7CiAgZm9yIChpbnQgaSA9IDA7IGkgPCBzLmxlbmd0aCgpOyBpKyspIHsKICAgIGZvciAoaW50IGogPSAwOyBqIDwgMTY7IGorKykgewogICAgICBpZiAoc1tpXSA9PSBzdHJbal0pIHsKICAgICAgICByZXQgPSByZXQgKyBoZXhbal07CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KICB9CiAgcmV0dXJuIHJldDsKfQoKc3RyaW5nIGJpbl90b19oZXgoc3RyaW5nIHMpIHsKICBjaGFyIHN0clsxNiArIDVdID0geycwJywgJzEnLCAnMicsICczJywgJzQnLCAnNScsICc2JywgJzcnLCAnOCcsICc5JywgJ0EnLCAnQicsICdDJywgJ0QnLCAnRScsICdGJ307CiAgc3RyaW5nIGhleFsxNiArIDVdID0geyIwMDAwIiwgIjAwMDEiLCAiMDAxMCIsICIwMDExIiwgIjAxMDAiLCAiMDEwMSIsICIwMTEwIiwgIjAxMTEiLCAiMTAwMCIsICIxMDAxIiwgIjEwMTAiLCAiMTAxMSIsICIxMTAwIiwgIjExMDEiLCAiMTExMCIsICIxMTExIn07CiAgc3RyaW5nIHJldCA9ICIiOwogIGZvciAoaW50IGkgPSAwOyBpIDwgcy5sZW5ndGgoKTsgaSArPSA0KSB7CiAgICBzdHJpbmcgZm91cl9iaXRzID0gIiI7CiAgICBmb3IgKGludCBqID0gaTsgaiA8IGkgKyA0OyBqKyspIHsKICAgICAgZm91cl9iaXRzID0gZm91cl9iaXRzICsgc1tqXTsKICAgIH0KICAgIGZvciAoaW50IGogPSAwOyBqIDwgMTY7IGorKykgewogICAgICBpZiAoZm91cl9iaXRzID09IGhleFtqXSkgewogICAgICAgIHJldCA9IHJldCArIHN0cltqXTsKICAgICAgICBicmVhazsKICAgICAgfQogICAgfQogIH0KICByZXR1cm4gcmV0Owp9CgppbnQgYmluX3RvX2RlYyhzdHJpbmcgcykgewogIGludCBkZWNpbWFsID0gMDsKICBpbnQgcG93ZXIgPSAwOwogIGZvciAoaW50IGkgPSBzLmxlbmd0aCgpIC0gMTsgaSA+PSAwOyBpLS0pIHsKICAgIGlmIChzW2ldID09ICcxJykgewogICAgICBkZWNpbWFsICs9IHBvdygyLCBwb3dlcik7CiAgICB9CiAgICBwb3dlcisrOwogIH0KICByZXR1cm4gZGVjaW1hbDsKfQoKc3RyaW5nIGRlY190b19iaW4oaW50IG4pIHsKICBzdHJpbmcgcmV0ID0gIiI7CiAgd2hpbGUgKG4gIT0gMCkgewogICAgaWYgKG4gJSAyID09IDApIHsKICAgICAgcmV0ID0gcmV0ICsgIjAiOwogICAgfSBlbHNlIHsKICAgICAgcmV0ID0gcmV0ICsgIjEiOwogICAgfQogICAgbiAvPSAyOwogIH0KICB3aGlsZSAocmV0Lmxlbmd0aCgpIDwgNCkgewogICAgcmV0ID0gcmV0ICsgIjAiOwogIH0KICByZXZlcnNlKHJldC5iZWdpbigpLCByZXQuZW5kKCkpOwogIHJldHVybiByZXQ7Cn0KCnN0cmluZyB4b3JfZihzdHJpbmcgYSwgc3RyaW5nIGIpIHsKICBzdHJpbmcgcmV0ID0gIiI7CiAgZm9yIChpbnQgaSA9IDA7IGkgPCBhLmxlbmd0aCgpOyBpKyspIHsKICAgIGlmIChhW2ldID09IGJbaV0pIHsKICAgICAgcmV0ID0gcmV0ICsgIjAiOwogICAgfSBlbHNlIHsKICAgICAgcmV0ID0gcmV0ICsgIjEiOwogICAgfQogIH0KICByZXR1cm4gcmV0Owp9CgpzdHJpbmcgZ2VuZXJhdGVfa2V5KCkgewogIHNyYW5kKHRpbWUoe30pKTsKICBpbnQgcmFuZ2VfYXNjaWlbXSA9IHs0OCwgNTcsIDY1LCA3MH07CiAgc3RyaW5nIGtleSA9ICIiOwogIGZvciAoaW50IGkgPSAwOyBpIDwgMTY7IGkrKykgewogICAgY2hhciBjID0gcmFuZCgpICUgKHJhbmdlX2FzY2lpWzNdICsgMSAtIHJhbmdlX2FzY2lpWzBdKSArIHJhbmdlX2FzY2lpWzBdOwogICAgaWYgKGMgPiByYW5nZV9hc2NpaVsxXSAmJiBjIDwgcmFuZ2VfYXNjaWlbMl0pIHsKICAgICAgaS0tOwogICAgICBjb250aW51ZTsKICAgIH0KICAgIGtleSA9IGtleSArIGM7CiAgfQogIHJldHVybiBrZXk7Cn0KCnN0cmluZyBwYXJpdHlfYml0X2Ryb3Bfa2V5KHN0cmluZyBrZXkpIHsKICBpbnQgcGFyaXR5X3RhYmxlW10gPSB7CiAgICA1NywgNDksIDQxLCAzMywgMjUsIDE3LCA5LAogICAgMSwgNTgsIDUwLCA0MiwgMzQsIDI2LCAxOCwKICAgIDEwLCAyLCA1OSwgNTEsIDQzLCAzNSwgMjcsCiAgICAxOSwgMTEsIDMsIDYwLCA1MiwgNDQsIDM2LAogICAgNjMsIDU1LCA0NywgMzksIDMxLCAyMywgMTUsCiAgICA3LCA2MiwgNTQsIDQ2LCAzOCwgMzAsIDIyLAogICAgMTQsIDYsIDYxLCA1MywgNDUsIDM3LCAyOSwKICAgIDIxLCAxMywgNSwgMjgsIDIwLCAxMiwgNAogIH07CiAgcmV0dXJuIChwZXJtdXRlKGtleSwgcGFyaXR5X3RhYmxlLCA1NikpOwp9CgpzdHJpbmcgY29tcHJlc3Npb25fNTZfdG9fNDgoc3RyaW5nIGtleSkgewogIGludCBjb21wcmVzc2lvbl90YWJsZVtdID0gewogICAgICAxNCwgMTcsIDExLCAyNCwgMSwgNSwKCQkJMywgMjgsIDE1LCA2LCAyMSwgMTAsCgkJCTIzLCAxOSwgMTIsIDQsIDI2LCA4LAoJCQkxNiwgNywgMjcsIDIwLCAxMywgMiwKCQkJNDEsIDUyLCAzMSwgMzcsIDQ3LCA1NSwKCQkJMzAsIDQwLCA1MSwgNDUsIDMzLCA0OCwKCQkJNDQsIDQ5LCAzOSwgNTYsIDM0LCA1MywKCQkJNDYsIDQyLCA1MCwgMzYsIDI5LCAzMgogIH07CiAgcmV0dXJuIChwZXJtdXRlKGtleSwgY29tcHJlc3Npb25fdGFibGUsIDQ4KSk7Cn0KCnZvaWQgc3BsaXRfc3RyaW5nKHN0cmluZyBzdHIsIHN0cmluZyAmbGVmdCwgc3RyaW5nICZyaWdodCkgewogIGZvciAoaW50IGkgPSAwOyBpIDwgc3RyLmxlbmd0aCgpIC8gMjsgaSsrKSB7CiAgICBsZWZ0ID0gbGVmdCArIHN0cltpXTsKICAgIHJpZ2h0ID0gcmlnaHQgKyBzdHJbc3RyLmxlbmd0aCgpIC8gMiArIGldOwogIH0KfQoKc3RyaW5nIHNoaWZ0X2xlZnQoc3RyaW5nIGtleSwgaW50IG5fc2hpZnRzKSB7CiAgaW50IHNoaWZ0X3RhYmxlW10gPSB7CiAgICAxLCAxLCAyLCAyLAogICAgMiwgMiwgMiwgMiwKICAgIDEsIDIsIDIsIDIsCiAgICAyLCAyLCAyLCAxCiAgfTsKCiAgc3RyaW5nIHNoaWZ0ZWRfa2V5ID0gIiI7CiAgZm9yIChpbnQgaSA9IDA7IGkgPCBzaGlmdF90YWJsZVtuX3NoaWZ0c107IGkrKykgewogICAgZm9yIChpbnQgaiA9IDE7IGogPCBrZXkubGVuZ3RoKCk7IGorKykgewogICAgICBzaGlmdGVkX2tleSA9IHNoaWZ0ZWRfa2V5ICsga2V5W2pdOwogICAgfQogICAgc2hpZnRlZF9rZXkgPSBzaGlmdGVkX2tleSArIGtleVswXTsKICAgIGtleSA9IHNoaWZ0ZWRfa2V5OwogICAgc2hpZnRlZF9rZXkgPSAiIjsKICB9CiAgcmV0dXJuIGtleTsKfQoKc3RydWN0IHJvdW5kX2tleXMgewogIHN0cmluZyByYW5kb21faGV4OwogIHN0cmluZyByb3VuZF9rZXlzX2JpblsxNiArIDVdOwogIHN0cmluZyByb3VuZF9rZXlzX2hleFsxNiArIDVdOwp9OwoKcm91bmRfa2V5cyBnZW5lcmF0ZV9yb3VuZF9rZXlzKHN0cmluZyBvcHRpb24sIHN0cmluZyBrZXkgPSAiIikgewogIHJvdW5kX2tleXMgcmV0OwogIGlmIChvcHRpb24gPT0gImVuY3J5cHRpb25fc2NoZW1lIikgewogICAgcmV0LnJhbmRvbV9oZXggPSAiQUFCQjA5MTgyNzM2Q0NERCI7CiAgfSBlbHNlIHsKICAgIHJldC5yYW5kb21faGV4ID0ga2V5OwogIH0KICBzdHJpbmcga2V5X2JpbiA9IGhleF90b19iaW4ocmV0LnJhbmRvbV9oZXgpOyAKICBzdHJpbmcga2V5X2Jpbl81NiA9IHBhcml0eV9iaXRfZHJvcF9rZXkoa2V5X2Jpbik7CiAgCiAgc3RyaW5nIGtleV9sZWZ0OwogIHN0cmluZyBrZXlfcmlnaHQ7CiAgc3BsaXRfc3RyaW5nKGtleV9iaW5fNTYsIGtleV9sZWZ0LCBrZXlfcmlnaHQpOwoKICBmb3IgKGludCBpID0gMDsgaSA8IDE2OyBpKyspIHsKICAgIGtleV9sZWZ0ID0gc2hpZnRfbGVmdChrZXlfbGVmdCwgaSk7CiAgICBrZXlfcmlnaHQgPSBzaGlmdF9sZWZ0KGtleV9yaWdodCwgaSk7CiAgICBzdHJpbmcgY29tYmluZWRfa2V5ID0ga2V5X2xlZnQgKyBrZXlfcmlnaHQ7CiAgICBzdHJpbmcgcm91bmRfa2V5ID0gY29tcHJlc3Npb25fNTZfdG9fNDgoY29tYmluZWRfa2V5KTsKICAgIHJldC5yb3VuZF9rZXlzX2JpbltpXSA9IHJvdW5kX2tleTsKICAgIHJldC5yb3VuZF9rZXlzX2hleFtpXSA9IGJpbl90b19oZXgocm91bmRfa2V5KTsKICB9CiAgcmV0dXJuIHJldDsKfQoKc3RyaW5nIGluaXRpYWxfcGVybXV0YXRpb24oc3RyaW5nIHRleHQpIHsKICBpbnQgSVBfdGFibGVbXSA9IHsKICAgIDU4LCA1MCwgNDIsIDM0LCAyNiwgMTgsIDEwLCAyLAogICAgNjAsIDUyLCA0NCwgMzYsIDI4LCAyMCwgMTIsIDQsCiAgICA2MiwgNTQsIDQ2LCAzOCwgMzAsIDIyLCAxNCwgNiwKICAgIDY0LCA1NiwgNDgsIDQwLCAzMiwgMjQsIDE2LCA4LAogICAgNTcsIDQ5LCA0MSwgMzMsIDI1LCAxNywgOSwgMSwKICAgIDU5LCA1MSwgNDMsIDM1LCAyNywgMTksIDExLCAzLAogICAgNjEsIDUzLCA0NSwgMzcsIDI5LCAyMSwgMTMsIDUsCiAgICA2MywgNTUsIDQ3LCAzOSwgMzEsIDIzLCAxNSwgNwogIH07CiAgcmV0dXJuIChwZXJtdXRlKHRleHQsIElQX3RhYmxlLCA2NCkpOwp9CgpzdHJpbmcgZXhwYW5zaW9uKHN0cmluZyB0ZXh0KSB7CiAgaW50IGV4cGFuc2lvbl90YWJsZVtdID0gewogICAgMzIsIDEsIDIsIDMsIDQsIDUsIDQsIDUsCiAgICA2LCA3LCA4LCA5LCA4LCA5LCAxMCwgMTEsCiAgICAxMiwgMTMsIDEyLCAxMywgMTQsIDE1LCAxNiwgMTcsCiAgICAxNiwgMTcsIDE4LCAxOSwgMjAsIDIxLCAyMCwgMjEsCiAgICAyMiwgMjMsIDI0LCAyNSwgMjQsIDI1LCAyNiwgMjcsCiAgICAyOCwgMjksIDI4LCAyOSwgMzAsIDMxLCAzMiwgMQogIH07CiAgcmV0dXJuIChwZXJtdXRlKHRleHQsIGV4cGFuc2lvbl90YWJsZSwgNDgpKTsKfQoKc3RyaW5nIHNib3hfb3BlcmF0aW9uKHN0cmluZyB0ZXh0KSB7CiAgaW50IHNib3hbOCArIDVdWzQgKyA1XVsxNiArIDVdID0gewogICAgewogICAgICB7MTQsIDQsIDEzLCAxLCAyLCAxNSwgMTEsIDgsIDMsIDEwLCA2LCAxMiwgNSwgOSwgMCwgN30sCiAgICAgIHswLCAxNSwgNywgNCwgMTQsIDIsIDEzLCAxLCAxMCwgNiwgMTIsIDExLCA5LCA1LCAzLCA4fSwKICAgICAgezQsIDEsIDE0LCA4LCAxMywgNiwgMiwgMTEsIDE1LCAxMiwgOSwgNywgMywgMTAsIDUsIDB9LAogICAgICB7MTUsIDEyLCA4LCAyLCA0LCA5LCAxLCA3LCA1LCAxMSwgMywgMTQsIDEwLCAwLCA2LCAxM30KICAgIH0sCgogICAgewogICAgICB7MTUsIDEsIDgsIDE0LCA2LCAxMSwgMywgNCwgOSwgNywgMiwgMTMsIDEyLCAwLCA1LCAxMH0sCiAgICAgIHszLCAxMywgNCwgNywgMTUsIDIsIDgsIDE0LCAxMiwgMCwgMSwgMTAsIDYsIDksIDExLCA1fSwKICAgICAgezAsIDE0LCA3LCAxMSwgMTAsIDQsIDEzLCAxLCA1LCA4LCAxMiwgNiwgOSwgMywgMiwgMTV9LAogICAgICB7MTMsIDgsIDEwLCAxLCAzLCAxNSwgNCwgMiwgMTEsIDYsIDcsIDEyLCAwLCA1LCAxNCwgOX0KICAgIH0sCgogICAgewogICAgICB7MTAsIDAsIDksIDE0LCA2LCAzLCAxNSwgNSwgMSwgMTMsIDEyLCA3LCAxMSwgNCwgMiwgOH0sCiAgICAgIHsxMywgNywgMCwgOSwgMywgNCwgNiwgMTAsIDIsIDgsIDUsIDE0LCAxMiwgMTEsIDE1LCAxfSwKICAgICAgezEzLCA2LCA0LCA5LCA4LCAxNSwgMywgMCwgMTEsIDEsIDIsIDEyLCA1LCAxMCwgMTQsIDd9LAogICAgICB7MSwgMTAsIDEzLCAwLCA2LCA5LCA4LCA3LCA0LCAxNSwgMTQsIDMsIDExLCA1LCAyLCAxMn0KICAgIH0sCgogICAgewogICAgICB7NywgMTMsIDE0LCAzLCAwLCA2LCA5LCAxMCwgMSwgMiwgOCwgNSwgMTEsIDEyLCA0LCAxNX0sCiAgICAgIHsxMywgOCwgMTEsIDUsIDYsIDE1LCAwLCAzLCA0LCA3LCAyLCAxMiwgMSwgMTAsIDE0LCA5fSwKICAgICAgezEwLCA2LCA5LCAwLCAxMiwgMTEsIDcsIDEzLCAxNSwgMSwgMywgMTQsIDUsIDIsIDgsIDR9LAogICAgICB7MywgMTUsIDAsIDYsIDEwLCAxLCAxMywgOCwgOSwgNCwgNSwgMTEsIDEyLCA3LCAyLCAxNH0KICAgIH0sCgogICAgewogICAgICB7MiwgMTIsIDQsIDEsIDcsIDEwLCAxMSwgNiwgOCwgNSwgMywgMTUsIDEzLCAwLCAxNCwgOX0sCiAgICAgIHsxNCwgMTEsIDIsIDEyLCA0LCA3LCAxMywgMSwgNSwgMCwgMTUsIDEwLCAzLCA5LCA4LCA2fSwKICAgICAgezQsIDIsIDEsIDExLCAxMCwgMTMsIDcsIDgsIDE1LCA5LCAxMiwgNSwgNiwgMywgMCwgMTR9LAogICAgICB7MTEsIDgsIDEyLCA3LCAxLCAxNCwgMiwgMTMsIDYsIDE1LCAwLCA5LCAxMCwgNCwgNSwgM30KICAgIH0sCgogICAgewogICAgICB7MTIsIDEsIDEwLCAxNSwgOSwgMiwgNiwgOCwgMCwgMTMsIDMsIDQsIDE0LCA3LCA1LCAxMX0sCiAgICAgIHsxMCwgMTUsIDQsIDIsIDcsIDEyLCA5LCA1LCA2LCAxLCAxMywgMTQsIDAsIDExLCAzLCA4fSwKICAgICAgezksIDE0LCAxNSwgNSwgMiwgOCwgMTIsIDMsIDcsIDAsIDQsIDEwLCAxLCAxMywgMTEsIDZ9LAogICAgICB7NCwgMywgMiwgMTIsIDksIDUsIDE1LCAxMCwgMTEsIDE0LCAxLCA3LCA2LCAwLCA4LCAxM30KICAgIH0sCgogICAgewogICAgICB7NCwgMTEsIDIsIDE0LCAxNSwgMCwgOCwgMTMsIDMsIDEyLCA5LCA3LCA1LCAxMCwgNiwgMX0sCiAgICAgIHsxMywgMCwgMTEsIDcsIDQsIDksIDEsIDEwLCAxNCwgMywgNSwgMTIsIDIsIDE1LCA4LCA2fSwKICAgICAgezEsIDQsIDExLCAxMywgMTIsIDMsIDcsIDE0LCAxMCwgMTUsIDYsIDgsIDAsIDUsIDksIDJ9LAogICAgICB7NiwgMTEsIDEzLCA4LCAxLCA0LCAxMCwgNywgOSwgNSwgMCwgMTUsIDE0LCAyLCAzLCAxMn0KICAgIH0sCgogICAgewogICAgICB7MTMsIDIsIDgsIDQsIDYsIDE1LCAxMSwgMSwgMTAsIDksIDMsIDE0LCA1LCAwLCAxMiwgN30sCiAgICAgIHsxLCAxNSwgMTMsIDgsIDEwLCAzLCA3LCA0LCAxMiwgNSwgNiwgMTEsIDAsIDE0LCA5LCAyfSwKICAgICAgezcsIDExLCA0LCAxLCA5LCAxMiwgMTQsIDIsIDAsIDYsIDEwLCAxMywgMTUsIDMsIDUsIDh9LAogICAgICB7MiwgMSwgMTQsIDcsIDQsIDEwLCA4LCAxMywgMTUsIDEyLCA5LCAwLCAzLCA1LCA2LCAxMX0KICAgIH0KICB9OwogIAogIHN0cmluZyByZXQgPSAiIjsKICBmb3IgKGludCBpID0gMDsgaSA8IDg7IGkrKykgewogICAgc3RyaW5nIG91dGVyID0gIiI7CiAgICBzdHJpbmcgaW5uZXIgPSAiIjsKICAgIG91dGVyID0gb3V0ZXIgKyB0ZXh0W2kgKiA2XSArIHRleHRbaSAqIDYgKyA1XTsKICAgIGlubmVyID0gaW5uZXIgKyB0ZXh0W2kgKiA2ICsgMV0gKyB0ZXh0W2kgKiA2ICsgMl0gKyB0ZXh0W2kgKiA2ICsgM10gKyB0ZXh0W2kgKiA2ICsgNF07CiAgICBpbnQgdmFsID0gc2JveFtpXVtiaW5fdG9fZGVjKG91dGVyKV1bYmluX3RvX2RlYyhpbm5lcildOwogICAgcmV0ID0gcmV0ICsgZGVjX3RvX2Jpbih2YWwpOwogIH0KICByZXR1cm4gcmV0Owp9CgpzdHJpbmcgcGVyKHN0cmluZyB0ZXh0KSB7CiAgaW50IHBlcltdID0gewogICAgMTYsIDcsIDIwLCAyMSwKICAgIDI5LCAxMiwgMjgsIDE3LAogICAgMSwgMTUsIDIzLCAyNiwKICAgIDUsIDE4LCAzMSwgMTAsCiAgICAyLCA4LCAyNCwgMTQsCiAgICAzMiwgMjcsIDMsIDksCiAgICAxOSwgMTMsIDMwLCA2LAogICAgMjIsIDExLCA0LCAyNQogIH07CiAgcmV0dXJuIHBlcm11dGUodGV4dCwgcGVyLCAzMik7Cn0KCnN0cmluZyBmaW5hbF9wZXJtdXRhdGlvbihzdHJpbmcgdGV4dCkgewogIGludCBmaW5hbF9wZXJtW10gPSB7CiAgICA0MCwgOCwgNDgsIDE2LCA1NiwgMjQsIDY0LCAzMiwKICAgIDM5LCA3LCA0NywgMTUsIDU1LCAyMywgNjMsIDMxLAogICAgMzgsIDYsIDQ2LCAxNCwgNTQsIDIyLCA2MiwgMzAsCiAgICAzNywgNSwgNDUsIDEzLCA1MywgMjEsIDYxLCAyOSwKICAgIDM2LCA0LCA0NCwgMTIsIDUyLCAyMCwgNjAsIDI4LAogICAgMzUsIDMsIDQzLCAxMSwgNTEsIDE5LCA1OSwgMjcsCiAgICAzNCwgMiwgNDIsIDEwLCA1MCwgMTgsIDU4LCAyNiwKICAgIDMzLCAxLCA0MSwgOSwgNDksIDE3LCA1NywgMjUKICB9OwogIHJldHVybiBwZXJtdXRlKHRleHQsIGZpbmFsX3Blcm0sIDY0KTsKfQoKc3RyaW5nIERFU19lbmNyeXB0KHN0cmluZyBwbGFpbl90ZXh0LCByb3VuZF9rZXlzIGtleSkgewogIHBsYWluX3RleHQgPSBoZXhfdG9fYmluKHBsYWluX3RleHQpOwogIHBsYWluX3RleHQgPSBpbml0aWFsX3Blcm11dGF0aW9uKHBsYWluX3RleHQpOwoKICBzdHJpbmcgY2hpcGVyX2xlZnQ7CiAgc3RyaW5nIGNoaXBlcl9yaWdodDsKCiAgLy8gVEhFIEZVTkNUSU9OCiAgc3BsaXRfc3RyaW5nKHBsYWluX3RleHQsIGNoaXBlcl9sZWZ0LCBjaGlwZXJfcmlnaHQpOwogIAogIGZvciAoaW50IGkgPSAwOyBpIDwgMTY7IGkrKykgewogICAgc3RyaW5nIGNoaXBlcl9yaWdodF9leHBhbmRlZCA9IGV4cGFuc2lvbihjaGlwZXJfcmlnaHQpOwoKICAgIHN0cmluZyBmaXJzdF94b3IgPSB4b3JfZihjaGlwZXJfcmlnaHRfZXhwYW5kZWQsIGtleS5yb3VuZF9rZXlzX2JpbltpXSk7CgogICAgc3RyaW5nIHNib3hfc3RyID0gc2JveF9vcGVyYXRpb24oZmlyc3RfeG9yKTsKICAgIHNib3hfc3RyID0gcGVyKHNib3hfc3RyKTsKICAgIHN0cmluZyByZXN1bHQgPSB4b3JfZihjaGlwZXJfbGVmdCwgc2JveF9zdHIpOwogICAgCiAgICBjaGlwZXJfbGVmdCA9IHJlc3VsdDsKCiAgICBpZiAoaSAhPSAxNSkgewogICAgICBzd2FwKGNoaXBlcl9sZWZ0LCBjaGlwZXJfcmlnaHQpOwogICAgfQogIH0KICBzdHJpbmcgY2hpcGVyX3RleHQgPSBjaGlwZXJfbGVmdCArIGNoaXBlcl9yaWdodDsKICBjaGlwZXJfdGV4dCA9IGZpbmFsX3Blcm11dGF0aW9uKGNoaXBlcl90ZXh0KTsKCiAgY291dCA8PCAiSW5pdGlhbCBwZXJtdXRhdGlvbiAgOiAiIDw8IGJpbl90b19oZXgocGxhaW5fdGV4dCkgPDwgIlxuIjsKICBjb3V0IDw8ICJGaW5hbCBjaGlwcGVyIHRleHQgICA6ICIgPDwgYmluX3RvX2hleChjaGlwZXJfdGV4dCkgPDwgIlxuIjsKCiAgcmV0dXJuIGJpbl90b19oZXgoY2hpcGVyX3RleHQpOwp9CgpzdHJpbmcgREVTX2RlY3J5cHQoc3RyaW5nIGNoaXBlcl90ZXh0LCBzdHJpbmcga2V5X2hleCkgewogIHJvdW5kX2tleXMga2V5ID0gZ2VuZXJhdGVfcm91bmRfa2V5cygiZGVjcnlwdGlvbl9zY2hlbWUiLCBrZXlfaGV4KTsKICByb3VuZF9rZXlzIHJldmVyc2VkX2tleTsKICBmb3IgKGludCBpID0gMTU7IGkgPj0gMDsgaS0tKSB7CiAgICByZXZlcnNlZF9rZXkucm91bmRfa2V5c19iaW5bMTUgLSBpXSA9IGtleS5yb3VuZF9rZXlzX2JpbltpXTsKICAgIHJldmVyc2VkX2tleS5yb3VuZF9rZXlzX2hleFsxNSAtIGldID0ga2V5LnJvdW5kX2tleXNfaGV4W2ldOwogIH0KICByZXR1cm4gREVTX2VuY3J5cHQoY2hpcGVyX3RleHQsIHJldmVyc2VkX2tleSk7Cn0KCnZlY3RvcjxzdHJpbmc+IGlucHV0X2VuY3J5cHQoKSB7IAogIC8vIFRoaXMgZnVuY3Rpb24gaXMgdXNlZCBmb3IgY29udmVydGluZyBsaXRlcmFsIHN0cmluZyBpbnRvIGhleGFkZWNpbWFsCiAgc3RyaW5nIGlucHV0X3RleHQ7CiAgY291dCA8PCAiSW5wdXQgcGxhaW4gdGV4dDoiIDw8ICJcbiI7CiAgY291dCA8PCAiPj4gIjsKICBjaW4uaWdub3JlKCk7CiAgZ2V0bGluZShjaW4sIGlucHV0X3RleHQpOwogIHZlY3RvcjxzdHJpbmc+IHBsYWluX3RleHQoMSk7CgogIGludCBrID0gMDsKICBmb3IgKGludCBpID0gMDsgaSA8IGlucHV0X3RleHQubGVuZ3RoKCk7IGkrKykgewogICAgc3RyaW5nIGNoYXJhY3RlciA9ICIiOwogICAgZm9yKGludCBqID0gNzsgaiA+PSAwOyBqLS0pIHsKICAgICAgYm9vbCBpc19zZXQgPSBpbnB1dF90ZXh0W2ldICYgKDEgPDwgaik7CiAgICAgIGlmIChpc19zZXQgPT0gMSkgewogICAgICAgIGNoYXJhY3RlciA9IGNoYXJhY3RlciArICIxIjsKICAgICAgfSBlbHNlIHsKICAgICAgICBjaGFyYWN0ZXIgPSBjaGFyYWN0ZXIgKyAiMCI7CiAgICAgIH0KICAgIH0KICAgIHN0cmluZyBjaGFyYWN0ZXJfbGVmdCwgY2hhcmFjdGVyX3JpZ2h0OwogICAgc3BsaXRfc3RyaW5nKGNoYXJhY3RlciwgY2hhcmFjdGVyX2xlZnQsIGNoYXJhY3Rlcl9yaWdodCk7CiAgICBpZiAocGxhaW5fdGV4dFtrXS5sZW5ndGgoKSA9PSAxNikgewogICAgICBrKys7CiAgICAgIHBsYWluX3RleHQucHVzaF9iYWNrKCIiICk7CiAgICB9CiAgICBwbGFpbl90ZXh0W2tdID0gcGxhaW5fdGV4dFtrXSArIGJpbl90b19oZXgoY2hhcmFjdGVyX2xlZnQpOwogICAgcGxhaW5fdGV4dFtrXSA9IHBsYWluX3RleHRba10gKyBiaW5fdG9faGV4KGNoYXJhY3Rlcl9yaWdodCk7CiAgfQoKICBpZiAocGxhaW5fdGV4dFtrXS5sZW5ndGgoKSAhPSAxNikgewogICAgZm9yIChpbnQgaSA9IHBsYWluX3RleHRba10ubGVuZ3RoKCk7IGkgPCAxNjsgaSsrKSB7CiAgICAgIHBsYWluX3RleHRba10gPSBwbGFpbl90ZXh0W2tdICsgJzAnOwogICAgfQogIH0KICByZXR1cm4gcGxhaW5fdGV4dDsKfQoKc3RyaW5nIG91dHB1dF9kZWNyeXB0KHZlY3RvcjxzdHJpbmc+IHBsYWluX3RleHRfaGV4KSB7CiAgc3RyaW5nIHJldCA9ICIiOwogIGZvciAoaW50IGkgPSAwOyBpIDwgcGxhaW5fdGV4dF9oZXguc2l6ZSgpOyBpKyspIHsKICAgIGZvciAoaW50IGogPSAwOyBqIDwgMTY7IGogKz0gMikgewogICAgICBzdHJpbmcgdHdvX2hleCA9IHBsYWluX3RleHRfaGV4W2ldLnN1YnN0cihqLCAyKTsKICAgICAgaW50IHZhbHVlID0gc3RvaSh0d29faGV4LCAwLCAxNik7CiAgICAgIGlmICh2YWx1ZSAhPSAwKSB7CiAgICAgICAgcmV0ICs9IChjaGFyKXZhbHVlOwogICAgICB9CiAgICB9CiAgfQogIHJldHVybiByZXQ7Cn0KCmludCBtYWluKCkgewogIHdoaWxlICgxKSB7CiAgICBpbnQgbWVudTsKICAgIGNvdXQgPDwgInx8PT09PT09PT09PT09PT09PT09PT09PSIgPDwgInx8IiA8PCAnXG4nOwogICAgY291dCA8PCAifHwgV2VsbGNvbWUgdG8gREVTIiA8PCAiXHQiIDw8ICJ8fCIgPDwgJ1xuJzsKICAgIGNvdXQgPDwgInx8IENob29zZSBNZW51OiIgPDwgIlx0XHQiIDw8ICJ8fCIgPDwgJ1xuJzsgCiAgICBjb3V0IDw8ICJ8fCAxOiBFbmNyeXB0IFRleHQiIDw8ICJcdCIgPDwgInx8IiA8PCAnXG4nOwogICAgY291dCA8PCAifHwgMjogRGVjcnlwdCBUZXh0IiA8PCAiXHQiIDw8ICJ8fCIgPDwgJ1xuJzsKICAgIGNvdXQgPDwgInx8IDA6IEV4aXQiIDw8ICJcdFx0IiA8PCAifHwiIDw8ICdcbic7CiAgICBjb3V0IDw8ICJ8fCA+PiAiOwogICAgY2luID4+IG1lbnU7CiAgICBjb3V0IDw8ICJ8fD09PT09PT09PT09PT09PT09PT09PT0iIDw8ICJ8fCIgPDwgJ1xuJyA8PCAnXG4nOwoKICAgIGlmIChtZW51ID09IDEpIHsKICAgICAgY291dCA8PCAiPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09IiA8PCAnXG4nOwogICAgICB2ZWN0b3I8c3RyaW5nPiBwbGFpbl90ZXh0ID0gaW5wdXRfZW5jcnlwdCgpOwogICAgICBjb25zdCBpbnQgbWVzc2FnZV9zaXplID0gcGxhaW5fdGV4dC5zaXplKCk7CiAgICAgIHJvdW5kX2tleXMga2V5ID0gZ2VuZXJhdGVfcm91bmRfa2V5cygiZW5jcnlwdGlvbl9zY2hlbWUiKTsKICAgICAgdmVjdG9yPHN0cmluZz4gY2hpcGVyX3RleHQ7CgogICAgICBjb3V0IDw8ICJcbiIgPDwgIkVuY3J5cHRpbmcgcGxhaW4gdGV4dC4uLiIgPDwgIlxuIjsgIAogICAgICBmb3IgKGludCBpID0gMDsgaSA8IG1lc3NhZ2Vfc2l6ZTsgaSsrKSB7CiAgICAgICAgY2hpcGVyX3RleHQucHVzaF9iYWNrKERFU19lbmNyeXB0KHBsYWluX3RleHRbaV0sIGtleSkpOwogICAgICAgIGNvdXQgPDwgIlBsYWluIHRleHQgZW5jcnlwdGVkIFsiIDw8IGkgKyAxIDw8ICIvIiA8PCBtZXNzYWdlX3NpemUgPDwgIl0iIDw8ICdcbicgPDwgJ1xuJzsKICAgICAgfQogICAgICBjb3V0IDw8ICJLZXkgPSAiIDw8IGtleS5yYW5kb21faGV4IDw8ICdcbic7CiAgICAgIGNvdXQgPDwgIkNoaXBlciB0ZXh0ID0geyIgPDwgJ1xuJzsKICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBtZXNzYWdlX3NpemU7IGkrKykgewogICAgICAgIGNvdXQgPDwgY2hpcGVyX3RleHRbaV07CiAgICAgIH0KICAgICAgY291dCA8PCAnXG4nIDw8ICJ9IiA8PCAnXG4nOwogICAgICBjb3V0IDw8ICI9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0iIDw8ICdcbicgPDwgJ1xuJzsKICAgIH0gZWxzZSBpZiAobWVudSA9PSAyKSB7ICAKICAgICAgY291dCA8PCAiPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09IiA8PCAnXG4nOwogICAgICBzdHJpbmcga2V5LCBjaGlwZXJfdGV4dDsKICAgICAgdmVjdG9yPHN0cmluZz4gcGxhaW5fdGV4dF9oZXg7CiAgICAgIGNvdXQgPDwgIklucHV0IGtleToiIDw8ICdcbicgPDwgIj4+ICI7CiAgICAgIGNpbiA+PiBrZXk7CiAgICAgIGNvdXQgPDwgIklucHV0IGNoaXBlciB0ZXh0OiIgPDwgJ1xuJyA8PCAiPj4gIjsKICAgICAgY2luID4+IGNoaXBlcl90ZXh0OwogICAgICBjb25zdCBpbnQgbWVzc2FnZV9zaXplID0gY2hpcGVyX3RleHQubGVuZ3RoKCkgLyAxNjsKICAgICAgY291dCA8PCAiXG4iIDw8ICJEZWNyeXB0aW5nIGNoaXBlciB0ZXh0Li4uIiA8PCAiXG4iOwogICAgICBmb3IgKGludCBpID0gMDsgaSA8IGNoaXBlcl90ZXh0Lmxlbmd0aCgpOyBpICs9IDE2KSB7CiAgICAgICAgc3RyaW5nIGNoaXBlcl90ZXh0X3BhcnRpdGlvbiA9IGNoaXBlcl90ZXh0LnN1YnN0cihpLCAxNik7CiAgICAgICAgcGxhaW5fdGV4dF9oZXgucHVzaF9iYWNrKERFU19kZWNyeXB0KGNoaXBlcl90ZXh0X3BhcnRpdGlvbiwga2V5KSk7CiAgICAgICAgY291dCA8PCAiQ2hpcGVyIHRleHQgZGVjcnlwdGVkIFsiIDw8IGkgLyAxNiArIDEgPDwgIi8iIDw8IG1lc3NhZ2Vfc2l6ZSA8PCAiXSIgPDwgJ1xuJyA8PCAnXG4nOwogICAgICB9CiAgICAgIHN0cmluZyBwbGFpbl90ZXh0ID0gb3V0cHV0X2RlY3J5cHQocGxhaW5fdGV4dF9oZXgpOwogICAgICBjb3V0IDw8IHBsYWluX3RleHQgPDwgJ1xuJzsKICAgICAgY291dCA8PCAiPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09IiA8PCAnXG4nIDw8ICdcbic7CiAgICB9IGVsc2UgaWYgKG1lbnUgPT0gMCkgewogICAgICBicmVhazsKICAgIH0gZWxzZSB7CiAgICAgIGNvdXQgPDwgIkludmFsaWQgY29tbWFuZCIgPDwgJ1xuJyA8PCAnXG4nOwogICAgfQogIH0KCiAgcmV0dXJuIDA7Cn0=