Merge branch 'master' of bitbucket.org:vishap/test

This commit is contained in:
Vahagn Khachatryan
2014-12-24 12:57:24 +04:00

View File

@@ -7,6 +7,7 @@ VIM: let g:argv=""
#include <map>
#include <limits>
#include <iostream>
#include <sstream>
// interval_map<K,V> is a data structure that efficiently associates intervals of keys of type K with values of type V.
@@ -57,30 +58,54 @@ public:
if ( !(keyBegin < keyEnd ) )
return;
//
// If there is a need to break the last interval with keyEnd do it.
// Everything prior itEnd till itBegin will be removed.
// - is bounded below, with the lowest value being std::numeric_limits<K>::min();
// std::numeric_limits<duble>::min() actually is not the smalles number.
//
auto ie = m_map.lower_bound( keyEnd );
if ( ie != m_map.end()
&& keyEnd < ie->first ) {
auto hint = ie--;
ie = m_map.insert(hint,std::make_pair(keyEnd,ie->second));
if (keyBegin < std::numeric_limits<K>::min())
throw std::runtime_error("K should be bounded below, with the lowest value being std::numeric_limits<K>::min().");
//
// Find the interval pointer before which the new interval ends.
//
auto ie = m_map.lower_bound(keyEnd);
//
// If there is a need to break the last interval with keyEnd do it now.
// Everything prior 'ie' till 'ib' will be removed later.
//
if ( ie == m_map.end() && keyEnd < std::numeric_limits<K>::max()
|| ie != m_map.end() && keyEnd < ie->first ) {
if (!( std::prev(ie)->second == val ))
ie = m_map.insert(ie, std::make_pair(keyEnd,std::prev(ie)->second));
}
//
// There should always be std::numeric_limits<K>::min()
// If the interval next to the inserting one should be joined?
//
else if (ie != m_map.end() && ie->second == val)
++ie;
//
// Find the interval pointer before which the new interval begins.
//
auto ib = m_map.lower_bound( keyBegin );
//
// If the interval before should be joined then ...
// Note: there should always be std::numeric_limits<K>::min()
//
if (ib != m_map.begin() && std::prev(ib)->second == val)
--ib;
//
// If keyBegin is less than 'ib' then insert an new interval.
//
else if ( ib == m_map.end() || keyBegin < ib->first )
ib = m_map.insert(ib, std::make_pair(keyBegin, val));
//
// Otherwise just change the value since keyBegin matches with an
// existing interval.
//
auto it = --m_map.upper_bound( keyBegin );
if ( !(it->second == val ) )
{
if ( it->first < keyBegin )
it = m_map.insert(++it,std::make_pair(keyBegin,val));
else
it->second = val;
}
ib->second = val;
//
// Find the range to be removed.
// Removed the range between ib and ie.
//
m_map.erase( ++it, ie );
m_map.erase( ++ib, ie );
}
// look-up of the value associated with key
@@ -150,12 +175,8 @@ void test_test_key() {
test_type b(T(5.5));
std::cout << "a<b before a=b: " << (a < b) << std::endl;
a = b;
std::cout << "a<b after a=b: " << (a < b) << std::endl;
// (a == b);
std::cout << "min: " << std::numeric_limits<test_type>::min() << std::endl;
std::cout << "max: " << std::numeric_limits<test_type>::max() << std::endl;
}
@@ -185,22 +206,39 @@ void test_test_value() {
test_value<T> b(T(5.5));
std::cout << "a==b before a=b: " << (a == b) << std::endl;
a = b;
std::cout << "a==b after a=b: " << (a == b) << std::endl;
// (a < b);
}
template <typename T>
inline std::ostream& operator << ( std::ostream& os, test_value<T> t ) {
return t.print(os);
}
//
// Test throws this exception if fails.
//
struct test_failed : public std::logic_error {
test_failed()
: logic_error("Test failed.")
{}
};
//
// The representation in m_map must be canonical, that is, consecutive map entries must not have the same value:
// ..., (0,'A'), (3,'A'), ... is not allowed.
//
template <class C>
void test_if_canonical(const C& c) {
for (auto it = std::next(c.begin()); it != c.end(); ++it) {
if (it->second == std::prev(it)->second)
throw test_failed();
}
}
// Provide a function IntervalMapTest() here that tests the functionality of the interval_map,
// for example using a map of unsigned int intervals to char.
// Many solutions we receive are incorrect. Consider using a randomized test to discover
// the cases that your implementation does not handle correctly.
void IntervalMapTest() {
try {
#if 0
std::cout << "=============================================" << std::endl;
std::cout << "Test test_key<int>" << std::endl;
@@ -219,21 +257,107 @@ void IntervalMapTest() {
test_test_value<double>();
#endif
typedef test_key<double> key;
typedef test_value<double> val;
// Check that key value is not less the std::numeric_limits<key>::min().
try {
interval_map<test_key<double>, test_value<double>> im(0);
im.assign(0, 500, 3);
throw test_failed();
}
catch (const std::runtime_error&) {
}
interval_map<key,val> im(0);
//
// Check map for some interesting values.
//
typedef test_key<int> key;
typedef test_value<int> val;
interval_map<key, val> im(0);
std::cout << "constrtuction: \n\t";
im.print(std::cout);
std::cout << std::endl;
std::stringstream log;
auto TEST = [&log,&im](const std::string& golden ) {
test_if_canonical(im.m_map);
std::stringstream ss;
im.print(ss);
log << ss.str() << std::endl;
if (ss.str() != golden)
throw test_failed();
};
// check initial state.
TEST("[-2147483648,0]");
im.assign(std::numeric_limits<key>::min(), std::numeric_limits<key>::min(), -1);
TEST("[-2147483648,0]");
im.assign( 1000, 2000, 1 );
std::cout << "constrtuction: \n\t";
im.print(std::cout);
std::cout << std::endl;
im.assign(std::numeric_limits<key>::max(), std::numeric_limits<key>::max(), -1);
TEST("[-2147483648,0]");
im.assign(0, 0, -1);
TEST("[-2147483648,0]");
im.assign(std::numeric_limits<key>::min(), std::numeric_limits<key>::max(), -1);
TEST("[-2147483648,-1]");
im.assign(1000, 2000, 1);
TEST("[-2147483648,-1][1000,1][2000,-1]");
im.assign(500, 1500, 1);
TEST("[-2147483648,-1][500,1][2000,-1]");
im.assign(1000, 1500, 2);
TEST("[-2147483648,-1][500,1][1000,2][1500,1][2000,-1]");
im.assign(0, 500, 3);
TEST("[-2147483648,-1][0,3][500,1][1000,2][1500,1][2000,-1]");
im.assign(-1000, -500, 3);
TEST("[-2147483648,-1][-1000,3][-500,-1][0,3][500,1][1000,2][1500,1][2000,-1]");
im.assign(-500, 0, 3);
TEST("[-2147483648,-1][-1000,3][500,1][1000,2][1500,1][2000,-1]");
im.assign(-500, 0, 4);
TEST("[-2147483648,-1][-1000,3][-500,4][0,3][500,1][1000,2][1500,1][2000,-1]");
im.assign(2000, std::numeric_limits<key>::max(), 4);
TEST("[-2147483648,-1][-1000,3][-500,4][0,3][500,1][1000,2][1500,1][2000,4]");
im.assign(3000, std::numeric_limits<key>::max(), 5);
TEST("[-2147483648,-1][-1000,3][-500,4][0,3][500,1][1000,2][1500,1][2000,4][3000,5]");
im.assign(2000, 3000, 5);
TEST("[-2147483648,-1][-1000,3][-500,4][0,3][500,1][1000,2][1500,1][2000,5]");
im.assign(std::numeric_limits<key>::min(), -1000, 4);
TEST("[-2147483648,4][-1000,3][-500,4][0,3][500,1][1000,2][1500,1][2000,5]");
im.assign(std::numeric_limits<key>::min(), -2000, 5);
TEST("[-2147483648,5][-2000,4][-1000,3][-500,4][0,3][500,1][1000,2][1500,1][2000,5]");
im.assign(-2000, -1000, 5);
TEST("[-2147483648,5][-1000,3][-500,4][0,3][500,1][1000,2][1500,1][2000,5]");
im.assign(-750, 1750, 4);
TEST("[-2147483648,5][-1000,3][-750,4][1750,1][2000,5]");
im.assign(-1000, 2000, 5);
TEST("[-2147483648,5]");
std::cout << log.str() << std::endl;
std::cout << "PASS" << std::endl;
}
catch (const test_failed&) {
std::cerr << "FAIL: test_failed" << std::endl;
}
catch (const std::exception& e)
{
std::cerr << std::endl
<< "FAIL: std::exception(\"" << e.what() << "\")" << std::endl;
}
catch (...)
{
std::cerr << std::endl
<< "FAIL: unknown exception." << std::endl;
}}
int main(int argc, char* argv[]) {
IntervalMapTest();