tpl120170908.cpp

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

/* COMIENZO DE DESCRIPCION

   __USE_WIKI__

   #extract-range:# Dada una lista de enteros #L1# y dos
   iteradores en la misma #p,q#, extraer el rango #[p,q)# de
   #L1# en la lista #L2#. Nota: ambos #p,q# pueden ser
   #end()# y no necesariamente #p# esta antes de #q#.

   #add-elements:# Insertar cada uno de los elementos de la
   pila #S# en la lista ordenada #L#, la cual debe permanecer ordenada
   luego de la insercion. La funcion debe retornar la cantidad de
   numeros repetidos en la lista #L# luego de la insercion. Tener en
   cuenta que si hay mas de dos ocurrencias del mismo numero, dicho
   numero cuenta una unica vez en la suma de elementos repetidos.

   #coprimos:# Escribir una funcion #bool coprimos(list<int>
   &L);# que retorna #true# si todos los elementos de #L#
   son coprimos entre si. Recordemos que dos enteros son
   coprimos entre si el unico entero que divide a ambos es
   1. 

   [Tomado en el TPL1 de 2017-09-08].  
   keywords: lista, pila, cola

FIN DE DESCRIPCION */

using namespace aed;
using namespace std;

//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
int distance(list<int> &L,list<int>::iterator p) {
  // Calcula la distancia entre begin y la posicion.
  // Notar que funciona tambien si p es end()
  int j=0;
  auto z=L.begin();
  while (z!=p) { j++; z++; }
  return j;
}

//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
void extract_range(list<int> &L1, list<int>::iterator p, 
                   list<int>::iterator q, list<int> &L2)  {
  // La funcion distance calcula la distancia entre el origen y
  // el iterador. En caso de no conocerla es muy facil de implementar
#if 0
  // Usa la distancia de la libreria standard
  int dp = std::distance(L1.begin(),p);
  int dq = std::distance(L1.begin(),q);
#else
  // Usa la distancia implementada arriba
  int dp = distance(L1,p);
  int dq = distance(L1,q);
#endif
  // q esta antes de p, no hay que hacer nada
  if (dq<=dp) return;
  L2.insert(L2.begin(),p,q);
  L1.erase(p,q);
}

//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
void extract_range2(list<int> &L1, list<int>::iterator p, 
                    list<int>::iterator q, list<int> &L2)  {
  // Asegurarse que L2 este vacia
  L2.clear();
  // Si p es end entonces no hay ningun elemento despues de p
  if (p==L1.end()) return;
  // Verifica si se puede llegar a q desde p
  // Notar que funciona incluso si q es end
  auto z=p;
  while (z!=L1.end() && z!=q) z++;
  // No se llega a q, por lo tanto no hay que hacer nada
  if (z!=q) return;
  // Recorre desde p a q y va eliminando los elementos de
  // L1 y los pone en L2. 
  z=p;
  while (z!=q) {
    L2.push_back(*z);
    z = L1.erase(z);
  }
}

//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
void extract_range3(list<int> &L1, list<int>::iterator p, 
                    list<int>::iterator q, list<int> &L2)  {
  // Asegurarse que L2 este vacia
  L2.clear();
  if (p==L1.end()) return;
  auto z = L1.begin();
  // Se fija si llega primero a p o a q
  while (z!=L1.end() && z!=p && z!=q) z++;
  // Si llega primero a q no hay que hacer nada
  if (z==q) return;
  z=p; // De todas formas esto deberia ser cierto
  // Recorre desde p a q y va eliminando los elementos de
  // L1 y los pone en L2. 
  while (z!=q) {
    L2.push_back(*z);
    z = L1.erase(z);
  }
  
}

//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
int add_elements(list<int>& L, stack<int> &S) {
  // Inserta todos los elementos de S en L
  // manteniendo L ordenada
  while(!S.empty()) {
    int x = S.top(); S.pop();
    list<int>::iterator it = L.begin();
    while(it!=L.end() && *it<x) ++it;
    L.insert(it,x);
  }
  // Cuenta los valores repetidos
  int ret = 0;
  for( list<int>::iterator it=L.begin(); it!=L.end(); ++it ) { 
    bool rep = false;
    while (next(it)!=L.end() && *it==*next(it)) {
      ++it; rep=true;
    }
    if (rep) ret++;
  }
  return ret;
}

//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
int add_elements2(list<int>& L, stack<int> &S) {
  // Otra solucion
  auto p=L.begin();
  while (!S.empty()) {
    int x = S.top(); S.pop();
    // S no esta necesariamente ordenada hay
    // que buscar desde el principio
    p=L.begin();
    while (p!=L.end() && *p<x) p++;
    L.insert(p,x);
  }
  // Cuenta los repetidos
  int reps=0;
  p=L.begin();
  while (p!=L.end()) {
    auto q=p; q++;
    if (q!=L.end() && *q==*p) reps++;
    // Avanza p hasta encontrar end() o un elemento distinto
    while (q!=L.end() && *q==*p) q++;
    p=q;
  }
  return reps;
}

//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
// Retorna en L los divisores (>=2) de x
void divisores(int x,list<int>&L){
  int i = 2;
  while(i<=x){
    if(x%i == 0)
      L.push_back(i);
    i++;
  }
}

// Retorna true si x esta en la lista L
bool contiene(int x, list<int>&L){
  for(auto y: L){
    if(y == x)
      return true;
  }
  return false;
}

bool repetidos(list<int>::iterator it1,list<int>::iterator it2){
  if(it1 == it2) return false;
  list<int>::iterator ita = it1;ita++;
  while(ita != it2){
    if(*ita == *it1)
      return true;
    ita++;
  }
  it1++;
  return repetidos(it1,it2);
}

bool coprimos(list<int>&L) {
  list<int>::iterator it = L.begin(),it2;
  it2 = it;it2++;
  if(repetidos(L.begin(),L.end()))return false;
  list<int> divs;
  divisores(*(L.begin()), divs);
  it++;
  while(it!= L.end()){
    list<int> aux;
    divisores(*it, aux);
    for(auto x : aux){
      if(contiene(x,divs))
        return false;
      else divs.push_back(x);
    }
    it++;
  }
  return true;
}

//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
// Otra posible solucion
bool coprimos2(list<int>&L) {
  // p,q recorren todos los pares distintos en L.
  // p recorre [begin,end)
  auto p=L.begin();
  while (p!=L.end()) {
    auto q=p; q++;
    // para cada p, q recorre [p+1,end)
    while (q!=L.end()) {
      // Determina si *p y *q son coprimos
      // recorre con k entre [2,min(*p,*q)] y para cada
      // k verifica si divide a *p y *q
      int k=2, min=(*p<*q? *p : *q);
      while (k<=min) {
        // Si k divide a *p y *q entonces no son coprimos
        if (*p%k==0 && *q%k==0) return false;
        k++;
      }
      q++;
    }
    p++;
  }
  // Todos los elementos son coprimos entre si
  return true;
}

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

#if 0
  // User typical call
  ev.eval<1>(extract_range,vrbs);
  h1 = ev.evalr<1>(extract_range,seed,vrbs);
  
  ev.eval<2>(add_elements,vrbs);
  h2 = ev.evalr<2>(add_elements,seed,vrbs);
  
  ev.eval<3>(coprimos,vrbs);
  h3 = ev.evalr<3>(coprimos,seed,vrbs);
  printf("S=%03d -> H1=%03d H2=%03d H3=%03d\n",
         seed,h1,h2,h3);
#else
#include "./tasks.cpp"
#endif
  
  return 0;
}

Generated by GNU Enscript 1.6.6.