Week 05 Extra Sample Solutions

Information

  • This page contains extra exercises for week 05.
  • These exercises are not compulsory, nor do they provide any marks in the course.
  • You cannot submit any of these exercises, however autotests are available for them (Command included at bottom of each exercise).

Exercise
(●◌◌)
:

Reverse an array

Write a C program, reverse_array.c, which reads integers line by line, and when it reaches the end of input, prints those integers in reverse order, line by line.

You will never be given more than 100 integers to print out.

Examples

dcc reverse_array.c -o reverse_array
./reverse_array
Enter numbers forwards:
10
50
20
40 

Reversed:
40
20
50
10
./reverse_array
Enter numbers forwards:
-5
-4
-3
-2
-1 

Reversed:
-1
-2
-3
-4
-5

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

1091 autotest reverse_array
Sample solution for reverse_array.c
// A program to print a list of integers in reverse
// Written by Tom Kunc (t.kunc@unsw.edu.au)
// Created in 2019-06-23

#include <stdio.h>

#define MAX_NUMBERS 100

int main(void) {
    
    int i = 0;
    int did_scan_something = 0;
    int scanned_value;
    int scanned_numbers[MAX_NUMBERS];

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

    while (scanf("%d", &scanned_value) == 1) {
        scanned_numbers[i] = scanned_value;
        did_scan_something = 1;
        i++;
    }
    
    printf("Reversed:\n");

    while (i > 0 && did_scan_something) {
        i--;
        printf("%d\n", scanned_numbers[i]);
    }

    return 0;
}

Exercise
(●●◌)
:

Max Pool Volume

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

cp -n /import/reed/A/dp1091/public_html/24T3/activities/pool_max_volume/pool_max_volume.c .

The Problem

For the last week, it has been raining continously. You have noticed that with this rain, water has been trapped in uneven parts of the land. You, being the curious person that you are, wish to find which pool of trapped water contains the most volume.

The Program

For this exercise, you have been given some starter code to scan in n numbers into an array. You are to write the function seen at the top of this question

The input provided to the program is the height of each consecutive piece of land that you have measured

Water is said to be trapped if it has two pieces of land to both sides of it (does not need to be directly next to either piece) such that both pieces of land are taller, or the same height as this water

An interactive example has been provided below to show where water is trapped

Number of Elements:
(Max 100)

You can generate arrays above and test with those as the maximum pool can be seen easily in the interactive

Examples

 dcc pool_max_volume.c -o pool_max_volume
 ./pool_max_volume
Please enter heights: 7 2 7 6 4 6 8 2 4 5

Maximum volume of pools: 5
 ./pool_max_volume
Please enter heights: 6 2 5 0 5 0 2 8 3 5 7 13 17 17 14 17 14 17 11 14

Maximum volume of pools: 22
 ./pool_max_volume
Please enter heights: 3 9 1 2 0 6 5 3 5 8

Maximum volume of pools: 34
 ./pool_max_volume
Please enter heights: 8 7 6 5 4 3 2 1

Maximum volume of pools: 0

Assumptions/Restrictions/Clarifications

  • You can assume that no more than 200 inputs will be provided
  • If you picked any height in the array, could you move forward in the array and find the the furthest height that could hold water with the selected height? Could you repeat this for every height?
  • It can be assumed that any land that appears before and after the inputs (E.g. not in the array) have a negative infinite height. This means that pools cannot be formed such that they would continue out of the array

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

1091 autotest pool_max_volume
Sample solution for pool_max_volume.c
// Program that takes in an array of heights and outputs the maximum volume
// that can be held in one region of these heights.
//
// Written by Rory Golledge (z5308772), 05-03-2022

#include <stdio.h>

#define MAX_HEIGHT 200

int max_pool_volume(int length, int heights[length]);

int main(void) {
    int height;

    int heights[MAX_HEIGHT];
    int n_heights = 0;
    printf("Please enter heights: ");
    while (n_heights < MAX_HEIGHT && scanf("%d", &height) == 1) {
        heights[n_heights] = height;
        n_heights++;
    }

    printf(
        "Maximum volume of pools: %d\n",
        max_pool_volume(n_heights, heights)
    );

    return 0;
}

// Given two integers, `a` and `b`, return whichever is smaller.
int min(int a, int b) {
    if (a < b) {
        return a;
    }
    return b;
}

// Given two integers, `a` and `b`, return whichever is larger.
int max(int a, int b) {
    if (a < b) {
        return b;
    }
    return a;
}

// Given an array `heights` of length `length`, returns the volume of the
// largest possible pool that can be formed between the heights.
int max_pool_volume(int length, int heights[length]) {
    int i = 0;
    int max_volume = 0;
    while (i < length) {
        int largest_volume_index = i + 1;
        int j = i + 1;
        while (j < length) {
            if (heights[j] >= heights[i]) {
                largest_volume_index = j;
                j = length;
            } else if (heights[j] >= heights[largest_volume_index]) {
                largest_volume_index = j;
            }
            j++;
        }

        // An index needs to be found for any water volume to exist
        if (largest_volume_index != -1) {
            int pool_volume = 0;
            int min_height = min(heights[i], heights[largest_volume_index]);
            j = i + 1;
            while (j < largest_volume_index) {
                pool_volume += min_height - heights[j];
                j++;
            }

            // Update max volume if it applies.
            max_volume = max(max_volume, pool_volume);
        }
        i++;
    }

    return max_volume;
}

Exercise
(●●●)
:

Max Pool Volume Without Nested Looping

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

cp -n /import/reed/A/dp1091/public_html/24T3/activities/pool_max_volume_challenge/pool_max_volume_challenge.c .
For this exercise, you will be completing the exact same question as the previous one. The difference however, is that you cannot use nested loops anymore. This means that you cannot put a loop inside of a loop For example, the below is illegal in this exercise!

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

cp -n /import/reed/A/dp1091/public_html/24T3/activities/pool_max_volume_challenge/pool_challenge_banned.c .

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

1091 autotest pool_max_volume_challenge
Sample solution for pool_max_volume_challenge.c
// Program that takes in an array of heights and outputs the maximum volume
// that can be held in one region between these heights.
//
// Written by Rory Golledge (z5308772), 05-03-2022
//
// In a perfect world, searching from left to right and from right to left would
// be a single function. However, for the sake of readability, they have been
// separated to prevent more complicated statements.

#include <stdio.h>

#define MAX_HEIGHT 200

int max_pool_volume(int length, int heights[length]);

int main(void) {
    int height;

    int heights[MAX_HEIGHT];
    int n_heights = 0;
    printf("Please enter heights: ");
    while (n_heights < MAX_HEIGHT && scanf("%d", &height) == 1) {
        heights[n_heights] = height;
        n_heights++;
    }

    printf(
        "Maximum volume of pools: %d\n",
        max_pool_volume(n_heights, heights)
    );

    return 0;
}


// Given two integers, `a` and `b`, return whichever is larger.
int max(int a, int b) {
    if (a < b) {
        return b;
    }
    return a;
}

// Finds the max pool given an array of heights and its length. Search direction
// is left to right
int max_pool_right_search(int length, int heights[length]) {
    int left = 0;
    int right = 1;

    int max_volume = 0;
    int running_land_sum = 0;
    while (right < length) {
        if (heights[right] >= heights[left]) {
            // Water height is always just the `left` piece of land here.
            int water_height = heights[left];
            int x_distance = right - left - 1;

            // Get the maximum possible water volume (width * height) of region
            int rectangle_sum = water_height * x_distance;

            // The final water volume is simply the difference between the max
            // water and the land heights in this region
            int water_volume = rectangle_sum - running_land_sum;

            // Update max_volume if required
            max_volume = max(max_volume, water_volume);

            // Now a new region is to be considered, so running sum is reset
            running_land_sum = 0;

            left = right;
        } else {
            running_land_sum += heights[right];
        }
        right++;
    }

    return max_volume;
}

// Finds the max pool given an array of heights and its length. Search direction
// is right to left
int max_pool_left_search(int length, int heights[length]) {
    int right = length - 1;
    int left = length - 2;

    int max_volume = 0;
    int running_land_sum = 0;
    while (left >= 0) {
        if (heights[left] >= heights[right]) {
            // Water height is always just the `right` piece of land here.
            int water_height = heights[right];
            int x_distance = right - left - 1;

            // Get the maximum possible water volume (width * height) of region
            int rectangle_sum = water_height * x_distance;

            // The final water volume is simply the difference between the max
            // water and the land heights in this region
            int water_volume = rectangle_sum - running_land_sum;

            // Update max_volume if required
            max_volume = max(max_volume, water_volume);

            // Now a new region is to be considered, so running sum is reset
            running_land_sum = 0;

            right = left;
        } else {
            running_land_sum += heights[left];
        }
        left--;
    }

    return max_volume;
}

// Given an array `heights` of length `length`, returns the volume of the
// largest possible pool that can be formed between the heights.
int max_pool_volume(int length, int heights[length]) {
    if (length <= 2) {
        return 0;
    }

    int max_right = max_pool_right_search(length, heights);
    int max_left = max_pool_left_search(length, heights);
    return max(max_left, max_right);
}