#ifndef AST_HPP
#define AST_HPP
#include <cmath>
#include <memory>
#define override
typedef double number;
struct node_base
{
virtual number evaluate() const = 0;
virtual ~node_base() {}
};
struct node_value : node_base
{
node_value(number value)
: value_(value)
{}
virtual number evaluate() const override
{
return value_;
}
private:
number value_;
};
template <typename BinaryOperator>
struct node_binary_operator : node_base
{
node_binary_operator(std::unique_ptr<node_base> left, std::unique_ptr<node_base> right)
: left_(std::move(left)), right_(std::move(right))
{}
virtual number evaluate() const override
{
return BinaryOperator()(left_->evaluate(), right_->evaluate());
}
private:
std::unique_ptr<node_base> left_, right_;
};
struct power
{
number operator () (number a, number b) const
{
return std::pow(a, b);
}
};
typedef node_binary_operator<std::plus <number>> node_add;
typedef node_binary_operator<std::minus <number>> node_sub;
typedef node_binary_operator<std::multiplies<number>> node_mul;
typedef node_binary_operator<std::divides <number>> node_div;
typedef node_binary_operator<power> node_pow;
#endif // AST_HPP
#ifndef MAKE_UNIQUE_HPP
#define MAKE_UNIQUE_HPP
#include <memory>
#include <utility>
template <typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args)
{
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
#endif // MAKE_UNIQUE_HPP
#ifndef PARSER_HPP
#define PARSER_HPP
//#include "ast.hpp"
//#include "make_unique.hpp"
template <char Symbol, typename NodeType>
struct operator_left;
template <char Symbol, typename NodeType>
struct operator_right;
template <typename... Operators>
struct operator_group;
template <typename... Groups>
struct operator_table;
template <typename LeftNextParser, typename RightNextParser, typename... Parsers>
struct operator_parser;
template <typename LeftNextParser, typename RightNextParser>
struct operator_parser<LeftNextParser, RightNextParser>
{
static bool parse(char const*&, std::unique_ptr<node_base>&)
{
return false;
}
};
template <typename LeftNextParser, typename RightNextParser, typename NextParser, char Symbol, typename NodeType, typename... Operators>
bool operator_parse_helper(char const*& string, std::unique_ptr<node_base>& result)
{
if(*string == Symbol)
{
result = make_unique<NodeType>(std::move(result), NextParser::parse(++string));
return true;
}
return operator_parser<LeftNextParser, RightNextParser, Operators...>::parse(string, result);
}
template <typename LeftNextParser, typename RightNextParser, char Symbol, typename NodeType, typename... Operators>
struct operator_parser<LeftNextParser, RightNextParser, operator_left<Symbol, NodeType>, Operators...>
{
static bool parse(char const*& string, std::unique_ptr<node_base>& result)
{
return operator_parse_helper<LeftNextParser, RightNextParser, LeftNextParser, Symbol, NodeType, Operators...>(string, result);
}
};
template <typename LeftNextParser, typename RightNextParser, char Symbol, typename NodeType, typename... Operators>
struct operator_parser<LeftNextParser, RightNextParser, operator_right<Symbol, NodeType>, Operators...>
{
static bool parse(char const*& string, std::unique_ptr<node_base>& result)
{
return operator_parse_helper<LeftNextParser, RightNextParser, RightNextParser, Symbol, NodeType, Operators...>(string, result);
}
};
template <typename Skipper, typename EndParser, typename NextParser, typename... Groups>
struct operator_group_parser;
template <typename Skipper, typename EndParser, typename NextParser, typename... GroupParsers, typename... Groups>
struct operator_group_parser<Skipper, EndParser, NextParser, operator_group<GroupParsers...>, Groups...>
{
static std::unique_ptr<node_base> parse(char const*& string)
{
std::unique_ptr<node_base> result = NextParser::parse(string);
do Skipper::skip(string);
while(operator_parser<NextParser, operator_group_parser<Skipper, EndParser, NextParser, operator_group<GroupParsers...>>, GroupParsers...>::parse(string, result));
return result;
}
};
template <typename Skipper, typename EndParser, typename Table>
struct operator_table_parser
{
static std::unique_ptr<node_base> parse(char const*& string)
{
return EndParser::parse(string);
}
};
template <typename Skipper, typename EndParser, typename Group, typename... Groups>
struct operator_table_parser<Skipper, EndParser, operator_table<Group, Groups...>>
{
static std::unique_ptr<node_base> parse(char const*& string)
{
return operator_group_parser<Skipper, EndParser, operator_table_parser<Skipper, EndParser, operator_table<Groups...>>, Group>::parse(string);
}
};
template <typename Skipper, typename EndParser, typename Table>
std::unique_ptr<node_base> parse(char const*& string)
{
return operator_table_parser<Skipper, EndParser, Table>::parse(string);
}
#endif // PARSER_HPP
#include <cctype>
#include <cstdlib>
#include <functional>
#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>
#include <utility>
//#include "ast.hpp"
//#include "parser.hpp"
struct parse_error : std::runtime_error
{
parse_error(std::string const& what)
: runtime_error(what)
{}
};
struct whitespace_skipper
{
static void skip(char const*& string)
{
while(std::isspace(*string))
++string;
}
};
std::unique_ptr<node_base> parse_number(char const*& string)
{
return make_unique<node_value>(std::strtod(string, const_cast<char**>(&string)));
}
std::unique_ptr<node_base> parse_binary_expression(char const*& string);
struct binary_operator_parser
{
static std::unique_ptr<node_base> parse(char const*& string);
};
struct primary_expression_parser
{
static std::unique_ptr<node_base> parse(char const*& string)
{
whitespace_skipper::skip(string);
if(*string == '(')
{
auto ast = binary_operator_parser::parse(++string);
whitespace_skipper::skip(string);
if(*string != ')')
throw parse_error("expected closing '(' here: " + std::string(string));
++string;
return ast;
}
return parse_number(string);
}
};
typedef operator_table
<
operator_group
<
operator_left<'+', node_add>,
operator_left<'-', node_sub>
>,
operator_group
<
operator_left<'*', node_mul>,
operator_left<'/', node_div>
>,
operator_group
<
operator_right<'^', node_pow>
>
> operators;
std::unique_ptr<node_base> binary_operator_parser::parse(char const*& string)
{
return ::parse<whitespace_skipper, primary_expression_parser, operators>(string);
}
std::unique_ptr<node_base> parse(char const* string)
{
auto ast = binary_operator_parser::parse(string);
if(*string)
throw parse_error("unexpected character here: " + std::string(string));
return ast;
}
int main()
{
for(std::string line; std::getline(std::cin, line);)
try
{
auto ast = parse(line.c_str());
std::cout << ast->evaluate() << '\n';
}
catch(parse_error const& e)
{
std::cout << e.what() << '\n';
}
}
I2lmbmRlZiBBU1RfSFBQCiNkZWZpbmUgQVNUX0hQUAoKI2luY2x1ZGUgPGNtYXRoPgojaW5jbHVkZSA8bWVtb3J5PgoKI2RlZmluZSBvdmVycmlkZQoKdHlwZWRlZiBkb3VibGUgbnVtYmVyOwoKc3RydWN0IG5vZGVfYmFzZQp7Cgl2aXJ0dWFsIG51bWJlciBldmFsdWF0ZSgpIGNvbnN0ID0gMDsKCXZpcnR1YWwgfm5vZGVfYmFzZSgpIHt9Cn07CgpzdHJ1Y3Qgbm9kZV92YWx1ZSA6IG5vZGVfYmFzZQp7Cglub2RlX3ZhbHVlKG51bWJlciB2YWx1ZSkKCQk6IHZhbHVlXyh2YWx1ZSkKCXt9CgoJdmlydHVhbCBudW1iZXIgZXZhbHVhdGUoKSBjb25zdCBvdmVycmlkZQoJewoJCXJldHVybiB2YWx1ZV87Cgl9Cgpwcml2YXRlOgoJbnVtYmVyIHZhbHVlXzsKfTsKCnRlbXBsYXRlIDx0eXBlbmFtZSBCaW5hcnlPcGVyYXRvcj4Kc3RydWN0IG5vZGVfYmluYXJ5X29wZXJhdG9yIDogbm9kZV9iYXNlCnsKCW5vZGVfYmluYXJ5X29wZXJhdG9yKHN0ZDo6dW5pcXVlX3B0cjxub2RlX2Jhc2U+IGxlZnQsIHN0ZDo6dW5pcXVlX3B0cjxub2RlX2Jhc2U+IHJpZ2h0KQoJCTogbGVmdF8oc3RkOjptb3ZlKGxlZnQpKSwgcmlnaHRfKHN0ZDo6bW92ZShyaWdodCkpCgl7fQoKCXZpcnR1YWwgbnVtYmVyIGV2YWx1YXRlKCkgY29uc3Qgb3ZlcnJpZGUKCXsKCQlyZXR1cm4gQmluYXJ5T3BlcmF0b3IoKShsZWZ0Xy0+ZXZhbHVhdGUoKSwgcmlnaHRfLT5ldmFsdWF0ZSgpKTsKCX0KCnByaXZhdGU6CglzdGQ6OnVuaXF1ZV9wdHI8bm9kZV9iYXNlPiBsZWZ0XywgcmlnaHRfOwp9OwoKc3RydWN0IHBvd2VyCnsKCW51bWJlciBvcGVyYXRvciAoKSAobnVtYmVyIGEsIG51bWJlciBiKSBjb25zdAoJewoJCXJldHVybiBzdGQ6OnBvdyhhLCBiKTsKCX0KfTsKCnR5cGVkZWYgbm9kZV9iaW5hcnlfb3BlcmF0b3I8c3RkOjpwbHVzICAgICAgPG51bWJlcj4+IG5vZGVfYWRkOwp0eXBlZGVmIG5vZGVfYmluYXJ5X29wZXJhdG9yPHN0ZDo6bWludXMgICAgIDxudW1iZXI+PiBub2RlX3N1YjsKdHlwZWRlZiBub2RlX2JpbmFyeV9vcGVyYXRvcjxzdGQ6Om11bHRpcGxpZXM8bnVtYmVyPj4gbm9kZV9tdWw7CnR5cGVkZWYgbm9kZV9iaW5hcnlfb3BlcmF0b3I8c3RkOjpkaXZpZGVzICAgPG51bWJlcj4+IG5vZGVfZGl2Owp0eXBlZGVmIG5vZGVfYmluYXJ5X29wZXJhdG9yPHBvd2VyPiBub2RlX3BvdzsKCiNlbmRpZiAvLyBBU1RfSFBQCgojaWZuZGVmIE1BS0VfVU5JUVVFX0hQUAojZGVmaW5lIE1BS0VfVU5JUVVFX0hQUAoKI2luY2x1ZGUgPG1lbW9yeT4KI2luY2x1ZGUgPHV0aWxpdHk+Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVCwgdHlwZW5hbWUuLi4gQXJncz4Kc3RkOjp1bmlxdWVfcHRyPFQ+IG1ha2VfdW5pcXVlKEFyZ3MmJi4uLiBhcmdzKQp7CglyZXR1cm4gc3RkOjp1bmlxdWVfcHRyPFQ+KG5ldyBUKHN0ZDo6Zm9yd2FyZDxBcmdzPihhcmdzKS4uLikpOwp9CgojZW5kaWYgLy8gTUFLRV9VTklRVUVfSFBQCgojaWZuZGVmIFBBUlNFUl9IUFAKI2RlZmluZSBQQVJTRVJfSFBQCgovLyNpbmNsdWRlICJhc3QuaHBwIgovLyNpbmNsdWRlICJtYWtlX3VuaXF1ZS5ocHAiCgp0ZW1wbGF0ZSA8Y2hhciBTeW1ib2wsIHR5cGVuYW1lIE5vZGVUeXBlPgpzdHJ1Y3Qgb3BlcmF0b3JfbGVmdDsKCnRlbXBsYXRlIDxjaGFyIFN5bWJvbCwgdHlwZW5hbWUgTm9kZVR5cGU+CnN0cnVjdCBvcGVyYXRvcl9yaWdodDsKCnRlbXBsYXRlIDx0eXBlbmFtZS4uLiBPcGVyYXRvcnM+CnN0cnVjdCBvcGVyYXRvcl9ncm91cDsKCnRlbXBsYXRlIDx0eXBlbmFtZS4uLiBHcm91cHM+CnN0cnVjdCBvcGVyYXRvcl90YWJsZTsKCnRlbXBsYXRlIDx0eXBlbmFtZSBMZWZ0TmV4dFBhcnNlciwgdHlwZW5hbWUgUmlnaHROZXh0UGFyc2VyLCB0eXBlbmFtZS4uLiBQYXJzZXJzPgpzdHJ1Y3Qgb3BlcmF0b3JfcGFyc2VyOwoKdGVtcGxhdGUgPHR5cGVuYW1lIExlZnROZXh0UGFyc2VyLCB0eXBlbmFtZSBSaWdodE5leHRQYXJzZXI+CnN0cnVjdCBvcGVyYXRvcl9wYXJzZXI8TGVmdE5leHRQYXJzZXIsIFJpZ2h0TmV4dFBhcnNlcj4KewoJc3RhdGljIGJvb2wgcGFyc2UoY2hhciBjb25zdComLCBzdGQ6OnVuaXF1ZV9wdHI8bm9kZV9iYXNlPiYpCgl7CgkJcmV0dXJuIGZhbHNlOwoJfQp9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIExlZnROZXh0UGFyc2VyLCB0eXBlbmFtZSBSaWdodE5leHRQYXJzZXIsIHR5cGVuYW1lIE5leHRQYXJzZXIsIGNoYXIgU3ltYm9sLCB0eXBlbmFtZSBOb2RlVHlwZSwgdHlwZW5hbWUuLi4gT3BlcmF0b3JzPgpib29sIG9wZXJhdG9yX3BhcnNlX2hlbHBlcihjaGFyIGNvbnN0KiYgc3RyaW5nLCBzdGQ6OnVuaXF1ZV9wdHI8bm9kZV9iYXNlPiYgcmVzdWx0KQp7CglpZigqc3RyaW5nID09IFN5bWJvbCkKCXsKCQlyZXN1bHQgPSBtYWtlX3VuaXF1ZTxOb2RlVHlwZT4oc3RkOjptb3ZlKHJlc3VsdCksIE5leHRQYXJzZXI6OnBhcnNlKCsrc3RyaW5nKSk7CgkJcmV0dXJuIHRydWU7Cgl9CgoJcmV0dXJuIG9wZXJhdG9yX3BhcnNlcjxMZWZ0TmV4dFBhcnNlciwgUmlnaHROZXh0UGFyc2VyLCBPcGVyYXRvcnMuLi4+OjpwYXJzZShzdHJpbmcsIHJlc3VsdCk7Cn0KCnRlbXBsYXRlIDx0eXBlbmFtZSBMZWZ0TmV4dFBhcnNlciwgdHlwZW5hbWUgUmlnaHROZXh0UGFyc2VyLCBjaGFyIFN5bWJvbCwgdHlwZW5hbWUgTm9kZVR5cGUsIHR5cGVuYW1lLi4uIE9wZXJhdG9ycz4Kc3RydWN0IG9wZXJhdG9yX3BhcnNlcjxMZWZ0TmV4dFBhcnNlciwgUmlnaHROZXh0UGFyc2VyLCBvcGVyYXRvcl9sZWZ0PFN5bWJvbCwgTm9kZVR5cGU+LCBPcGVyYXRvcnMuLi4+CnsKCXN0YXRpYyBib29sIHBhcnNlKGNoYXIgY29uc3QqJiBzdHJpbmcsIHN0ZDo6dW5pcXVlX3B0cjxub2RlX2Jhc2U+JiByZXN1bHQpCgl7CgkJcmV0dXJuIG9wZXJhdG9yX3BhcnNlX2hlbHBlcjxMZWZ0TmV4dFBhcnNlciwgUmlnaHROZXh0UGFyc2VyLCBMZWZ0TmV4dFBhcnNlciwgU3ltYm9sLCBOb2RlVHlwZSwgT3BlcmF0b3JzLi4uPihzdHJpbmcsIHJlc3VsdCk7Cgl9Cn07Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgTGVmdE5leHRQYXJzZXIsIHR5cGVuYW1lIFJpZ2h0TmV4dFBhcnNlciwgY2hhciBTeW1ib2wsIHR5cGVuYW1lIE5vZGVUeXBlLCB0eXBlbmFtZS4uLiBPcGVyYXRvcnM+CnN0cnVjdCBvcGVyYXRvcl9wYXJzZXI8TGVmdE5leHRQYXJzZXIsIFJpZ2h0TmV4dFBhcnNlciwgb3BlcmF0b3JfcmlnaHQ8U3ltYm9sLCBOb2RlVHlwZT4sIE9wZXJhdG9ycy4uLj4KewoJc3RhdGljIGJvb2wgcGFyc2UoY2hhciBjb25zdComIHN0cmluZywgc3RkOjp1bmlxdWVfcHRyPG5vZGVfYmFzZT4mIHJlc3VsdCkKCXsKCQlyZXR1cm4gb3BlcmF0b3JfcGFyc2VfaGVscGVyPExlZnROZXh0UGFyc2VyLCBSaWdodE5leHRQYXJzZXIsIFJpZ2h0TmV4dFBhcnNlciwgU3ltYm9sLCBOb2RlVHlwZSwgT3BlcmF0b3JzLi4uPihzdHJpbmcsIHJlc3VsdCk7Cgl9Cn07Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgU2tpcHBlciwgdHlwZW5hbWUgRW5kUGFyc2VyLCB0eXBlbmFtZSBOZXh0UGFyc2VyLCB0eXBlbmFtZS4uLiBHcm91cHM+CnN0cnVjdCBvcGVyYXRvcl9ncm91cF9wYXJzZXI7Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgU2tpcHBlciwgdHlwZW5hbWUgRW5kUGFyc2VyLCB0eXBlbmFtZSBOZXh0UGFyc2VyLCB0eXBlbmFtZS4uLiBHcm91cFBhcnNlcnMsIHR5cGVuYW1lLi4uIEdyb3Vwcz4Kc3RydWN0IG9wZXJhdG9yX2dyb3VwX3BhcnNlcjxTa2lwcGVyLCBFbmRQYXJzZXIsIE5leHRQYXJzZXIsIG9wZXJhdG9yX2dyb3VwPEdyb3VwUGFyc2Vycy4uLj4sIEdyb3Vwcy4uLj4KewoJc3RhdGljIHN0ZDo6dW5pcXVlX3B0cjxub2RlX2Jhc2U+IHBhcnNlKGNoYXIgY29uc3QqJiBzdHJpbmcpCgl7CgkJc3RkOjp1bmlxdWVfcHRyPG5vZGVfYmFzZT4gcmVzdWx0ID0gTmV4dFBhcnNlcjo6cGFyc2Uoc3RyaW5nKTsKCgkJZG8gU2tpcHBlcjo6c2tpcChzdHJpbmcpOwoJCXdoaWxlKG9wZXJhdG9yX3BhcnNlcjxOZXh0UGFyc2VyLCBvcGVyYXRvcl9ncm91cF9wYXJzZXI8U2tpcHBlciwgRW5kUGFyc2VyLCBOZXh0UGFyc2VyLCBvcGVyYXRvcl9ncm91cDxHcm91cFBhcnNlcnMuLi4+PiwgR3JvdXBQYXJzZXJzLi4uPjo6cGFyc2Uoc3RyaW5nLCByZXN1bHQpKTsKCgkJcmV0dXJuIHJlc3VsdDsKCX0KfTsKCnRlbXBsYXRlIDx0eXBlbmFtZSBTa2lwcGVyLCB0eXBlbmFtZSBFbmRQYXJzZXIsIHR5cGVuYW1lIFRhYmxlPgpzdHJ1Y3Qgb3BlcmF0b3JfdGFibGVfcGFyc2VyCnsKCXN0YXRpYyBzdGQ6OnVuaXF1ZV9wdHI8bm9kZV9iYXNlPiBwYXJzZShjaGFyIGNvbnN0KiYgc3RyaW5nKQoJewoJCXJldHVybiBFbmRQYXJzZXI6OnBhcnNlKHN0cmluZyk7Cgl9Cn07Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgU2tpcHBlciwgdHlwZW5hbWUgRW5kUGFyc2VyLCB0eXBlbmFtZSBHcm91cCwgdHlwZW5hbWUuLi4gR3JvdXBzPgpzdHJ1Y3Qgb3BlcmF0b3JfdGFibGVfcGFyc2VyPFNraXBwZXIsIEVuZFBhcnNlciwgb3BlcmF0b3JfdGFibGU8R3JvdXAsIEdyb3Vwcy4uLj4+CnsKCXN0YXRpYyBzdGQ6OnVuaXF1ZV9wdHI8bm9kZV9iYXNlPiBwYXJzZShjaGFyIGNvbnN0KiYgc3RyaW5nKQoJewoJCXJldHVybiBvcGVyYXRvcl9ncm91cF9wYXJzZXI8U2tpcHBlciwgRW5kUGFyc2VyLCBvcGVyYXRvcl90YWJsZV9wYXJzZXI8U2tpcHBlciwgRW5kUGFyc2VyLCBvcGVyYXRvcl90YWJsZTxHcm91cHMuLi4+PiwgR3JvdXA+OjpwYXJzZShzdHJpbmcpOwoJfQp9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIFNraXBwZXIsIHR5cGVuYW1lIEVuZFBhcnNlciwgdHlwZW5hbWUgVGFibGU+CnN0ZDo6dW5pcXVlX3B0cjxub2RlX2Jhc2U+IHBhcnNlKGNoYXIgY29uc3QqJiBzdHJpbmcpCnsKCXJldHVybiBvcGVyYXRvcl90YWJsZV9wYXJzZXI8U2tpcHBlciwgRW5kUGFyc2VyLCBUYWJsZT46OnBhcnNlKHN0cmluZyk7Cn0KCiNlbmRpZiAvLyBQQVJTRVJfSFBQCgojaW5jbHVkZSA8Y2N0eXBlPgojaW5jbHVkZSA8Y3N0ZGxpYj4KI2luY2x1ZGUgPGZ1bmN0aW9uYWw+CiNpbmNsdWRlIDxpb3N0cmVhbT4KI2luY2x1ZGUgPG1lbW9yeT4KI2luY2x1ZGUgPHN0ZGV4Y2VwdD4KI2luY2x1ZGUgPHN0cmluZz4KI2luY2x1ZGUgPHV0aWxpdHk+CgovLyNpbmNsdWRlICJhc3QuaHBwIgovLyNpbmNsdWRlICJwYXJzZXIuaHBwIgoKc3RydWN0IHBhcnNlX2Vycm9yIDogc3RkOjpydW50aW1lX2Vycm9yCnsKCXBhcnNlX2Vycm9yKHN0ZDo6c3RyaW5nIGNvbnN0JiB3aGF0KQoJCTogcnVudGltZV9lcnJvcih3aGF0KQoJe30KfTsKCnN0cnVjdCB3aGl0ZXNwYWNlX3NraXBwZXIKewoJc3RhdGljIHZvaWQgc2tpcChjaGFyIGNvbnN0KiYgc3RyaW5nKQoJewoJCXdoaWxlKHN0ZDo6aXNzcGFjZSgqc3RyaW5nKSkKCQkJKytzdHJpbmc7Cgl9Cn07CgpzdGQ6OnVuaXF1ZV9wdHI8bm9kZV9iYXNlPiBwYXJzZV9udW1iZXIoY2hhciBjb25zdComIHN0cmluZykKewoJcmV0dXJuIG1ha2VfdW5pcXVlPG5vZGVfdmFsdWU+KHN0ZDo6c3RydG9kKHN0cmluZywgY29uc3RfY2FzdDxjaGFyKio+KCZzdHJpbmcpKSk7Cn0KCnN0ZDo6dW5pcXVlX3B0cjxub2RlX2Jhc2U+IHBhcnNlX2JpbmFyeV9leHByZXNzaW9uKGNoYXIgY29uc3QqJiBzdHJpbmcpOwoKc3RydWN0IGJpbmFyeV9vcGVyYXRvcl9wYXJzZXIKewoJc3RhdGljIHN0ZDo6dW5pcXVlX3B0cjxub2RlX2Jhc2U+IHBhcnNlKGNoYXIgY29uc3QqJiBzdHJpbmcpOwp9OwoKc3RydWN0IHByaW1hcnlfZXhwcmVzc2lvbl9wYXJzZXIKewoJc3RhdGljIHN0ZDo6dW5pcXVlX3B0cjxub2RlX2Jhc2U+IHBhcnNlKGNoYXIgY29uc3QqJiBzdHJpbmcpCgl7CgkJd2hpdGVzcGFjZV9za2lwcGVyOjpza2lwKHN0cmluZyk7CgoJCWlmKCpzdHJpbmcgPT0gJygnKQoJCXsKCQkJYXV0byBhc3QgPSBiaW5hcnlfb3BlcmF0b3JfcGFyc2VyOjpwYXJzZSgrK3N0cmluZyk7CgkJCXdoaXRlc3BhY2Vfc2tpcHBlcjo6c2tpcChzdHJpbmcpOwoKCQkJaWYoKnN0cmluZyAhPSAnKScpCgkJCQl0aHJvdyBwYXJzZV9lcnJvcigiZXhwZWN0ZWQgY2xvc2luZyAnKCcgaGVyZTogIiArIHN0ZDo6c3RyaW5nKHN0cmluZykpOwoKCQkJKytzdHJpbmc7CgkJCXJldHVybiBhc3Q7CgkJfQoKCQlyZXR1cm4gcGFyc2VfbnVtYmVyKHN0cmluZyk7Cgl9Cn07Cgp0eXBlZGVmIG9wZXJhdG9yX3RhYmxlCjwKCW9wZXJhdG9yX2dyb3VwCgk8CgkJb3BlcmF0b3JfbGVmdDwnKycsIG5vZGVfYWRkPiwKCQlvcGVyYXRvcl9sZWZ0PCctJywgbm9kZV9zdWI+Cgk+LAoJb3BlcmF0b3JfZ3JvdXAKCTwKCQlvcGVyYXRvcl9sZWZ0PCcqJywgbm9kZV9tdWw+LAoJCW9wZXJhdG9yX2xlZnQ8Jy8nLCBub2RlX2Rpdj4KCT4sCglvcGVyYXRvcl9ncm91cAoJPAoJCW9wZXJhdG9yX3JpZ2h0PCdeJywgbm9kZV9wb3c+Cgk+Cj4gb3BlcmF0b3JzOwoKc3RkOjp1bmlxdWVfcHRyPG5vZGVfYmFzZT4gYmluYXJ5X29wZXJhdG9yX3BhcnNlcjo6cGFyc2UoY2hhciBjb25zdComIHN0cmluZykKewoJcmV0dXJuIDo6cGFyc2U8d2hpdGVzcGFjZV9za2lwcGVyLCBwcmltYXJ5X2V4cHJlc3Npb25fcGFyc2VyLCBvcGVyYXRvcnM+KHN0cmluZyk7Cn0KCnN0ZDo6dW5pcXVlX3B0cjxub2RlX2Jhc2U+IHBhcnNlKGNoYXIgY29uc3QqIHN0cmluZykKewoJYXV0byBhc3QgPSBiaW5hcnlfb3BlcmF0b3JfcGFyc2VyOjpwYXJzZShzdHJpbmcpOwoKCWlmKCpzdHJpbmcpCgkJdGhyb3cgcGFyc2VfZXJyb3IoInVuZXhwZWN0ZWQgY2hhcmFjdGVyIGhlcmU6ICIgKyBzdGQ6OnN0cmluZyhzdHJpbmcpKTsKCglyZXR1cm4gYXN0Owp9CgppbnQgbWFpbigpCnsKCWZvcihzdGQ6OnN0cmluZyBsaW5lOyBzdGQ6OmdldGxpbmUoc3RkOjpjaW4sIGxpbmUpOykKCQl0cnkKCQl7CgkJCWF1dG8gYXN0ID0gcGFyc2UobGluZS5jX3N0cigpKTsKCQkJc3RkOjpjb3V0IDw8IGFzdC0+ZXZhbHVhdGUoKSA8PCAnXG4nOwoJCX0KCgkJY2F0Y2gocGFyc2VfZXJyb3IgY29uc3QmIGUpCgkJewoJCQlzdGQ6OmNvdXQgPDwgZS53aGF0KCkgPDwgJ1xuJzsKCQl9Cn0K