Merge branch 'master' of bitbucket.org:vishap/test
This commit is contained in:
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user