// // main.cpp // autogram // // Created by Bob Polis at 2020-11-19 // Copyright (c) 2020 SwiftCoder. All rights reserved. // #include #include #include #include #include #include #include #include #include #include #include "robinsonizer_mode.hpp" #include "engine.hpp" void print_help() { std::cout << "usage: autogram [-h|--version]\n"; std::cout << " -a, --autogram autogram type, default relaxed\n"; std::cout << " -h, --help show this help text and exit\n"; std::cout << " -i, --maxiiter maximum iterations before restart, default 10\n"; std::cout << " -l, --lang language, default en\n"; std::cout << " -s, --start start of sentence\n"; std::cout << " -v, --verbose increase verbosity\n"; std::cout << " --version show version number and exit\n"; } void print_version() { std::cout << "autogram version 1.0\n"; } void read_nums_from_db(std::vector& numerals, const std::string& db_path, int lang_id) { sqlite3* db {nullptr}; int rc = sqlite3_open(db_path.c_str(), &db); if (rc) { sqlite3_close(db); throw std::runtime_error("can't open database"); } std::unique_ptr dbh {db, sqlite3_close}; const char* query = "SELECT num FROM numerals WHERE language_id = ? ORDER BY value"; sqlite3_stmt* stmt {nullptr}; sqlite3_prepare_v2(db, query, -1, &stmt, nullptr); std::unique_ptr stmth {stmt, sqlite3_finalize}; sqlite3_bind_int(stmt, 1, lang_id); while (true) { rc = sqlite3_step(stmt); if (rc == SQLITE_ROW) { const unsigned char* data = sqlite3_column_text(stmt, 0); std::string num {reinterpret_cast(data)}; numerals.push_back(num); } else { break; } } } int main(int argc, const char * argv[]) { try { robinsonizer_mode mode {robinsonizer_mode::lax_autogram}; std::string lang {"en"}; std::string start; int maxiter {0}; std::string db_path {"numerals.db"}; unsigned int verbose {0}; int opt_char, opt_val; struct option long_options[] = { {"autogram", required_argument, nullptr, 'a'}, {"help", no_argument, nullptr, 'h'}, {"max-iter", required_argument, nullptr, 'i'}, {"lang", required_argument, nullptr, 'l'}, {"start", required_argument, nullptr, 's'}, {"verbose", required_argument, nullptr, 'v'}, {"version", no_argument, &opt_val, 1}, {nullptr, 0, nullptr, 0} }; while ((opt_char = getopt_long(argc, const_cast(argv), "a:hi:l:s:v", long_options, nullptr)) != -1) { std::string arg {optarg ? optarg : ""}; switch (opt_char) { case 0: { // handle long-only options here switch (opt_val) { case 1: print_version(); return EXIT_SUCCESS; } break; } case 'a': if (arg == "relaxed") { mode = robinsonizer_mode::lax_autogram; } else if (arg == "strict") { mode = robinsonizer_mode::strict_autogram; } else if (arg == "pangram") { mode = robinsonizer_mode::pangram; } else { throw std::invalid_argument("invalid autogram type"); } break; case 'h': print_help(); return EXIT_SUCCESS; case 'i': maxiter = atoi(optarg); break; case 'l': lang = arg; break; case 's': start = arg; break; case 'v': verbose++; break; case '?': throw std::runtime_error("unrecognized option"); } } if (optind == argc) { // here when no file args } for (int i = optind; i < argc; ++i) { try { // process file argv[i] db_path = argv[i]; break; // ignore other args } catch (const std::runtime_error& ex) { std::cerr << "autogram: " << ex.what() << '\n'; } } std::vector numerals; numerals.push_back(lang == "nl" ? "en" : "and"); read_nums_from_db(numerals, db_path, (lang == "nl" ? 1 : 2)); if (start.size() == 0) start = "This sentence contains"; if (maxiter == 0) maxiter = 10; engine robinsonizer {start, std::move(numerals), maxiter, mode, verbose}; if (verbose) { std::locale loc {std::locale {}, new sc::integer_locale}; std::cerr.imbue(loc); std::cout.imbue(loc); std::thread worker {[&robinsonizer](){robinsonizer.run();}}; unsigned long long cur_iter {robinsonizer.total_iterations()}; unsigned long long prev_iter {0}; while (!robinsonizer.found()) { // show progress info prev_iter = cur_iter; std::this_thread::sleep_for(std::chrono::seconds{1}); cur_iter = robinsonizer.total_iterations(); std::cerr << '\r' << cur_iter - prev_iter << " iterations per second, " << cur_iter << " total "; } worker.join(); } else { robinsonizer.run(); } std::cout << '\n' << robinsonizer << '\n'; } catch (const std::exception& ex) { std::cerr << "autogram: " << ex.what() << '\n'; return EXIT_FAILURE; } return EXIT_SUCCESS; }