Week 11 Lecture Code

// Pantea Aria


// 1) How could I print the data in the first node?
// 2) How could I print the data in the second node?
// 3) How could I modify the next field in the first node to be NULL? What would that do?

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

struct node {
    int data;
    struct node *next;
};

struct node *create_node(int data, struct node *next);

int main(void) {

    // Build a simple list with 3 nodes: 10 -> 20 -> 30 -> NULL
    struct node *third  = create_node(30, NULL);
    struct node *second = create_node(20, third);
    struct node *head   = create_node(10, second);

    printf("List is: 10 -> 20 -> 30 -> NULL\n");

    // TODO 1: Print the data in the first node (head).
    // Hint: the first node is head itself.
    printf("First node data: %d\n", head->data);

    // TODO 2: Print the data in the second node.
    // Hint: the second node is the node after head.
    printf("Second node data: %d\n", head->next->data);

    // TODO 3: Set the next field in the first node to NULL.
    // What would that do?
    // Hint: it "cuts" the list after the first node.
    //
    head->next = NULL;

    // After TODO 3, try printing what the head points to now:
    printf("\nAfter setting head->next to NULL:\n");
    printf("Head data: %d\n", head->data);

    // TODO 4 (optional): Check if there is still a second node reachable from head.
    // If you cut the list correctly, head->next should be NULL.
     if (head->next != NULL) {
         printf("There is still a second node reachable!\n");
     } else {
         printf("No second node reachable from head (list was cut).\n");
     }

    // Cleanup:
    // IMPORTANT: If you cut the list, you *still* need to free the other nodes
    // using the pointers you saved (second, third), otherwise you leak memory.
    free(head);
    free(second);
    free(third);

    return 0;
}


struct node *create_node(int data, struct node *next) {
    struct node *new_node = malloc(sizeof(struct node));
    if (new_node == NULL) {
        printf("Out of memory\n");
        exit(1);
    }
    new_node->data = data;
    new_node->next = next;
    return new_node;
}
#include <stdio.h>
#include <stdlib.h>

#define SIZE 5

// Return the number of elements divisible by 3
int count_multiples(int size, int arr[]) {
    //TODO
    int i = 0;
    int count = 0;
    while (i < size) {
        if (arr[i] % 3 == 0) {
            count++;
        }
        i++;
    }
    return count;
}

int main(void) {

    // Only your function is called during testing
    // Any changes in this main function will not
    // be used in testing

    int array1[SIZE] = {9, -3, 1, 5, 12};

    printf("%d are multiples of 3\n", count_multiples(SIZE, array1));

    return 0;
}
#include <stdio.h>
#include <stdlib.h>

struct steps {
    int number;
    char direction;
};

// Return the total of steps in the given direction
int step_count(char dir, int size, struct steps array[]) {
    //TODO
    int i = 0;
    int count = 0;
    while (i < size) {
        if (array[i].direction == dir) {
            count = count + array[i].number;
        }
        i++;
    }
    return count;
}

// This is a simple main function which could be used
// to test your step_count function.
// It will not be marked.
// Only your step_count function will be marked.

#define TEST_ARRAY_SIZE 5

int main(void) {
    struct steps test_array[TEST_ARRAY_SIZE] = {
        { .number = 3, .direction = 'l'},
        { .number = 5, .direction = 'l'},
        { .number = 2, .direction = 'l'},
        { .number = 13, .direction = 'd'},
        { .number = 30, .direction = 'l'}
    };
    printf("%d\n", step_count('l', TEST_ARRAY_SIZE, test_array));

    return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

struct initials {
    char first_initial;
    char last_initial;
};

// Return the total number of structs that don't
// have both initials set to capital letters
int struct_capitals(int size, struct initials array[]) {
    //TODO
    return 42;
}

// This is a simple main function which could be used
// to test your struct_capitals function.
// It will not be marked.
// Only your struct_capitals function will be marked.

#define TEST_ARRAY_SIZE 5

int main(void) {
    struct initials test_array[TEST_ARRAY_SIZE] = {
        { .first_initial = 'A', .last_initial = 'F'},
        { .first_initial = '!', .last_initial = 'Z'}, 
        { .first_initial = 'Z', .last_initial = 'X'},
        { .first_initial = 'N', .last_initial = 's'}, 
        { .first_initial = 't', .last_initial = 'a'} 
    };
    printf("%d\n", struct_capitals(TEST_ARRAY_SIZE, test_array));

    return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <math.h>

struct node {
    struct node *next;
    char         data;
};

// List 1: 'a' 'b' 'c' (3 nodes)
// List 2: 'd' 'e' 'f' 'g' 'h' (5 nodes)
// difference function should return 2

int len(struct node *head);
int difference(struct node *head1, struct node *head2) {
    //TODO
    // count the number of nodes in each list
    int count1 = len(head1);
    int count2 = len(head2);

    // return abs(count1 - count2);
    if (count1 > count2) {
        return count1 - count2;

    }
    return count2 - count1;


    return 2;
}
int len(struct node *head) {
    struct node *tmp = head;
    int i = 0;
    while(tmp != NULL) {
        tmp = tmp->next;
        i++;
    }
    return i;
}

struct node *strings_to_list(int len, char *strings[]);

// DO NOT CHANGE THIS MAIN FUNCTION
int main(int argc, char *argv[]) {
    // create two linked lists from command line arguments
    int dash_arg = argc - 1;
    while (dash_arg > 0 && strcmp(argv[dash_arg], "-") != 0) {
        dash_arg = dash_arg - 1;
    }
    struct node *head1 = strings_to_list(dash_arg - 1, &argv[1]);
    struct node *head2 = strings_to_list(argc - dash_arg - 1, &argv[dash_arg + 1]);

    int diff = difference(head1, head2);
    printf("%d\n", diff);

    return 0;
}


// DO NOT CHANGE THIS FUNCTION
// create linked list from array of strings
struct node *strings_to_list(int len, char *strings[]) {
    struct node *head = NULL;
    for (int i = len - 1; i >= 0; i = i - 1) {
        struct node *n = malloc(sizeof (struct node));
        assert(n != NULL);
        n->next = head;
        n->data = strings[i][0];
        head = n;
    }
    return head;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

struct node {
    struct node *next;
    int          data;
};

int equal(struct node *head1, struct node *head2);
struct node *strings_to_list(int len, char *strings[]);

// DO NOT CHANGE THIS MAIN FUNCTION
int main(int argc, char *argv[]) {
    // create two linked lists from command line arguments
    int dash_arg = argc - 1;
    while (dash_arg > 0 && strcmp(argv[dash_arg], "-") != 0) {
        dash_arg = dash_arg - 1;
    }
    struct node *head1 = strings_to_list(dash_arg - 1, &argv[1]);
    struct node *head2 = strings_to_list(argc - dash_arg - 1, &argv[dash_arg + 1]);

    int result = equal(head1, head2);
    printf("%d equal values found\n", result);

    return 0;
}

// return the number of values in the first linked list 
// that are equal to the corresponding values in the 
// second linked list. 

// 1->5->10->3->X
// 2->5->10->1->4->X
// Returns 2
// the 5s and 10s are equal
// the 1s are not in the same position
int equal(struct node *head1, struct node *head2) {
    //TODO
    struct node *p1 = head1;
    struct node *p2 = head2;
    int count = 0;
    while(p1 != NULL && p2 != NULL) {
        if (p1->data == p2->data) {
            count++;
        }
        p1 = p1->next;
        p2 = p2->next;
    }

    return count;
}


// DO NOT CHANGE THIS FUNCTION
// create linked list from array of strings
struct node *strings_to_list(int len, char *strings[]) {
    struct node *head = NULL;
    for (int i = len - 1; i >= 0; i = i - 1) {
        struct node *n = malloc(sizeof (struct node));
        assert(n != NULL);
        n->next = head;
        n->data = atoi(strings[i]);
        head = n;
    }
    return head;
}
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

struct node {
    struct node *next;
    int          data;
};

// You want to traverse a linked list and 
// find the largest number in it 
// For example, -3, -4, -5, -6 
// Would return -3
int largest(struct node *head) { 
    if (head == NULL) {
        return -1;
    }
    struct node *curr = head;
    int max = curr->data;
    while(curr != NULL) {
        if (curr->data > max) {
            max = curr->data;
        }
        curr = curr->next;
    }

     return max;
}

struct node *strings_to_list(int len, char *strings[]);

// DO NOT CHANGE THIS MAIN FUNCTION

int main(int argc, char *argv[]) {
    // create linked list from command line arguments
    struct node *head = strings_to_list(argc - 1, &argv[1]);

    printf("%d\n", largest(head));

    return 0;
}


// DO NOT CHANGE THIS FUNCTION

// create linked list from array of strings
struct node *strings_to_list(int len, char *strings[]) {
    struct node *head = NULL;
    for (int i = len - 1; i >= 0; i = i - 1) {
        struct node *n = malloc(sizeof (struct node));
        assert(n != NULL);
        n->next = head;
        n->data = atoi(strings[i]);
        head = n;
    }
    return head;
}
#include <stdio.h>
#include <stdlib.h>

#define SIZE 5

// Return the number of elements divisible by 3
int count_multiples(int size, int arr[]) {
    //TODO
    return 42;
}

int main(void) {

    // Only your function is called during testing
    // Any changes in this main function will not
    // be used in testing

    int array1[SIZE] = {9, -3, 1, 5, 12};

    printf("%d are multiples of 3\n", count_multiples(SIZE, array1));

    return 0;
}
#include <stdio.h>
#include <stdlib.h>

struct steps {
    int number;
    char direction;
};

// Return the total of steps in the given direction
int step_count(char dir, int size, struct steps array[]) {
    //TODO
    return 42;
}

// This is a simple main function which could be used
// to test your step_count function.
// It will not be marked.
// Only your step_count function will be marked.

#define TEST_ARRAY_SIZE 5

int main(void) {
    struct steps test_array[TEST_ARRAY_SIZE] = {
        { .number = 3, .direction = 'l'},
        { .number = 5, .direction = 'l'},
        { .number = 2, .direction = 'l'},
        { .number = 13, .direction = 'd'},
        { .number = 30, .direction = 'l'}
    };
    printf("%d\n", step_count('l', TEST_ARRAY_SIZE, test_array));

    return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

struct initials {
    char first_initial;
    char last_initial;
};

// Return the total number of structs that don't
// have both initials set to capital letters
int struct_capitals(int size, struct initials array[]) {
    //TODO
    return 42;
}

// This is a simple main function which could be used
// to test your struct_capitals function.
// It will not be marked.
// Only your struct_capitals function will be marked.

#define TEST_ARRAY_SIZE 5

int main(void) {
    struct initials test_array[TEST_ARRAY_SIZE] = {
        { .first_initial = 'A', .last_initial = 'F'},
        { .first_initial = '!', .last_initial = 'Z'}, 
        { .first_initial = 'Z', .last_initial = 'X'},
        { .first_initial = 'N', .last_initial = 's'}, 
        { .first_initial = 't', .last_initial = 'a'} 
    };
    printf("%d\n", struct_capitals(TEST_ARRAY_SIZE, test_array));

    return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

struct node {
    struct node *next;
    char         data;
};

// List 1: 'a' 'b' 'c' (3 nodes)
// List 2: 'd' 'e' 'f' 'g' 'h' (5 nodes)
// difference function should return 2


int difference(struct node *head1, struct node *head2) {
    //TODO
    return 42;
}


struct node *strings_to_list(int len, char *strings[]);

// DO NOT CHANGE THIS MAIN FUNCTION
int main(int argc, char *argv[]) {
    // create two linked lists from command line arguments
    int dash_arg = argc - 1;
    while (dash_arg > 0 && strcmp(argv[dash_arg], "-") != 0) {
        dash_arg = dash_arg - 1;
    }
    struct node *head1 = strings_to_list(dash_arg - 1, &argv[1]);
    struct node *head2 = strings_to_list(argc - dash_arg - 1, &argv[dash_arg + 1]);

    int diff = difference(head1, head2);
    printf("%d\n", diff);

    return 0;
}


// DO NOT CHANGE THIS FUNCTION
// create linked list from array of strings
struct node *strings_to_list(int len, char *strings[]) {
    struct node *head = NULL;
    for (int i = len - 1; i >= 0; i = i - 1) {
        struct node *n = malloc(sizeof (struct node));
        assert(n != NULL);
        n->next = head;
        n->data = strings[i][0];
        head = n;
    }
    return head;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

struct node {
    struct node *next;
    int          data;
};

int equal(struct node *head1, struct node *head2);
struct node *strings_to_list(int len, char *strings[]);

// DO NOT CHANGE THIS MAIN FUNCTION
int main(int argc, char *argv[]) {
    // create two linked lists from command line arguments
    int dash_arg = argc - 1;
    while (dash_arg > 0 && strcmp(argv[dash_arg], "-") != 0) {
        dash_arg = dash_arg - 1;
    }
    struct node *head1 = strings_to_list(dash_arg - 1, &argv[1]);
    struct node *head2 = strings_to_list(argc - dash_arg - 1, &argv[dash_arg + 1]);

    int result = num_equal(head1, head2);
    printf("%d equal values found\n", result);

    return 0;
}

// return the number of values in the first linked list 
// that are equal to the corresponding values in the 
// second linked list. 

// 1->5->10->3->X
// 2->5->10->X
// Returns 2
// the 5s and 10s are equal
// the 1s are not in the same position
int equal(struct node *head1, struct node *head2) {
    //TODO
    return 42;
}


// DO NOT CHANGE THIS FUNCTION
// create linked list from array of strings
struct node *strings_to_list(int len, char *strings[]) {
    struct node *head = NULL;
    for (int i = len - 1; i >= 0; i = i - 1) {
        struct node *n = malloc(sizeof (struct node));
        assert(n != NULL);
        n->next = head;
        n->data = atoi(strings[i]);
        head = n;
    }
    return head;
}
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

struct node {
    struct node *next;
    int          data;
};

// You want to traverse a linked list and 
// find the largest number in it 
// For example, 3, 4, 5, 6 
// Would return 6
int largest(struct node *head) { 
     return 42;
}

struct node *strings_to_list(int len, char *strings[]);

// DO NOT CHANGE THIS MAIN FUNCTION

int main(int argc, char *argv[]) {
    // create linked list from command line arguments
    struct node *head = strings_to_list(argc - 1, &argv[1]);

    printf("%d\n", largest(head));

    return 0;
}


// DO NOT CHANGE THIS FUNCTION

// create linked list from array of strings
struct node *strings_to_list(int len, char *strings[]) {
    struct node *head = NULL;
    for (int i = len - 1; i >= 0; i = i - 1) {
        struct node *n = malloc(sizeof (struct node));
        assert(n != NULL);
        n->next = head;
        n->data = atoi(strings[i]);
        head = n;
    }
    return head;
}
// package_delivery_system.c
// Pantea Aria
// (TODO)

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

#include "package_delivery_system.h"

// Function prototypes
// ADD YOUR OWN FUNCTION PROTOTYPES HERE


// Function definitions

// Creates a new empty delivery centre
// (TODO)
struct delivery_centre *create_centre(char name[]) {
    // TODO: implement this function
    printf("create_centre not yet implemented.\n");
    exit(1);
}

// Add a new package to the centre at the head
// Similar to previous lecture code insert_head
// (TODO)
void insert_package_at_head(struct delivery_centre *centre, char sender[],
    char receiver[], double weight, enum priority_type priority,
    enum status_type status) {
    // TODO: implement this function
    printf("insert_package_at_head not yet implemented.\n");
    exit(1);
}

// Given a string, look for package where the receiver is this string
// (TODO)
struct package *search_package(struct delivery_centre *centre,
    char receiver[]) {
    // TODO: implement this function
    printf("search_package not yet implemented.\n");
    exit(1);
}

// Removes all packages from a centre
// clears and deletes associated memory of centre and packages in it
void clear_centre(struct delivery_centre *centre) {
    // TODO: implement this function
    printf("clear_centre not yet implemented.\n");
    exit(1);
}

// Remove package(s) with certain priority
void delete_package_of_priority(struct delivery_centre *centre,
    enum priority_type priority) {
    // TODO: implement this function
    printf("delete_package_of_priority not yet implemented.\n");
    exit(1);
}

// Append packages from centre_2 after centre_1 and returns them in one centre
// Assumption made here assumes no same receiver package in centre_1 and centre_2
struct delivery_centre *merge_centres(char merged_centre_name[],
    struct delivery_centre *centre_1, struct delivery_centre *centre_2) {
    // TODO: implement this function
    printf("merge_centres not yet implemented.\n");
    exit(1);
}

// Split packages in a given centre into 3 centres based on package status
// keeping original ordering
// assumption: pending, in_transit and delivered are centres already malloc-ed
// and initialised
void split_centre(struct delivery_centre *given_centre,
    struct delivery_centre *pending,
    struct delivery_centre *in_transit,
    struct delivery_centre *delivered) {
    // TODO: implement this function
    printf("split_centre not yet implemented.\n");
    exit(1);
}

// returns number of packages in a given centre
// (EXTENSION TODO: Improve this)
int count_packages(struct delivery_centre *centre) {
    int counter = 0;
    struct package *current = centre->packages;
    while (current != NULL) {
        counter++;
        current = current->next;
    }
    return counter;
}


// Your functions here (include function comments):


////////////////////////////////////////////////////////////////////////////////
//                              Provided Code                                //
////////////////////////////////////////////////////////////////////////////////

// Print/display all packages in centre
// Similar to previous lecture code print_list
void print_packages(struct delivery_centre *centre) {
    printf("Centre Name: %s\n", centre->name);
    struct package *current = centre->packages;

    if (current == NULL) {
        printf("There are no packages in this centre.\n");
    }

    while (current != NULL) {
        printf("---\n");
        print_single_package(current);
        current = current->next;
    }
}

// Prints out details of a single package
void print_single_package(struct package *package) {
    if (package == NULL) {
        printf("Package is NULL.\n");
        return;
    }

    printf("Sender: %s\n", package->sender);
    printf("Receiver: %s\n", package->receiver);
    printf("Weight: %lfkg\n", package->weight);

    printf("Priority: ");
    if (package->priority == STANDARD) {
        printf("STANDARD\n");
    } else if (package->priority == EXPRESS) {
        printf("EXPRESS\n");
    } else if (package->priority == URGENT) {
        printf("URGENT\n");
    } else {
        printf("UNKNOWN\n");
    }

    printf("Status: ");
    if (package->status == PENDING) {
        printf("PENDING\n");
    } else if (package->status == IN_TRANSIT) {
        printf("IN_TRANSIT\n");
    } else if (package->status == DELIVERED) {
        printf("DELIVERED\n");
    } else {
        printf("UNKNOWN\n");
    }
}
// Pantea Aria
// main.c
// Program to test logistics hub system functions

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

#include "package_delivery_system.h"

int main(void) {
    // STAGE 1
    printf("*****1. Creating Hub A...*****\n");
    struct delivery_centre *hub_a = create_centre("Hub A");

    printf("\n*****2. Number of parcels in Empty Hub A:*****\n");
    printf("%d\n", count_packages(hub_a));

    printf("\n*****3. Printing Empty Hub A...*****\n");
    print_packages(hub_a);

    printf("\n*****4. Inserting parcels in Empty Hub A *****\n");

    insert_package_at_head(hub_a, "Liam", "Noah", 8.5, URGENT, PENDING);
    insert_package_at_head(hub_a, "Olivia", "Ava", 12.3, EXPRESS, IN_TRANSIT);
    insert_package_at_head(hub_a, "Emma", "Mia", 6.7, STANDARD, DELIVERED);
    insert_package_at_head(hub_a, "Sophia", "Lucas", 9.1, EXPRESS, DELIVERED);
    insert_package_at_head(hub_a, "Isabella", "Ethan", 11.0, STANDARD, IN_TRANSIT);

    printf("\n*****5. Printing Hub A...*****\n");
    print_packages(hub_a);

    printf("\n*****6. Number of parcels in Hub A: *****\n");
    printf("%d\n", count_packages(hub_a));

    printf("\n*****7. Look for parcel with receiver 'Noah'...*****\n");
    struct package *parcel_found = search_package(hub_a, "Noah");

    printf("\n*****8. Printing parcel found in Hub A ...*****\n");
    print_single_package(parcel_found);

    printf("\n*****9. Look for parcel with receiver 'Lucas'...*****\n");
    parcel_found = search_package(hub_a, "Lucas");

    printf("\n*****10. Printing parcel found in Hub A ...*****\n");
    print_single_package(parcel_found);

    printf("\n*****11. Look for parcel with receiver 'Ethan'...*****\n");
    parcel_found = search_package(hub_a, "Ethan");

    printf("\n*****12. Printing parcel found in Hub A ...*****\n");
    print_single_package(parcel_found);

    printf("\n*****13. Look for parcel with receiver 'Zoe'...*****\n");
    parcel_found = search_package(hub_a, "Zoe");

    printf("\n*****14. Printing parcel found in Hub A ...*****\n");
    print_single_package(parcel_found);

    printf("\n*****15. Creating Hub B... and inserting parcels...*****\n");
    struct delivery_centre *hub_b = create_centre("Hub B");

    insert_package_at_head(hub_b, "Mason", "Chloe", 4.2, STANDARD, DELIVERED);
    insert_package_at_head(hub_b, "Harper", "Ella", 7.8, URGENT, PENDING);
    insert_package_at_head(hub_b, "Evelyn", "James", 14.5, EXPRESS, DELIVERED);
    insert_package_at_head(hub_b, "Logan", "Amelia", 5.0, STANDARD, PENDING);
    insert_package_at_head(hub_b, "Benjamin", "Charlotte", 10.6, STANDARD, PENDING);
    insert_package_at_head(hub_b, "Elijah", "Henry", 13.2, EXPRESS, IN_TRANSIT);

    printf("\n*****16. Printing Hub B...*****\n");
    print_packages(hub_b);

    // STAGE 2

    //printf("\n*****17. Deleting STANDARD parcels from Hub B...*****\n");
    //delete_package_of_priority(hub_b, STANDARD);

    //printf("\n*****18. Printing Hub B...*****\n");
    //print_packages(hub_b);

    /*
    printf("\n*****19. Merging Hub A and Hub B...*****\n");
    struct delivery_centre *merged_hub = merge_centres("Merged Hub",
                                                      hub_a,
                                                      hub_b);

    printf("\n*****20. Printing merged hub...*****\n");
    print_packages(merged_hub);

    printf("\n*****21. Split merged hub into pending, in_transit, delivered...*****\n");
    struct delivery_centre *pending = create_centre("pending");
    struct delivery_centre *in_transit = create_centre("in_transit");
    struct delivery_centre *delivered = create_centre("delivered");

    split_centre(merged_hub, pending, in_transit, delivered);

    printf("\n*****22. Printing pending...*****\n");
    print_packages(pending);

    printf("\n*****23. Printing in_transit...*****\n");
    print_packages(in_transit);

    printf("\n*****24. Printing delivered...*****\n");
    print_packages(delivered);
    */

    // STAGE 1 cleanup
    printf("\n*****Clearing stage 1 hubs hub_a and hub_b...*****\n");
    clear_centre(hub_a);
    clear_centre(hub_b);

    return 0;
}
// package_delivery_system.c
// Pantea Aria
// Implementation file for package delivery system functions
// (TODO)

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

#include "package_delivery_system.h"

// Function prototypes
static struct package *create_package(char sender[], char receiver[],
    double weight, enum priority_type priority, enum status_type status);
static void append_package(struct delivery_centre *centre,
    struct package *new_package);


// Function definitions

// Creates a new empty delivery centre
struct delivery_centre *create_centre(char name[]) {
    struct delivery_centre *new_centre = malloc(sizeof(struct delivery_centre));
    if (new_centre == NULL) {
        printf("Memory allocation failed.\n");
        exit(1);
    }

    strcpy(new_centre->name, name);
    new_centre->packages = NULL;

    return new_centre;
}

// Add a new package to the centre at the head
// Similar to previous lecture code insert_head
void insert_package_at_head(struct delivery_centre *centre, char sender[],
    char receiver[], double weight, enum priority_type priority,
    enum status_type status) {

    struct package *new_package = create_package(sender, receiver, weight,
        priority, status);

    new_package->next = centre->packages;
    centre->packages = new_package;
}

// Given a string, look for package where the receiver is this string
struct package *search_package(struct delivery_centre *centre,
    char receiver[]) {

    struct package *current = centre->packages;

    while (current != NULL) {
        if (strcmp(current->receiver, receiver) == 0) {
            return current;
        }
        current = current->next;
    }

    return NULL;
}

// Removes all packages from a centre
// clears and deletes associated memory of centre and packages in it
void clear_centre(struct delivery_centre *centre) {
    struct package *current = centre->packages;

    while (current != NULL) {
        struct package *temp = current;
        current = current->next;
        free(temp);
    }

    free(centre);
}

// Remove package(s) with certain priority
void delete_package_of_priority(struct delivery_centre *centre,
    enum priority_type priority) {

   struct package *prev = NULL;
   struct package *curr = centre->packages;

    // Find node to delete
    while (curr != NULL) {
        if (curr->priority == priority) {
            if (prev == NULL) {
                centre->packages = centre->packages->next;
                free(curr);
                curr = centre->packages;
            } else {
                prev->next = curr->next;
                free(curr);
                curr = prev->next;
            }
            
        } else {
            prev = curr;
            curr = curr->next;
        }
    }    
}



// Append packages from centre_2 after centre_1 and returns them in one centre
// Assumption made here assumes no same receiver package in centre_1 and centre_2
struct delivery_centre *merge_centres(char merged_centre_name[],
    struct delivery_centre *centre_1, struct delivery_centre *centre_2) {

    struct delivery_centre *merged_centre = create_centre(merged_centre_name);

    if (centre_1->packages == NULL) {
        merged_centre->packages = centre_2->packages;
    } else {
        merged_centre->packages = centre_1->packages;

        struct package *current = centre_1->packages;
        while (current->next != NULL) {
            current = current->next;
        }
        current->next = centre_2->packages;
    }

    free(centre_1);
    free(centre_2);

    return merged_centre;
}

// Split packages in a given centre into 3 centres based on package status
// keeping original ordering
// assumption: pending, in_transit and delivered are centres already malloc-ed
// and initialised
void split_centre(struct delivery_centre *given_centre,
    struct delivery_centre *pending,
    struct delivery_centre *in_transit,
    struct delivery_centre *delivered) {

    struct package *current = given_centre->packages;

    pending->packages = NULL;
    in_transit->packages = NULL;
    delivered->packages = NULL;

    while (current != NULL) {
        struct package *next = current->next;
        current->next = NULL;

        if (current->status == PENDING) {
            append_package(pending, current);
        } else if (current->status == IN_TRANSIT) {
            append_package(in_transit, current);
        } else if (current->status == DELIVERED) {
            append_package(delivered, current);
        }

        current = next;
    }

    free(given_centre);
}

// returns number of packages in a given centre
// Improved
int count_packages(struct delivery_centre *centre) {
    if (centre == NULL) {
        return 0;
    }

    int count = 0;
    for (struct package *curr = centre->packages; curr != NULL; curr = curr->next) {
        count++;
    }

    return count;
}

// Your functions here (include function comments):

// Creates and returns a new package node
static struct package *create_package(char sender[], char receiver[],
    double weight, enum priority_type priority, enum status_type status) {

    struct package *new_package = malloc(sizeof(struct package));
    if (new_package == NULL) {
        printf("Memory allocation failed.\n");
        exit(1);
    }

    strcpy(new_package->sender, sender);
    strcpy(new_package->receiver, receiver);
    new_package->weight = weight;
    new_package->priority = priority;
    new_package->status = status;
    new_package->next = NULL;

    return new_package;
}

// Appends a package node to the end of a centre list
static void append_package(struct delivery_centre *centre,
    struct package *new_package) {

    if (centre->packages == NULL) {
        centre->packages = new_package;
        return;
    }

    struct package *current = centre->packages;
    while (current->next != NULL) {
        current = current->next;
    }

    current->next = new_package;
}


////////////////////////////////////////////////////////////////////////////////
//                              Provided Code                                //
////////////////////////////////////////////////////////////////////////////////

// Print/display all packages in centre
// Similar to previous lecture code print_list
void print_packages(struct delivery_centre *centre) {
    printf("Centre Name: %s\n", centre->name);
    struct package *current = centre->packages;

    if (current == NULL) {
        printf("There are no packages in this centre.\n");
    }

    while (current != NULL) {
        printf("---\n");
        print_single_package(current);
        current = current->next;
    }
}

// Prints out details of a single package
void print_single_package(struct package *package) {
    if (package == NULL) {
        printf("Package is NULL.\n");
        return;
    }

    printf("Sender: %s\n", package->sender);
    printf("Receiver: %s\n", package->receiver);
    printf("Weight: %lfkg\n", package->weight);

    printf("Priority: ");
    if (package->priority == STANDARD) {
        printf("STANDARD\n");
    } else if (package->priority == EXPRESS) {
        printf("EXPRESS\n");
    } else if (package->priority == URGENT) {
        printf("URGENT\n");
    } else {
        printf("UNKNOWN\n");
    }

    printf("Status: ");
    if (package->status == PENDING) {
        printf("PENDING\n");
    } else if (package->status == IN_TRANSIT) {
        printf("IN_TRANSIT\n");
    } else if (package->status == DELIVERED) {
        printf("DELIVERED\n");
    } else {
        printf("UNKNOWN\n");
    }
}
// package_delivery_system.h
// Pantea Aria
// Header file for package delivery system functions



#define PACKAGE_DELIVERY_SYSTEM_H

// #defines
#define MAX_LEN 100

// enum definition
enum priority_type {
    STANDARD,
    EXPRESS,
    URGENT
};

enum status_type {
    PENDING,
    IN_TRANSIT,
    DELIVERED
};

// struct definitions
struct delivery_centre {
    char name[MAX_LEN];
    //int num_packages; // to use later :)
    struct package *packages;
};

struct package {
    char sender[MAX_LEN];
    char receiver[MAX_LEN];
    double weight;
    enum priority_type priority;
    enum status_type status;
    struct package *next;
};

// Creates a new empty delivery centre
struct delivery_centre *create_centre(char name[]);

// Add a new package to the centre at the head
void insert_package_at_head(struct delivery_centre *centre,
    char sender[], char receiver[],
    double weight, enum priority_type priority,
    enum status_type status);

// Given a string, look for package where the receiver is this string
struct package *search_package(struct delivery_centre *centre,
    char receiver[]);

// Remove package(s) with certain priority
void delete_package_of_priority(struct delivery_centre *centre,
    enum priority_type priority);

// Append packages from centre_2 after centre_1 and returns them in one centre
struct delivery_centre *merge_centres(char merged_centre_name[],
    struct delivery_centre *centre_1, struct delivery_centre *centre_2);

// Split packages into 3 centres based on status
void split_centre(struct delivery_centre *given_centre,
    struct delivery_centre *pending,
    struct delivery_centre *in_transit,
    struct delivery_centre *delivered);

// Removes all packages from a centre
void clear_centre(struct delivery_centre *centre);

// Returns number of packages in a given centre
int count_packages(struct delivery_centre *centre);

// Prints out details of a single package
void print_single_package(struct package *package);

// Print/display all packages in centre
void print_packages(struct delivery_centre *centre);

// create package
struct package *create_package(char sender[],
    char receiver[], double weight, enum priority_type priority,
    enum status_type status);
// Pantea Aria
// test_main.c
// Program to test logistics hub system functions

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

#include "package_delivery_system.h"

int main(void) {
    printf("=== Creating hubs ===\n");
    struct delivery_centre *hub_a = create_centre("Hub A");
    struct delivery_centre *hub_b = create_centre("Hub B");

    printf("\n=== Testing empty hubs ===\n");
    printf("Hub A parcel count: %d\n", count_packages(hub_a));
    printf("Hub B parcel count: %d\n", count_packages(hub_b));

    printf("\n=== Adding parcels to Hub A ===\n");
    insert_package_at_head(hub_a, "Liam", "Noah", 8.5, URGENT, PENDING);
    insert_package_at_head(hub_a, "Olivia", "Ava", 12.3, EXPRESS, IN_TRANSIT);
    insert_package_at_head(hub_a, "Emma", "Mia", 6.7, STANDARD, DELIVERED);
    insert_package_at_head(hub_a, "Sophia", "Lucas", 9.1, EXPRESS, DELIVERED);
    insert_package_at_head(hub_a, "Isabella", "Ethan", 11.0, STANDARD, IN_TRANSIT);

    print_packages(hub_a);
    printf("Hub A parcel count: %d\n", count_packages(hub_a));

    printf("\n=== Searching in Hub A ===\n");
    struct package *found = search_package(hub_a, "Lucas");
    print_single_package(found);

    found = search_package(hub_a, "Zoe");
    print_single_package(found);

    printf("\n=== Adding parcels to Hub B ===\n");
    insert_package_at_head(hub_b, "Mason", "Chloe", 4.2, STANDARD, DELIVERED);
    insert_package_at_head(hub_b, "Harper", "Ella", 7.8, URGENT, PENDING);
    insert_package_at_head(hub_b, "Evelyn", "James", 14.5, EXPRESS, DELIVERED);
    insert_package_at_head(hub_b, "Logan", "Amelia", 5.0, STANDARD, PENDING);
    insert_package_at_head(hub_b, "Benjamin", "Charlotte", 10.6, STANDARD, PENDING);
    insert_package_at_head(hub_b, "Elijah", "Henry", 13.2, EXPRESS, IN_TRANSIT);

    print_packages(hub_b);
    printf("Hub B parcel count: %d\n", count_packages(hub_b));

    printf("\n=== Deleting STANDARD parcels from Hub B ===\n");
    delete_package_of_priority(hub_b, STANDARD);
    print_packages(hub_b);

    printf("\n=== Rebuilding Hub B for merge test ===\n");
    clear_centre(hub_b);
    hub_b = create_centre("Hub B");

    insert_package_at_head(hub_b, "Mason", "Chloe", 4.2, STANDARD, DELIVERED);
    insert_package_at_head(hub_b, "Harper", "Ella", 7.8, URGENT, PENDING);
    insert_package_at_head(hub_b, "Evelyn", "James", 14.5, EXPRESS, DELIVERED);
    insert_package_at_head(hub_b, "Logan", "Amelia", 5.0, STANDARD, PENDING);

    printf("\n=== Merging Hub A and Hub B ===\n");
    struct delivery_centre *merged_hub = merge_centres("Merged Hub",
        hub_a, hub_b);
    print_packages(merged_hub);
    printf("Merged Hub parcel count: %d\n", count_packages(merged_hub));

    printf("\n=== Splitting merged hub by status ===\n");
    struct delivery_centre *pending = create_centre("pending");
    struct delivery_centre *in_transit = create_centre("in_transit");
    struct delivery_centre *delivered = create_centre("delivered");

    split_centre(merged_hub, pending, in_transit, delivered);

    printf("\nPending parcels:\n");
    print_packages(pending);

    printf("\nIn-transit parcels:\n");
    print_packages(in_transit);

    printf("\nDelivered parcels:\n");
    print_packages(delivered);

    printf("\n=== Cleaning up memory ===\n");
    clear_centre(pending);
    clear_centre(in_transit);
    clear_centre(delivered);

    return 0;
}