Programming Fundamentals

Q1

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

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


// Check if something is prime
int is_prime(int value) {
    if (value <= 1) {
        return 0;
    }
    for (int i = 2; i < value; i++) {
        if (value % i == 0) {
            return 0;
        }
    }
    return 1;
}

// first_prime should return the first prime number in the given linked list

int first_prime(struct node *head) {
    struct node *current = head;
    //int prime = -1;

    while (current != NULL) {
        if (is_prime(current->data)) {
            return current->data;
        }
        current = current->next;
    }    
        
    return -1;
}


////////////////////////////////////////////////////////////////////////
//               DO NOT CHANGE THE CODE BELOW                         //
////////////////////////////////////////////////////////////////////////

int first_prime(struct node *head);
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]);

    // If you're getting an error here,
    // you have returned an uninitialized value
    printf("%d\n", first_prime(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;
}

Q2

#include <stdio.h>

#define MAX_COLS 100

char min_lowercase(int size, char array[MAX_COLS]);

// This is a simple main function which could be used
// to test your min_lowercase function.
// It will not be marked.
// Only your min_lowercase function will be marked.
int main(int argc, char *argv[]) {
    char test_array[MAX_COLS] = {'a', 'B', 'c', 'D', '!'};

    int result = min_lowercase(5, test_array);
    printf("%c\n", result);

    return 0;
}

// Returns the lowercase character with the lowest ASCII value from the array.
char min_lowercase(int size, char array[MAX_COLS]) {
    char min_letter = 'z';

    for (int i = 0; i < size; i++) {
        if (array[i] >= 'a' && array[i] <= 'z' && array[i] < min_letter) {
            min_letter = array[i];
        }
    }

    return min_letter;
}

Q3

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

// DO NOT MODIFY THIS STRUCT
struct node {
    struct node *next;
    int          data;
};

////////////////////////////////////////////////////////////////////////////////
// DO NOT CHANGE THESE FUNCTION PROTOTYPES
////////////////////////////////////////////////////////////////////////////////
struct node *delete_nth_even(struct node *head, int n);
struct node *strings_to_list(int len, char *strings[]);
void print_list(struct node *head);
void free_list(struct node *head);
int list_length(struct node *head);

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

    struct node *new_head = delete_nth_even(head, n);
    print_list(new_head);
    free_list(new_head);

    return 0;
}

//##############################################################################
// TODO: IMPLEMENT THIS FUNCTION
//##############################################################################

// This function should delete the even node at position n from the start of the list.
struct node *delete_nth_even(struct node *head, int n) {
    if (head == NULL) {
        return head;
    }

    struct node *prev = NULL;
    struct node *curr = head;
    int even_total = 0;
    int even_count = 0;

    while (curr != NULL) {

        if (curr->data % 2 == 0) {
            even_total++;
        }
        curr = curr->next;
    }

    curr = head;

    // iterate till you either find the target node or the end of the list
    while (curr != NULL) {
        
        if (curr->data % 2 == 0) {
            even_count++;

            if ((n > list_length(head) || n > even_total)&& even_count == 1) {
            // delete first even
                if (prev == NULL) {
                    head = curr->next;
                } else {
                    prev->next = curr->next;
                }
                free(curr);
                return head;
            }

            if (even_count == n) {
                if (prev == NULL) {
                    head = curr->next;
                } else {
                    prev->next = curr->next;
                }
                free(curr);
                return head;
            }
        }
        prev = curr;
        curr = curr->next;
        
    }

    return head;
}

int list_length(struct node *head) {
    int length = 0;
    for (struct node *curr = head; curr != NULL; curr = curr->next) {
        length++;
    }
    return length;
}

////////////////////////////////////////////////////////////////////////////////
// DO NOT CHANGE BELOW HERE INCLUDING THIS FUNCTION OR THE FUNCTIONS BELOW
////////////////////////////////////////////////////////////////////////////////

// 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;
}

// print linked list
void print_list(struct node *head) {
    printf("[");

    for (struct node *n = head; n != NULL; n = n->next) {
        // If you're getting an error here,
        // you have returned an invalid list
        printf("%d", n->data);
        if (n->next != NULL) {
            printf(", ");
        }
    }
    printf("]\n");
}

// free linked list
void free_list(struct node *head) {
    struct node *curr = head;
    while (curr != NULL) {
        struct node *temp = curr;
        curr = curr->next;
        free(temp);
    }
}

Q4

// Written by Jake Renzella
#include <stdio.h>

#define MAX_ROWS 100

int vowels_exactly_balanced(int size, char *array[MAX_ROWS]);

// This is a simple main function which could be used
// to test your vowels_exactly_balanced function.
// It will not be marked.
// Only your count_neutral_rows function will be marked.
int main(int argc, char *argv[]) {
    char *test_arrray[MAX_ROWS] = {
        "abUUcd",
        "abcdUU",
        "Abaa",
        "asdaa",
    };

    char *test_arrray_2[MAX_ROWS] = {
        "abcdaa",
        "abcda",
        "babau",
    };

    char *test_arr_3[MAX_ROWS] = {
        "fgh",
        "j",
        "zxcvbnm",
    };

    int result = vowels_exactly_balanced(4, test_arrray);
    printf("The vowels_exactly_balanced function returned: %d\n", result);

    result = vowels_exactly_balanced(3, test_arrray_2);
    printf("The vowels_exactly_balanced function returned: %d\n", result);

    result = vowels_exactly_balanced(3, test_arr_3);
    printf("%d\n", result);
    return 0;
}

int vowels_exactly_balanced(int size, char *array[MAX_ROWS]) {
    if (size <= 1) {
        // 0 or 1 row is always balanced
        return 1;
    } 

    if (size > MAX_ROWS) {
        // Error: size exceeds MAX_ROWS
        return 0;
    } 

    // Will store the first non-zero vowel count
    int target_vowels = -1; 

    for (int row = 0; row < size; row++) {
        int vowels = 0;

        for (int col = 0; array[row][col] != '\0'; col++) {
            char c = array[row][col];
            if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' ||
                c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U') {
                vowels++;
            }
        }

        if (target_vowels == -1) {
            if (vowels > 0) {
                target_vowels = vowels;
            }
        } else if (vowels != target_vowels) {
            // Imbalance found, early return
            return 0; 
        }
    }

    return 1; // No imbalances found
}

Q5

// This program scans in an integer representing a month of the year.
// It prints out a message to say what season the month is in Australia.
//
// Unfortunately, this code contains a number of errors. Please help fix it!

#include <stdio.h>

int main(void) {
    int month; // BUG #0 - forgot to declare the variable

    printf("Enter the month number (1-12): ");
    scanf("%d", &month); // Bug #1 - forgot & before month

    if (month < 1 || month > 12) { // BUG #1.5 >= 12 instead of > 12
        printf("Invalid month entered.\n");
    } else if (month >= 3 && month <= 5) { // Bug #2 - use || instead of &&
        printf("It's autumn in Australia.\n");
    } else if (month >= 6 && month <= 8) {
        printf("It's winter in Australia.\n");
    } else if (month >= 9 && month <= 11) {
        printf("It's spring in Australia.\n");
    } else { // Bug #3 - forgot to handle December, January, and February
        printf("It's summer in Australia.\n");
    }

    return 0;
}

Q6

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

////////////////////////////////////////////////////////////////////////////////
// DO NOT MODIFY THIS STRUCT
////////////////////////////////////////////////////////////////////////////////
struct node {
    struct node *next;
    int          data;
};

// only_evens should create a new linked list `only_evens` that contains
// only the even-valued nodes from the original list
// Unfortunately this function contains a number of errors.
// It's your job to fix them, good luck!
struct node *extract_evens(struct node *head) {
    struct node *only_evens = NULL;
    struct node *current = head;
    
    // BUG: current is missing the last node in the list
    while (current != NULL) {
        // BUG: next is not a pointer
        struct node *next = current->next;
        current->next = NULL;
        // BUG: Not accessing data field
        if (current->data % 2 == 0) {
            // BUG: no null check for an empty list
            if (only_evens == NULL) {
                only_evens = current;
            } else {
                // BUG: current is not a pointer
                struct node *current_evens = only_evens;
                // BUG: traversing past the last node
                while (current_evens->next != NULL) {
                    current_evens = current_evens->next;
                }
                current_evens->next = current;
            }
        }
        current = next;
    }
    return only_evens;
}

////////////////////////////////////////////////////////////////////////////////
// DO NOT MODIFY THE CODE BELOW THIS LINE, THIS CODE ALLOWS YOU TO
// TAKE IN A LIST OF NUMBERS TO TEST WHETHER YOUR FUNCTION IS WORKING
////////////////////////////////////////////////////////////////////////////////
struct node *strings_to_list(int len, char *strings[]);
void print_list(struct node *head);

////////////////////////////////////////////////////////////////////////////////
// DO NOT MODIFY THIS FUNCTION
////////////////////////////////////////////////////////////////////////////////
int main(int argc, char *argv[]) {
    struct node *head = strings_to_list(argc - 1, &argv[1]);

    struct node *only_evens = extract_evens(head);

    if (only_evens == NULL) {
        printf("No even nodes\n");
    } else {
        print_list(only_evens);
    }

    return 0;
}
////////////////////////////////////////////////////////////////////////////////
// DO NOT MODIFY THIS FUNCTION
////////////////////////////////////////////////////////////////////////////////
struct node *strings_to_list(int len, char *strings[]) {
    struct node *head = NULL;
    for (int i = len - 1; i >= 0; i--) {
        struct node *n = malloc(sizeof(struct node));
        assert(n != NULL);
        n->data = atoi(strings[i]);
        n->next = head;
        head = n;
    }
    return head;
}

////////////////////////////////////////////////////////////////////////////////
// DO NOT MODIFY THIS FUNCTION
////////////////////////////////////////////////////////////////////////////////
void print_list(struct node *head) {
    struct node *current = head;
    while (current != NULL) {
        printf("%d", current->data);
        if (current->next != NULL) {
            printf(" ");
        }
        current = current->next;
    }
    printf("\n");
}

Q7

// debug points functions gcd
// written by Sofia De Bellis, z5418801
// 30 Mar 2025

#include <stdio.h>

void find_sum_of_square(int n, int *result);

int main(void) {
	int n;
    int result;

	printf("Enter n: ");
    // BUG: * used for scanf
	scanf("%d", &n);

    // BUG: missing & in function call
    find_sum_of_square(n, &result);

    printf("The sum of squares from 1 to %d is: %d\n", n, result);

	return 0;
}

// Function definition
// This function computes the sum of squares from 1 to n
// and stores the result in the variable pointed to by result
void find_sum_of_square(int n, int *result) {
    // BUG: sum not initialized
    int sum = 0;

    // BUG: i should start from 1 not 0
    // BUG: should be <= n
    for (int i = 1; i <= n; i++) {
        // BUG: ^ should be *
        sum += i * i;
    }

    // BUG: result should be dereferenced
    *result = sum;
    return;
}

Q8

// This program should create and scan in the elements of a 3x3 2d array, 
// then multiply all the odd numbers in the 2d array by 100.
//
// Unfortunately, this code contains a number of errors. Please help fix it!

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

#define SIZE 3

int main(void) {

    printf("Enter your numbers:\n");

    int array[SIZE][SIZE]; // char instead of int
    for (int row = 0; row < SIZE; row++) {
        for (int col = 0; col < SIZE; col++) { // loop decrements
            scanf("%d", &array[row][col]); // %c instead of $d
        }
    }

    for (int row = 0; row < SIZE; row++) {
        for (int col = 0; col < SIZE; col++) {
            if (array[row][col] % 2 != 0) { // swapped with the line above and [col] is replaced by another [row], and / instead of %
                array[row][col] = array[row][col] * 100; 
            }
        }
    }

    // ==================== DO NOT NEED TO EDIT BELOW HERE =====================
    // There are no bugs in here, this is simply to assist in printing out
    // the contents of the 2D array
    printf("Converted:\n");
    for (int row = 0; row < SIZE; row++) {
        for (int col = 0; col < SIZE; col++) {
            printf("%d ", array[row][col]);
        }
        printf("\n");
    }

    return 0;
}

Q9

#include <ctype.h>
#include <stdio.h>

#define MAX_SIZE 100

void increment_after(char string[MAX_SIZE]);

int main(void) {
    char string[MAX_SIZE];
    
    printf("Original String: ");
    fgets(string, MAX_SIZE, stdin);

    increment_after(string);
    printf("New String: %s", string);
    return 0;
}

void increment_after(char string[MAX_SIZE]) {
    int offarray[MAX_SIZE];
    for (int i = 0; string[i] ; i++) {
        if (!isalpha(string[i])) continue;

        int bigger = 0;
        for (int j = i + 1; string[j]; j++) {
            if (!isalpha(string[j])) continue;
            if (tolower(string[i]) < tolower(string[j])) {
                bigger++; 
            }
        }
        char start = (isupper(string[i]) ? 'A' : 'a');
        int offset = ((bigger + string[i] - start));
        if (offset > 25) {
            offset = 25;
        }

        offarray[i] = offset;
    }

    for (int i = 0; string[i]; i++) {
        if (!isalpha(string[i])) continue;
        string[i] = offarray[i] + (isupper(string[i]) ? 'A' : 'a');
    }
}

Q10

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

int num_trains_to_target(int **routes, int routes_size, int *routes_col_size, int source, int target);

int main(int argc, char *argv[]) {

    int arg_index = 1;
    int n = atoi(argv[arg_index++]);

    int **routes = malloc(n * sizeof(int *));
    int *routes_col_size = malloc(n * sizeof(int));

    for (int i = 0; i < n; i++) {
        routes_col_size[i] = atoi(argv[arg_index++]);
        routes[i] = malloc(routes_col_size[i] * sizeof(int));
        for (int j = 0; j < routes_col_size[i]; j++) {
            routes[i][j] = atoi(argv[arg_index++]);
        }
    }

    int source = atoi(argv[arg_index++]);
    int target = atoi(argv[arg_index++]);

    int result = num_trains_to_target(routes, n, routes_col_size, source, target);

    
    if (result == -1) {
        printf("Stop %d from stop %d is not reachable.\n", target, source);
    } else {
        printf("The minimum number of trains to travel from stop %d to stop %d is %d.\n", source, target, result);
    }

    return 0;
}

int num_trains_to_target(int** routes, int routes_size, int* routes_col_size, int source, int target) {
    if (source == target) {
        return 0;
    }
    
    int max_stop = -1;
    for (int i = 0; i < routes_size; i++) {
        for (int j = 0; j < routes_col_size[i]; j++) {
            if (routes[i][j] > max_stop) {
                max_stop = routes[i][j];
            }
        }
    }
    
    if (max_stop < target) {
        return -1;
    }
    
    int n = routes_size;
    int *min_trains_to_reach = malloc((max_stop + 1) * sizeof(int));
    for (int i = 0; i <= max_stop; i++) {
        min_trains_to_reach[i] = n + 1;
    }
    
    min_trains_to_reach[source] = 0;
    bool flag = true;
    
    while (flag) {
        flag = false;
        for (int i = 0; i < routes_size; i++) {
            int min = n + 1;
            for (int j = 0; j < routes_col_size[i]; j++) {
                if (min_trains_to_reach[routes[i][j]] < min) {
                    min = min_trains_to_reach[routes[i][j]];
                }
            }
            min++;
            for (int j = 0; j < routes_col_size[i]; j++) {
                if (min_trains_to_reach[routes[i][j]] > min) {
                    min_trains_to_reach[routes[i][j]] = min;
                    flag = true;
                }
            }
        }
    }
    
    int result = (min_trains_to_reach[target] < n + 1) ? min_trains_to_reach[target] : -1;
    free(min_trains_to_reach);
    return result;
}

Q11

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

struct node {
    int val;
    int height;
    struct node *left;
    struct node *right;
};

int **get_skyline(int **buildings, int buildings_size, int* buildings_col_size, int *return_size, int **return_col_size);
struct node *create_node(int val, int height, struct node* node);
void insert_node(struct node *node, struct node *left, struct node *right);

int main(int argc, char *argv[]) {
    // num buildings is argc - program name / 3
    int buildings_size = (argc - 1) / 3;
    
    int **buildings = malloc(buildings_size * sizeof(int *));
    int *buildings_col_size = malloc(buildings_size * sizeof(int));

    // Parse CLAs
    for (int i = 0; i < buildings_size; i++) {
        buildings[i] = malloc(3 * sizeof(int));
        buildings[i][0] = atoi(argv[i * 3 + 1]);
        buildings[i][1] = atoi(argv[i * 3 + 2]);
        buildings[i][2] = atoi(argv[i * 3 + 3]);
        buildings_col_size[i] = 3;
    }

    int return_size = 0;
    int *return_col_size = NULL;

    int **result = get_skyline(buildings, buildings_size, buildings_col_size, &return_size, &return_col_size);

    printf("Skyline: [");
    for (int i = 0; i < return_size; i++) {
        if (i == return_size - 1) {
            printf("[%d, %d]]\n", result[i][0], result[i][1]);
        } else {
            printf("[%d, %d], ", result[i][0], result[i][1]);
        }
    }

    return 0;
}


int **get_skyline(int **buildings, int buildings_size, int *buildings_col_size, int *return_size, int **return_col_size) {

    // make a new node with x coord as val and height = height if start of the building and 0 or height of next one    
    // insert a node between two others
    int left, right, height; 
    int n = buildings_size;

    if (n < 1){
        printf("Less then 1 building\n");
        return NULL;
    }

    //get memory for all nodes x2 buildings
    struct node *base = malloc((n * 2) * sizeof(struct node)); 

    struct node *p, *new_left, *new_right;
    p = base;

    struct node* end_left = create_node(buildings[0][0], buildings[0][2], p++);
    struct node* end_right = create_node(buildings[0][1], 0, p++);
    end_left->right = end_right;
    end_right->left = end_left;
    
    for(int i = 1; i < n; i++){

        left = buildings[i][0];
        right = buildings[i][1];
        height = buildings[i][2];

        new_left = NULL;
        new_right = NULL;

        // searching for place
        while (end_right->right && end_right->val <= left) end_right = end_right->right; 
        
        // left is in open space
        if (!end_right->right && left >= end_right->val){   
            
            new_right = create_node(right, 0, p++);

            if (end_right->val == left) {
                if (height == end_right->left->height) {
                    new_left = end_right->left;
                }
                else {
                    end_right->height = height;
                    new_left = end_right;
                }
            }
            else {
                new_left = create_node(left, height, p++);
                end_right->right = new_left;
                new_left->left = end_right;
            }
            new_left->right = new_right;
            new_right->left = new_left;
            
            end_left = new_left;
            end_right = new_right;
            continue;
        }
        
        end_left = end_right->left;

        // left == old left 
        if (left == end_left->val){ 
            // new height is higher or same
            if (end_left->height <= height){  

                //there is a point to the left from end_left and it's height is equal
                if (end_left->left && end_left->left->height == height){  
                    new_left = end_left->left;     
                }
                // there is no left to the end_left or it's hight != height
                else { 
                    new_left = end_left;
                    new_left->height = height;
                }
            }

        }

        // if hights is equal and left is between end_l and end_r
        else if (height == end_left->height){ 
            new_left = end_left;
        }

        // higher
        else if (height > end_left->height){ 
            new_left = create_node(left, height, p++);
            new_left->left = end_left;
            end_left->right = new_left;
        }

         //lower -> need to find where to start from
        if (!new_left){
            //scanning down the new "roof"
            while (end_right->right && right > end_right->val && height < end_right->height) {
                end_right = end_right->right;
            }

            //end of new building no lower ones found
            if (right <= end_right->val){ 
                end_right = end_left->right;
                continue;
            }
            
            //end of all old buildings
            if (!end_right->right){ 
                new_right = create_node(right, 0, p++);
                end_right->height = height;
                end_right->right = new_right;
                new_right->left = end_right;
                end_right = end_left->right;
                continue;
            }

            new_left = end_right;
            // confined to one cell
            if (right < end_right->right->val) { 
                new_right = create_node(right, end_right->height, p++);
                new_left->height = height;
                insert_node(new_right, new_left, end_right->right);
                end_right = end_left->right;
                continue;
            } 
            new_left->height = height;
        }

        // suppose to have a new_left node for all possible cases by now
        if (!new_left){
            printf("Error new_left node hasn't been defined\n");
            free(base);
            exit(1);
        }

        // searching for a place for new_right node, deleting everything between new_left and new_right
        while (end_right->right && right >= end_right->val) {
            end_right = end_right->right;
        }

        if (right < end_right->val){
            new_right = create_node(right, end_right->left->height, p++);
            insert_node(new_right, new_left, end_right);
        } else {
            new_right = create_node(right, 0, p++);
            new_left->right = new_right;
            new_right->left = new_left;
        }
        if (new_left->height > end_left->height) {
            end_left = new_left;
        }
        end_right = end_left->right;
    }
        
    struct node* start = NULL;
    
    // finding the start of Llist
    while (end_left->left) {
        end_left = end_left->left;
    }
    
    start = end_left;
    
    if (!start) {
        printf("Error: start node is NULL\n");
        free(base);
        exit(1);
    }

    int ret_len = 1;
    while (end_left->right){   
        ret_len++;
        end_left = end_left->right;
    }

    int **result = malloc(ret_len * sizeof(int*)); 

    result[0] = malloc(ret_len * 2 * sizeof(int));

    for (int i = 1; i < ret_len; i++) result[i] = result[0] + (i * 2);

    end_left = start;
    for (int i = 0; i < ret_len; i ++){
        result[i][0] = end_left->val;
        result[i][1] = end_left->height;
        end_left = end_left->right;
    }

    *return_size = ret_len;

    free(base);

    *return_col_size = malloc(sizeof(int) * (*return_size));
    for (int i = 0 ; i < *return_size ; i++){
        (*return_col_size)[i] = 2;
    }

    return result;
}


struct node *create_node(int val, int height, struct node* node) {
    node->val = val;
    node->height = height;
    node->right = NULL;
    node->left = NULL;
    return node;
}


void insert_node(struct node* node, struct node* left, struct node* right){
    left->right = node;
    node->left = left;
    right->left = node;
    node->right = right;
    return;
}