#include <cstddef>
#include <list>
#include <vector>
#include <set>
#include <algorithm>
#include <iostream>
typedef std::size_t entity_id_t;
typedef long entity_pos_t;
typedef std::size_t entity_length_t;
struct Entity {
entity_id_t id;
entity_pos_t pos;
entity_length_t length;
};
typedef std::pair<entity_id_t, entity_id_t> collision_t;
template<class EntityContainer>
std::list<collision_t> collision_check(const EntityContainer& entities) {
struct Boundary {
entity_id_t id;
entity_pos_t pos;
enum {
StartBound,
EndBound
} type;
};
const std::size_t n = entities.size();
std::vector<Boundary> boundaries(2 * n);
{
std::size_t i = 0;
for(const Entity cur : entities) {
boundaries[i] = {cur.id, cur.pos, Boundary::StartBound};
boundaries[++i] = {cur.id, entity_pos_t(cur.pos + cur.length),
Boundary::EndBound};
++i;
}
}
std::sort(boundaries.begin(), boundaries.end(),
[](Boundary fst, Boundary snd) {
return fst.pos < snd.pos ||
(fst.pos == snd.pos && fst.type == Boundary::EndBound &&
snd.type == Boundary::StartBound);
});
std::set<entity_id_t> unclosed;
std::list<collision_t> collisions;
for(const Boundary bound : boundaries) {
if(bound.type == Boundary::StartBound) {
for(const entity_id_t id : unclosed)
collisions.push_back({id, bound.id});
unclosed.insert(bound.id);
}
else
unclosed.erase(bound.id);
}
return collisions;
}
int main() {
/* entity 0: ....____
* entity 1: ..___...
* entity 2: __......
* entity 3: .__.....
*/
std::vector<Entity> entities({{0, 4, 4}, {1, 2, 3}, {2, 0, 2}, {3, 1, 2}});
const auto collisions = collision_check(entities);
for(collision_t cur : collisions)
std::cout << "entities " << cur.first << " and " << cur.second
<< " collide\n";
}
I2luY2x1ZGUgPGNzdGRkZWY+CiNpbmNsdWRlIDxsaXN0PgojaW5jbHVkZSA8dmVjdG9yPgojaW5jbHVkZSA8c2V0PgojaW5jbHVkZSA8YWxnb3JpdGhtPgojaW5jbHVkZSA8aW9zdHJlYW0+Cgp0eXBlZGVmIHN0ZDo6c2l6ZV90IGVudGl0eV9pZF90Owp0eXBlZGVmIGxvbmcgZW50aXR5X3Bvc190Owp0eXBlZGVmIHN0ZDo6c2l6ZV90IGVudGl0eV9sZW5ndGhfdDsKCnN0cnVjdCBFbnRpdHkgewogIGVudGl0eV9pZF90IGlkOwogIGVudGl0eV9wb3NfdCBwb3M7CiAgZW50aXR5X2xlbmd0aF90IGxlbmd0aDsKfTsKCnR5cGVkZWYgc3RkOjpwYWlyPGVudGl0eV9pZF90LCBlbnRpdHlfaWRfdD4gY29sbGlzaW9uX3Q7Cgp0ZW1wbGF0ZTxjbGFzcyBFbnRpdHlDb250YWluZXI+CnN0ZDo6bGlzdDxjb2xsaXNpb25fdD4gY29sbGlzaW9uX2NoZWNrKGNvbnN0IEVudGl0eUNvbnRhaW5lciYgZW50aXRpZXMpIHsKICBzdHJ1Y3QgQm91bmRhcnkgewogICAgZW50aXR5X2lkX3QgaWQ7CiAgICBlbnRpdHlfcG9zX3QgcG9zOwogICAgZW51bSB7CiAgICAgIFN0YXJ0Qm91bmQsCiAgICAgIEVuZEJvdW5kCiAgICB9IHR5cGU7CiAgfTsKICAKICBjb25zdCBzdGQ6OnNpemVfdCBuID0gZW50aXRpZXMuc2l6ZSgpOwogIHN0ZDo6dmVjdG9yPEJvdW5kYXJ5PiBib3VuZGFyaWVzKDIgKiBuKTsKICB7CiAgICBzdGQ6OnNpemVfdCBpID0gMDsKICAgIGZvcihjb25zdCBFbnRpdHkgY3VyIDogZW50aXRpZXMpIHsKICAgICAgYm91bmRhcmllc1tpXSA9IHtjdXIuaWQsIGN1ci5wb3MsIEJvdW5kYXJ5OjpTdGFydEJvdW5kfTsKICAgICAgYm91bmRhcmllc1srK2ldID0ge2N1ci5pZCwgZW50aXR5X3Bvc190KGN1ci5wb3MgKyBjdXIubGVuZ3RoKSwKICAgICAgICAgICAgICAgICAgICAgICAgIEJvdW5kYXJ5OjpFbmRCb3VuZH07CiAgICAgICsraTsKICAgIH0KICB9CiAgc3RkOjpzb3J0KGJvdW5kYXJpZXMuYmVnaW4oKSwgYm91bmRhcmllcy5lbmQoKSwKICAgICAgICAgICAgW10oQm91bmRhcnkgZnN0LCBCb3VuZGFyeSBzbmQpIHsKICAgIHJldHVybiBmc3QucG9zIDwgc25kLnBvcyB8fAogICAgICAgICAgIChmc3QucG9zID09IHNuZC5wb3MgJiYgZnN0LnR5cGUgPT0gQm91bmRhcnk6OkVuZEJvdW5kICYmCiAgICAgICAgICAgIHNuZC50eXBlID09IEJvdW5kYXJ5OjpTdGFydEJvdW5kKTsKICB9KTsKICBzdGQ6OnNldDxlbnRpdHlfaWRfdD4gdW5jbG9zZWQ7CiAgc3RkOjpsaXN0PGNvbGxpc2lvbl90PiBjb2xsaXNpb25zOwogIGZvcihjb25zdCBCb3VuZGFyeSBib3VuZCA6IGJvdW5kYXJpZXMpIHsKICAgIGlmKGJvdW5kLnR5cGUgPT0gQm91bmRhcnk6OlN0YXJ0Qm91bmQpIHsKICAgICAgZm9yKGNvbnN0IGVudGl0eV9pZF90IGlkIDogdW5jbG9zZWQpCiAgICAgICAgY29sbGlzaW9ucy5wdXNoX2JhY2soe2lkLCBib3VuZC5pZH0pOwogICAgICB1bmNsb3NlZC5pbnNlcnQoYm91bmQuaWQpOwogICAgfQogICAgZWxzZQogICAgICB1bmNsb3NlZC5lcmFzZShib3VuZC5pZCk7CiAgfQogIHJldHVybiBjb2xsaXNpb25zOwp9CgppbnQgbWFpbigpIHsKICAvKiBlbnRpdHkgMDogLi4uLl9fX18KICAgKiBlbnRpdHkgMTogLi5fX18uLi4KICAgKiBlbnRpdHkgMjogX18uLi4uLi4KICAgKiBlbnRpdHkgMzogLl9fLi4uLi4KICAgKi8KICBzdGQ6OnZlY3RvcjxFbnRpdHk+IGVudGl0aWVzKHt7MCwgNCwgNH0sIHsxLCAyLCAzfSwgezIsIDAsIDJ9LCB7MywgMSwgMn19KTsKICBjb25zdCBhdXRvIGNvbGxpc2lvbnMgPSBjb2xsaXNpb25fY2hlY2soZW50aXRpZXMpOwogIGZvcihjb2xsaXNpb25fdCBjdXIgOiBjb2xsaXNpb25zKQogICAgc3RkOjpjb3V0IDw8ICJlbnRpdGllcyAiIDw8IGN1ci5maXJzdCA8PCAiIGFuZCAiIDw8IGN1ci5zZWNvbmQKICAgICAgICAgICAgICA8PCAiIGNvbGxpZGVcbiI7Cn0=