Prac Exam Solutions

Q1

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

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

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

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 = product(head1, head2);
    printf("%d\n", result);

    return 0;
}


// product should the sum of the elements in list1 multiplied by
// the corresponding element in list2
// if one list is longer than the other, the extra list elements are ignored
int product(struct node *head1, struct node *head2) {
    if (!head1 || !head2) {
        return 0;
    } else {
        return (head1->data * head2->data) + product(head1->next, head2->next);
    }
}



// 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>
#include <stdlib.h>
#include <string.h>

enum room_type { LECTURE, SEMINAR, LABORATORY };

struct room {
  int capacity;
  enum room_type type;
};

// Return the average capacity of all seminar rooms
int average_capacity_room(int size, struct room rooms[size]) {

  int i = 0;
  int number_of_seminar = 0;
  int total = 0;

  while (i < size) {
    if (rooms[i].type == SEMINAR) {
      total += rooms[i].capacity;
      number_of_seminar ++;
    }
    i++;
  }
  
  if (number_of_seminar == 0) {
    return 0;
  }
  	
  return total/number_of_seminar;
}

// This is a simple main function which could be used
// to test your average_capacity_room function.
// It will not be marked.
// Only your average_capacity_room function will be marked.
#define TEST_ARRAY_SIZE 6

int main(void) {
  struct room test_array[TEST_ARRAY_SIZE] = {
      {.capacity = 10, .type = LECTURE},
      {.capacity = 25, .type = SEMINAR},
      {.capacity = 30, .type = LABORATORY},
      {.capacity = 40, .type = SEMINAR},
      {.capacity = 50, .type = LECTURE},
      {.capacity = 60, .type = LABORATORY}};
  printf ("%d\n", average_capacity_room(TEST_ARRAY_SIZE, test_array));

  return 0;
}

Q3

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

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

int mixed(struct node *head);
int member(int i, struct node *head);
struct node *strings_to_list(int len, char *strings[]);

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

    int result = mixed(head);
    printf("%d\n", result);

    return 0;
}

// mixed should return 1 if list contains both even and odd numbers
// mixed should return 0 otherwise
int mixed(struct node *head) {
    if (!head || !head->next) {
        return 0;
    } if ((head->data % 2) != (head->next->data % 2)) {
        return 1;
    } else {
        return mixed(head->next);
    }
}


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

Q4

#include <stdio.h>

// Do not change this #define, or your program will fail the autotests!
#define NO_TRIPLE -1

// find_triple should find and return the value in the array that
// occurs three times, if one exists.
// If no values occur three times, it should return NO_TRIPLE.
int find_triple(int length, int array[]) {
    for (int i = 0; i < length; i++) {
        int count = 0;
        int k = -1;
        for (int j = 0; j < length; j++) {
            if (array[i] == array[j]) {
                count ++;
                k = i;
            }                  
        }
        if (count == 3) {
            return array[k];
        }    
    }
    return NO_TRIPLE;
}

#define TEST_ARRAY_SIZE 8

// This is a simple main function which could be used
// to test your find_triple function.
// It will not be marked.
// Only your find_triple function will be marked.
int main(void) {
    int test_array[TEST_ARRAY_SIZE] = {3, 1, 4, 1, 5, 9, 2, 6};

    int result = find_triple(TEST_ARRAY_SIZE, test_array);
    printf("%d\n", result);

    return 0;
}

Q5

#include <stdio.h>

#define MAX_LETTERS 100

int main (void) {

    char my_arr[MAX_LETTERS];
    printf("Enter string: ");
    while (fgets(my_arr, MAX_LETTERS, stdin) != NULL) {
        printf("Input received: %s", my_arr);
        printf("Enter string: ");
    }

    return 0;
}

Q6

#include <stdio.h>

#define MAX_SIZE 100

int main(void) {
    int scanned_length;
    int length_count = 0;
    int scanned_value;
    int scanned_num[MAX_SIZE];

    // Prompt user for the specific number of integers to be taken from input
    printf("How many numbers: ");
    scanf("%d", &scanned_length);

    // Take in scanned_length number of integers
    printf("Please enter numbers: ");
    while (length_count < scanned_length) {
        scanf("%d", &scanned_value);
        scanned_num[length_count] = scanned_value;

        length_count++;
    }

    // Iterate over the array and print the minimum and maximum values in the array
    int index = 0;
    if (scanned_length > 0) {
        int minimum = scanned_num[index];
        int maximum = scanned_num[index];

        while (index < scanned_length) {
            if (scanned_num[index] < minimum) {
                minimum = scanned_num[index];
            } else if (scanned_num[index] > maximum) {
                maximum = scanned_num[index];
            }

            index++;
        }

        printf("Minimum: %d\nMaximum: %d\n", minimum, maximum);
    }

    return 0;
}

Q7

#include <stdio.h>

struct time {
    int days;
    int hours;
    int minutes;
};

void increment_time(struct time *current_time);

int main(void) {

    struct time current_time;
    current_time.days = 3;
    current_time.hours = 4;
    current_time.minutes = 59;

    printf("One minute ago: %d days, %d hours and %d minutes\n",
        current_time.days, current_time.hours, current_time.minutes);

    increment_time(&current_time);

    printf("Now: %d days, %d hours and %d minutes\n",
        current_time.days, current_time.hours, current_time.minutes);

    return 0;
}

// increments the time by 1 minute
void increment_time(struct time *current_time) {
    current_time->minutes++;
    if (current_time->minutes == 60) {
        current_time->minutes = 0;
        current_time->hours++;
    }

    if (current_time->hours == 24) {
        current_time->hours = 0;
        current_time->days++;
    }
}

Q8

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

#define MAX_LIST_LEN 100

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

struct node *delete_last(struct node *head);
void print_list(struct node *head);
struct node *array_to_list(int len, int array[]);

// DO NOT CHANGE THE MAIN FUNCTION
int main(void) {

    // Get list size
    int list_size;
    printf("Total numbers: ");
    scanf(" %d", &list_size);

    // Read in numbers
    int list[MAX_LIST_LEN] = {0};
    int index_count = 0;
    while (index_count < list_size && scanf(" %d", &list[index_count])) {
        index_count++;
    }

    // Create linked list from input numbers
    struct node *head = NULL;
    if (index_count > 0) {
        // List has elements
        head = array_to_list(list_size, list);
    }

    struct node *new_head = delete_last(head);
    print_list(new_head);

    return 0;
}

// Delete the last element from a given linked list
struct node *delete_last(struct node *head) {

    if (head == NULL) {
        return head;
    }

    struct node *prev = NULL;
    struct node *curr = head;

    while (curr->next != NULL) {
        prev = curr;
        curr = curr->next;
    }

    if (prev == NULL) {
        free(curr);
        return NULL;
    }

    prev->next = curr->next;
    free(curr);
    return head;
}

// DO NOT CHANGE THIS FUNCTION
// prints the given linked list
void print_list(struct node *head) {
    struct node *curr = head;
    while (curr != NULL) {
        printf("%d -> ", curr->data);
        curr = curr->next;
    }
    printf("X\n");
}

// DO NOT CHANGE THIS FUNCTION
// create linked list from array of strings
struct node *array_to_list(int len, int array[]) {
    struct node *head = NULL;
    int i = len - 1;
    while (i >= 0) {
        struct node *n = malloc(sizeof (struct node));
        assert(n != NULL);
        n->next = head;
        n->data = array[i];
        head = n;
        i -= 1;
    }
    return head;
}

Q9

#include <stdio.h>
#include <ctype.h>
#include <assert.h>
int main(int argc, char *argv[]) {
    int both_lines = 0;
    int letter_count[26] = {0};
    char line1[1024];
    char line2[1024];
    assert(fgets(line1, sizeof line1, stdin));
    assert(fgets(line2, sizeof line2, stdin));
    for (int i = 0; line1[i]; i++) {
        if (isalpha(line1[i])) {
            letter_count[tolower(line1[i]) - 'a']++;
        }
    }
    for (int i = 0; line2[i]; i++) {
        if (isalpha(line2[i])) {
            int index = tolower(line2[i]) - 'a';
            if (letter_count[index]) {
                both_lines++;
                letter_count[index] = 0;
            }
        }
    }
    printf("%d\n", both_lines);
    return 0;
}

Q10

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

#define MAX_LEN 4096

struct card {
    int num;
    struct card *next;
};

struct card *deck_read(int player_num);
void print_deck(struct card *deck);

int main(void) {
    struct card *player1 = deck_read(1);
    struct card *player2 = deck_read(2);
    struct card *pile = NULL;

    struct card *curr = player1;
    bool has_snapped = false;
    while (player1 && player2 && !has_snapped) {

        struct card *popped = curr;
        if (curr == player1) {
            player1 = player1->next;
            curr = player2;
        } else {
            player2 = player2->next;
            curr = player1;
        }
        popped->next = pile;
        pile = popped;

        if (pile && pile->next && pile->num == pile->next->num) {
            printf("Snap! Matched card %d\n", pile->num);
            has_snapped = true;
        }
    }
    if (!has_snapped) {
        if (!player1) {
            printf("Player 2 has won!\n");
        } else if (!player2) {
            printf("Player 1 has won!\n");
        }
    }
    printf("Player 1's deck: ");
    print_deck(player1);
    printf("Player 2's deck: ");
    print_deck(player2);
    printf("Pile: ");
    print_deck(pile);

    return 0;
}

void print_deck(struct card *deck) {
    while (deck != NULL) {
        printf("%d -> ", deck->num);
        deck = deck->next;
    }
    printf("X\n");
}

// Function to create a deck for the specified player.
// Returns a pointer to the top card in the deck.
struct card *deck_read(int player_num) {
    int num;
    printf("Enter Player %d's deck values:\n", player_num);
    struct card *head = NULL;
    struct card *tail = NULL;
    while (scanf("%d", &num) == 1) {
        if (num == -1) break;
        struct card *new_card = malloc(sizeof(struct card));
        new_card->num = num;
        new_card->next = NULL;
        if (head == NULL) {
            head = tail = new_card;
        } else {
            tail = tail->next = new_card;
        }
    }
    return head;
}

Q11

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

#define MAXDIGITS 1500

typedef struct bignum {
    char digits[MAXDIGITS];
} bignum;

void
add(bignum *op0, bignum *op1, bignum *op2, bignum *result) {
    int i, carry = 0;
    for (i = 0; i < MAXDIGITS; i++) {
        int sum = op0->digits[i] + op1->digits[i] + op2->digits[i] + carry;
        result->digits[i] = sum % 10;
        carry = sum / 10;
    }
    if (carry > 0) {
        printf("Overflow\n");
        exit(1);
    }

}

void
print(bignum *b) {
    int i;
    for (i = MAXDIGITS - 1; i > 0 && b->digits[i] == 0; i--)
        ;
    for (; i >= 0; i--) {
        printf("%d", b->digits[i]);
    }
    printf("\n");
}

int
main(int argc, char *argv[]) {
    bignum x0 = {{1}}, x1 = {{1}}, x2 = {{1}}, x3 = {{1}};
    for (int i = atoi(argv[1]); i > 0; i--) {
        x0 = x1;
        x1 = x2;
        x2 = x3;
        add(&x0, &x1, &x2, &x3);
    }
    print(&x0);
    return 0;
}