tpl220181011.cpp

#define USECHRONO
#undef HAVE_MPI
#include "eval.hpp"
#include <cassert>
#include <climits>
#include <cstdlib>
#include <stack>
#include <map>

/* COMIENZO DE DESCRIPCION

   __USE_WIKI__

   #classify_relative:# Implemente una funcion 
   #void classify_relative(tree<int> &T,int n1,int n2,int &m1, int&m2);#
   que dados dos valores nodales #n1# y #n2# en un arbol #T# retorna
   las distancias #m1# y #m2# de ambos nodos al antecesor comun mas
   cercano. Por ejemplo si #T1=(5 (1 8 (9 2)) (7 3))#, #n1=8# y #n2=7#
   entonces el antecesor comun es el nodo #5# (la raiz) y las
   distancias correspondientes son #m1=2# y #m2=1#.

   #prom-path:#
   Dado un arbol #T#, escribir una funcion
   #float prom_path(tree<int> &T);#
   que retorne la longitud
   promedio de los caminos desde la raiz a las hojas. Por ejemplo, para
   el arbol #T=(1 (2 3 4 (5 6)) 7 8)#, los 5 posibles caminos desde la
   raiz a una hoja son:\\
   #{1,2,3}, {1,2,4}, {1,2,5,6}, {1,7}, {1,8};#
   cuyas longitudes son 2, 2, 3, 1 y 1; lo cual da un promedio de
   (2+2+3+1+1)/5 = 9/5 = 1.8.

   #filtra-deps:# Se tiene un #map<string,list<string>>#
   que representa un grafo dirigido donde los nodos son nombres
   paquetes de software en un repositorio, y los arcos dependencias
   entre paquetes.

   [Tomado en el Trabajo Practico de Laboratorio Nro 2
   (TPL2) de 2018-10-11].
   keywords: arbol orientado, correspondencia

FIN DE DESCRIPCION */


using namespace aed;
using namespace std;

typedef tree<int>::iterator node_t;

//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
// Extraer el camino desde el nodo que contiene el entero
// "n". La lista contiene todos los nodos desde la raiz
// hasta el nodo.  Funcion recursiva auxiliar. Extrae el
// camino desde el nodo "q". Si el entero "n" no esta en el
// subarbol de "q" entonces retorna la lista vacia. 
void get_path(tree<int> &T,node_t q,int n,list<int> &L) {
  // Si el nodo es Lambda entonces retorna la lista vacia
  if (q==T.end()) return;
  // Si el nodo contiene el valor buscado retorna una lista
  // solo con el valor del nodo
  if (*q==n) {
    L.clear();
    L.push_back(n);
    return;
  }

  // Busca en los hijos "c" de "q". Si alguno retorna un
  // lista no vacia es que ahi esta el nodo y solo basta con
  // prependizar el valor del nodo "q"
  auto c =q.lchild();
  while (c!=T.end()) {
    get_path(T,c,n,L);
    if (!L.empty()) {
      // Lo encontro. Prependiza *q y retorna
      L.push_front(*q);
      return;
    }
    // Incrementa c
    c++;
  }
}

//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
// Wrapper llama desde la raiz
void get_path(tree<int> &T,int n,list<int> &L) {
  L.clear();
  get_path(T,T.begin(),n,L);
}

//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
// Retorna los indices m1 m2 de n1 y n2 que contabilizan la
// distancia al antecesor comun
void classify_relative(tree<int> &T,
                       int n1,int n2,int &m1, int&m2) {
  // Busca el camino de la raiz a n1 y a n2
  list<int> L1,L2;
  get_path(T,n1,L1);
  get_path(T,n2,L2);
  // Busca el ultimo antecesor comun 
  auto q1=L1.begin(), q2=L2.begin();
  while (q1!=L1.end() && q2!=L2.end()
         && *q1==*q2) {
    q1++; q2++;
  }
  m1=0; m2=0;
  // Cuenta cuantos nodos hay desde el antecesor comun hasta n1
  while (q1!=L1.end()) { q1++; m1++; }
  // Cuenta cuantos nodos hay desde el antecesor comun hasta n2
  while (q2!=L2.end()) { q2++; m2++; }
}

//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
void prom_path(tree<int> &T, tree<int>::iterator it,
               int l, int &sum, int &cant) {
 auto itC = it.lchild();
 if (itC==T.end()) { cant++; sum+=l; return; }
 while(itC!=T.end()) {
   prom_path(T,itC,l+1,sum,cant);
   ++itC;
 }
}

float prom_path(tree<int> &T) {
 int sum=0,cant=0;
 prom_path(T,T.begin(),0,sum,cant);
 return float(sum)/cant;
}

//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
void marca_necesarios(map<string,list<string>> &G,
                      std::string s, std::set<std::string> &necesarios) {
  if (necesarios.count(s)) return;
  necesarios.insert(s);
  for(auto d:G[s]) marca_necesarios(G,d,necesarios);
}

void filtra_deps(map<string,list<string>> &G, list<string> &L) {
  std::set<std::string> necesarios;
  for(auto s:L) 
    marca_necesarios(G,s,necesarios);
 
  for(auto itG=G.begin();itG!=G.end();) {
    if (necesarios.count(itG->first)) {
      auto &D=itG->second;
      for(auto itD=D.begin();itD!=D.end();) {
        if (necesarios.count(*itD)) ++itD;
        else itD = D.erase(itD);
      }
      ++itG;
    } else {
      itG = G.erase(itG);
    }
  }
}

//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
int main() {
  Eval ev;
  int vrbs = 0;
  int seed = 123;
  int h1=0,h2=0,h3=0;

  do {

    ev.eval<1>(classify_relative,vrbs);
    h1 = ev.evalr<1>(classify_relative,seed,vrbs);

    ev.eval<2>(prom_path,vrbs);
    h2 = ev.evalr<2>(prom_path,seed,vrbs);

    ev.eval<3>(filtra_deps,vrbs);
    h3 = ev.evalr<3>(filtra_deps,seed,vrbs);

    printf("S=%03d -> H1=%03d H2=%03d H3=%03d\n",
           seed,h1,h2,h3);
    
    printf("\n\nIngrese un valor para la semilla:");
  } while (cin>>seed);

  return 0;
}

Generated by GNU Enscript 1.6.6.