Implementa la classe Finder, que té la següent
especificació:
template <class T>
class Finder {
public:
Finder();
void add(const T *t);
void update(const T *t);
void remove(const T *t);
std::set<const T *> query(pro2::Rect qrect) const;
};
La classe és un contenidor de punters a objectes de tipus
T, i el tipus T ha de ser una classe amb un
mètode get_rect, que obtingui el "rectangle de l’objecte",
amb la següent declaració:
pro2::Rect get_rect() const;
El rectangle és una tupla amb 4 enters left,
top, right, bottom. El
Finder ha de poder associar cada objecte amb el rectangle
que ocupa, de tal manera que es puguin fer consultes. Aquestes
consultes, amb el mètode query, reben un rectangle
qrect i ens retornen tots els punters a objectes de tipus
T tals que si demanem el seu rectangle amb
get_rect, aquest intersecta amb qrect. Si
qrect representa una finestra, query permet
localitzar aquells objectes que són visibles a través de la finestra (ja
sigui totalment o en part).
L’objectiu és que Finder pugui emmagatzemar molts milers
d’objectes, però si aquests estan distribuits per tot l’espai
bidimensional, una consulta a una zona petita de l’espai només ha de
retornar uns pocs objectes.
Per acotar el problema, es defineixen els següents tamanys límit:
El rectangle màxim de l’espai bidimensional és (0, 0, 20000, 20000), és a dir, un quadrat de amb la cantonada superior esquerra al punt (0, 0). (Recordeu que l’eix de les s creix en direcció descendent.)
Un sol objecte no pot tenir un rectangle amb amplada o alçada major que 2000.
Intersecció de rectangles
Els rectangles tenen coordenades enteres, i el Finder fa
la suposició que les coordenades límit d’un rectangle estan incloses en
el propi rectangle, de manera que dos rectangles (en ordre left
top right bottom) com 0 0 10 10
i 10 10 30 50 intersecten just al punt
,
que en primer cas és la cantonada de baix a la dreta i en el segon cas
és la cantonada de dalt a l’esquerra.
Codi disponible
Per poder fer el programa més còmodament, el codi públic d’aquest problema (la icona del gatet) proporciona:
Un Makefile que compila el programa amb només fer
make.
Una carpeta .vscode que permet compilar i depurar
només prement F5.
El fitxer geometry.hh, que defineix les tuples
Pt i Rect, que fa servir la majoria d’altres
classes.
Una classe TestObject, un objecte de prova que té el
mètode get_rect i es pot posar al
Finder.
El programa principal, que llegeix l’entrada i produeix la
sortida utilitzant el Finder.
Per entregar, descarrega el codi públic, i implementa o afegeix el
fitxer finder.hh. Cal enviar un .tar
només amb el fitxer finder.hh.
El programa principal ja gestiona l’entrada. Aquesta conté 5 tipus de "comandes", cadascuna en una línia apart:
+, per afegir un objecte, amb
l’id (un string) i les seves
coordenades;
-, per esborrar un objecte, donat
l’id;
=, per actualitzar un objecte,
donat l’id i les noves coordenades;
?, per consultar una zona, donades
les coordenades d’un rectangle;
0, per esborrar el
Finder i crear-ne un de nou.
Totes les coordenades de rectangles segueixen l’ordre left, top, right, bottom.
El programa principal defineix una classe FinderTester
que s’ocupa de relacionar els ids amb els punters als
objectes i en un fitxer apart (test-object.hh) es defineix
una classe TestObject mínima que serveix per fer les
proves.
La sortida és el resultat de les consultes (les altres comandes no
produeixen sortida). D’això també s’encarrega el programa principal.
Quan una consulta no retorna objectes, s’escriu "empty", i
quan hi ha objectes, es mostren els seus ids per ordre
lexicogràfic.
Input
? 0 0 1 1 + a 0 0 1 1 ? 0 0 0 0 + b 2 2 3 3 ? 1 1 1 1 ? 1 1 2 2 ? 2 2 3 3 ? 4 4 5 5
Output
empty objs: a objs: a objs: a b objs: b empty