Commit 77671c51 authored by Dubský Jan's avatar Dubský Jan
Browse files

Solution 1.04 (Speed: 0.65)

parent 7b1811a4
#!/bin/bash
rsync -rP --inplace * mff-parlab:args/ --exclude build
......@@ -9,104 +9,92 @@
namespace macrosol {
void macroprocessor_impl::apply_defines(std::string_view token, std::string& out) {
auto it = defines.find(token);
if (it == defines.end()) {
out.append(token.begin(), token.end());
out.push_back(' ');
return;
}
// std::string_view(&t.front(), t.length())
for (auto&& t : it->second) {
apply_defines(t, out);
if (pf.is_present(token)) {
auto it = defines.find(token);
if (it != defines.end()) {
for (auto&& t : it->second) {
apply_defines(t, out);
}
return;
}
}
out.append(token.begin(), token.end());
out.push_back(' ');
}
bool macroprocessor_impl::process(const std::string& s, std::string& output) {
auto tokens = parse_tokens(s);
assert((s.find("=") == std::string::npos) || (tokens[1] == "="));
if (tokens.size() == 0) {
token_iterator tit(s.begin(), s.end()), tend(s.end(), s.end());
if (tit == tend) {
output = "";
return true;
}
if (tokens.size() > 1 && tokens[1] == "=") {
auto it = defines.find(tokens[0]);
if (it != defines.end()) it->second.update(tokens);
auto first = *tit;
++tit;
if (tit != tend && *tit == "=") {
auto it = defines.find(first);
if (it != defines.end()) it->second.update(tit, tend);
else {
macro m(tokens);
macro m(first, tit, tend);
auto view = m.get_left_view();
pf.insert(view);
defines.emplace(std::move(view), std::move(m));
}
return false;
}
assert(output.size() == 0);
for (auto&& t : tokens) apply_defines(t, output);
apply_defines(first, output);
for (; tit != tend; ++tit) apply_defines(*tit, output);
if (output.size()) output.pop_back();
return true;
}
std::vector<std::string_view> macroprocessor_impl::parse_tokens(const std::string& s) {
std::vector<std::string_view> ret;
for (auto it = s.begin(), end = s.end(); it != end;) {
auto b = it;
while (*b == ' ') ++b;
if (b == end) break;
auto e = b + 1;
while (*e != ' ' && *e != '=' && e != end) ++e;
size_t len = e - b;
if (*b == '=' && len > 1) {
ret.emplace_back(&(*b), 1);
b++;
len--;
}
ret.emplace_back(&(*b), len);
it = e;
}
return std::move(ret);
}
macroprocessor_impl::macro::macro(const std::vector<std::string_view>& tokens) {
assert(tokens.size() > 1);
assert(tokens[1] == "=");
this->left_len = tokens.front().size();
this->left = new char[left_len + 1];
tokens.front().copy(left, left_len);
macroprocessor_impl::macro::macro(std::string_view define, macroprocessor_impl::macro::stoken_iterator_t tit, macroprocessor_impl::macro::stoken_iterator_t tend) {
left_len = define.size();
this->left = new char[left_len + 1];
define.copy(left, left_len);
left[left_len] = 0;
assert(tokens.front() == left);
update(tokens);
assert(define == left);
update(tit, tend);
}
void macroprocessor_impl::macro::update(const std::vector<std::string_view>& tokens) {
assert(tokens.size() > 1);
assert(tokens[0] == std::string(left));
assert(tokens[1] == "=");
right.resize(tokens.size() - 2);
std::copy(tokens.begin() + 2, tokens.end(), right.begin());
right_len = 0;
for (auto&& r : right) right_len += r.size();
void macroprocessor_impl::macro::update(macroprocessor_impl::macro::stoken_iterator_t tit, macroprocessor_impl::macro::stoken_iterator_t tend) {
assert(*tit == "=");
right.clear();
for (++tit; tit != tend; ++tit) right.push_back(std::string(*tit));
}
macroprocessor_impl::macro::macro(macro&& m) {
this->left = m.left;
this->left_len = m.left_len;
m.left = 0;
this->right = std::move(m.right);
this->right_len = m.right_len;
m.left_len = m.right_len = 0;
}
macroprocessor_impl::macro& macroprocessor_impl::macro::operator=(macro&& m) {
this->left = m.left;
this->left_len = m.left_len;
m.left = 0;
this->right = std::move(m.right);
this->right_len = m.right_len;
m.left_len = m.right_len = 0;
return *this;
left = m.left;
m.left = 0;
left_len = m.left_len;
m.left_len = 0;
right = std::move(m.right);
}
macroprocessor_impl::macro::~macro() {
delete[] left;
}
void macroprocessor_impl::prefix_filter::insert(const std::string_view& val) {
filter[hash(val)] = 1;
}
bool macroprocessor_impl::prefix_filter::is_present(const std::string_view& val) {
return filter[hash(val)];
}
size_t macroprocessor_impl::prefix_filter::chtoi(char c) {
return (c <= 'Z') ? (c - 'A') : (c - 'a');
}
size_t macroprocessor_impl::prefix_filter::hash(const std::string_view& val) {
size_t ret = chtoi(val[0]);
for (size_t i = 1; i < cnt; ++i) {
ret *= 26;
if (i < val.size()) ret += chtoi(val[i]);
}
return ret;
}
} // namespace macrosol
......@@ -4,7 +4,10 @@
#ifndef macrosol_hpp_
#define macrosol_hpp_
#include <cassert>
#include <iterator>
#include <map>
#include <random>
#include <string>
#include <string_view>
#include <unordered_map>
......@@ -35,29 +38,77 @@ public:
bool process(const std::string& s, std::string& output);
private:
template <typename T>
class token_iterator {
public:
token_iterator(T begin, T end) :
ibegin(begin), iend(begin), end(end) { this->operator++(); }
token_iterator<T>& operator++() {
ibegin = iend;
while (ibegin != end && *ibegin == ' ') ++ibegin;
iend = ibegin;
if (ibegin == end) return *this;
++iend;
if (*ibegin == '=') return *this;
while (iend != end && *iend != ' ' && *iend != '=') ++iend;
return *this;
}
std::string_view operator*() {
return std::string_view(&*ibegin, iend - ibegin);
}
template <typename U>
bool operator==(const token_iterator<U>& other) {
return ibegin == other.ibegin;
}
template <typename U>
bool operator!=(const token_iterator<U>& other) {
return !(*this == other);
}
private:
T ibegin;
T iend;
const T end;
};
class macro {
typedef token_iterator<std::string::const_iterator> stoken_iterator_t;
public:
macro(const std::vector<std::string_view>& tokens);
macro(std::string_view define, stoken_iterator_t tit, stoken_iterator_t tend);
macro(macro&& m);
macro& operator =(macro&& m);
macro(macro& m) = delete;
macro& operator=(macro&& m) = delete;
macro(macro& m) = delete;
macro& operator=(macro& m) = delete;
~macro();
void update(const std::vector<std::string_view>& tokens);
void update(stoken_iterator_t tit, stoken_iterator_t tend);
inline std::string_view get_left_view() const { return std::string_view(left, left_len); }
inline auto begin() const { return right.cbegin(); }
inline auto end() const { return right.cend(); }
private:
char* left;
size_t left_len;
char* left = 0;
size_t left_len = 0;
std::vector<std::string> right;
size_t right_len;
};
class prefix_filter {
public:
void insert(const std::string_view& val);
bool is_present(const std::string_view& val);
private:
const static size_t cnt = 3; // number of chars compares by hash()
bool filter[26 * 26 * 26];
inline size_t chtoi(char c);
size_t hash(const std::string_view& val);
};
std::unordered_map<std::string_view, macro> defines;
prefix_filter pf;
std::vector<std::string_view> parse_tokens(const std::string& s);
void apply_defines(std::string_view token, std::string& out);
};
......
#!/bin/bash
cd "$(dirname -- "$0")" || exit 1
rsync -rP --inplace * mff-parlab:asgn/ --exclude build --exclude "gold-*" --exclude "*.vscode*"
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment