tpl220191010.cpp
#define USECHRONO
#undef HAVE_MPI
#include "eval.hpp"
#include <cassert>
#include <climits>
#include <cstdlib>
#include <stack>
#include <map>
/* COMIENZO DE DESCRIPCION
__USE_WIKI__
#fill-oprev:# Dado un AOO #T# y una lista #L# reemplaza
los nodos de #T# con los valores de #L#. Si hay mas
nodos en #T# que valores en #L# entonces los nodos
restantes de #T# quedan en su valor
original. Reciprocamente, si hay mas valores en #L# que
en #T# los valores restantes de #L# son descartados.
#a-lo-ancho:# Implemente una funcion que reciba un grafo
no dirigido #G# y genere un arbol de expansion #T# de
la componente conexa a la que pertenece el primer
vertice del grafo (que sera la raiz del arbol), a
partir del algoritmo de busqueda a lo ancho.
#intersect-map:# Implemente una funcion que, a partir de
las correspondencias A# y #B# construye una
correspondencia #C# de manera que las claves de #C# son
la interseccion de las claves de #A# y B# y para cada
clave #k# en #C# la imagen #C[k]# es la interseccion
ordenada de las listas ordenadas #A[k]# y B[k]#. Si
esta interseccion de listas es nula, no debe incluirse
la entrada de clave #k# en #C#.
[Tomado en el Trabajo Practico de Laboratorio Nro 2
(TPL2) de 2019-10-10].
keywords: arbol orientado, correspondencia
FIN DE DESCRIPCION */
using namespace aed;
using namespace std;
void fill_ordprev(tree<int> &T,tree<int>::iterator n,
list<int> &L) {
// Si el arbol esta vacio o la lista esta vacia no hay que
// hacer nada
if (n==T.end()) return;
if (L.empty()) return;
// Extrae el primer elemento de la lista y pisa el valor
// del nodo
*n = L.front();
// Hay que extraer el elemento de la lista (en este caso
// es destructivo sobre la lista). Si no la otra
// posibilidad seria tener un iterador en la lista.
L.pop_front();
// Aplica recursivamente a los hijos
auto c = n.lchild();
while (c!=T.end()) fill_ordprev(T,c++,L);
}
//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
// Wrapper
void fill_ordprev(tree<int> &T,list<int> &L) {
fill_ordprev(T,T.begin(),L);
}
//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
// Lo mismo que fill_ordprev, pero llenando en orden posterior.
void fill_ordpost(tree<int> &T,tree<int>::iterator n,
list<int> &L) {
if (n==T.end()) return;
auto c = n.lchild();
while (c!=T.end()) fill_ordpost(T,c++,L);
if (L.empty()) return;
*n = L.front();
L.pop_front();
}
void fill_ordpost(tree<int> &T,list<int> &L) {
fill_ordpost(T,T.begin(),L);
}
//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
void a_lo_ancho(graph& G, tree<char>& T){
typedef tree<char>::iterator node;
// Conjunto de nodos que ya fueron visitados
map<char,bool> visitados;
// En cada iteracion toma los nodos de la capa actual
// "current layer", recorre sus adyacencias y las inserta
// en los hijos. Va llenando listas que son la siguiente
// capa (next layer). Por cada capa mantenemos una lista
// de valores y una lista de nodos en el arbol.
list<char> nextLayer;
list<char> currLayer;
list<node> nextLayerTree;
list<node> currLayerTree;
// inicializa poniendo la primera clave del grafo como
// raiz del arbol
currLayer.push_back(G.begin()->first);
currLayerTree.push_back(T.insert(T.begin(),G.begin()->first));
visitados[G.begin()->first];
// En cada iteracion de este lazo se agrega una capa. El
// algoritmo se termina cuando no hay mas nodos en una
// capa. OJO que si el grafo es disconexo entonces solo
// inserta en el arbol la componente conexa conectada a la
// primera clave del grafo.
while(currLayer.size()){
// Limpiar los contenedores para la siguiente capa
nextLayer.clear();
nextLayerTree.clear();
// Itera sobre los nodos de la capa actual
auto itLayer = currLayerTree.begin();
for(int n:currLayer) {
// n es el char, it es el nodo correspondiente en la
// capa
auto it = *itLayer;
it = it.lchild();
// Vecinos del nodo
auto &vecinos = G[n];
for(auto &v : vecinos){
if(visitados.find(v)==visitados.end()){
// Los nodos no visitados los agrega a las listas
// (ambas cosas, el char y el iterador)
nextLayer.push_back(v);
it = T.insert(it,v);
nextLayerTree.push_back(it);
visitados[v];
it++;
}
}
// incrementa el iterador en la lista de iterators
itLayer++;
}
// Swapea los contenedores de los niveles
currLayer = nextLayer;
currLayerTree = nextLayerTree;
}
}
//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
void intersect_map(map<int,list<int>> &A,
map<int,list<int>> &B,
map<int,list<int>> &C){
// Recorre las claves de A
for(auto &p :A){
auto itB = B.find(p.first);
if(itB!=B.end()){
// la clave esta en A y en B
// LB es una referencia a la lista en B
auto &LB = itB->second;
// eA es un elemento de la lista en A
for(auto &eA: p.second){
// Si el elemento esta en LB lo inserta en C
if(find(LB.begin(),LB.end(),eA)!=LB.end()){
C[p.first].push_back(eA);
}
}
}
}
}
//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
int main() {
Eval ev;
int vrbs = 0;
int seed = 123;
int h1=0,h2=0,h3=0;
cout << "seed: 123" << endl;
do {
ev.eval<1>(fill_ordprev,vrbs);
h1 = ev.evalr<1>(fill_ordprev,seed,vrbs);
ev.eval<2>(a_lo_ancho,vrbs);
h2 = ev.evalr<2>(a_lo_ancho,seed,vrbs);
ev.eval<3>(intersect_map,vrbs);
h3 = ev.evalr<3>(intersect_map,seed,vrbs);
printf("S=%03d -> H1=%03d H2=%03d H3=%03d\n",
seed,h1,h2,h3);
cout << endl << "Siguiente seed: ";
} while (cin>>seed);
return 0;
}
Generated by GNU Enscript 1.6.6.