/* File: insint.c */

/* Scopo: realizzazione del tipo di dato astratto "insieme di interi"
          tramite liste collegate */

#include <stdio.h>
#include <stdlib.h>

typedef int bool;
#define TRUE  1
#define FALSE 0

typedef long TipoIntero;

/* vengono rappresentati solo gli interi nell'intervallo LONG_MIN...LONG_MAX */

typedef TipoIntero TipoElemLista;

struct nodoLista {
  TipoElemLista info;           /* elemento della lista */
  struct nodoLista *next;       /* puntatore all'elem. successivo */
};
typedef struct nodoLista NodoLista;
typedef NodoLista *TipoLista;
typedef TipoLista TipoInsInteri;

#include "liste.c"

bool UgualeElemento(TipoIntero intero1, TipoIntero intero2)
  /* Funzione di supporto per il confronto tra due elementi, usata nelle
     funzioni sulle liste che richiedono il confronto tra elementi. */
{
  return (intero1 == intero2);
}

#include "listecon.c"

void InitInsInteri(TipoInsInteri *ins)
  /* Inizializza l'insieme di interi ins all'insieme vuoto inizializzando la
     lista che rappresenta l'insieme. */
{
  InitLista(ins);
}  /* InitInsInteri */


bool TestInsiemeVuoto(TipoInsInteri ins)
  /* Restituisce TRUE se ins rappreseta l'insieme vuoto, FALSE altrimenti. */
{
  return (TestListaVuota(ins));
}  /* TestInsiemeVuoto */


void InserisciIntero(TipoInsInteri *ins, TipoIntero intero)
  /* Inserisce intero nell'insieme di interi ins. */
{
  if (!EsisteInLista(*ins, intero))
    InserisciTestaLista(ins, intero);
}  /* InserisciIntero */


void EliminaIntero(TipoInsInteri *ins, TipoIntero intero)
  /* Elimina intero dall'insieme di interi ins. */
{
  CancellaElementoLista(ins, intero);
}  /* EliminaIntero */


bool VerificaAppartenenza(TipoInsInteri ins, TipoIntero intero)
  /* Restituisce TRUE se intero appartiene ad ins, FALSE altrimenti. */
{
  return (EsisteInLista(ins, intero));
}  /* VerificaAppartenenza */


void Unione(TipoInsInteri ins1, TipoInsInteri ins2, TipoInsInteri *ins_unione)
  /* Restituisce in ins_unione l'unione dei due insiemi ins1 e ins2. */
{
  TipoIntero intero;

  /* la lista che rappresenta il primo insieme viene copiata nella lista
     risultato */
  CopiaLista(ins1, ins_unione);

  /* ogni intero in ins2 non ancora presente in ins1 viene inserito nella lista
     risultato */
  while (!TestListaVuota(ins2)) {
    TestaLista(ins2, &intero);
    if (!EsisteInLista(ins1, intero))
      InserisciTestaLista(ins_unione, intero);
    RestoLista(&ins2);
  }
}  /* Unione */


void Intersezione(TipoInsInteri ins1, TipoInsInteri ins2,
                  TipoInsInteri *ins_int)
  /* Restituisce in ins_int l'intersezione dei due insiemi ins1 e ins2. */
{
  TipoIntero intero;

  /* la lista risultato viene inizializzata alla lista vuota */
  InitLista(ins_int);

  /* ogni intero in ins1 presente anche in ins2 viene inserito nella lista
     risultato */
  while (!TestListaVuota(ins1)) {
    TestaLista(ins1, &intero);
    if (EsisteInLista(ins2, intero))
      InserisciTestaLista(ins_int, intero);
    RestoLista(&ins1);
  }
}  /* Intersezione */


void Complemento(TipoInsInteri ins, TipoInsInteri *ins_compl)
  /* Restituisce in ins_compl il complemento dell'insieme ins. */
{
  printf("ERRORE: la rappresentazione scelta NON permette di implementare\n");
  printf("        l'operazione di complemento di un insieme\n");
  printf("Viene restituito l'insieme vuoto\n");
  InitLista(ins_compl);
}  /* Complemento */