Merge branch 'master' of bitbucket.org:vishap/test
This commit is contained in:
@@ -7,6 +7,7 @@ VIM: let g:argv=""
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <iostream>
|
#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.
|
// 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 ) )
|
if ( !(keyBegin < keyEnd ) )
|
||||||
return;
|
return;
|
||||||
//
|
//
|
||||||
// If there is a need to break the last interval with keyEnd do it.
|
// - is bounded below, with the lowest value being std::numeric_limits<K>::min();
|
||||||
// Everything prior itEnd till itBegin will be removed.
|
// std::numeric_limits<duble>::min() actually is not the smalles number.
|
||||||
//
|
//
|
||||||
auto ie = m_map.lower_bound( keyEnd );
|
if (keyBegin < std::numeric_limits<K>::min())
|
||||||
if ( ie != m_map.end()
|
throw std::runtime_error("K should be bounded below, with the lowest value being std::numeric_limits<K>::min().");
|
||||||
&& keyEnd < ie->first ) {
|
//
|
||||||
auto hint = ie--;
|
// Find the interval pointer before which the new interval ends.
|
||||||
ie = m_map.insert(hint,std::make_pair(keyEnd,ie->second));
|
//
|
||||||
|
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?
|
||||||
//
|
//
|
||||||
auto it = --m_map.upper_bound( keyBegin );
|
else if (ie != m_map.end() && ie->second == val)
|
||||||
if ( !(it->second == val ) )
|
++ie;
|
||||||
{
|
|
||||||
if ( it->first < keyBegin )
|
|
||||||
it = m_map.insert(++it,std::make_pair(keyBegin,val));
|
|
||||||
else
|
|
||||||
it->second = val;
|
|
||||||
}
|
|
||||||
//
|
//
|
||||||
// Find the range to be removed.
|
// Find the interval pointer before which the new interval begins.
|
||||||
//
|
//
|
||||||
m_map.erase( ++it, ie );
|
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.
|
||||||
|
//
|
||||||
|
else
|
||||||
|
ib->second = val;
|
||||||
|
//
|
||||||
|
// Removed the range between ib and ie.
|
||||||
|
//
|
||||||
|
m_map.erase( ++ib, ie );
|
||||||
}
|
}
|
||||||
|
|
||||||
// look-up of the value associated with key
|
// look-up of the value associated with key
|
||||||
@@ -150,12 +175,8 @@ void test_test_key() {
|
|||||||
test_type b(T(5.5));
|
test_type b(T(5.5));
|
||||||
|
|
||||||
std::cout << "a<b before a=b: " << (a < b) << std::endl;
|
std::cout << "a<b before a=b: " << (a < b) << std::endl;
|
||||||
|
|
||||||
a = b;
|
a = b;
|
||||||
std::cout << "a<b after a=b: " << (a < b) << std::endl;
|
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 << "min: " << std::numeric_limits<test_type>::min() << std::endl;
|
||||||
std::cout << "max: " << std::numeric_limits<test_type>::max() << std::endl;
|
std::cout << "max: " << std::numeric_limits<test_type>::max() << std::endl;
|
||||||
}
|
}
|
||||||
@@ -185,55 +206,158 @@ void test_test_value() {
|
|||||||
test_value<T> b(T(5.5));
|
test_value<T> b(T(5.5));
|
||||||
|
|
||||||
std::cout << "a==b before a=b: " << (a == b) << std::endl;
|
std::cout << "a==b before a=b: " << (a == b) << std::endl;
|
||||||
|
|
||||||
a = b;
|
a = b;
|
||||||
std::cout << "a==b after a=b: " << (a == b) << std::endl;
|
std::cout << "a==b after a=b: " << (a == b) << std::endl;
|
||||||
|
|
||||||
// (a < b);
|
|
||||||
}
|
}
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline std::ostream& operator << ( std::ostream& os, test_value<T> t ) {
|
inline std::ostream& operator << ( std::ostream& os, test_value<T> t ) {
|
||||||
return t.print(os);
|
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,
|
// Provide a function IntervalMapTest() here that tests the functionality of the interval_map,
|
||||||
// for example using a map of unsigned int intervals to char.
|
// for example using a map of unsigned int intervals to char.
|
||||||
// Many solutions we receive are incorrect. Consider using a randomized test to discover
|
// Many solutions we receive are incorrect. Consider using a randomized test to discover
|
||||||
// the cases that your implementation does not handle correctly.
|
// the cases that your implementation does not handle correctly.
|
||||||
void IntervalMapTest() {
|
void IntervalMapTest() {
|
||||||
|
try {
|
||||||
#if 0
|
#if 0
|
||||||
std::cout << "=============================================" << std::endl;
|
std::cout << "=============================================" << std::endl;
|
||||||
std::cout << "Test test_key<int>" << std::endl;
|
std::cout << "Test test_key<int>" << std::endl;
|
||||||
test_test_key<int>();
|
test_test_key<int>();
|
||||||
|
|
||||||
std::cout << "=============================================" << std::endl;
|
std::cout << "=============================================" << std::endl;
|
||||||
std::cout << "Test test_key<double>" << std::endl;
|
std::cout << "Test test_key<double>" << std::endl;
|
||||||
test_test_key<double>();
|
test_test_key<double>();
|
||||||
|
|
||||||
std::cout << "=============================================" << std::endl;
|
std::cout << "=============================================" << std::endl;
|
||||||
std::cout << "Test test_value<int>" << std::endl;
|
std::cout << "Test test_value<int>" << std::endl;
|
||||||
test_test_value<int>();
|
test_test_value<int>();
|
||||||
|
|
||||||
std::cout << "=============================================" << std::endl;
|
std::cout << "=============================================" << std::endl;
|
||||||
std::cout << "Test test_value<double>" << std::endl;
|
std::cout << "Test test_value<double>" << std::endl;
|
||||||
test_test_value<double>();
|
test_test_value<double>();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef test_key<double> key;
|
// Check that key value is not less the std::numeric_limits<key>::min().
|
||||||
typedef test_value<double> val;
|
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";
|
std::stringstream log;
|
||||||
im.print(std::cout);
|
auto TEST = [&log,&im](const std::string& golden ) {
|
||||||
std::cout << std::endl;
|
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( 1000, 2000, 1 );
|
im.assign(std::numeric_limits<key>::min(), std::numeric_limits<key>::min(), -1);
|
||||||
std::cout << "constrtuction: \n\t";
|
TEST("[-2147483648,0]");
|
||||||
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[]) {
|
int main(int argc, char* argv[]) {
|
||||||
IntervalMapTest();
|
IntervalMapTest();
|
||||||
|
|||||||
Reference in New Issue
Block a user