<commit_before>#include <utility>
#include <iterator>
#include <limits>
#include <cstdlib>
#include <cstring>
#include <stdexcept>
#include "puzzle.hpp"

/// We don't want to rely on C++14 yet.
template<typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args)
{
	return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}

namespace Puzzle {

// BEGIN Implementation of Expressions

Expression::~Expression() = default;

class BinaryExpr : public Expression
{
protected:
	BinaryExpr(std::unique_ptr<Expression> left,
	           std::unique_ptr<Expression> right)
		: left(std::move(left)), right(std::move(right)) {}

	std::unique_ptr<Expression> left, right;
};

class EqualsExpr : public BinaryExpr
{
public:
	EqualsExpr(std::unique_ptr<Expression> left,
	           std::unique_ptr<Expression> right)
		: BinaryExpr(std::move(left), std::move(right)) {}

	fraction<int64_t> eval(const int *assignment) const override
		{ return left->eval(assignment) == right->eval(assignment); }
};

class SumExpr : public BinaryExpr
{
public:
	SumExpr(std::unique_ptr<Expression> left,
	        std::unique_ptr<Expression> right)
		: BinaryExpr(std::move(left), std::move(right)) {}

	fraction<int64_t> eval(const int *assignment) const override
		{ return left->eval(assignment) + right->eval(assignment); }
};

class DifferenceExpr : public BinaryExpr
{
public:
	DifferenceExpr(std::unique_ptr<Expression> left,
	               std::unique_ptr<Expression> right)
		: BinaryExpr(std::move(left), std::move(right)) {}

	fraction<int64_t> eval(const int *assignment) const override
		{ return left->eval(assignment) - right->eval(assignment); }
};

class ProductExpr : public BinaryExpr
{
public:
	ProductExpr(std::unique_ptr<Expression> left,
	            std::unique_ptr<Expression> right)
		: BinaryExpr(std::move(left), std::move(right)) {}

	fraction<int64_t> eval(const int *assignment) const override
		{ return left->eval(assignment) * right->eval(assignment); }
};

class QuotientExpr : public BinaryExpr
{
public:
	QuotientExpr(std::unique_ptr<Expression> left,
	             std::unique_ptr<Expression> right)
		: BinaryExpr(std::move(left), std::move(right)) {}

	fraction<int64_t> eval(const int *assignment) const override
		{ return left->eval(assignment) / right->eval(assignment); }
};

class WordExpr : public Expression
{
public:
	WordExpr(const char *begin, const char *end,
	         const std::map<char, int> &transmap, int radix)
		: word(new int[std::distance(begin, end) + 1]), radix(radix)
	{
		size_t len = std::distance(begin, end);
		for (size_t i = 0; i < len; ++i)
			word[i] = transmap.at(begin[(len-1) - i]);
		word[len] = -1;
	}

	fraction<int64_t> eval(const int *assignment) const override
	{
		int64_t res = 0, val = 1;
		for (size_t i = 0; word[i] >= 0; ++i) {
			res += assignment[word[i]] * val;
			val *= radix;
		}
		return fraction<int64_t>(res);
	}

private:
	std::unique_ptr<int[]> word;
	int radix;
};

class NumberExpr : public Expression
{
public:
	NumberExpr(const char* begin, const char* end, int radix)
	{
		value = strtol(begin, const_cast<char **>(&end), radix);
	}

	fraction<int64_t> eval(const int*) const override
	{
		return fraction<int64_t>(value);
	}

private:
	int64_t value;
};

// END Implementation of Expressions

// BEGIN Implementation of ExpressionParser

/**<commit_msg>Replace strtol by our own implementation<commit_after>#include <utility>
#include <iterator>
#include <limits>
#include <cstring>
#include <stdexcept>
#include "puzzle.hpp"

/// We don't want to rely on C++14 yet.
template<typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args)
{
	return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}

namespace Puzzle {

// BEGIN Implementation of Expressions

Expression::~Expression() = default;

class BinaryExpr : public Expression
{
protected:
	BinaryExpr(std::unique_ptr<Expression> left,
	           std::unique_ptr<Expression> right)
		: left(std::move(left)), right(std::move(right)) {}

	std::unique_ptr<Expression> left, right;
};

class EqualsExpr : public BinaryExpr
{
public:
	EqualsExpr(std::unique_ptr<Expression> left,
	           std::unique_ptr<Expression> right)
		: BinaryExpr(std::move(left), std::move(right)) {}

	fraction<int64_t> eval(const int *assignment) const override
		{ return left->eval(assignment) == right->eval(assignment); }
};

class SumExpr : public BinaryExpr
{
public:
	SumExpr(std::unique_ptr<Expression> left,
	        std::unique_ptr<Expression> right)
		: BinaryExpr(std::move(left), std::move(right)) {}

	fraction<int64_t> eval(const int *assignment) const override
		{ return left->eval(assignment) + right->eval(assignment); }
};

class DifferenceExpr : public BinaryExpr
{
public:
	DifferenceExpr(std::unique_ptr<Expression> left,
	               std::unique_ptr<Expression> right)
		: BinaryExpr(std::move(left), std::move(right)) {}

	fraction<int64_t> eval(const int *assignment) const override
		{ return left->eval(assignment) - right->eval(assignment); }
};

class ProductExpr : public BinaryExpr
{
public:
	ProductExpr(std::unique_ptr<Expression> left,
	            std::unique_ptr<Expression> right)
		: BinaryExpr(std::move(left), std::move(right)) {}

	fraction<int64_t> eval(const int *assignment) const override
		{ return left->eval(assignment) * right->eval(assignment); }
};

class QuotientExpr : public BinaryExpr
{
public:
	QuotientExpr(std::unique_ptr<Expression> left,
	             std::unique_ptr<Expression> right)
		: BinaryExpr(std::move(left), std::move(right)) {}

	fraction<int64_t> eval(const int *assignment) const override
		{ return left->eval(assignment) / right->eval(assignment); }
};

class WordExpr : public Expression
{
public:
	WordExpr(const char *begin, const char *end,
	         const std::map<char, int> &transmap, int radix)
		: word(new int[std::distance(begin, end) + 1]), radix(radix)
	{
		size_t len = std::distance(begin, end);
		for (size_t i = 0; i < len; ++i)
			word[i] = transmap.at(begin[(len-1) - i]);
		word[len] = -1;
	}

	fraction<int64_t> eval(const int *assignment) const override
	{
		int64_t res = 0, val = 1;
		for (size_t i = 0; word[i] >= 0; ++i) {
			res += assignment[word[i]] * val;
			val *= radix;
		}
		return fraction<int64_t>(res);
	}

private:
	std::unique_ptr<int[]> word;
	int radix;
};

class NumberExpr : public Expression
{
public:
	NumberExpr(const char* begin, const char* end, int radix) : value(0)
	{
		for (const char *cur = begin; cur != end; ++cur) {
			value *= radix;
			value += *cur - '0';
		}
	}

	fraction<int64_t> eval(const int*) const override
	{
		return fraction<int64_t>(value);
	}

private:
	int64_t value;
};

// END Implementation of Expressions

// BEGIN Implementation of ExpressionParser

/**
{'fraction_non_alphanumeric': 0.15372120496160663, 'fraction_numerical': 0.009746012994683993, 'mean_word_length': 4.793840889649273, 'pattern_counts': {'":': 0, '<': 73, '<?xml version=': 0, '>': 93, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4773849', 'n_tokens_mistral': 2460, 'n_tokens_neox': 2285, 'n_words': 528}