Last active
August 27, 2017 18:00
-
-
Save dodheim/3433f542c9d15c10ce2871bac3216bb9 to your computer and use it in GitHub Desktop.
C++17 solution for /r/dailyprogrammer challenge #284 [easy]
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <cstddef> | |
#include <cstdlib> | |
#include <utility> | |
#include <exception> | |
#include <stdexcept> | |
#include <chrono> | |
#include <string_view> | |
#include <string> | |
#include <unordered_map> | |
#include <vector> | |
#include <fstream> | |
#include <iostream> | |
#include <range/v3/core.hpp> | |
#include <range/v3/algorithm/for_each.hpp> | |
#include <range/v3/view/filter.hpp> | |
#include <range/v3/view/transform.hpp> | |
#include <boost/functional/hash.hpp> | |
namespace rngs = ranges; | |
namespace rngvs = ranges::view; | |
using namespace std::string_view_literals; | |
using word_key = std::pair<char, char>; | |
constexpr word_key word_to_key(std::string_view const sv) noexcept { return {sv.front(), sv.back()}; } | |
using dictionary = std::unordered_map<word_key, std::vector<std::string>, boost::hash<word_key>>; | |
dictionary load_dictionary(char const* const path) { | |
static auto constexpr letters = "abcdefghijklmnopqrstuvwxyz"sv; | |
dictionary ret(letters.size() * letters.size()); | |
for (auto const fl : letters) { | |
for (auto const ll : letters) { | |
ret[{fl, ll}]; | |
} | |
} | |
if (std::ifstream words{path}) { | |
rngs::for_each( | |
rngs::getlines(words) | |
| rngvs::filter([](auto const& word) noexcept { return word.size() >= 5; }), | |
[&ret](auto const& word) { ret.find(word_to_key(word))->second.push_back(word); } | |
); | |
} else { | |
throw std::runtime_error{"path not found"}; | |
} | |
return ret; | |
} | |
struct word_filter { | |
explicit constexpr word_filter(std::string_view const input) noexcept : input_{input} { } | |
constexpr bool operator ()(std::string_view const word) const noexcept { | |
auto input = input_; | |
for (auto const letter : word) { | |
if (auto const idx = input.find(letter); idx != input.npos) { | |
input.remove_prefix(idx); | |
} else { | |
return false; | |
} | |
} | |
return true; | |
} | |
private: | |
std::string_view input_; | |
}; | |
static void impl(char const* const dictionary_path) { | |
namespace chrono = std::chrono; | |
auto const inputs = rngs::getlines(std::cin) | rngs::to_vector; | |
auto const start_time = chrono::high_resolution_clock::now(); | |
auto const dict = load_dictionary(dictionary_path); | |
auto const loaded_time = chrono::high_resolution_clock::now(); | |
auto const results = | |
inputs | |
| rngvs::transform([&dict](std::string_view const input) { | |
return std::make_pair( | |
input, | |
rngs::to_vector( | |
dict.find(word_to_key(input))->second | |
| rngvs::transform([](auto const& word) noexcept -> std::string_view { return word; }) | |
| rngvs::filter(word_filter{input}) | |
) | |
); | |
}) | |
| rngs::to_vector; | |
auto const end_time = chrono::high_resolution_clock::now(); | |
for (auto const& [input, words] : results) { | |
std::cout << input << '\n'; | |
for (auto const word : words) { | |
std::cout << '\t' << word << '\n'; | |
} | |
} | |
auto constexpr to_us = [](auto const dur) noexcept { return chrono::duration_cast<chrono::microseconds>(dur).count(); }; | |
std::cout | |
<< "total time elapsed: "sv | |
<< to_us(end_time - start_time) << " us ("sv | |
<< to_us(loaded_time - start_time) << " us loading dictionary, "sv | |
<< to_us(end_time - loaded_time) << " us processing inputs)\n"sv; | |
} | |
int main(int argc, char* argv[]) { | |
if (argc == 2) { | |
std::ios::sync_with_stdio(false); | |
std::cerr << std::boolalpha; | |
std::cout << std::boolalpha; | |
try { | |
impl(argv[1]); | |
return EXIT_SUCCESS; | |
} catch (std::exception const& ex) { | |
std::cerr << ex.what() << '\n'; | |
} catch (...) { | |
std::cerr << "unknown exception (...)\n"sv; | |
} | |
} | |
return EXIT_FAILURE; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment