feat: metamorphic test and partial verification
This commit is contained in:
parent
b2fac0ffd3
commit
4b09788441
@ -4,12 +4,15 @@
|
||||
Possible references include:
|
||||
https://stackoverflow.com/a/7304184 - custom delimeter for istream
|
||||
*/
|
||||
#include "lib_random.h"
|
||||
#include <cassert>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <locale>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
struct semicolon_is_space : std::ctype<char> {
|
||||
@ -25,8 +28,8 @@ struct semicolon_is_space : std::ctype<char> {
|
||||
|
||||
class input {
|
||||
public:
|
||||
std::string s;
|
||||
unsigned long k;
|
||||
std::string s = "";
|
||||
unsigned long k = 1;
|
||||
friend std::istream &operator>>(std::istream &in, input &i);
|
||||
friend std::ostream &operator<<(std::ostream &out, const input &i);
|
||||
};
|
||||
@ -121,7 +124,34 @@ result find(const std::string &s, const unsigned long k) {
|
||||
return r;
|
||||
}
|
||||
|
||||
void test(const test_case &t) {
|
||||
std::cout << t;
|
||||
if (find(t.i.s, t.i.k) == t.r) {
|
||||
std::cout << "Test case with string \"" << t.i.s << "\" and k=" << t.i.k
|
||||
<< " passed.\n";
|
||||
} else {
|
||||
std::cout << std::flush;
|
||||
std::cerr << "TEST CASE WITH STRING \"" << t.i.s << "\" AND k=" << t.i.k
|
||||
<< " FAILED.\n";
|
||||
}
|
||||
std::cout << "\n";
|
||||
}
|
||||
|
||||
bool K_verify(const test_case &t) {
|
||||
// Verifies if found solution has exactly K unique characters (one of the
|
||||
// problem requirement)
|
||||
if (!t.r.match_found)
|
||||
return true; // Do not check if no match found
|
||||
std::unordered_set<char> unique_chars;
|
||||
for (const char c : t.i.s.substr(t.r.longest_start,
|
||||
t.r.longest_end - t.r.longest_start + 1)) {
|
||||
unique_chars.insert(c);
|
||||
}
|
||||
return unique_chars.size() == t.i.k;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
std::cout << "Processing static test cases from input file (if any)\n";
|
||||
semicolon_is_space delimeter;
|
||||
for (int i = 1; i < argc; i++) {
|
||||
std::ifstream f(argv[i]);
|
||||
@ -130,16 +160,43 @@ int main(int argc, char *argv[]) {
|
||||
test_case t;
|
||||
f >> t;
|
||||
if (t.i.s.length()) { // skip empty line/string inputs
|
||||
std::cout << t;
|
||||
if (find(t.i.s, t.i.k) == t.r) {
|
||||
std::cout << "Test case with string \"" << t.i.s
|
||||
<< "\" and k=" << t.i.k << " passed.\n";
|
||||
} else {
|
||||
std::cout << std::flush;
|
||||
std::cerr << "TEST CASE WITH STRING \"" << t.i.s
|
||||
<< "\" AND k=" << t.i.k << " FAILED.\n";
|
||||
test(t);
|
||||
}
|
||||
}
|
||||
|
||||
std::cout
|
||||
<< "\n\n\nPerforming metamorphic tests from randomly generated input "
|
||||
"(string and K values)"
|
||||
<< std::endl;
|
||||
random_number_generator<unsigned int> random_ascii_char(97, 122); // a-z
|
||||
random_number_generator<unsigned int> rng;
|
||||
for (unsigned int i = 0; i < 1; i++) {
|
||||
test_case t;
|
||||
t.i.s += (char)random_ascii_char();
|
||||
std::cout << t;
|
||||
t.r = find(t.i.s, t.i.k);
|
||||
for (unsigned int j = 0; j < 10; j++) {
|
||||
for (unsigned int k = 0, increase_str_len_by = rng(100, 1000);
|
||||
k < increase_str_len_by; k++) {
|
||||
t.i.s += (char)random_ascii_char();
|
||||
std::cout << t;
|
||||
result r = find(t.i.s, t.i.k);
|
||||
if (r.match_found && t.r.match_found)
|
||||
assert(r.longest_end - r.longest_start >=
|
||||
t.r.longest_end - t.r.longest_start);
|
||||
t.r = r;
|
||||
assert(K_verify(t));
|
||||
}
|
||||
std::cout << "\n";
|
||||
while (t.r.match_found) {
|
||||
std::cout << t;
|
||||
result r = find(t.i.s, ++t.i.k);
|
||||
if (r.match_found)
|
||||
assert(r.longest_end - r.longest_start >=
|
||||
t.r.longest_end - t.r.longest_start);
|
||||
t.r = r;
|
||||
assert(K_verify(t));
|
||||
}
|
||||
t.i.k = rng(1, --t.i.k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user