148e3f363b 2011-09-10 kinaba: #include <iostream> 148e3f363b 2011-09-10 kinaba: #include <sstream> 148e3f363b 2011-09-10 kinaba: #include <iomanip> 148e3f363b 2011-09-10 kinaba: #include <vector> 148e3f363b 2011-09-10 kinaba: #include <string> 148e3f363b 2011-09-10 kinaba: #include <map> 148e3f363b 2011-09-10 kinaba: #include <set> 148e3f363b 2011-09-10 kinaba: #include <algorithm> 148e3f363b 2011-09-10 kinaba: #include <numeric> 148e3f363b 2011-09-10 kinaba: #include <iterator> 148e3f363b 2011-09-10 kinaba: #include <functional> 148e3f363b 2011-09-10 kinaba: #include <complex> 148e3f363b 2011-09-10 kinaba: #include <queue> 148e3f363b 2011-09-10 kinaba: #include <stack> 148e3f363b 2011-09-10 kinaba: #include <cmath> 148e3f363b 2011-09-10 kinaba: #include <cassert> 148e3f363b 2011-09-10 kinaba: #include <cstring> 148e3f363b 2011-09-10 kinaba: using namespace std; 148e3f363b 2011-09-10 kinaba: typedef long long LL; 148e3f363b 2011-09-10 kinaba: typedef complex<double> CMP; 148e3f363b 2011-09-10 kinaba: 148e3f363b 2011-09-10 kinaba: class NetworkXOneTimePad { public: 148e3f363b 2011-09-10 kinaba: int crack(vector <string> plaintexts, vector <string> ciphertexts) 148e3f363b 2011-09-10 kinaba: { 148e3f363b 2011-09-10 kinaba: set<string> possible_keys; 148e3f363b 2011-09-10 kinaba: for(int i=0; i<plaintexts.size(); ++i) 148e3f363b 2011-09-10 kinaba: for(int j=0; j<ciphertexts.size(); ++j) 148e3f363b 2011-09-10 kinaba: possible_keys.insert(key(plaintexts[i], ciphertexts[j])); 148e3f363b 2011-09-10 kinaba: 148e3f363b 2011-09-10 kinaba: int cnt = 0; 148e3f363b 2011-09-10 kinaba: for(set<string>::iterator it=possible_keys.begin(); it!=possible_keys.end(); ++it) 148e3f363b 2011-09-10 kinaba: { 148e3f363b 2011-09-10 kinaba: const string& key = *it; 148e3f363b 2011-09-10 kinaba: set<string> target(plaintexts.begin(), plaintexts.end()); 148e3f363b 2011-09-10 kinaba: for(int i=0; i<ciphertexts.size(); ++i) { 148e3f363b 2011-09-10 kinaba: string ci = cipher(ciphertexts[i], key); 148e3f363b 2011-09-10 kinaba: if( !target.count(ci) ) 148e3f363b 2011-09-10 kinaba: goto next; 148e3f363b 2011-09-10 kinaba: target.erase(ci); 148e3f363b 2011-09-10 kinaba: } 148e3f363b 2011-09-10 kinaba: ++cnt; 148e3f363b 2011-09-10 kinaba: next:; 148e3f363b 2011-09-10 kinaba: } 148e3f363b 2011-09-10 kinaba: return cnt; 148e3f363b 2011-09-10 kinaba: } 148e3f363b 2011-09-10 kinaba: 148e3f363b 2011-09-10 kinaba: string cipher(const string& a, const string& b) 148e3f363b 2011-09-10 kinaba: { 148e3f363b 2011-09-10 kinaba: string c; 148e3f363b 2011-09-10 kinaba: for(int i=0; i<a.size(); ++i) 148e3f363b 2011-09-10 kinaba: c += char(a[i]^(b[i]=='1')); 148e3f363b 2011-09-10 kinaba: return c; 148e3f363b 2011-09-10 kinaba: } 148e3f363b 2011-09-10 kinaba: 148e3f363b 2011-09-10 kinaba: string key(const string& a, const string& b) 148e3f363b 2011-09-10 kinaba: { 148e3f363b 2011-09-10 kinaba: string c; 148e3f363b 2011-09-10 kinaba: for(int i=0; i<a.size(); ++i) 148e3f363b 2011-09-10 kinaba: c += (a[i]==b[i] ? '0' : '1'); 148e3f363b 2011-09-10 kinaba: return c; 148e3f363b 2011-09-10 kinaba: } 148e3f363b 2011-09-10 kinaba: }; 148e3f363b 2011-09-10 kinaba: 148e3f363b 2011-09-10 kinaba: // BEGIN CUT HERE 148e3f363b 2011-09-10 kinaba: #include <ctime> 148e3f363b 2011-09-10 kinaba: double start_time; string timer() 148e3f363b 2011-09-10 kinaba: { ostringstream os; os << " (" << int((clock()-start_time)/CLOCKS_PER_SEC*1000) << " msec)"; return os.str(); } 148e3f363b 2011-09-10 kinaba: template<typename T> ostream& operator<<(ostream& os, const vector<T>& v) 148e3f363b 2011-09-10 kinaba: { os << "{ "; 148e3f363b 2011-09-10 kinaba: for(typename vector<T>::const_iterator it=v.begin(); it!=v.end(); ++it) 148e3f363b 2011-09-10 kinaba: os << '\"' << *it << '\"' << (it+1==v.end() ? "" : ", "); os << " }"; return os; } 148e3f363b 2011-09-10 kinaba: void verify_case(const int& Expected, const int& Received) { 148e3f363b 2011-09-10 kinaba: bool ok = (Expected == Received); 148e3f363b 2011-09-10 kinaba: if(ok) cerr << "PASSED" << timer() << endl; else { cerr << "FAILED" << timer() << endl; 148e3f363b 2011-09-10 kinaba: cerr << "\to: \"" << Expected << '\"' << endl << "\tx: \"" << Received << '\"' << endl; } } 148e3f363b 2011-09-10 kinaba: #define CASE(N) {cerr << "Test Case #" << N << "..." << flush; start_time=clock(); 148e3f363b 2011-09-10 kinaba: #define END verify_case(_, NetworkXOneTimePad().crack(plaintexts, ciphertexts));} 148e3f363b 2011-09-10 kinaba: int main(){ 148e3f363b 2011-09-10 kinaba: 148e3f363b 2011-09-10 kinaba: CASE(0) 148e3f363b 2011-09-10 kinaba: string plaintexts_[] = {"110", "001"}; 148e3f363b 2011-09-10 kinaba: vector <string> plaintexts(plaintexts_, plaintexts_+sizeof(plaintexts_)/sizeof(*plaintexts_)); 148e3f363b 2011-09-10 kinaba: string ciphertexts_[] = {"101", "010"}; 148e3f363b 2011-09-10 kinaba: vector <string> ciphertexts(ciphertexts_, ciphertexts_+sizeof(ciphertexts_)/sizeof(*ciphertexts_)); 148e3f363b 2011-09-10 kinaba: int _ = 2; 148e3f363b 2011-09-10 kinaba: END 148e3f363b 2011-09-10 kinaba: CASE(1) 148e3f363b 2011-09-10 kinaba: string plaintexts_[] = {"00", "01", "10", "11"}; 148e3f363b 2011-09-10 kinaba: vector <string> plaintexts(plaintexts_, plaintexts_+sizeof(plaintexts_)/sizeof(*plaintexts_)); 148e3f363b 2011-09-10 kinaba: string ciphertexts_[] = {"00", "01", "10", "11"}; 148e3f363b 2011-09-10 kinaba: vector <string> ciphertexts(ciphertexts_, ciphertexts_+sizeof(ciphertexts_)/sizeof(*ciphertexts_)); 148e3f363b 2011-09-10 kinaba: int _ = 4; 148e3f363b 2011-09-10 kinaba: END 148e3f363b 2011-09-10 kinaba: CASE(2) 148e3f363b 2011-09-10 kinaba: string plaintexts_[] = {"01", "10"}; 148e3f363b 2011-09-10 kinaba: vector <string> plaintexts(plaintexts_, plaintexts_+sizeof(plaintexts_)/sizeof(*plaintexts_)); 148e3f363b 2011-09-10 kinaba: string ciphertexts_[] = {"00"}; 148e3f363b 2011-09-10 kinaba: vector <string> ciphertexts(ciphertexts_, ciphertexts_+sizeof(ciphertexts_)/sizeof(*ciphertexts_)); 148e3f363b 2011-09-10 kinaba: int _ = 2; 148e3f363b 2011-09-10 kinaba: END 148e3f363b 2011-09-10 kinaba: CASE(3) 148e3f363b 2011-09-10 kinaba: string plaintexts_[] = {"000", "111", "010", "101", "110", "001"}; 148e3f363b 2011-09-10 kinaba: vector <string> plaintexts(plaintexts_, plaintexts_+sizeof(plaintexts_)/sizeof(*plaintexts_)); 148e3f363b 2011-09-10 kinaba: string ciphertexts_[] = {"011", "100"}; 148e3f363b 2011-09-10 kinaba: vector <string> ciphertexts(ciphertexts_, ciphertexts_+sizeof(ciphertexts_)/sizeof(*ciphertexts_)); 148e3f363b 2011-09-10 kinaba: int _ = 6; 148e3f363b 2011-09-10 kinaba: END 148e3f363b 2011-09-10 kinaba: /* 148e3f363b 2011-09-10 kinaba: CASE(4) 148e3f363b 2011-09-10 kinaba: string plaintexts_[] = ; 148e3f363b 2011-09-10 kinaba: vector <string> plaintexts(plaintexts_, plaintexts_+sizeof(plaintexts_)/sizeof(*plaintexts_)); 148e3f363b 2011-09-10 kinaba: string ciphertexts_[] = ; 148e3f363b 2011-09-10 kinaba: vector <string> ciphertexts(ciphertexts_, ciphertexts_+sizeof(ciphertexts_)/sizeof(*ciphertexts_)); 148e3f363b 2011-09-10 kinaba: int _ = ; 148e3f363b 2011-09-10 kinaba: END 148e3f363b 2011-09-10 kinaba: CASE(5) 148e3f363b 2011-09-10 kinaba: string plaintexts_[] = ; 148e3f363b 2011-09-10 kinaba: vector <string> plaintexts(plaintexts_, plaintexts_+sizeof(plaintexts_)/sizeof(*plaintexts_)); 148e3f363b 2011-09-10 kinaba: string ciphertexts_[] = ; 148e3f363b 2011-09-10 kinaba: vector <string> ciphertexts(ciphertexts_, ciphertexts_+sizeof(ciphertexts_)/sizeof(*ciphertexts_)); 148e3f363b 2011-09-10 kinaba: int _ = ; 148e3f363b 2011-09-10 kinaba: END 148e3f363b 2011-09-10 kinaba: */ 148e3f363b 2011-09-10 kinaba: } 148e3f363b 2011-09-10 kinaba: // END CUT HERE