tpl2r20141016.cpp

#include "eval.hpp"
#include <cstdlib>
#include <stack>

/* COMIENZO DE DESCRIPCION

   __USE_WIKI__
  #mkmtree:# Escribir una funcion que dados dos enteros
  positivos #m#, #k#, construye un AOO, tal que tiene a #m#
  en la raiz y dado un nodo #n# los hijos de #n# son
  #(*n)-j*k#, mientras sean no negativos. Por ejemplo si
  #m=10,k=3# debe retornar #T=(10 (7 (4 1) 1) (4 1) 1)#.

  #has-equal-path:# Dado un arbol ordenado orientado (AOO)
  escribir una funcion predicado que determina si contiene
  un camino de valores iguales que va desde la raiz a una
  hoja con todos elementos iguales. 

  #pancake-sort:# Dada una pila de numeros #S#, implementar
  el algoritmo de ordenamiento Pancake Sort, el cual ordena 
  la pila solo haciendo operaciones en las cuales se invierte 
  un rango contiguo de elementos en el tope de la pila. 

  #count-cycles:# Dado un #map<int,int> &M# que representa
  una permutacion (es decir tal que el conjunto de las
  claves es igual al conjunto de las imagenes) escribir una
  funcion que cuenta sus ciclos. 

  [Tomado en el Recup Trabajo Practico de Laboratorio Nro 2 
     (TPL2R) de 2014-10-16].  
  keywords: arbol orientado,cola,pila,grafo,correspondencia

FIN DE DESCRIPCION */

using namespace aed;
using namespace std;

typedef tree<int> tree_t;
typedef tree<int>::iterator node_t;

//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
void mkmtree(tree_t &T,node_t n, int k) {
  node_t c = n.lchild();
  int wc = *n-k;
  while (wc>0) {
    c = T.insert(c,wc);
    mkmtree(T,c,k);
    c++; wc -= k;
  }
}

//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
void mkmtree(tree_t &T,int m,int k) {
  T.clear();
  T.insert(T.begin(),m);
  mkmtree(T,T.begin(),k);
}

//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
bool has_equal_path(tree_t &T,node_t n) {
  if (n==T.end()) return true;
  node_t c = n.lchild();
  if (c==T.end()) return true;
  while (c!=T.end()) {
    if (*c==*n && has_equal_path(T,c)) return true;
    c++;
  }
  return false;
}

bool has_equal_path(tree_t &T) {
  return has_equal_path(T,T.begin());
}

//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
//Le pasas una pila y te devuelve la posicion al valor maximo desde el
//principio de la pila hasta la n-esima posicion
int pos_of_max(stack<int> s, int n){
  if(n==1) return 1;
	
  int maxi = s.top(), pos = 0;
  s.pop();
	
  for(int i = 1 ; i < n ; i++){
    if(s.top() > maxi){
      maxi = s.top();
      pos = i;
    }
    s.pop();
  }
  return pos;
}

//Le pasas una pila y 2 enteros. Se encarga de primero invertir los primeros
//n valores de la pila, y luego se encarga de invertir los j valores de la
//pila, previamente habiendo invertido los primeros n, asi se simula el
//algoritmo de panquequeado.
stack<int> flip(stack<int> s, int n, int j){
  queue<int> q1,q2;
  stack<int> s2,s3;
	
  for(int i = 0 ; i < n ; i++){
    q1.push(s.top());
    s.pop();
  }
	
  for(int i = n ; i < j ; i++){
    q2.push(s.top());
    s.pop();
  }
	
  while(!q1.empty()){
    q2.push(q1.front());
    q1.pop();
  }
	
  while(!q2.empty()){
    s.push(q2.front());
    q2.pop();
  }
	
  return s;
}

//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
void pancake_sort(stack<int> &s){
  int n;
  //a lo mas, va a requerir s.size panquequeadas
  for(int i = s.size() ; i > 0 ; i--){ 
    //se obtiene el mayor de la pila hasta la i-esima posicion
    n = pos_of_max(s,i);
    //se realiza el panquequeo para dejar ese mayor encontrado
    //en la ultima posicion posible
    s = flip(s,n,i);
    //		cout<<"Iteracion "<< s.size()-i<< ": " ;
    ////		mostrar_stack(s);
    //		cout<<endl;
  }
}

#define mii map<int,int>
#define miit map<int,int>::iterator

int count_cycles(mii &m){
  int cont = 0,first_pos,primero,segundo;
  miit mit = m.begin();
  //recorre todo el mapa, y para cada par, se fija si encuentra un ciclo
  while(mit!=m.end()){
    first_pos = mit->first;
    primero = mit->second;
    int cont_aux = m.size(); //por si las moscas no corta con algun ciclo, igualmente el erase me lo evitaria
    //el while se fija si se puede formar un ciclo
    while(first_pos != primero && cont_aux>0 ){
      if(m.find(primero)==m.end()) break;
      segundo = primero;
      primero = m[segundo];
      //elimino del mapa para evitar contar ciclos repetidos
      m.erase(segundo);
      cont_aux--;
    }
    if(first_pos == primero) cont++;
    mit++;
  }
  return cont;
}

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

  ev.eval1(mkmtree,vrbs);
  ev.eval2(has_equal_path,vrbs);
  ev.eval3(pancake_sort,vrbs);
  ev.eval4(count_cycles,vrbs);

  for (int j=0; j<30; j++) {
    seed = rand()%1000;
    if (j==0) seed = 123;
    h1 = ev.eval1r(mkmtree,seed); // para SEED=123 debe dar H1=170
    h2 = ev.eval2r(has_equal_path,seed); // para SEED=123 debe dar H2=959
    h3 = ev.eval3r(pancake_sort,seed); // para SEED=123 debe dar H3=489
    h4 = ev.eval4r(count_cycles,seed); // para SEED=123 debe dar H4=392
    printf("SEED=%03d -> HASH1=%03d, HASH2=%03d, "
           "HASH3=%03d, HASH4=%03d\n",
           seed,h1,h2,h3,h4);
  }

  return 0;
}

Generated by GNU Enscript 1.6.6.