Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

A class to represent group data type and how to use it in code

0.00/5 (No votes)
28 Nov 2004 1  
A class to represent group data type and an example code to demonstrate how to use it in code.

Introduction

Unlike other programming languages like Pascal, a group data type does not exist in C#. That is the reason why I decided to write such a class to represent a group type.

Background

The two main basic ideas of group type are:

  • The order is not important, therefore the groups {1,2,3} and {3,2,1} are equal, and that is why when handling groups you do not ask about the position of member in a group but just whether the member belongs to group or not.
  • Every member of the group is counted only once, and therefore the groups {1,2,3,1,1} and {1,2,3} are equal, and of course, the more conventional display is {1,2,3}.

All the operators about groups are based on these main ideas.

Using the code

The main class is Group. The public methods of Group are:

  • public Group (params string[] group): Constructor.
  • public void update(params string[] group): Update the group with new one.
  • public void clear(): Empty the group.
  • public Group copyto(): Copy the group to another one.
  • public void print(): Print the members of the class to console
  • public override string ToString(): Return the members of the group in string.
  • public int power(): Return the size of the group.
  • public bool is_empty(): Check whether the group is empty.
  • public bool is_exist(s): Check whether s exists in the group.
  • public static Group operator+(Group g, string s): Add member to group.
  • public static Group operator+(string s, Group g): Add group to member.
  • public static Group operator+(Group g1,Group g2): A union operator between two groups.
  • public static Group operator*(Group g1,Group g2): An intersection operator between two groups.
  • public static Group operator-(Group g, string s): Remove member from group.
  • public static Group operator-(Group g1, Group g2): Sub one group from another.
  • public static bool operator<=(Group g1, Group g2): Check whether g1 group is sub group of g2 or equal to g2.
  • public static bool operator>=(Group g1, Group g2): Check whether g2 group is sub group of g1 or equal to g1.
  • public static bool operator==(Group g1, Group g2): Check whether g1 is equal to g2.
  • public static bool operator!=(Group g1, Group g2): Check whether g1 is different from g2.
  • public static bool operator<(Group g1, Group g2): Check whether g1 is sub group of g2 but does not equal to g2.
  • public static bool operator>(Group g1, Group g2): Check whether g2 is sub group of g1 but does not equal to g1.
  • public Group[] P(): Compute all the sub groups of the current group.

The P method to compute the sub groups of a group is using the stack class which is a private class of the Group class and represents a data structure of stack. The public properties and methods of stack are:

  • public int count: Property to return the size of the stack.
  • public stack(int sub_group_size): Constructor.
  • public void push(int val): Push to stack.
  • public int pop(): Pop from stack.
  • public int scan(int i): Return the value in position i.
  • public bool is_empty(): Check whether the stack is empty.

All those methods are simple and trivial, and the code can be found in the source file attached to the document, and that is why I didn�t display the code here except the P method which computes the sub groups of current group.

The P method is complex and took me a long time to write. My first thought at writing this method was to use the recursion way, but then I changed my mind and decided to use stack instead, and I think it was a wise choice.

Here is the code for the P method, and because of its complexity, it is very well documented:

//return all the subgroups of current group

public Group[] P()
{
  //hold the sub groups

  Group[] temp=new Group[(int)((Math.Pow(2,this.power())-1))];
  //hold the positions of the members of each sub group

  stack s=new stack(this.power());
  int sub_group_size=1; //hold the size of each sub group

  int sub_group_counter=0; //hold the index of each sub group

  int member_position=0, //hold the value poped up from satck

  prev_member_position=-1; //hold the previous value poped up from stack


  //loop to control the creation of each group of subgroups

  //according to their size

  while (sub_group_size<=this.power())  
   {
    //initialize the stack for each size n from 1 ro n

    for (int i=1;i<=sub_group_size;i++)
      s.push(i);

    //the process of building sub groups at each size is continue

    //until the stack is empty.

    //when the stack is empty it's mean that we finished creating all the

    //sub groups of this size.

    while (!s.is_empty())
    {
      temp[sub_group_counter]=new Group();

      for (int i=0;i<=s.count-1;i++) //building specific subgroup

        temp[sub_group_counter]+=(string)this.group[s.scan(i)-1];

      sub_group_counter++;

      //after creating each specific sub group we should to drop out

      //from stack all the positions that came to end or in a nother word

      //finished their job in the most internal loop

      do
          {

        prev_member_position=member_position;
        member_position=s.pop();
      }
      while (member_position>=this.power() || 
             prev_member_position==member_position+1);

      //if the stack is not empty we should advance the new internal position

      //and if necessary also to accomplish new positions instead of the

      //positions we droped out

      if (member_position!=-1) 
      {
        s.push(++member_position); //advancing the new internal position


        //accomplishing the new sub group to the correct size instead

        //of the positions we droped out from the stack

        for (int i=s.count;i<sub_group_size;i++)
          s.push(++member_position);
      }
    } //end of loop control about the stack emptiness

    sub_group_size++;
  } //end of loop control about the sub group size

  return temp;
}

Here is an example code that demonstrates using the Group class:

using System;
using Groups;

class main
{

  static void Main(string[] args)
  {
    //this program  is coming to demonstrate the use of the Group class.

    //the input of the program is lists of words.

    //the outputs are:

    // 1. all the words in each list (every word is displayed only once).

    // 2. all the words exist in each list that don't exist in the other lists.

    // 3. all the words of all input lists (every word is displayed only once).

    // 4. all the common words which exist

    //    in all the lists(every word is dispayed once).

    // 5. the most representing relation between every pair of lists.


    int lists_counter;
    Group g=new Group();
    System.Console.WriteLine();

    num_of_lists:
    try
    {
      System.Console.Write("please insert number of lists: ");
      lists_counter=int.Parse(System.Console.ReadLine());
    }
    catch (Exception)
    {
      goto num_of_lists;
    }

    Group[] group=new Group[lists_counter];
    for (int i=0;i<=lists_counter-1;i++)
    {
      System.Console.Write("please insert list" + 
             "of words with space between them: ");
      string s=System.Console.ReadLine();
      string[] list=s.Split(' ');
      group[i]=new Group(list);
    }

    //printing the members of every group

    System.Console.WriteLine();
    System.Console.WriteLine("printing the groups");
    System.Console.WriteLine("===================");
    for (int i=0;i<=group.Length-1;i++)
      group[i].print();
    System.Console.WriteLine();

    //printing the members of every group which not belong to the other groups

    g.clear();
    System.Console.WriteLine("printing members of each group" + 
                         " that don't belong to other groups");
    System.Console.WriteLine("==============================" +
                        "===================================");
    for (int i=0;i<=group.Length-1;i++)
    {
      g=group[i].copyto();
      for (int j=0;j<=group.Length-1;j++)
      if (i!=j) g-=group[j];
      g.print();
    }
    System.Console.WriteLine();

    //printing the union of all lists

    System.Console.WriteLine("printing the union of all lists");
    System.Console.WriteLine("===============================");
    g.clear();
    for (int i=0;i<=group.Length-1;i++)
      g+=group[i];
    g.print();
    System.Console.WriteLine();

    //printing the intersection of all lists

    System.Console.WriteLine("printing the intersection of all lists");
    System.Console.WriteLine("======================================");
    g=group[0];
    for (int i=1;i<=group.Length-1;i++)
      g*=group[i];
    g.print();
    System.Console.WriteLine();

    //printing the relation between each pair of groups

    System.Console.WriteLine("printing the relation between each pair of groups");
    System.Console.WriteLine("==================================================");
    System.Console.WriteLine();
       for (int i=0;i<=group.Length-2;i++)
      for (int j=i+1;j<=group.Length-1;j++)
        if (i!=j)
        {
          if (group[i]<group[j])
            System.Console.WriteLine("{0} < {1}",group[i],group[j]);
          else if (group[i]>group[j])
            System.Console.WriteLine("{0} > {1}",group[i],group[j]);
          else if (group[i]==group[j])
            System.Console.WriteLine("{0} = {1}",group[i],group[j]);
          else
            System.Console.WriteLine("{0} <> {1}",group[i],group[j]);
        }
        System.Console.ReadLine();
  }
}

Points of Interest

The most challenging part of the code is the P method. By writing this code, I also learnt how to work with operators overloading, and in this issue, I felt sorry about the absence of the = operator because I noticed it can't be overloaded.

History

  • 26/11/2004 � first version.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here