tplr20161110.cpp

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

/* COMIENZO DE DESCRIPCION

   __USE_WIKI__

   #max_sublist_m# Programar una funcion 
   #max_sublist_m(list<int> &L, int m);# que reciba una lista de
   enteros #L# y un entero #m# tal que #0<m<=L.size(),# y encuentre y
   retorne el valor de la mayor suma de entre todas las posibles
   sumas de sublistas de longitud #m.#

   #remove_max_sibling:# Escribir un funcion 
   #void remove_max_sibling(tree<int>&T);# que borra el mayor hijo
   de cada lista de hijos. 

   #max_siblings_sum:# Escriba una funcion 
   #void max_siblings_sum(tree<int>&T,list<int>&L);#
   que reciba un AOO y retorne la lista de nodos
   hermanos (ordenados desde el mas izquierdo) que obtenga
   la mayor suma entre todas sus etiquetas.

   #max_valid_path:# Implementar la funcion
   #int max_valid_path(map<int,set<int>>& G, bool (*pred)(int));# 
   que recibe un grafo no dirigido #G#
   y retorna la longitud del camino mas largo (sin repetir vertices) 
   tal que cada uno de los nodos que lo
   compone satisface el predicado #pred.# 

   [Tomado en el Recup TPLs (TPLR) de 2016-11-10].  
   keywords: lista, arbol orientado, arbol binario, correspondencia, conjunto, programacion funcional

FIN DE DESCRIPCION */

using namespace aed;
using namespace std;

//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>

int max_sublist_m(list<int> &L, int m){
  int mx = numeric_limits<int>::min(); // para guardar la maxima suma
  int I = L.size()-m+1; // si las sublistas son de largo m, no
                        // pueden empezar mas alla de I
  auto it = L.begin();
  for(int i=0;i<I;i++) { 
    auto it2 = it++; // lista que empieza en it (y de paso
                     // lo incremento para la proxima)
    int aux = 0; // para acumular
    for(int j=0;j<m;j++) aux+=*(it2++);
    mx = max(mx,aux); // me quedo con la max entre lo que tenia
                      // y la que acabo de probar
  }
  return mx;
}

//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>

void remove_max_sibling(tree<int>&T, tree<int>::iterator it){
  auto itm = T.end(); // aca va el maximo hijo-hoja, empiezo con
                      // end para decir que todavia no hay
  for(auto c = it.lchild();c!=T.end();++c)
    if (c.lchild()==T.end()) { // si es hoja, ver si es el maximo
      if (itm==T.end()||*itm<*c) itm=c; // queda como maximo si
                                        // no habia otro, o si es mejor
                                        // que el que habia
  } else {
    remove_max_sibling(T,c); // si no es hoja, aplicar recursivamente
  }
  if (itm!=T.end()) T.erase(itm); // si habia algun hijo-hoja,
                                  // aca quedo el maximo; borrarlo
}

void remove_max_sibling(tree<int>&T){
  remove_max_sibling(T,T.begin());
}

//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
const list<int> &maxL(const list<int> &L1, const list<int> &L2) {
  // funcion auxiliar para elegir la mejor entre
  // dos posibles listas de hermanos
  return accumulate(L1.begin(),L1.end(),0) >=
    accumulate(L2.begin(),L2.end(),0) ? L1: L2;
}

list<int> max_siblings_sum(tree<int>&T, tree<int>::iterator it) {
  list<int> Lc, Lm; // Lc es la lista de hijos de este nodo, 
                    // Lm es la mejor entre las que retornan
                    // las llamadas recursivas
  for(auto c=it.lchild();c!=T.end();++c) {
    Lc.push_back(*c);
    // si hay empate entre hijos, en preorden gana el primer hijo
    Lm = maxL(Lm,max_siblings_sum(T,c)); 
  }
  return maxL(Lm,Lc); // si hay empate entre la del nodo
                      // actual y la de los hijos, en preorden
                      // termina antes la de un hijo
}

list<int> max_siblings_sum(tree<int>&T) {
  list<int> Lbeg = { *T.begin() }; // habia que considerar a la raiz
                                   // como una lista con un unico "hermano"
  return maxL(Lbeg,max_siblings_sum(T,T.begin()));
}

//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>

int max_valid_path(map<int,set<int>>& G, bool (*pred)(int),
                   int node, int len, set<int> visited) {
  int mx = len; // cantidad de nodos en el camino hasta llegar a este punto
  visited.insert(node); // marcar el actual como visitado
  for(int v:G[node]) // buscar otros nodos que cumplan
                     // el pred y no visitados para seguir
    if (pred(v) && visited.count(v)==0)
      // quedarse siempre con el mayor
      mx = max (mx, max_valid_path(G,pred,v,len+1,visited)); 
  return mx;
}

int max_valid_path(map<int,set<int>>& G, bool (*pred)(int)){
  set<int> visited; // si esta en el set esta visitado, sino no
  int mx = 0; // maximo numero de nodos en el camino
              // (la long del camino es mx-1)
  for(auto p:G) 
    if (pred(p.first)) // por cada nodo que cumple con el
                       // pred, probar iniciar ahi un camino
      // quedarse siempre con el mayor
      mx = max(mx,max_valid_path(G,pred,p.first,1,visited)); 
  return mx-1;
}

//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>

int main() {
  
  Eval ev;
  int vrbs = 0;
  int seed = 123;
  int h1=0,h2=0,h3=0,h4=0;
  
  cout << "seed: 123" << endl;
  do {
    ev.eval<1>(max_sublist_m,vrbs);
    h1 = ev.evalr<1>(max_sublist_m,seed,vrbs);
    
    ev.eval<2>(remove_max_sibling,vrbs);
    h2 = ev.evalr<2>(remove_max_sibling,seed,vrbs);
    
    ev.eval<3>(max_siblings_sum,vrbs);
    h3 = ev.evalr<3>(max_siblings_sum,seed,vrbs);
    
    ev.eval<4>(max_valid_path,vrbs);
    h4 = ev.evalr<4>(max_valid_path,seed,vrbs);
    
    printf("S=%03d -> H1=%03d H2=%03d H3=%03d H4=%03d\n",
           seed,h1,h2,h3,h4);
    
    cout << endl << "Siguiente seed: ";
  } while (cin>>seed);
  return 0;
  
}

Generated by GNU Enscript 1.6.6.