diffsym.cpp
// $Id: diffsym.cpp,v 1.5 2006/04/25 12:45:20 mstorti Exp $
/* COMIENZO DE DESCRIPCION
__USE_WIKI__
Dada una lista de conjuntos de enteros
#list< set<int> > l# escribir una funci\'on
#void diffsym(list< set<int> > &L, set<int> &ad)#
que retorna en #ad# el conjunto de los elementos que
pertenecen a uno y s\'olo uno de los conjuntos de #L#.
Por ejemplo, si #L = ({1,2,3},{2,4,5},{4,6})# entonces
#ad# debe ser #{1,3,5,6}#. Notar que si el n\'umero
de conjuntos en #l# es 2 y los llamamos #A# y #B#,
entonces debe retornar #ad = (A-B) union (B-A)#.
[Tomado en el 3er parcial 23/6/2005].
keywords: conjunto
FIN DE DESCRIPCION */
#include <cmath>
#include <set>
#include <list>
#include <algorithm>
#include "./util.h"
using namespace std;
void print(const set<int> &s,
const char *t=NULL) {
if (t) printf("%s",t);
set<int>::iterator q = s.begin();
while (q!=s.end()) printf("%d ",*q++);
printf("\n");
}
// Un algoritmo posible es recorrer todos los elementos
// #x# que pertenecen a alg\'un conjunto de #l# y contar
// en cuantos elementos de #l# est\'a (debe estar en al
// menos uno). El elemento es insertado en #ad# s\'olo
// si el conteo da exactamente 1.
//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
void diffsym(list< set<int> > &l,set<int> &ad) {
list< set<int> >::iterator q = l.begin();
while (q!=l.end()) {
set<int> &s = *q;
set<int>::iterator r = s.begin();
while (r!=s.end()) {
int count = 0;
list< set<int> >::iterator w = l.begin();
while (w!=l.end()) {
if (w->find(*r) != w->end()) count++;
if (count>=2) break;
w++;
}
if (count==1) ad.insert(*r);
r++;
}
q++;
}
}
//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
// Otro algoritmo, basado en funciones binarias
// Notar que en el caso de tres conjuntos si:
// S=diffsym(A,B) y
// U= A union B,
// entonces:
// diffsym(A,B,C) = (S-C) \cup (C-U).
// Esto vale en general para cualquier n\'umero de conjuntos, de manera
// que podemos utilizar el siguiente lazo
// L = lista de conjuntos, S=U=<conjunto-vacio>
// FOR Q en la lista de conjuntos de L
// S = (S-Q) union (Q-U)
// U = U union Q
// Al terminar el lazo, S es la diferencia sim\'etrica buscada.
void diffsym2(list< set<int> > &l,
set<int> &all_diff) {
all_diff.clear();
set<int> all_union,s1,s2;
list< set<int> >::iterator
q = l.begin();
while (q!=l.end()) {
s2.clear();
set_difference(all_diff.begin(),all_diff.end(),
q->begin(),q->end(),
inserter(s2,s2.begin()));
all_diff = s2;
set_difference(q->begin(),q->end(),
all_union.begin(),all_union.end(),
inserter(all_diff,all_diff.begin()));
s1.clear();
set_union(q->begin(),q->end(),
all_union.begin(),all_union.end(),
inserter(s1,s1.begin()));
all_union = s1;
q++;
}
}
//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
void make_random_set(set<int> &s,
int m,int n,int N) {
double lambda = 1.0/(m+1); // Probability of stopping
s.clear();
while(1) {
if (drand()<lambda) break;
int w = rand() % N;
s.insert(w);
}
}
// -------------------------------------------------------------------
int main () {
int N = 20; // Max nbr of elements in all sets
int m = 5; // Nbr oe elements in each set
int n = 5; // nbr of sets
list< set<int> > l;
double lambda = 1.0/(m+1); // Probability of stopping
double sav = 0.0;
for (int k=0; k<n; k++) {
l.push_back(set<int>());
set<int> &s = l.back();
make_random_set(s,m,n,N);
printf("set[%d]: ",k);
print(s);
sav += s.size();
}
printf("average set size %f\n",sav/n);
set<int> S;
S.clear();
diffsym(l,S);
print(S,"using diffsym():");
S.clear();
diffsym2(l,S);
print(S,"using diffsym2():");
}
Generated by GNU enscript 1.6.4.