2

I got tasked to make a typedef which will represent an array of numbers from 0 to 127.

The numbers cannot repeat - it's a set of integers.

This is not good because it consumes too much data:

typedef struct set {
    char array[128];
} some_set;

as for later this data structure will be used to define different sets (set_a, set_b, set_c, etc.) which will be used for different operations like:

  • print_set which will print the set
  • union_set which combines 2 sets into a 3rd set
  • intersect_set which will intersect 2 sets and save the data in the 3rd

Someone suggested to represent each number with a bit, but I can't really wrap my head around it.

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
Milo
  • 131
  • 10
  • 3
    Please clarify what you mean by _an array of number taken from 0 to 128_. – 001 May 16 '18 at 16:20
  • Are you to reflect numbers of the range between 0 and 127? Or are to represent 128 separate numbers of char range? – Yunnosch May 16 '18 at 16:20
  • It's unclear what you're asking – Tormund Giantsbane May 16 '18 at 16:21
  • @Yunnosch to reflect array of numbers range between 0 and 127, English is not my native tongue, thanks – Milo May 16 '18 at 16:23
  • 1
    Will each of the number be unique? I.e. any present value will not be repeated? I.e. any value is present once or never? – Yunnosch May 16 '18 at 16:24
  • @Yunnosch yes they can't repeat, it's a number's set – Milo May 16 '18 at 16:25
  • What is the `sizeof( long long int )` in your environment? Or can you use uint128_t? – Yunnosch May 16 '18 at 16:25
  • @Yunnosch it's not restricted, but given the fact that the numbers range from 0 to 127, they can't be logically more than 128 numbers total in each set – Milo May 16 '18 at 16:27
  • I would have sworn that I did not post that comment.. Mind reader, are you? ;-) Or just fast in reading comments I deleted or edited.... :-) – Yunnosch May 16 '18 at 16:28
  • @Yunnosch I didn't understand your question about the environment but i use UNIX Ubuntu for this project – Milo May 16 '18 at 16:30
  • Does the typedef have to do all the work? Currently I am thinking of identifying any 128 bit integer and then do some magic with bit manipulation. A typedef wouldn't even occur in that.... I.e. is your task to create an ingenious typedef or more about making an abstract datatype? I.e. a typedef accompanied by some functions for the needed operations. – Yunnosch May 16 '18 at 16:31
  • @Yunnosch No the typedef is only for defining the structure as for later I will use it to maintain 6 different sets with the same attribute and do actions with them, like union, intersects etc.... – Milo May 16 '18 at 16:32
  • Could you provide your frame? E.g. the prototypes of the functions which should be useable with the construct? And please show the output of `printf("%d\n", sizeof(long long int));`. Or state that your solution has to be platform independent. – Yunnosch May 16 '18 at 16:34
  • @Yunnosch I added some examples to the discription – Milo May 16 '18 at 16:41
  • 1
    See [How can I use bit fields to save memory?](https://stackoverflow.com/questions/31096894/how-can-i-use-bit-fields-to-save-memory) – the answers don't use bit-fields. My code is available in my [SOQ](https://github.com/jleffler/soq) (Stack Overflow Questions) repository on GitHub as files `sets.c` and `sets.h` in the [src/so-3109-6894](https://github.com/jleffler/soq/tree/master/src/so-3109-6894) sub-directory. – Jonathan Leffler May 16 '18 at 16:53
  • @JonathanLeffler thank you! – Milo May 16 '18 at 16:55

1 Answers1

2

You cannot do this just with a typedef.

Given that, any type which contains at least 128 bits will be enough to implement this. Examples:

typedef uint32_t intset[4]; // array
typedef struct {uint64_t data[2];} intset; // struct containing an array
typedef uint128_t intset; // built-in 128-bit integer type

In addition to the typedef, you have to define functions that work with the data structure. For example:

void intset_init(intset *set);
void intset_add(intset *set, int n);
void intset_remove(intset *set, int n);
bool intset_check(intset *set, int n);
bool intset_is_empty(intset *set);

Each such function should use bit-fiddling to do its work. For example:

typedef uint32_t intset[4];

void intset_add(intset *set, int n)
{
    (*set)[n / 32] |= (uint32_t)1 << (n % 32);
}

It may be more efficient to pass and return the data structure by value, not by pointer. If you want this, you cannot use an array typedef - use any other one which is convenient.

typedef struct {uint64_t data[2];} intset;

intset intset_add(intset set, int n)
{
    set.data[n / 64] |= (uint64_t)1 << (n % 64);
    return set;
}
anatolyg
  • 26,506
  • 9
  • 60
  • 134
  • Thanks for acting upon the clarifications I got from OP, for using the concept I described and for giving credit. It will of course totally surprise you that I was also making an answer. – Yunnosch May 16 '18 at 16:50