amfern / think-cell-test

15 stars 6 forks source link

my failed solution #2

Open vadimen opened 1 year ago

vadimen commented 1 year ago

maybe will offer some ideas to someone

#include <map>
#include <limits>
#include <iostream>
#include <vector>
#include <type_traits>
template<typename K, typename V>
class interval_map {
    friend void IntervalMapTest();
    V m_valBegin;
    std::map<K,V> m_map;
public:
    // constructor associates whole range of K with val
    interval_map(V const& val) : m_valBegin(val) {
        m_map[std::numeric_limits<K>::min()]=val;
    }

    // Assign value val to interval [keyBegin, keyEnd).
    // Overwrite previous values in this interval.
    // Conforming to the C++ Standard Library conventions, the interval
    // includes keyBegin, but excludes keyEnd.
    // If !( keyBegin < keyEnd ), this designates an empty interval,
    // and assign must do nothing.
    void assign( K const& keyBegin, K const& keyEnd, V const& val ) {
        //the following 2 if's didn't work, just left them here
        if(     !std::is_arithmetic<K>::value &&
                std::is_copy_assignable<K>::value &&
                std::is_copy_constructible<K>::value &&
                std::is_same<decltype(std::declval<K>() < std::declval<K>()), bool>::value)
        {
            return;
        }

        if(     !std::is_arithmetic<V>::value &&
                 std::is_copy_assignable<V>::value &&
                 std::is_copy_constructible<K>::value &&
                 std::is_same<decltype(std::declval<V>() == std::declval<V>()), bool>::value)
        {
            return;
        }

        if( !(keyBegin < keyEnd) )
            return;

        //everything bigger than keyEnd is whatever was there before
        //get that value
        V valEnd = (*this)[keyEnd];

        //delete everything in between
        auto it=m_map.upper_bound(keyBegin);
        while(it!=m_map.upper_bound(keyEnd)){
            auto it_next = it;
            it_next++;
            m_map.erase(it);
            it = it_next;
        }

        //assign that value to keyEnd
        m_map[keyEnd]=valEnd;

        //everything bigger than keyBegin is val
        if(val != m_valBegin) m_map[keyBegin]=val;

    }

    // look-up of the value associated with key
    V const& operator[]( K const& key ) const {
        auto it=m_map.upper_bound(key);
        if(it==m_map.begin()) {
            return m_valBegin;
        } else {
            return (--it)->second;
        }
    }
};

template<typename K, typename V>
void InnerIntervalMapTest(interval_map<K, V> imap, K key, V val, int test_nr){
    V res_val = imap[key];
    if(res_val != val){
        std::cout << "Test " << test_nr << " failed" << "Error: " << key <<
                        " should be " << val << " but is " << res_val << std::endl;
    }else{
        std::cout << "Test " << test_nr << " passed" << std::endl;
    }
}

// Many solutions we receive are incorrect. Consider using a randomized test
// to discover the cases that your implementation does not handle correctly.
// We recommend to implement a test function that tests the functionality of
// the interval_map, for example using a map of int intervals to char.
void IntervalMapTest(){
    interval_map<int,char> imap('A');

    struct Data{
        int key;
        char value;
    };

    std::vector<Data> test_map;

    imap.assign(60, 70, 'B');
    imap.assign(60, 61, 'C');
    imap.assign(-1000, -100, 'K');
    imap.assign(-1, 0, 'K');
    imap.assign(10, 20, 'X');
    imap.assign(22, 23, 'Y');
    imap.assign(24, 30, 'Z');
    imap.assign(15, 25, 'W');
    imap.assign(15, 25, 'M');
    imap.assign(15, 32, 'M');

    imap.assign(10000, 10100, 'M');
    imap.assign(10050, 10150, 'N');

    test_map.push_back({ 10040, 'M'});
    test_map.push_back({ 10060, 'N'});

    test_map.push_back({ 10, 'X'});
    test_map.push_back({ 14, 'X'});
    test_map.push_back({ 15, 'M'});
    test_map.push_back({ 17, 'M'});
    test_map.push_back({ 20, 'M'});
    test_map.push_back({ 22, 'M'});
    test_map.push_back({ 24, 'M'});
    test_map.push_back({ 31, 'M'});
    test_map.push_back({ 35, 'A'});
    test_map.push_back({70, 'A'});
    test_map.push_back({100, 'A'});
    test_map.push_back({1000, 'A'});
    test_map.push_back({59, 'A'});
    test_map.push_back({60, 'C'});
    test_map.push_back({61, 'B'});
    test_map.push_back({69, 'B'});
    test_map.push_back({70, 'A'});
    test_map.push_back({71, 'A'});
    test_map.push_back({-1, 'K'});
    test_map.push_back({0, 'A'});
    test_map.push_back({-100, 'A'});
    test_map.push_back({-1000, 'K'});
    test_map.push_back({-1001, 'A'});
    test_map.push_back({-2, 'A'});

    int test_cnt = 1;
    for(auto i: test_map)
        InnerIntervalMapTest(imap, i.key, i.value, test_cnt++);

}

int main(){
    IntervalMapTest();
    return 0;
}
rijonshahariar commented 7 months ago

it worked?