2020-06-30 20:38:36 +03:00
|
|
|
/**
|
|
|
|
* @file
|
2020-06-30 20:47:44 +03:00
|
|
|
* @brief Program to generate [Cantor ternary
|
2020-06-30 20:38:36 +03:00
|
|
|
* set](https://en.wikipedia.org/wiki/Cantor_set)
|
|
|
|
*/
|
2019-10-01 08:11:58 +03:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2020-06-30 20:38:36 +03:00
|
|
|
/** structure to define Cantor set */
|
2020-06-30 20:52:43 +03:00
|
|
|
typedef struct _cantor_set
|
2019-10-01 08:11:58 +03:00
|
|
|
{
|
2020-06-30 20:52:43 +03:00
|
|
|
double start; /**< start of interval */
|
|
|
|
double end; /**< end of interval */
|
|
|
|
struct _cantor_set *next; /**< pointer to next set */
|
|
|
|
} CantorSet;
|
2020-06-30 20:38:36 +03:00
|
|
|
|
|
|
|
/** Iterative constructor of all sets in the current level. This function
|
|
|
|
* dynamically allocates memory when creating new sets. These are freed by the
|
|
|
|
* function ::free_memory.
|
|
|
|
* @param head pointer to interval set instance to update
|
|
|
|
*/
|
2020-06-30 20:52:43 +03:00
|
|
|
void propagate(CantorSet *head)
|
2019-10-01 08:11:58 +03:00
|
|
|
{
|
2020-06-30 20:38:36 +03:00
|
|
|
// if input is NULL, ignore the process
|
2020-05-29 23:23:24 +03:00
|
|
|
if (head == NULL)
|
2020-06-30 20:38:36 +03:00
|
|
|
return;
|
2019-10-01 08:11:58 +03:00
|
|
|
|
2020-06-30 20:52:43 +03:00
|
|
|
CantorSet *temp = head; // local pointer to track propagation
|
2019-10-01 08:11:58 +03:00
|
|
|
|
2020-06-30 20:38:36 +03:00
|
|
|
// create new node for the new set
|
2020-06-30 20:52:43 +03:00
|
|
|
CantorSet *newNode = (CantorSet *)malloc(sizeof(CantorSet));
|
2019-11-04 14:26:45 +03:00
|
|
|
|
2020-06-30 20:38:36 +03:00
|
|
|
// get 1/3rd of interval
|
|
|
|
double diff = (((temp->end) - (temp->start)) / 3);
|
2019-11-04 14:26:45 +03:00
|
|
|
|
2020-06-30 20:38:36 +03:00
|
|
|
// update interval ranges
|
|
|
|
newNode->end = temp->end;
|
|
|
|
temp->end = ((temp->start) + diff);
|
|
|
|
newNode->start = (newNode->end) - diff;
|
2019-11-04 14:26:45 +03:00
|
|
|
|
2020-06-30 20:38:36 +03:00
|
|
|
// update pointer to next set in this level
|
|
|
|
newNode->next = temp->next;
|
2019-10-01 08:11:58 +03:00
|
|
|
|
2020-06-30 20:38:36 +03:00
|
|
|
// point to next set
|
|
|
|
temp->next = newNode;
|
|
|
|
|
|
|
|
// create next set
|
|
|
|
propagate(temp->next->next);
|
2019-10-01 08:11:58 +03:00
|
|
|
}
|
|
|
|
|
2020-06-30 20:38:36 +03:00
|
|
|
/** Print sets in the current range to `stdout`
|
|
|
|
* @param head pointer to first set in the current level
|
|
|
|
*/
|
2020-06-30 20:52:43 +03:00
|
|
|
void print(CantorSet *head)
|
2019-10-01 08:11:58 +03:00
|
|
|
{
|
2020-06-30 20:52:43 +03:00
|
|
|
CantorSet *temp = head;
|
2020-06-30 20:38:36 +03:00
|
|
|
while (temp != NULL) // print while a valid set is found
|
2020-05-29 23:23:24 +03:00
|
|
|
{
|
|
|
|
printf("\t");
|
|
|
|
printf("[%lf] -- ", temp->start);
|
|
|
|
printf("[%lf]", temp->end);
|
|
|
|
temp = temp->next;
|
|
|
|
}
|
2019-10-01 08:11:58 +03:00
|
|
|
|
2020-05-29 23:23:24 +03:00
|
|
|
printf("\n");
|
2019-11-04 14:26:45 +03:00
|
|
|
}
|
2019-10-01 08:11:58 +03:00
|
|
|
|
2020-06-30 20:38:36 +03:00
|
|
|
/** Clear memory allocated by ::propagate function.
|
|
|
|
* @param head pointer to first allocated instance.
|
|
|
|
*/
|
2020-06-30 20:52:43 +03:00
|
|
|
void free_memory(CantorSet *head)
|
2019-10-01 08:11:58 +03:00
|
|
|
{
|
2020-06-30 20:38:36 +03:00
|
|
|
if (!head)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (head->next)
|
|
|
|
free_memory(head->next);
|
|
|
|
|
|
|
|
free(head);
|
|
|
|
}
|
2020-05-29 23:23:24 +03:00
|
|
|
|
2020-06-30 20:38:36 +03:00
|
|
|
/** Main function */
|
|
|
|
int main(int argc, char const *argv[])
|
|
|
|
{
|
2020-05-29 23:23:24 +03:00
|
|
|
int start_num, end_num, levels;
|
|
|
|
|
|
|
|
if (argc < 2)
|
|
|
|
{
|
|
|
|
printf("Enter 3 arguments: start_num \t end_num \t levels\n");
|
|
|
|
scanf("%d %d %d", &start_num, &end_num, &levels);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
start_num = atoi(argv[1]);
|
|
|
|
end_num = atoi(argv[2]);
|
|
|
|
levels = atoi(argv[3]);
|
|
|
|
}
|
|
|
|
|
2020-06-30 20:38:36 +03:00
|
|
|
if (start_num < 0 || end_num < 0 || levels < 0)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "All numbers must be positive\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2020-06-30 20:52:43 +03:00
|
|
|
CantorSet head = {.start = start_num, .end = end_num, .next = NULL};
|
2020-05-29 23:23:24 +03:00
|
|
|
|
2020-06-30 20:38:36 +03:00
|
|
|
// loop to propagate each level from top to bottom
|
2020-05-29 23:23:24 +03:00
|
|
|
for (int i = 0; i < levels; i++)
|
|
|
|
{
|
|
|
|
printf("Level %d\t", i);
|
2020-06-30 20:38:36 +03:00
|
|
|
print(&head);
|
|
|
|
propagate(&head);
|
2020-05-29 23:23:24 +03:00
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
printf("Level %d\t", levels);
|
2020-06-30 20:38:36 +03:00
|
|
|
print(&head);
|
|
|
|
|
|
|
|
// delete all memory allocated
|
|
|
|
free_memory(head.next);
|
2020-05-29 23:23:24 +03:00
|
|
|
|
|
|
|
return 0;
|
2019-11-04 14:26:45 +03:00
|
|
|
}
|