Week 10 Weekly Test Sample Answers

Test Conditions

These questions must be completed under self-administered exam-like conditions. You must time the test yourself and ensure you comply with the conditions below.

You may access this language documentation while attempting this test:

You may also access manual entries (the man command).

Any violation of the test conditions will results in a mark of zero for the entire weekly test component.


weekly test question:
Example Exam Q1: Return the Maximum Value in an Array

Download array_max.c here, or copy it to your CSE account using the following command:

cp -n /web/cs1511/20T1/activities/array_max/array_max.c .

Your task is to add code to this function in array_max.c:

// Return the largest value in a given array.
int array_max(int size, int array[size]) {
    // Put your code here
    return 42;
}
You are to implement the array_max function which should return the largest value in the array.

The file array_max.c contains a main function which reads values into an array and calls array_max.

Here is how array_max.c should behave after you add the correct code to the function array_max:

dcc array_max.c -o array_max
./array_max
Enter array size: 5
Enter array values: 1 2 3 4 5
Maximum value is 5.
./array_max
Enter array size: 6
Enter array values: -1 -3 -9 -17 -2 -8
Maximum value is -1.

When you think your program is working you can autotest to run some simple automated tests:

1511 autotest array_max
When you are finished working on this exercise you must submit your work by running give:
give cs1511 test10_array_max array_max.c
Sample solution for array_max.c
// Find the maximum value in an array.
// Sample solution.

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

#define MAX_SIZE 1000

int array_max(int size, int array[size]);

// DO NOT CHANGE THIS MAIN FUNCTION
int main(int argc, char *argv[]) {
    int array[MAX_SIZE];

    // Get the array size.
    int size;
    printf("Enter array size: ");
    scanf("%d", &size);
    assert(size > 0);

    // Scan in values for the array.
    printf("Enter array values: ");
    int i = 0;
    while (i < size) {
        assert(scanf("%d", &array[i]) == 1);
        i = i + 1;
    }

    printf("Maximum value is %d.\n", array_max(size, array));

    return 0;
}

// Return the largest value in a given array.
int array_max(int size, int array[size]) {
    // Set the max to initially be the first element in the array.
    int max = array[0];
    int i = 0;
    while (i < size) {
        // If we find something that's bigger than our current max...
        if (array[i] > max) {
            // ... update our current max to that value.
            max = array[i];
        }
        i = i + 1;
    }

    return max;
}

weekly test question:
Example Exam Q4: Find the Middle Element of a Linked List

Download list_get_middle.c here, or copy it to your CSE account using the following command:

cp -n /web/cs1511/20T1/activities/list_get_middle/list_get_middle.c .

Your task is to add code to this function in list_get_middle.c:

// Return middle element of a linked list
// if list contains [6,7,8,9,10]  8 is returned
// if a list has even number of elements, first of middle two elements returned
// if list contains [1,2,3,4] 2 is returned
// list can not be empty
int get_middle(struct node *head) {

    // PUT YOUR CODE HERE (change the next line!)
    return 42;

}
get_middle is given one argument, head, which is the pointer to the first node in a linked list.

Add code to get_middle so that its returns the middle value of the list. If the list an even number of elements the first of the 2 elements in the middle of the list should be returned.

For example if the linked list contains these 8 elements:

1, 7, 8, 9, 13, 19, 21, 42

get_middle should return 9 because 9 and 13 are the middle two elements/

And or example if the linked list contains these 8 elements:

1, 2, 8, 1,  42

get_middle should return 8 because it is the middle element.

get_middle can assume the list is not empty.

Testing

list_get_middle.c also contains a main function which allows you to test your get_middle function.

This main function:

  • converts the command-line arguments to a linked list
  • assigns a pointer to the first node in the linked list to head
  • calls list_get_middle(head)
  • prints the result.

Do not change this main function. If you want to change it, you have misread the question.

Your list_get_middle function will be called directly in marking. The main function is only to let you test your list_get_middle function

Here is how you use main function allows you to test list_get_middle:

dcc list_get_middle.c -o list_get_middle
./list_get_middle 1 2 4 8 16 32 64 128 256
16
./list_get_middle 2 4 6 5 8 9
6
./list_get_middle 13 15 17 19 18
17
./list_get_middle 42 4
42
./list_get_middle 42
42

Assumptions/Restrictions/Clarifications.

get_middle should return a single integer.

get_middle can assume the list has at least one element.

get_middle should not change the linked list it is given. Your function should not change the next or data fields of list nodes.

get_middle should not use arrays.

get_middle should not call malloc.

get_middle should not call scanf (or getchar or fgets).

get_middle should not print anything. It should not call printf.

Do not change the supplied main function. It will not be tested or marked.

When you think your program is working you can autotest to run some simple automated tests:

1511 autotest list_get_middle
When you are finished working on this exercise you must submit your work by running give:
give cs1511 test10_list_get_middle list_get_middle.c
Sample solution for list_get_middle.c
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

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

int get_middle(struct node *head);
int length(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 = get_middle(head);
    printf("%d\n", result);

    return 0;
}

// Return middle element of a linked list
// if list contains [6,7,8,9,10]  8 is returned
// if a list has even number of elements, first of middle two elements returned
// if list contains [1,2,3,4] 2 is returned
// list can not be empty
int get_middle(struct node *head) {
    assert(head != NULL);
    int len = length(head);
    int middle = (len - 1)/2;

    int i = 0;
    struct node *n = head;
    while (i < middle) {
        i = i + 1;
        n = n->next;
    }
    return n->data;
}

// Return length of a linked list.
int length(struct node *head) {
    int len = 0;
    struct node *n = head;
    while (n != NULL) {
        len = len + 1;
        n = n->next;
    }
    return len;
}


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

weekly test question:
Example Exam Q6: Delete all the elements of a Linked List that have the highest value

Download list_delete_highest.c here, or copy it to your CSE account using the following command:

cp -n /web/cs1511/20T1/activities/list_delete_highest/list_delete_highest.c .

Your task is to add code to this function in list_delete_highest.c:

//
// Delete the node(s) in the list that contain the highest value
// The deleted node(s) are freed.
// The head of the list is returned.
//
struct node *delete_highest(struct node *head) {

    // PUT YOUR CODE HERE (change the next line!)
    return NULL;

}
Note list_delete_highest.c uses the following familiar data type:
struct node {
    struct node *next;
    int          data;
};
delete_highest is given one argument, head. head is the pointer to the first node in a linked list.

Add code to delete_highest so that it deletes the all nodes in the linked list whose data field are equal to the highest data value in the list.

delete_highest should return a pointer to the new list.

If the list is now empty delete_highest should return NULL.

delete_highest should call free to free the memory of any node it deletes.

For example if the linked list contains these 8 elements:

16, 7, 8, 19, 13, 19, 2, 12

delete_highest should return a pointer to a list with these elements:

16, 7, 8, 13, 2, 12

Testing

list_delete_highest.c also contains a main function which allows you to test your delete_highest function.

This main function:

  • converts the command-line arguments to a linked list
  • assigns a pointer to the first node in the linked list to head
  • calls delete_highest(head)
  • prints the result.

Do not change this main function. If you want to change it, you have misread the question.

Your delete_highest function will be called directly in marking. The main function is only to let you test your delete_highest function

cp -n /web/cs1511/20T1/activities/list_delete_highest/list_delete_highest.c .
dcc list_delete_highest.c -o list_delete_highest
./list_delete_highest 16 7 8 19 13 19 2 12
[16, 7, 8, 13, 2, 12]
./list_delete_highest 200 150 27 200 200
[150, 27]
./list_delete_highest 4 6 2 4 6
[4, 2, 4]
./list_delete_highest 42
[]
./list_delete_highest
[]

Assumptions/Restrictions/Clarifications.

delete_highest should call free to free the memory for any nodes it deletes

delete_first should not change the data fields of list nodes.

delete_highest should not use arrays.

delete_highest should not call malloc.

delete_highest should not call scanf (or getchar or fgets).

delete_highest should not print anything. It should not call printf.

Do not change the supplied main function. It will not be tested or marked.

When you think your program is working you can autotest to run some simple automated tests:

1511 autotest list_delete_highest
When you are finished working on this exercise you must submit your work by running give:
give cs1511 test10_list_delete_highest list_delete_highest.c
Sample solution for list_delete_highest.c
// List Delete Highest
// Will find the highest value stored in a linked list
// then will delete all occurences of that value
// in the list.

// Marc Chee (cs1511@cse.unsw.edu.au), April 2020

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

#define MIN_VALUE -1

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

struct node *delete_highest(struct node *head);
int return_highest(struct node *head);
struct node *delete_contains(int value, struct node *head, int *num_removed);
struct node *strings_to_list(int len, char *strings[]);
void print_list(struct node *head);

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

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

    return 0;
}

// deletes all occurences of the highest value
// nodes in a list
// returns the head of the list
struct node *delete_highest(struct node *head) {
    if (head == NULL) {
        return head;
    }
    int highest = return_highest(head);
    
    // keep removing elements until there are none
    // of the highest left
    int num_removed = 1;
    while (num_removed) {
        head = delete_contains(highest, head, &num_removed);
    }
    return head;
}

// returns the highest value in the list
// this function assumes that the list has
// at least one element!
int return_highest(struct node *head) {
    int highest = head->data;
    struct node *current = head->next;
    while (current != NULL) {
        if (current->data > highest) {
            highest = current->data;
        }
        current = current->next;
    }
    return highest;
}

// Delete the first node in the list containing i
// The deleted node is freed.
// If no node contains i, the list is not changed
// num_removed will contain how many elements were removed
// The head of the list is returned.

struct node *delete_contains(int value, struct node *head, int *num_removed) {
    *num_removed = 0;
    if (head == NULL) {
        // list is empty no node to delete
        return NULL;
    } else if (head->data == value) {
        // deleting the first node
        struct node *new_head = head->next;
        free(head);
        *num_removed = 1;
        return new_head;
    } else if (head->next == NULL) {
        // first node is the only node
        // first node is definitely not value
        return head;
    }

    struct node *n = head;
    // find node before first node containing i
    while (n->next->next != NULL && n->next->data != value) {
        n = n->next;
    }

    if (n->next->data == value) {
        struct node *new_next = n->next->next;
        free(n->next);
        n->next = new_next;
        *num_removed = 1;
    }
    return head;
}

// create linked list from array of strings
struct node *strings_to_list(int len, char *strings[]) {
    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 = atoi(strings[i]);
        head = n;
        i -= 1;
    }   
    return head;
}

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

Submission

When you are finished each exercise make sure you submit your work by running give.

You can run give multiple times. Only your last submission will be marked.

Don't submit any exercises you haven't attempted.

If you are working at home, you may find it more convenient to upload your work via give's web interface.

Remember you have until Week 11 Sunday 17:00 to complete this test.

Automarking will be run by the lecturer several days after the submission deadline for the test, using test cases that you haven't seen: different to the test cases autotest runs for you.

(Hint: do your own testing as well as running autotest)

Test Marks

After automarking is run by the lecturer you can view it here the resulting mark will also be available via via give's web interface or by running this command on a CSE machine:

1511 classrun -sturec

The test exercises for each week are worth in total 1 marks.

The best 7 of your 8 test marks for weeks 3-10 will be summed to give you a mark out of 7.