| home | contents | previous | next page | send comment | send link | add bookmark |

sets.cpp

/*----------------------------------------------------------------------------*
**  sets.cpp : class definitions for set operations using bit representations. 
**
**  Stephen R. Schmitt
*/

#include "stdafx.h"                                 // MS Visual C++ file
#include "sets.h"
#include <ctype.h>
#include <stdio.h>
#include <string.h>

/*----------------------------------------------------------------------------*
**  "sets()" default constructor, initializes elements of the set to zero.  
**
**  returns: nothing
*/
sets::sets()
{
    clear();                                        // initialize to empty
}

/*----------------------------------------------------------------------------*
**  "sets()" copy constructor, initializes elements of the set to be
**  equal to the values of the argument set.  
**
**  returns: nothing
*/
sets::sets( const sets &rhs )                       // the set to copy
{
    for( int i = 0; i < MAX_WORDS; i++ )            // copy into new set
        set[i] = rhs.set[i];
}

/*----------------------------------------------------------------------------*
**  "item()" checks for existence of an item in the set.  
**
**  returns: 1 if item present, 0 if not, -1 on range error
*/
int sets::item( int bit )                           // index of the item
{
    if( bit <= 0 || bit > MAX_WORDS * WORD_SIZE )   // in range?
        return -1;

    int i = bit / WORD_SIZE;
    bit -= i * WORD_SIZE;
    
    return set[i] & 1 << ( bit - 1 );               // binary AND
}

/*----------------------------------------------------------------------------*
**  "insert()" puts an item into the set. Range errors are ignored.  
**
**  returns: nothing
*/
void sets::insert( int bit )                        // index of the item
{
    if( bit <= 0 || bit > MAX_WORDS * WORD_SIZE )   // in range?
        return;

    int i = bit / WORD_SIZE;
    bit -= i * WORD_SIZE;

    set[i] |= 1 << ( bit - 1 );                     // binary OR
}

/*----------------------------------------------------------------------------*
**  "remove()" takes an item out of the set. Range errors are ignored.  
**
**  returns: nothing
*/
void sets::remove( int bit )                        // index of the item
{
    if( bit <= 0 || bit > MAX_WORDS * WORD_SIZE )   // in range?
        return;

    int i = bit / WORD_SIZE;
    bit -= i * WORD_SIZE;

    set[i] &= ~( 1 << ( bit - 1 ) );                // binary AND
}

/*----------------------------------------------------------------------------*
**  "clear()" removes all items from the set.  
**
**  returns: nothing
*/
void sets::clear()
{
    for( int i = 0; i < MAX_WORDS; i++ )            // all words in set
        set[i] = 0;
}

/*----------------------------------------------------------------------------*
**  "define()" initializes elements of the set using an enumerated input 
**  string (numbers separated by spaces).  
**
**  NOTE: Values of set elements that are too large are ignored.
**
**  returns: nothing
*/
void sets::define( char *input )                    // string of numbers
{
    int length = strlen( input );                   // of input buffer
    int pos = 0;                                    // current character
    clear();                                        // initialize to empty

    while( pos < length )                           // more input
    {
        int bit = 0;                                // init bit to set

        while( isdigit( input[pos] ) )
        {
            bit *= 10;                              // compute bit to set
            bit += input[pos] - '0';

            pos++;                                  // advance
        }

        if( bit )                                   // zero means no bit
            insert( bit );

        pos++;                                      // advance
    }
}

/*----------------------------------------------------------------------------*
**  "binary()" prints binary representation of set to stdout.
**
**  returns:  nothing
*/
void sets::binary()
{
    for( int j = 0; j < MAX_WORDS; j++ )            // do all words
    {
        unsigned long mask = 1;                     // start at low bit

        for( int i = 0; i < WORD_SIZE; i++ )        // every bit in word
        {
            if( i % 4 == 0 )                        // add space
                putchar( ' ' );
            
            set[j] & mask ? putchar( '1' ) : putchar( '0' );
	    
            mask <<= 1;                             // next higher bit 
        }
    }
}

/*----------------------------------------------------------------------------*
**  "cardinality()" counts items in the set.
**
**  returns:  total items
*/
int sets::cardinality()
{
    int count = 0;                                  // init counter

    for( int j = 0; j < MAX_WORDS; j++ )            // do all words
    {
        unsigned long mask = 1;                     // start at low bit
        
        for( int i = 0; i < WORD_SIZE; i++ )        // every bit in word
        {
            count += set[j] & mask ? 1 : 0;
            mask <<= 1;                             // next higher bit
        }
    }

    return count;
}

/*----------------------------------------------------------------------------*
**  "print()" displays set to stdout as a list of integers.
**
**  returns:  nothing
*/
void sets::print()
{
    printf( "{ " );

    for( int j = 0; j < MAX_WORDS; j++ )            // do all words
    {
        unsigned long mask = 1;                     // start at low bit
        
        for( int i = 1; i <= WORD_SIZE; i++ )
        {
            if( set[j] & mask )                     // check bit
                printf( "%d ", ( WORD_SIZE * j + i ) );

            mask <<= 1;                             // next higher bit
        }
    }
    
    printf( "}" );
}

/*----------------------------------------------------------------------------*
**  "operator = " assigns the right hand side to this set.
**
**  returns: nothing
*/
const sets &sets::operator = ( const sets &rhs )
{
    if( &rhs != this )                              // avoid self assignment
    {
        for( int i = 0; i < MAX_WORDS; i++ )        // copy into this set
            set[i] = rhs.set[i];
    }

    return *this;                                   // enable x = y = z;
}

/*----------------------------------------------------------------------------*
**  "operator ~ " performs set complement operation (not).
**
**  returns: pointer to set
*/
sets sets::operator ~ () const
{
    sets rv;
	
    for( int i = 0; i < MAX_WORDS; i++ )
        rv.set[i] = ~set[i];                        // bitwise complement

    return rv;
}
		      
/*----------------------------------------------------------------------------*
**  "operator + " performs set union operation (or).
**
**  returns: pointer to set
*/
sets sets::operator + ( const sets &rhs )
{
    sets rv;
	
    for( int i = 0; i < MAX_WORDS; i++ )
        rv.set[i] = set[i] | rhs.set[i];            // bitwise OR

    return rv;
}

/*----------------------------------------------------------------------------*
**  "operator * " performs set intersection operation (and).
**
**  returns: pointer to set
*/
sets sets::operator * ( const sets &rhs )
{
    sets rv;
    
    for( int i = 0; i < MAX_WORDS; i++ )
        rv.set[i] = set[i] & rhs.set[i];            // bitwise AND
                       
    return rv;
}

/*----------------------------------------------------------------------------*
**  "operator - " performs set difference operation.
**
**  returns: pointer to set
*/
sets sets::operator - ( const sets &rhs )
{
    sets rv;
    
    for( int i = 0; i < MAX_WORDS; i++ )
        rv.set[i] = set[i] & ( ~rhs.set[i] );       // bitwise a AND ~b
                       
    return rv;
}

/*----------------------------------------------------------------------------*
**  "operator ^ " performs set symmetric difference operation (xor).
**
**  returns: pointer to set
*/
sets sets::operator ^ ( const sets &rhs )
{
    sets rv;
    
    for( int i = 0; i < MAX_WORDS; i++ )
        rv.set[i] = set[i] ^ rhs.set[i];            // bitwise XOR
                       
    return rv;
}

#define TEST_CLASS                                  // define to test class
#ifdef TEST_CLASS

/*----------------------------------------------------------------------------*
**  "result()" prints test result to stdout.
**
**  returns: nothing
*/
void result( sets *r, char *msg )
{
    printf( msg ); 
    r->print(); 
    printf( "\n" );
}

/*----------------------------------------------------------------------------*
**  "main()" program entry point, this test several set operation cases.
**
**  returns: 0 if no errors occur
*/
int main( int argc, char* argv[] )
{
    sets A, B, C;

    printf( "Set operations program.\n");

    A.define( "1 2 3 4 5 6" ); 
    result( &A, "A = " );
    
    printf( "A - in binary low bit to high bit-\n" );
    A.binary();
    printf( " cardinality of A = %d\n", A.cardinality() );

    B.define( "4 5 6 7 8 9" );
    result( &B, "B = " );
    
    C.define( "7 8 9 10 11 12" );
    result( &C, "C = " ); 
    
    sets D = A + B + C;                             // uses copy constructor
    result( &D, "A + B + C = "  );

    D = A + B;                                      // A or B             
    result( &D, "A + B = " );

    D = A * B;                                      // A and B     
    result( &D, "A * B = " );

    D = A + C;                                      // A or C      
    result( &D, "A + C = " );

    D = A * C;                                      // A and C     
    result( &D, "A * C = " );

    D = A - B;                                      // set difference
    result( &D, "A - B = " );

    D = A * ~B;                                     // should equal A - B     
    result( &D, "A * ~B = " );

    D = A ^ B;                                      // A xor B (symmetric difference)
    result( &D, "A ^ B = " );

    D = ( A + B ) - ( A * B );                      // should equal A xor B 
    result( &D, "( A + B ) - ( A * B ) = " );

    D = ( A - B ) + ( B - A );                      // should equal A xor B  
    result( &D, "( A - B ) + ( B - A ) = " );

    D = ~(( ~A ) * ( ~B ));                         // should equal A or B (DeMorgan Law)
    result( &D, "~(( ~A ) * ( ~B )) = " );

    D = ~(( ~A ) + ( ~B ));                         // should equal A and B (DeMorgan Law)
    result( &D, "~(( ~A ) + ( ~B )) = " );

    D.item( 2 ) ? D.remove( 2 ) : D.insert( 2 );
    result( &D, "toggle item 2; D = " );

    D.item( 4 ) ? D.remove( 4 ) : D.insert( 4 );
    result( &D, "toggle item 4; D = " );

    return 0;
}

#undef TEST_CLASS
#endif

| home | contents | previous | next page | send comment | send link | add bookmark |

Copyright © 2004, Stephen R. Schmitt