ContentsFoundations to FrontierBezhig

cp/cp01/gate/gate_check.cpp

All lab code. Download this file.

// CP01 gate checks. Do not edit this file; edit gate.h. Run with   .\run.ps1 -Gate
// A failing check prints what your code returned, after "got".
#include <chrono>
#include <exception>
#include <iostream>
#include <string>
#include <vector>

#include "gate.h"

static int failures = 0;

static std::string show(int x) { return std::to_string(x); }
static std::string show(bool b) { return b ? "true" : "false"; }
static std::string show(char c) { return std::string("'") + c + "'"; }

static void check(bool ok, const std::string& what, const std::string& got = "") {
    std::cout << (ok ? "ok     " : "WRONG  ") << what;
    if (!ok && !got.empty()) std::cout << "   (got " << got << ")";
    std::cout << "\n";
    if (!ok) ++failures;
}

template <class T, class U>
static void expect(const T& got, const U& want, const std::string& what) {
    check(got == want, what, show(got));
}

static void g1() {
    expect(countDistinct({}), 0, "countDistinct({}) is 0");
    expect(countDistinct({1, 1, 1}), 1, "countDistinct({1, 1, 1}) is 1");
    expect(countDistinct({3, 1, 3, 2}), 3, "countDistinct({3, 1, 3, 2}) is 3");
    expect(countDistinct({-1, 1}), 2, "countDistinct({-1, 1}) is 2");
    std::vector<int> big;
    for (int i = 0; i < 10000; ++i) { big.push_back(i); big.push_back(i); }
    expect(countDistinct(big), 10000, "countDistinct(0..9999, each twice) is 10000");
}

static void g2() {
    expect(mostCommonLetter("a"), 'a', "mostCommonLetter(\"a\") is 'a'");
    expect(mostCommonLetter("banana"), 'a', "mostCommonLetter(\"banana\") is 'a'");
    expect(mostCommonLetter("abab"), 'a', "mostCommonLetter(\"abab\") is 'a' (a tie goes to the earlier letter)");
    expect(mostCommonLetter("zzzyyx"), 'z', "mostCommonLetter(\"zzzyyx\") is 'z'");
    expect(mostCommonLetter("bcab"), 'b', "mostCommonLetter(\"bcab\") is 'b'");
    expect(mostCommonLetter("zyxzyx"), 'x', "mostCommonLetter(\"zyxzyx\") is 'x' (three-way tie)");
}

static void g3() {
    expect(hasPairWithSum({}, 0), false, "hasPairWithSum({}, 0) is false");
    expect(hasPairWithSum({5}, 10), false, "hasPairWithSum({5}, 10) is false (one value cannot pair with itself)");
    expect(hasPairWithSum({5, 5}, 10), true, "hasPairWithSum({5, 5}, 10) is true");
    expect(hasPairWithSum({1, 2, 3, 9}, 8), false, "hasPairWithSum({1, 2, 3, 9}, 8) is false");
    expect(hasPairWithSum({1, 2, 4, 4}, 8), true, "hasPairWithSum({1, 2, 4, 4}, 8) is true");
    expect(hasPairWithSum({-2, 7}, 5), true, "hasPairWithSum({-2, 7}, 5) is true");
    // 300'000 values: at 100'000 a compiler-vectorized pair of nested loops can finish in under a second.
    std::vector<int> big;
    for (int i = 0; i < 300000; ++i) big.push_back(2 * i);  // all even, so no pair sums to an odd target
    auto start = std::chrono::steady_clock::now();
    bool got = hasPairWithSum(big, 7);
    double seconds = std::chrono::duration<double>(std::chrono::steady_clock::now() - start).count();
    expect(got, false, "hasPairWithSum(300000 even values, 7) is false");
    check(seconds < 1.5, "hasPairWithSum on 300000 values finishes in under 1.5 s (took " + std::to_string(seconds) + " s)");
}

int main() {
    void (*parts[])() = {g1, g2, g3};
    for (int p = 0; p < 3; ++p) {
        std::cout << "-- G" << (p + 1) << " --\n";
        try {
            parts[p]();
        } catch (const std::exception& e) {
            std::cout << "WRONG  threw: " << e.what() << "\n";
            ++failures;
        }
    }
    std::cout << (failures == 0 ? "\nAll gate checks passed.\n" : "\nSome gate checks failed.\n");
    return failures == 0 ? 0 : 1;
}