Created
February 3, 2019 12:14
-
-
Save tinyzero4/f10716347d689aed935ce77b7aa20ade to your computer and use it in GitHub Desktop.
Fail: time limit exceeded. Execution time: 9.97s, limit: 5.00s
This file contains hidden or 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 "test_runner.h" | |
#include "profile.h" | |
#include <vector> | |
#include <iostream> | |
#include <algorithm> | |
using namespace std; | |
template<typename T> | |
void PrintCoeff(std::ostream& out, int i, const T& coef, bool printed) { | |
bool coeffPrinted = false; | |
if (coef == 1 && i > 0) { | |
out << (printed ? "+" : ""); | |
} else if (coef == -1 && i > 0) { | |
out << "-"; | |
} else if (coef >= 0 && printed) { | |
out << "+" << coef; | |
coeffPrinted = true; | |
} else { | |
out << coef; | |
coeffPrinted = true; | |
} | |
if (i > 0) { | |
out << (coeffPrinted ? "*" : "") << "x"; | |
} | |
if (i > 1) { | |
out << "^" << i; | |
} | |
} | |
template<typename T> | |
class Polynomial { | |
private: | |
std::vector<T> coeffs_ = {0}; | |
void Shrink() { | |
while (!coeffs_.empty() && coeffs_.back() == 0) coeffs_.pop_back(); | |
} | |
class IndexProxy { | |
public: | |
IndexProxy(Polynomial& poly, size_t degree) :poly_(poly), degree_(degree) {} | |
operator T() const { | |
return std::as_const(poly_)[degree_]; | |
} | |
T& operator=(const T &v) { | |
if (degree_ >= poly_.coeffs_.size() && v!= 0) { | |
poly_.coeffs_.resize(degree_ + 1, 0); | |
poly_.coeffs_[degree_] = v; | |
} else if (degree_ == (poly_.coeffs_.size() - 1) && v == 0) { | |
poly_.coeffs_[degree_] = v; | |
poly_.Shrink(); | |
} else { | |
poly_.coeffs_[degree_] = v; | |
} | |
} | |
bool operator==(const T &lhs) { | |
return poly_.coeffs_[degree_] == lhs; | |
} | |
friend std::ostream& operator<<(std::ostream& out, const IndexProxy& proxy) { | |
out << std::as_const(proxy.poly_)[proxy.degree_]<< endl; | |
} | |
private: | |
Polynomial& poly_; | |
size_t degree_; | |
}; | |
public: | |
Polynomial() = default; | |
Polynomial(vector<T> coeffs) : coeffs_(std::move(coeffs)) { | |
Shrink(); | |
} | |
template<typename Iterator> | |
Polynomial(Iterator first, Iterator last) : coeffs_(first, last) { | |
Shrink(); | |
} | |
bool operator ==(const Polynomial& other) const { | |
return coeffs_ == other.coeffs_; | |
} | |
bool operator !=(const Polynomial& other) const { | |
return !operator==(other); | |
} | |
int Degree() const { | |
return coeffs_.size() - 1; | |
} | |
Polynomial& operator +=(const Polynomial& r) { | |
if (r.coeffs_.size() > coeffs_.size()) { | |
coeffs_.resize(r.coeffs_.size()); | |
} | |
for (size_t i = 0; i != r.coeffs_.size(); ++i) { | |
coeffs_[i] += r.coeffs_[i]; | |
} | |
Shrink(); | |
return *this; | |
} | |
Polynomial& operator -=(const Polynomial& r) { | |
if (r.coeffs_.size() > coeffs_.size()) { | |
coeffs_.resize(r.coeffs_.size()); | |
} | |
for (size_t i = 0; i != r.coeffs_.size(); ++i) { | |
coeffs_[i] -= r.coeffs_[i]; | |
} | |
Shrink(); | |
return *this; | |
} | |
T operator [](size_t degree) const { | |
return degree < coeffs_.size() ? coeffs_[degree] : 0; | |
} | |
IndexProxy operator [](size_t degree) { | |
return IndexProxy(*this, degree); | |
} | |
T operator ()(const T& x) const { | |
T res = 0; | |
for (auto it = coeffs_.rbegin(); it != coeffs_.rend(); ++it) { | |
res *= x; | |
res += *it; | |
} | |
return res; | |
} | |
using const_iterator = typename std::vector<T>::const_iterator; | |
const_iterator begin() const { | |
return coeffs_.cbegin(); | |
} | |
const_iterator end() const { | |
return coeffs_.cend(); | |
} | |
}; | |
template <typename T> | |
std::ostream& operator <<(std::ostream& out, const Polynomial<T>& p) { | |
bool printed = false; | |
for (int i = p.Degree(); i >= 0; --i) { | |
if (p[i] != 0) { | |
PrintCoeff(out, i, p[i], printed); | |
printed = true; | |
} | |
} | |
return out; | |
} | |
template <typename T> | |
Polynomial<T> operator +(Polynomial<T> lhs, const Polynomial<T>& rhs) { | |
lhs += rhs; | |
return lhs; | |
} | |
template <typename T> | |
Polynomial<T> operator -(Polynomial<T> lhs, const Polynomial<T>& rhs) { | |
lhs -= rhs; | |
return lhs; | |
} | |
void TestCreation() { | |
{ | |
Polynomial<int> default_constructed; | |
ASSERT_EQUAL(default_constructed.Degree(), 0); | |
ASSERT_EQUAL(default_constructed[0], 0); | |
} | |
{ | |
Polynomial<double> from_vector({1.0, 2.0, 3.0, 4.0}); | |
ASSERT_EQUAL(from_vector.Degree(), 3); | |
ASSERT_EQUAL(from_vector[0], 1.0); | |
ASSERT_EQUAL(from_vector[1], 2.0); | |
ASSERT_EQUAL(from_vector[2], 3.0); | |
ASSERT_EQUAL(from_vector[3], 4.0); | |
} | |
{ | |
const vector<int> coeffs = {4, 9, 7, 8, 12}; | |
Polynomial<int> from_iterators(begin(coeffs), end(coeffs)); | |
ASSERT_EQUAL(from_iterators.Degree(), coeffs.size() - 1); | |
ASSERT(std::equal(cbegin(from_iterators), cend(from_iterators), begin(coeffs))); | |
} | |
} | |
void TestEqualComparability() { | |
Polynomial<int> p1({9, 3, 2, 8}); | |
Polynomial<int> p2({9, 3, 2, 8}); | |
Polynomial<int> p3({1, 2, 4, 8}); | |
ASSERT_EQUAL(p1, p2); | |
ASSERT(p1 != p3); | |
} | |
void TestAddition() { | |
Polynomial<int> p1({9, 3, 2, 8}); | |
Polynomial<int> p2({1, 2, 4}); | |
p1 += p2; | |
ASSERT_EQUAL(p1, Polynomial<int>({10, 5, 6, 8})); | |
auto p3 = p1 + p2; | |
ASSERT_EQUAL(p3, Polynomial<int>({11, 7, 10, 8})); | |
p3 += Polynomial<int>({-11, 1, -10, -8}); | |
ASSERT_EQUAL(p3.Degree(), 1); | |
const Polynomial<int> expected{{0, 8}}; | |
ASSERT_EQUAL(p3, expected); | |
} | |
void TestSubtraction() { | |
Polynomial<int> p1({9, 3, 2, 8}); | |
Polynomial<int> p2({1, 2, 4}); | |
p1 -= p2; | |
ASSERT_EQUAL(p1, Polynomial<int>({8, 1, -2, 8})); | |
auto p3 = p1 - p2; | |
ASSERT_EQUAL(p3, Polynomial<int>({7, -1, -6, 8})); | |
p3 -= Polynomial<int>({7, -5, -6, 8}); | |
ASSERT_EQUAL(p3.Degree(), 1); | |
const Polynomial<int> expected{{0, 4}}; | |
ASSERT_EQUAL(p3, expected); | |
} | |
void TestEvaluation() { | |
const Polynomial<int> default_constructed; | |
ASSERT_EQUAL(default_constructed(0), 0); | |
ASSERT_EQUAL(default_constructed(1), 0); | |
ASSERT_EQUAL(default_constructed(-1), 0); | |
ASSERT_EQUAL(default_constructed(198632), 0); | |
const Polynomial<int64_t> cubic({1, 1, 1, 1}); | |
ASSERT_EQUAL(cubic(0), 1); | |
ASSERT_EQUAL(cubic(1), 4); | |
ASSERT_EQUAL(cubic(2), 15); | |
ASSERT_EQUAL(cubic(21), 9724); | |
} | |
void TestConstAccess() { | |
const Polynomial<int> poly(std::initializer_list<int> {1, 2, 3, 4, 5}); | |
ASSERT_EQUAL(poly[0], 1); | |
ASSERT_EQUAL(poly[1], 2); | |
ASSERT_EQUAL(poly[2], 3); | |
ASSERT_EQUAL(poly[3], 4); | |
ASSERT_EQUAL(poly[4], 5); | |
ASSERT_EQUAL(poly[5], 0); | |
ASSERT_EQUAL(poly[6], 0); | |
ASSERT_EQUAL(poly[608], 0); | |
} | |
void TestNonconstAccess() { | |
Polynomial<int> poly; | |
poly[0] = 1; | |
poly[3] = 12; | |
poly[5] = 4; | |
ASSERT_EQUAL(poly.Degree(), 5); | |
ASSERT_EQUAL(poly[0], 1); | |
ASSERT_EQUAL(poly[1], 0); | |
ASSERT_EQUAL(poly[2], 0); | |
ASSERT_EQUAL(poly[3], 12); | |
ASSERT_EQUAL(poly[4], 0); | |
ASSERT_EQUAL(poly[5], 4); | |
ASSERT_EQUAL(poly[6], 0); | |
ASSERT_EQUAL(poly[608], 0); | |
ASSERT_EQUAL(poly.Degree(), 5); | |
poly[608] = 0; | |
ASSERT_EQUAL(poly.Degree(), 5); | |
// { | |
// LOG_DURATION("Iteration over const"); | |
// for (size_t i = 10; i < 50000; ++i) { | |
// ASSERT_EQUAL(std::as_const(poly)[i], 0); | |
// ASSERT_EQUAL(poly.Degree(), 5); | |
// } | |
// } | |
// { | |
// LOG_DURATION("Iteration over non-const"); | |
// for (size_t i = 10; i < 50000; ++i) { | |
// ASSERT_EQUAL(poly[i], 0); | |
// ASSERT_EQUAL(poly.Degree(), 5); | |
// } | |
// } | |
// { | |
// LOG_DURATION("Non-const update time"); | |
// for (size_t i = 10; i < 50000; ++i) { | |
// cout << i << endl; | |
// poly[i] = 0; | |
// } | |
// } | |
} | |
int main() { | |
TestRunner tr; | |
RUN_TEST(tr, TestCreation); | |
RUN_TEST(tr, TestEqualComparability); | |
RUN_TEST(tr, TestAddition); | |
RUN_TEST(tr, TestSubtraction); | |
RUN_TEST(tr, TestEvaluation); | |
RUN_TEST(tr, TestConstAccess); | |
RUN_TEST(tr, TestNonconstAccess); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment