#include <iostream>
#include <cmath>
#include <string>
#include <vector>
#include <functional>
using namespace std;
// ═══════════════════════════════════════════════════════
// СТРУКТУРА РЕЗУЛЬТАТА
// ═══════════════════════════════════════════════════════
struct QuadraticResult {
enum class Type { NO_ROOTS, ONE_ROOT, TWO_ROOTS };
Type type;
float root1 = 0.0f;
float root2 = 0.0f;
string message;
};
// ═══════════════════════════════════════════════════════
// ФУНКЦИЯ (переработана: возвращает результат)
// ═══════════════════════════════════════════════════════
QuadraticResult quadratic_equation(float a, float b, float c) {
QuadraticResult result;
float d = b * b - 4 * c * a;
if (d < 0) {
result.type = QuadraticResult::Type::NO_ROOTS;
result.message = "Корней нет!";
} else if (d == 0) {
result.type = QuadraticResult::Type::ONE_ROOT;
result.root1 = -b / (2 * a);
result.message = "Единственный Корень";
} else {
result.type = QuadraticResult::Type::TWO_ROOTS;
result.root1 = (-b + sqrt(d)) / (2 * a);
result.root2 = (-b - sqrt(d)) / (2 * a);
result.message = "Два корня";
}
return result;
}
// ═══════════════════════════════════════════════════════
// МИНИ-ФРЕЙМВОРК ДЛЯ ТЕСТОВ
// ═══════════════════════════════════════════════════════
int tests_passed = 0;
int tests_failed = 0;
void EXPECT_EQ_TYPE(const string& name, QuadraticResult::Type actual, QuadraticResult::Type expected) {
if (actual == expected) {
cout << " [OK] " << name << "\n";
tests_passed++;
} else {
cout << " [FAIL] " << name << " → ожидался тип " << (int)expected << ", получен " << (int)actual << "\n";
tests_failed++;
}
}
void EXPECT_NEAR_VAL(const string& name, float actual, float expected, float eps = 1e-3f) {
if (fabs(actual - expected) <= eps) {
cout << " [OK] " << name << "\n";
tests_passed++;
} else {
cout << " [FAIL] " << name << " → ожидалось " << expected << ", получено " << actual << "\n";
tests_failed++;
}
}
void EXPECT_EQ_STR(const string& name, const string& actual, const string& expected) {
if (actual == expected) {
cout << " [OK] " << name << "\n";
tests_passed++;
} else {
cout << " [FAIL] " << name << " → ожидалось \"" << expected << "\", получено \"" << actual << "\"\n";
tests_failed++;
}
}
void RUN_TEST(const string& group, const string& name, function<void()> fn) {
cout << "\n[TEST] " << group << " :: " << name << "\n";
fn();
}
// ═══════════════════════════════════════════════════════
// МОДУЛЬНЫЕ ТЕСТЫ
// ═══════════════════════════════════════════════════════
void test_two_roots() {
// Тест 1: исходный вызов из кода → x=-1, x=-3
RUN_TEST("TwoRoots", "BasicExample (1, 4, 3)", []() {
auto r = quadratic_equation(1, 4, 3);
EXPECT_EQ_TYPE ("тип = TWO_ROOTS", r.type, QuadraticResult::Type::TWO_ROOTS);
EXPECT_NEAR_VAL("root1 == -1.0", r.root1, -1.0f);
EXPECT_NEAR_VAL("root2 == -3.0", r.root2, -3.0f);
});
// Тест 2: исходный вызов (53, 400, 100) — корни подставляются обратно
RUN_TEST("TwoRoots", "BigCoefficients (53, 400, 100)", []() {
auto r = quadratic_equation(53, 400, 100);
EXPECT_EQ_TYPE("тип = TWO_ROOTS", r.type, QuadraticResult::Type::TWO_ROOTS);
float check1 = 53*r.root1*r.root1 + 400*r.root1 + 100;
float check2 = 53*r.root2*r.root2 + 400*r.root2 + 100;
EXPECT_NEAR_VAL("a*x1^2+b*x1+c == 0", check1, 0.0f, 0.5f);
EXPECT_NEAR_VAL("a*x2^2+b*x2+c == 0", check2, 0.0f, 0.5f);
});
// Тест 3: x^2 - 5x + 6 = 0 → x=3, x=2
RUN_TEST("TwoRoots", "PositiveRoots (1, -5, 6)", []() {
auto r = quadratic_equation(1, -5, 6);
EXPECT_EQ_TYPE ("тип = TWO_ROOTS", r.type, QuadraticResult::Type::TWO_ROOTS);
EXPECT_NEAR_VAL("root1 == 3.0", r.root1, 3.0f);
EXPECT_NEAR_VAL("root2 == 2.0", r.root2, 2.0f);
});
// Тест 4: 2x^2 - 4x - 6 = 0 → x=3, x=-1
RUN_TEST("TwoRoots", "LeadCoeff=2 (2, -4, -6)", []() {
auto r = quadratic_equation(2, -4, -6);
EXPECT_EQ_TYPE ("тип = TWO_ROOTS", r.type, QuadraticResult::Type::TWO_ROOTS);
EXPECT_NEAR_VAL("root1 == 3.0", r.root1, 3.0f);
EXPECT_NEAR_VAL("root2 == -1.0", r.root2, -1.0f);
});
// Тест 5: x^2 - 1 = 0 → x=1, x=-1
RUN_TEST("TwoRoots", "DifferenceOfSquares (1, 0, -1)", []() {
auto r = quadratic_equation(1, 0, -1);
EXPECT_EQ_TYPE ("тип = TWO_ROOTS", r.type, QuadraticResult::Type::TWO_ROOTS);
EXPECT_NEAR_VAL("root1 == 1.0", r.root1, 1.0f);
EXPECT_NEAR_VAL("root2 == -1.0", r.root2, -1.0f);
});
}
void test_one_root() {
// Тест 6: x^2 + 2x + 1 = 0 → x=-1
RUN_TEST("OneRoot", "PerfectSquare (1, 2, 1)", []() {
auto r = quadratic_equation(1, 2, 1);
EXPECT_EQ_TYPE ("тип = ONE_ROOT", r.type, QuadraticResult::Type::ONE_ROOT);
EXPECT_NEAR_VAL("root1 == -1.0", r.root1, -1.0f);
});
// Тест 7: 4x^2 - 4x + 1 = 0 → x=0.5
RUN_TEST("OneRoot", "LeadCoeff=4 (4, -4, 1)", []() {
auto r = quadratic_equation(4, -4, 1);
EXPECT_EQ_TYPE ("тип = ONE_ROOT", r.type, QuadraticResult::Type::ONE_ROOT);
EXPECT_NEAR_VAL("root1 == 0.5", r.root1, 0.5f);
});
// Тест 8: 9x^2 + 6x + 1 = 0 → x=-1/3
RUN_TEST("OneRoot", "NegativeRoot (9, 6, 1)", []() {
auto r = quadratic_equation(9, 6, 1);
EXPECT_EQ_TYPE ("тип = ONE_ROOT", r.type, QuadraticResult::Type::ONE_ROOT);
EXPECT_NEAR_VAL("root1 == -0.3333", r.root1, -1.0f/3.0f);
});
}
void test_no_roots() {
// Тест 9: исходный вызов из кода (14, 28, 320)
RUN_TEST("NoRoots", "OriginalCall (14, 28, 320)", []() {
auto r = quadratic_equation(14, 28, 320);
EXPECT_EQ_TYPE("тип = NO_ROOTS", r.type, QuadraticResult::Type::NO_ROOTS);
});
// Тест 10: x^2 + x + 1 = 0
RUN_TEST("NoRoots", "Classic (1, 1, 1)", []() {
auto r = quadratic_equation(1, 1, 1);
EXPECT_EQ_TYPE("тип = NO_ROOTS", r.type, QuadraticResult::Type::NO_ROOTS);
});
// Тест 11: x^2 + 1 = 0
RUN_TEST("NoRoots", "NoB (1, 0, 1)", []() {
auto r = quadratic_equation(1, 0, 1);
EXPECT_EQ_TYPE("тип = NO_ROOTS", r.type, QuadraticResult::Type::NO_ROOTS);
});
// Тест 12: 3x^2 + 2x + 5 = 0
RUN_TEST("NoRoots", "LargeC (3, 2, 5)", []() {
auto r = quadratic_equation(3, 2, 5);
EXPECT_EQ_TYPE("тип = NO_ROOTS", r.type, QuadraticResult::Type::NO_ROOTS);
});
}
void test_messages() {
// Тест 13
RUN_TEST("Messages", "NoRoots message", []() {
auto r = quadratic_equation(1, 0, 1);
EXPECT_EQ_STR("message == 'Корней нет!'", r.message, "Корней нет!");
});
// Тест 14
RUN_TEST("Messages", "OneRoot message", []() {
auto r = quadratic_equation(1, 2, 1);
EXPECT_EQ_STR("message == 'Единственный Корень'", r.message, "Единственный Корень");
});
// Тест 15
RUN_TEST("Messages", "TwoRoots message", []() {
auto r = quadratic_equation(1, 4, 3);
EXPECT_EQ_STR("message == 'Два корня'", r.message, "Два корня");
});
}
// ═══════════════════════════════════════════════════════
// MAIN
// ═══════════════════════════════════════════════════════
int main() {
cout << "╔══════════════════════════════════════════╗\n";
cout << "║ МОДУЛЬНЫЕ ТЕСТЫ: quadratic_equation ║\n";
cout << "╚══════════════════════════════════════════╝\n";
test_two_roots();
test_one_root();
test_no_roots();
test_messages();
cout << "\n══════════════════════════════════════════\n";
cout << " Итого: " << (tests_passed + tests_failed) << " тестов\n";
cout << " Пройдено: " << tests_passed << "\n";
cout << " Провалено: " << tests_failed << "\n";
cout << "══════════════════════════════════════════\n";
return tests_failed == 0 ? 0 : 1;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8Y21hdGg+CiNpbmNsdWRlIDxzdHJpbmc+CiNpbmNsdWRlIDx2ZWN0b3I+CiNpbmNsdWRlIDxmdW5jdGlvbmFsPgoKdXNpbmcgbmFtZXNwYWNlIHN0ZDsKCi8vIOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkAovLyAg0KHQotCg0KPQmtCi0KPQoNCQINCg0JXQl9Cj0JvQrNCi0JDQotCQCi8vIOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkAoKc3RydWN0IFF1YWRyYXRpY1Jlc3VsdCB7CiAgICBlbnVtIGNsYXNzIFR5cGUgeyBOT19ST09UUywgT05FX1JPT1QsIFRXT19ST09UUyB9OwogICAgVHlwZSB0eXBlOwogICAgZmxvYXQgcm9vdDEgPSAwLjBmOwogICAgZmxvYXQgcm9vdDIgPSAwLjBmOwogICAgc3RyaW5nIG1lc3NhZ2U7Cn07CgovLyDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZAKLy8gINCk0KPQndCa0KbQmNCvICjQv9C10YDQtdGA0LDQsdC+0YLQsNC90LA6INCy0L7Qt9Cy0YDQsNGJ0LDQtdGCINGA0LXQt9GD0LvRjNGC0LDRgikKLy8g4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQCgpRdWFkcmF0aWNSZXN1bHQgcXVhZHJhdGljX2VxdWF0aW9uKGZsb2F0IGEsIGZsb2F0IGIsIGZsb2F0IGMpIHsKICAgIFF1YWRyYXRpY1Jlc3VsdCByZXN1bHQ7CiAgICBmbG9hdCBkID0gYiAqIGIgLSA0ICogYyAqIGE7CgogICAgaWYgKGQgPCAwKSB7CiAgICAgICAgcmVzdWx0LnR5cGUgICAgPSBRdWFkcmF0aWNSZXN1bHQ6OlR5cGU6Ok5PX1JPT1RTOwogICAgICAgIHJlc3VsdC5tZXNzYWdlID0gItCa0L7RgNC90LXQuSDQvdC10YIhIjsKICAgIH0gZWxzZSBpZiAoZCA9PSAwKSB7CiAgICAgICAgcmVzdWx0LnR5cGUgICAgPSBRdWFkcmF0aWNSZXN1bHQ6OlR5cGU6Ok9ORV9ST09UOwogICAgICAgIHJlc3VsdC5yb290MSAgID0gLWIgLyAoMiAqIGEpOwogICAgICAgIHJlc3VsdC5tZXNzYWdlID0gItCV0LTQuNC90YHRgtCy0LXQvdC90YvQuSDQmtC+0YDQtdC90YwiOwogICAgfSBlbHNlIHsKICAgICAgICByZXN1bHQudHlwZSAgICA9IFF1YWRyYXRpY1Jlc3VsdDo6VHlwZTo6VFdPX1JPT1RTOwogICAgICAgIHJlc3VsdC5yb290MSAgID0gKC1iICsgc3FydChkKSkgLyAoMiAqIGEpOwogICAgICAgIHJlc3VsdC5yb290MiAgID0gKC1iIC0gc3FydChkKSkgLyAoMiAqIGEpOwogICAgICAgIHJlc3VsdC5tZXNzYWdlID0gItCU0LLQsCDQutC+0YDQvdGPIjsKICAgIH0KICAgIHJldHVybiByZXN1bHQ7Cn0KCi8vIOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkAovLyAg0JzQmNCd0Jgt0KTQoNCV0JnQnNCS0J7QoNCaINCU0JvQryDQotCV0KHQotCe0JIKLy8g4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQCgppbnQgdGVzdHNfcGFzc2VkID0gMDsKaW50IHRlc3RzX2ZhaWxlZCA9IDA7Cgp2b2lkIEVYUEVDVF9FUV9UWVBFKGNvbnN0IHN0cmluZyYgbmFtZSwgUXVhZHJhdGljUmVzdWx0OjpUeXBlIGFjdHVhbCwgUXVhZHJhdGljUmVzdWx0OjpUeXBlIGV4cGVjdGVkKSB7CiAgICBpZiAoYWN0dWFsID09IGV4cGVjdGVkKSB7CiAgICAgICAgY291dCA8PCAiICBbT0tdICIgPDwgbmFtZSA8PCAiXG4iOwogICAgICAgIHRlc3RzX3Bhc3NlZCsrOwogICAgfSBlbHNlIHsKICAgICAgICBjb3V0IDw8ICIgIFtGQUlMXSAiIDw8IG5hbWUgPDwgIiDihpIg0L7QttC40LTQsNC70YHRjyDRgtC40L8gIiA8PCAoaW50KWV4cGVjdGVkIDw8ICIsINC/0L7Qu9GD0YfQtdC9ICIgPDwgKGludClhY3R1YWwgPDwgIlxuIjsKICAgICAgICB0ZXN0c19mYWlsZWQrKzsKICAgIH0KfQoKdm9pZCBFWFBFQ1RfTkVBUl9WQUwoY29uc3Qgc3RyaW5nJiBuYW1lLCBmbG9hdCBhY3R1YWwsIGZsb2F0IGV4cGVjdGVkLCBmbG9hdCBlcHMgPSAxZS0zZikgewogICAgaWYgKGZhYnMoYWN0dWFsIC0gZXhwZWN0ZWQpIDw9IGVwcykgewogICAgICAgIGNvdXQgPDwgIiAgW09LXSAiIDw8IG5hbWUgPDwgIlxuIjsKICAgICAgICB0ZXN0c19wYXNzZWQrKzsKICAgIH0gZWxzZSB7CiAgICAgICAgY291dCA8PCAiICBbRkFJTF0gIiA8PCBuYW1lIDw8ICIg4oaSINC+0LbQuNC00LDQu9C+0YHRjCAiIDw8IGV4cGVjdGVkIDw8ICIsINC/0L7Qu9GD0YfQtdC90L4gIiA8PCBhY3R1YWwgPDwgIlxuIjsKICAgICAgICB0ZXN0c19mYWlsZWQrKzsKICAgIH0KfQoKdm9pZCBFWFBFQ1RfRVFfU1RSKGNvbnN0IHN0cmluZyYgbmFtZSwgY29uc3Qgc3RyaW5nJiBhY3R1YWwsIGNvbnN0IHN0cmluZyYgZXhwZWN0ZWQpIHsKICAgIGlmIChhY3R1YWwgPT0gZXhwZWN0ZWQpIHsKICAgICAgICBjb3V0IDw8ICIgIFtPS10gIiA8PCBuYW1lIDw8ICJcbiI7CiAgICAgICAgdGVzdHNfcGFzc2VkKys7CiAgICB9IGVsc2UgewogICAgICAgIGNvdXQgPDwgIiAgW0ZBSUxdICIgPDwgbmFtZSA8PCAiIOKGkiDQvtC20LjQtNCw0LvQvtGB0YwgXCIiIDw8IGV4cGVjdGVkIDw8ICJcIiwg0L/QvtC70YPRh9C10L3QviBcIiIgPDwgYWN0dWFsIDw8ICJcIlxuIjsKICAgICAgICB0ZXN0c19mYWlsZWQrKzsKICAgIH0KfQoKdm9pZCBSVU5fVEVTVChjb25zdCBzdHJpbmcmIGdyb3VwLCBjb25zdCBzdHJpbmcmIG5hbWUsIGZ1bmN0aW9uPHZvaWQoKT4gZm4pIHsKICAgIGNvdXQgPDwgIlxuW1RFU1RdICIgPDwgZ3JvdXAgPDwgIiA6OiAiIDw8IG5hbWUgPDwgIlxuIjsKICAgIGZuKCk7Cn0KCi8vIOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkAovLyAg0JzQntCU0KPQm9Cs0J3Qq9CVINCi0JXQodCi0KsKLy8g4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQCgp2b2lkIHRlc3RfdHdvX3Jvb3RzKCkgewogICAgLy8g0KLQtdGB0YIgMTog0LjRgdGF0L7QtNC90YvQuSDQstGL0LfQvtCyINC40Lcg0LrQvtC00LAg4oaSIHg9LTEsIHg9LTMKICAgIFJVTl9URVNUKCJUd29Sb290cyIsICJCYXNpY0V4YW1wbGUgKDEsIDQsIDMpIiwgW10oKSB7CiAgICAgICAgYXV0byByID0gcXVhZHJhdGljX2VxdWF0aW9uKDEsIDQsIDMpOwogICAgICAgIEVYUEVDVF9FUV9UWVBFICgi0YLQuNC/ID0gVFdPX1JPT1RTIiwgICByLnR5cGUsICBRdWFkcmF0aWNSZXN1bHQ6OlR5cGU6OlRXT19ST09UUyk7CiAgICAgICAgRVhQRUNUX05FQVJfVkFMKCJyb290MSA9PSAtMS4wIiwgICAgIHIucm9vdDEsIC0xLjBmKTsKICAgICAgICBFWFBFQ1RfTkVBUl9WQUwoInJvb3QyID09IC0zLjAiLCAgICAgci5yb290MiwgLTMuMGYpOwogICAgfSk7CgogICAgLy8g0KLQtdGB0YIgMjog0LjRgdGF0L7QtNC90YvQuSDQstGL0LfQvtCyICg1MywgNDAwLCAxMDApIOKAlCDQutC+0YDQvdC4INC/0L7QtNGB0YLQsNCy0LvRj9GO0YLRgdGPINC+0LHRgNCw0YLQvdC+CiAgICBSVU5fVEVTVCgiVHdvUm9vdHMiLCAiQmlnQ29lZmZpY2llbnRzICg1MywgNDAwLCAxMDApIiwgW10oKSB7CiAgICAgICAgYXV0byByID0gcXVhZHJhdGljX2VxdWF0aW9uKDUzLCA0MDAsIDEwMCk7CiAgICAgICAgRVhQRUNUX0VRX1RZUEUoItGC0LjQvyA9IFRXT19ST09UUyIsIHIudHlwZSwgUXVhZHJhdGljUmVzdWx0OjpUeXBlOjpUV09fUk9PVFMpOwogICAgICAgIGZsb2F0IGNoZWNrMSA9IDUzKnIucm9vdDEqci5yb290MSArIDQwMCpyLnJvb3QxICsgMTAwOwogICAgICAgIGZsb2F0IGNoZWNrMiA9IDUzKnIucm9vdDIqci5yb290MiArIDQwMCpyLnJvb3QyICsgMTAwOwogICAgICAgIEVYUEVDVF9ORUFSX1ZBTCgiYSp4MV4yK2IqeDErYyA9PSAwIiwgY2hlY2sxLCAwLjBmLCAwLjVmKTsKICAgICAgICBFWFBFQ1RfTkVBUl9WQUwoImEqeDJeMitiKngyK2MgPT0gMCIsIGNoZWNrMiwgMC4wZiwgMC41Zik7CiAgICB9KTsKCiAgICAvLyDQotC10YHRgiAzOiB4XjIgLSA1eCArIDYgPSAwIOKGkiB4PTMsIHg9MgogICAgUlVOX1RFU1QoIlR3b1Jvb3RzIiwgIlBvc2l0aXZlUm9vdHMgKDEsIC01LCA2KSIsIFtdKCkgewogICAgICAgIGF1dG8gciA9IHF1YWRyYXRpY19lcXVhdGlvbigxLCAtNSwgNik7CiAgICAgICAgRVhQRUNUX0VRX1RZUEUgKCLRgtC40L8gPSBUV09fUk9PVFMiLCByLnR5cGUsICBRdWFkcmF0aWNSZXN1bHQ6OlR5cGU6OlRXT19ST09UUyk7CiAgICAgICAgRVhQRUNUX05FQVJfVkFMKCJyb290MSA9PSAzLjAiLCAgICByLnJvb3QxLCAzLjBmKTsKICAgICAgICBFWFBFQ1RfTkVBUl9WQUwoInJvb3QyID09IDIuMCIsICAgIHIucm9vdDIsIDIuMGYpOwogICAgfSk7CgogICAgLy8g0KLQtdGB0YIgNDogMnheMiAtIDR4IC0gNiA9IDAg4oaSIHg9MywgeD0tMQogICAgUlVOX1RFU1QoIlR3b1Jvb3RzIiwgIkxlYWRDb2VmZj0yICgyLCAtNCwgLTYpIiwgW10oKSB7CiAgICAgICAgYXV0byByID0gcXVhZHJhdGljX2VxdWF0aW9uKDIsIC00LCAtNik7CiAgICAgICAgRVhQRUNUX0VRX1RZUEUgKCLRgtC40L8gPSBUV09fUk9PVFMiLCByLnR5cGUsICBRdWFkcmF0aWNSZXN1bHQ6OlR5cGU6OlRXT19ST09UUyk7CiAgICAgICAgRVhQRUNUX05FQVJfVkFMKCJyb290MSA9PSAzLjAiLCAgICByLnJvb3QxLCAzLjBmKTsKICAgICAgICBFWFBFQ1RfTkVBUl9WQUwoInJvb3QyID09IC0xLjAiLCAgIHIucm9vdDIsIC0xLjBmKTsKICAgIH0pOwoKICAgIC8vINCi0LXRgdGCIDU6IHheMiAtIDEgPSAwIOKGkiB4PTEsIHg9LTEKICAgIFJVTl9URVNUKCJUd29Sb290cyIsICJEaWZmZXJlbmNlT2ZTcXVhcmVzICgxLCAwLCAtMSkiLCBbXSgpIHsKICAgICAgICBhdXRvIHIgPSBxdWFkcmF0aWNfZXF1YXRpb24oMSwgMCwgLTEpOwogICAgICAgIEVYUEVDVF9FUV9UWVBFICgi0YLQuNC/ID0gVFdPX1JPT1RTIiwgci50eXBlLCAgUXVhZHJhdGljUmVzdWx0OjpUeXBlOjpUV09fUk9PVFMpOwogICAgICAgIEVYUEVDVF9ORUFSX1ZBTCgicm9vdDEgPT0gIDEuMCIsICAgci5yb290MSwgIDEuMGYpOwogICAgICAgIEVYUEVDVF9ORUFSX1ZBTCgicm9vdDIgPT0gLTEuMCIsICAgci5yb290MiwgLTEuMGYpOwogICAgfSk7Cn0KCnZvaWQgdGVzdF9vbmVfcm9vdCgpIHsKICAgIC8vINCi0LXRgdGCIDY6IHheMiArIDJ4ICsgMSA9IDAg4oaSIHg9LTEKICAgIFJVTl9URVNUKCJPbmVSb290IiwgIlBlcmZlY3RTcXVhcmUgKDEsIDIsIDEpIiwgW10oKSB7CiAgICAgICAgYXV0byByID0gcXVhZHJhdGljX2VxdWF0aW9uKDEsIDIsIDEpOwogICAgICAgIEVYUEVDVF9FUV9UWVBFICgi0YLQuNC/ID0gT05FX1JPT1QiLCAgci50eXBlLCAgUXVhZHJhdGljUmVzdWx0OjpUeXBlOjpPTkVfUk9PVCk7CiAgICAgICAgRVhQRUNUX05FQVJfVkFMKCJyb290MSA9PSAtMS4wIiwgICByLnJvb3QxLCAtMS4wZik7CiAgICB9KTsKCiAgICAvLyDQotC10YHRgiA3OiA0eF4yIC0gNHggKyAxID0gMCDihpIgeD0wLjUKICAgIFJVTl9URVNUKCJPbmVSb290IiwgIkxlYWRDb2VmZj00ICg0LCAtNCwgMSkiLCBbXSgpIHsKICAgICAgICBhdXRvIHIgPSBxdWFkcmF0aWNfZXF1YXRpb24oNCwgLTQsIDEpOwogICAgICAgIEVYUEVDVF9FUV9UWVBFICgi0YLQuNC/ID0gT05FX1JPT1QiLCAgci50eXBlLCAgUXVhZHJhdGljUmVzdWx0OjpUeXBlOjpPTkVfUk9PVCk7CiAgICAgICAgRVhQRUNUX05FQVJfVkFMKCJyb290MSA9PSAwLjUiLCAgICByLnJvb3QxLCAwLjVmKTsKICAgIH0pOwoKICAgIC8vINCi0LXRgdGCIDg6IDl4XjIgKyA2eCArIDEgPSAwIOKGkiB4PS0xLzMKICAgIFJVTl9URVNUKCJPbmVSb290IiwgIk5lZ2F0aXZlUm9vdCAoOSwgNiwgMSkiLCBbXSgpIHsKICAgICAgICBhdXRvIHIgPSBxdWFkcmF0aWNfZXF1YXRpb24oOSwgNiwgMSk7CiAgICAgICAgRVhQRUNUX0VRX1RZUEUgKCLRgtC40L8gPSBPTkVfUk9PVCIsICAgICAgci50eXBlLCAgUXVhZHJhdGljUmVzdWx0OjpUeXBlOjpPTkVfUk9PVCk7CiAgICAgICAgRVhQRUNUX05FQVJfVkFMKCJyb290MSA9PSAtMC4zMzMzIiwgICAgci5yb290MSwgLTEuMGYvMy4wZik7CiAgICB9KTsKfQoKdm9pZCB0ZXN0X25vX3Jvb3RzKCkgewogICAgLy8g0KLQtdGB0YIgOTog0LjRgdGF0L7QtNC90YvQuSDQstGL0LfQvtCyINC40Lcg0LrQvtC00LAgKDE0LCAyOCwgMzIwKQogICAgUlVOX1RFU1QoIk5vUm9vdHMiLCAiT3JpZ2luYWxDYWxsICgxNCwgMjgsIDMyMCkiLCBbXSgpIHsKICAgICAgICBhdXRvIHIgPSBxdWFkcmF0aWNfZXF1YXRpb24oMTQsIDI4LCAzMjApOwogICAgICAgIEVYUEVDVF9FUV9UWVBFKCLRgtC40L8gPSBOT19ST09UUyIsIHIudHlwZSwgUXVhZHJhdGljUmVzdWx0OjpUeXBlOjpOT19ST09UUyk7CiAgICB9KTsKCiAgICAvLyDQotC10YHRgiAxMDogeF4yICsgeCArIDEgPSAwCiAgICBSVU5fVEVTVCgiTm9Sb290cyIsICJDbGFzc2ljICgxLCAxLCAxKSIsIFtdKCkgewogICAgICAgIGF1dG8gciA9IHF1YWRyYXRpY19lcXVhdGlvbigxLCAxLCAxKTsKICAgICAgICBFWFBFQ1RfRVFfVFlQRSgi0YLQuNC/ID0gTk9fUk9PVFMiLCByLnR5cGUsIFF1YWRyYXRpY1Jlc3VsdDo6VHlwZTo6Tk9fUk9PVFMpOwogICAgfSk7CgogICAgLy8g0KLQtdGB0YIgMTE6IHheMiArIDEgPSAwCiAgICBSVU5fVEVTVCgiTm9Sb290cyIsICJOb0IgKDEsIDAsIDEpIiwgW10oKSB7CiAgICAgICAgYXV0byByID0gcXVhZHJhdGljX2VxdWF0aW9uKDEsIDAsIDEpOwogICAgICAgIEVYUEVDVF9FUV9UWVBFKCLRgtC40L8gPSBOT19ST09UUyIsIHIudHlwZSwgUXVhZHJhdGljUmVzdWx0OjpUeXBlOjpOT19ST09UUyk7CiAgICB9KTsKCiAgICAvLyDQotC10YHRgiAxMjogM3heMiArIDJ4ICsgNSA9IDAKICAgIFJVTl9URVNUKCJOb1Jvb3RzIiwgIkxhcmdlQyAoMywgMiwgNSkiLCBbXSgpIHsKICAgICAgICBhdXRvIHIgPSBxdWFkcmF0aWNfZXF1YXRpb24oMywgMiwgNSk7CiAgICAgICAgRVhQRUNUX0VRX1RZUEUoItGC0LjQvyA9IE5PX1JPT1RTIiwgci50eXBlLCBRdWFkcmF0aWNSZXN1bHQ6OlR5cGU6Ok5PX1JPT1RTKTsKICAgIH0pOwp9Cgp2b2lkIHRlc3RfbWVzc2FnZXMoKSB7CiAgICAvLyDQotC10YHRgiAxMwogICAgUlVOX1RFU1QoIk1lc3NhZ2VzIiwgIk5vUm9vdHMgbWVzc2FnZSIsIFtdKCkgewogICAgICAgIGF1dG8gciA9IHF1YWRyYXRpY19lcXVhdGlvbigxLCAwLCAxKTsKICAgICAgICBFWFBFQ1RfRVFfU1RSKCJtZXNzYWdlID09ICfQmtC+0YDQvdC10Lkg0L3QtdGCISciLCByLm1lc3NhZ2UsICLQmtC+0YDQvdC10Lkg0L3QtdGCISIpOwogICAgfSk7CgogICAgLy8g0KLQtdGB0YIgMTQKICAgIFJVTl9URVNUKCJNZXNzYWdlcyIsICJPbmVSb290IG1lc3NhZ2UiLCBbXSgpIHsKICAgICAgICBhdXRvIHIgPSBxdWFkcmF0aWNfZXF1YXRpb24oMSwgMiwgMSk7CiAgICAgICAgRVhQRUNUX0VRX1NUUigibWVzc2FnZSA9PSAn0JXQtNC40L3RgdGC0LLQtdC90L3Ri9C5INCa0L7RgNC10L3RjCciLCByLm1lc3NhZ2UsICLQldC00LjQvdGB0YLQstC10L3QvdGL0Lkg0JrQvtGA0LXQvdGMIik7CiAgICB9KTsKCiAgICAvLyDQotC10YHRgiAxNQogICAgUlVOX1RFU1QoIk1lc3NhZ2VzIiwgIlR3b1Jvb3RzIG1lc3NhZ2UiLCBbXSgpIHsKICAgICAgICBhdXRvIHIgPSBxdWFkcmF0aWNfZXF1YXRpb24oMSwgNCwgMyk7CiAgICAgICAgRVhQRUNUX0VRX1NUUigibWVzc2FnZSA9PSAn0JTQstCwINC60L7RgNC90Y8nIiwgci5tZXNzYWdlLCAi0JTQstCwINC60L7RgNC90Y8iKTsKICAgIH0pOwp9CgovLyDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZAKLy8gIE1BSU4KLy8g4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQCgppbnQgbWFpbigpIHsKICAgIGNvdXQgPDwgIuKVlOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVl1xuIjsKICAgIGNvdXQgPDwgIuKVkSAgICDQnNCe0JTQo9Cb0KzQndCr0JUg0KLQldCh0KLQqzogcXVhZHJhdGljX2VxdWF0aW9uICAg4pWRXG4iOwogICAgY291dCA8PCAi4pWa4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWdXG4iOwoKICAgIHRlc3RfdHdvX3Jvb3RzKCk7CiAgICB0ZXN0X29uZV9yb290KCk7CiAgICB0ZXN0X25vX3Jvb3RzKCk7CiAgICB0ZXN0X21lc3NhZ2VzKCk7CgogICAgY291dCA8PCAiXG7ilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZBcbiI7CiAgICBjb3V0IDw8ICIgINCY0YLQvtCz0L46ICIgPDwgKHRlc3RzX3Bhc3NlZCArIHRlc3RzX2ZhaWxlZCkgPDwgIiDRgtC10YHRgtC+0LJcbiI7CiAgICBjb3V0IDw8ICIgINCf0YDQvtC50LTQtdC90L46ICIgPDwgdGVzdHNfcGFzc2VkIDw8ICJcbiI7CiAgICBjb3V0IDw8ICIgINCf0YDQvtCy0LDQu9C10L3QvjogIiA8PCB0ZXN0c19mYWlsZWQgPDwgIlxuIjsKICAgIGNvdXQgPDwgIuKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkFxuIjsKCiAgICByZXR1cm4gdGVzdHNfZmFpbGVkID09IDAgPyAwIDogMTsKfQo=