Week 06 Laboratory Sample Solutions

Objectives

  • creating functions
  • manipulating 2D arrays
  • scanning until ctrl-d
  • basic string manipulation

Activities To Be Completed

The following is a list of all the activities available to complete this week...

Worth 0.7 mark(s) in total:

  • debug_stringcmp
  • word_square
  • alternating_case
  • simple_snake

Worth 0.7 mark(s) in total:

  • planter
  • palindrome

Worth 0.4 mark(s) in total:

  • remove_duplicates_function
  • largest_z_sum

Problem sets are capped at 15 marks (there are 4 possible bonus marks from the three-dot exercises that can bring you up to a total of 15 if you missed out on any other marks in the one- or two-dot exercises).

Completing just the one and two-dot exercises every week can give you the full 15 marks needed in this component.

For more details, see the course outline.

Exercise
(●◌◌)
:

Debugging - stringcmp

Copy the program debug_stringcmp.c from the course account to your directory by typing (make sure you type the dot at the end):

cp ~dp1091/public_html/24T3/activities/debug_stringcmp/debug_stringcmp.c .

Debugging Tips!

Some debugging tips for you:

  • dcc output - as you run into issues, dcc will point you to where the errors are. Remember that dcc gives you the line number the issue is on, and will give some sort of explanation. Make sure you read everything dcc gives you. Sometimes we get “errors carried forward”, so find your first error, fix that, then recompile.
  • print statements - sometimes it can be handy to see if the flow of your code puts you in the spot you expect it to be (ie. inside the right if statement, or going through a loop the correct amount of times). A quick way you can check this is by putting print statements in your code for testing purposes, like "the value of x is %d and y is %d". This lets you check that you got against what you expected.
  • DPST1091 debugging guide

The Task

This exercise takes in two strings as input, calcuates if they are equal and prints out the result. Currently it has some issues - it is your job to figure them out and fix the code.

Examples

dcc debug_stringcmp.c -o debug_stringcmp
./debug_stringcmp
Enter the first string: Hello, World!
Enter the second string: Hello, World!
The strings are equal!
./debug_stringcmp
Enter the first string: It's illegal to own just one guinea pig in Switzerland
Enter the second string: Pigeons can tell the difference between Picasso and Monet
The strings are not equal!
New! You can run an automated code style checker using the following command:
1091 style debug_stringcmp.c
    

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

1091 autotest debug_stringcmp

When you are finished working on this exercise, you must submit your work by running give:

give dp1091 lab06_debug_stringcmp debug_stringcmp.c
    

You must run give before Monday 14 October 09:00 to obtain the marks for this lab exercise. Note that this is an individual exercise, the work you submit with give must be entirely your own.

Sample solution for debug_stringcmp.c
// debug_stringcmp.c
//
// This program takes in two strings as input and checks if they are the same
// Wrriten by Sofia De Bellis, z5418801
// on June, 2023

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

#define MAX_SIZE 100

int main() {
    char str1[MAX_SIZE];
    char str2[MAX_SIZE];

    // Read input from user
    printf("Enter the first string: ");
    fgets(str1, MAX_SIZE, stdin);

    printf("Enter the second string: ");
    fgets(str2, MAX_SIZE, stdin);

    // Check if the strings are equal
    if (strcmp(str1, str2) == 0) {
        printf("The strings are equal!\n");
    } else {
        printf("The strings are not equal!\n");
    }

    return 0;
}

Exercise
(●◌◌)
:

Word Square

Write a program called word_square.c that prompts the user to enter a word, and afterwards, prints that word out n amount of times, where n is the length of the word.

You should use the function fgets to scan in the input word.

Examples

dcc word_square.c -o word_square
./word_square
Input word: a

Word square is:
a
./word_square
Input word: word

Word square is:
word
word
word
word
./word_square
Input word: abrakadabra

Word square is:
abrakadabra
abrakadabra
abrakadabra
abrakadabra
abrakadabra
abrakadabra
abrakadabra
abrakadabra
abrakadabra
abrakadabra
abrakadabra

Assumptions/Restrictions/Clarifications

  • You can assume that you will be given a word no longer than 1024 character (Including the null-terminator).
New! You can run an automated code style checker using the following command:
1091 style word_square.c
    

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

1091 autotest word_square

When you are finished working on this exercise, you must submit your work by running give:

give dp1091 lab06_word_square word_square.c
    

You must run give before Monday 14 October 09:00 to obtain the marks for this lab exercise. Note that this is an individual exercise, the work you submit with give must be entirely your own.

Sample solution for word_square.c
// Program to take in a word and print it out by its length amount of times.
// Written by Rory Golledge (z5308772) on October 2021

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

#define MAX_WORD 1024

int main(void) {
    char word[MAX_WORD];

    printf("Input word: ");
    fgets(word, MAX_WORD, stdin);

    printf("\nWord square is:\n");

    int i = 0;
    while (i < strlen(word) - 1) {
        printf("%s", word);
        i++;
    }

    return 0;
}

Exercise
(●◌◌)
:

Alternating case

Copy the program alternating_case.c from the course account to your directory by typing (make sure you type the dot at the end):

cp ~dp1091/public_html/24T3/activities/alternating_case/alternating_case.c .

Complete the C program, alternating_case.c.

The main function has already been written for you. You must not modify it in any way.

This function takes in a string, and should modify it so that the first letter is lowercase, and the case of each following letter alternates.

In other words, the string should be modified so that:

  • The first letter is lowercase,
  • The second letter is uppercase,
  • The third letter is lowercase,
  • The forth letter is uppercase,
  • etc.

All non letter characters should be left unmodified.

Examples

./alternating_case
hello
hElLo
./alternating_case
Hello World
hElLo WoRlD
./alternating_case
The quick brown fox jumps over the lazy dog
tHe QuIcK bRoWn FoX jUmPs OvEr ThE lAzY dOg
./alternating_case
a1b2c3e4d5 f6g7
a1B2c3E4d5 F6g7

Assumptions/Restrictions/Clarifications

  • You can assume the string will contain at most 1024 characters
New! You can run an automated code style checker using the following command:
1091 style alternating_case.c
    

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

1091 autotest alternating_case

When you are finished working on this exercise, you must submit your work by running give:

give dp1091 lab06_alternating_case alternating_case.c
    

You must run give before Monday 14 October 09:00 to obtain the marks for this lab exercise. Note that this is an individual exercise, the work you submit with give must be entirely your own.

Sample solution for alternating_case.c
// Written by ...
// June, 2022

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

#define MAX_STRING_LENGTH 1024

//////////////// DO NOT CHANGE ANY OF THE CODE BELOW HERE //////////////////
void make_alternating(char string[MAX_STRING_LENGTH]);

int main (void) {
    //You don't need to understand this code to complete the exercise.

    //Scans in a string from the user.
    char buffer[MAX_STRING_LENGTH];
    fgets(buffer, MAX_STRING_LENGTH, stdin);

    // Runs your function
    make_alternating(buffer);

    // Prints resulting string.
    printf("%s", buffer);

    return 0;
}
//////////////// DO NOT CHANGE ANY OF THE CODE ABOVE HERE //////////////////

////////////////////////////////////////////////////////////////////////////
///////////////////// ONLY WRITE CODE BELOW HERE ///////////////////////////
////////////////////////////////////////////////////////////////////////////

// Modifies `string` so that the first letter is converted to lowercase, 
// and the case of each following letter alternates.
// i.e. in the resulting string: 
//      the first letter is lowercase, 
//      second letter is uppercase, 
//      third letter is lower case, 
//      etc.
//
// e.g.: "Hello" -> "hElLo"
void make_alternating(char string[MAX_STRING_LENGTH]) {

    int i = 0;
    int letter_counter = 0;

    while (string[i] != '\0') {
        if (isalpha(string[i])) {
            if (letter_counter % 2 == 0) {
                string[i] = tolower(string[i]);
            } else {
                string[i] = toupper(string[i]);
            }
            letter_counter++;
        }
        i++;
    }
}

////////////////////////////////////////////////////////////////////////////
///////////////////// ONLY WRITE CODE ABOVE HERE ///////////////////////////
////////////////////////////////////////////////////////////////////////////

Exercise
(●◌◌)
:

Creating a simple Snake game

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

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

Snake is one of the oldest and most famous digital games

The Snake game involves controlling a snake that moves along a 2D plane. The goal is to lead this snake to an apple on the map, that upon eating, increases the length of the snake.

As more apples are eaten, the player must be careful as they move the snake, as the game will end if the snake moves back into their tail.

For this exercise, you will be implementing a simpler version of Snake. This version involves:

  1. Spawning the snake and the apple
  2. Moving the snake up/down/left/right in a loop (using u/d/l/r commands)
  3. Ending the game when the snake reaches the apple

Since this game is fundamentally about moving a snake on a 2D plane, it should make sense to represent this as a 2D array in code. In the starter code provided, you should notice that the first line of code in the main() function defines this array as:

enum land map[SIZE][SIZE];

This means that the map is made up only of values defined in the enum land definition above the main() function.

Let's have a look at what each value in enum land represents:

  • NOT_VISITED - Indicates a land tile that the snake has not visited yet
  • VISITED - Indicates a land tile that the snake has visited
  • SNAKE - The land tile the snake is currently on
  • APPLE - The land tile the apple is currently on

You have been provided a print_map() function that will print the 2D array with the enum land tiles set.

Make sure you understand everything mentioned above before reading the example below!

Examples

dcc simple_snake.c -o simple_snake
./simple_snake
Welcome to Snake!
Please enter apple location: 2 3
Please enter snake location: 4 3
. . . . . . . . 
. . . . . . . . 
. . . A . . . . 
. . . . . . . . 
. . . S . . . . 
. . . . . . . . 
. . . . . . . . 
. . . . . . . . 
r
. . . . . . . . 
. . . . . . . . 
. . . A . . . . 
. . . . . . . . 
. . . - S . . . 
. . . . . . . . 
. . . . . . . . 
. . . . . . . . 
u
. . . . . . . . 
. . . . . . . . 
. . . A . . . . 
. . . . S . . . 
. . . - - . . . 
. . . . . . . . 
. . . . . . . . 
. . . . . . . . 
u
. . . . . . . . 
. . . . . . . . 
. . . A S . . . 
. . . . - . . . 
. . . - - . . . 
. . . . . . . . 
. . . . . . . . 
. . . . . . . . 
u
. . . . . . . . 
. . . . S . . . 
. . . A - . . . 
. . . . - . . . 
. . . - - . . . 
. . . . . . . . 
. . . . . . . . 
. . . . . . . . 
l
. . . . . . . . 
. . . S - . . . 
. . . A - . . . 
. . . . - . . . 
. . . - - . . . 
. . . . . . . . 
. . . . . . . . 
. . . . . . . . 
d
. . . . . . . . 
. . . - - . . . 
. . . S - . . . 
. . . . - . . . 
. . . - - . . . 
. . . . . . . . 
. . . . . . . . 
. . . . . . . . 
Chomp!

Assumptions/Restrictions/Clarifications

  • You will always be given snake/apple locations inside the map
  • You will always be given correct direction commands (u/d/l/r)
  • You will never be given commands such that the snake walks off the map
New! You can run an automated code style checker using the following command:
1091 style simple_snake.c
    

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

1091 autotest simple_snake

When you are finished working on this exercise, you must submit your work by running give:

give dp1091 lab06_simple_snake simple_snake.c
    

You must run give before Monday 14 October 09:00 to obtain the marks for this lab exercise. Note that this is an individual exercise, the work you submit with give must be entirely your own.

Sample solution for simple_snake.c
// A simpler version of the famous Snake game!
//
// Written by Rory Golledge (z5308772) on 3/3/23


#include <stdio.h>

#define SIZE 8

enum land {
    NOT_VISITED,
    VISITED,
    SNAKE,
    APPLE
};

void initialise_map(enum land map[SIZE][SIZE]);
void print_map(enum land map[SIZE][SIZE]);

int main(void) {
    enum land map[SIZE][SIZE];
    initialise_map(map);
 
    printf("Welcome to Snake!\n");
    printf("Please enter apple location: ");
    int apple_row;
    int apple_col;
    scanf("%d %d", &apple_row, &apple_col);

    map[apple_row][apple_col] = APPLE;

    printf("Please enter snake location: ");
    int snake_row;
    int snake_col;
    scanf("%d %d", &snake_row, &snake_col);

    map[snake_row][snake_col] = SNAKE;

    print_map(map);

    while (!(snake_row == apple_row && snake_col == apple_col)) {
        char dir;
        scanf(" %c", &dir);

        map[snake_row][snake_col] = VISITED;    
        if (dir == 'u') {
            --snake_row;
        } else if (dir == 'd') {
            ++snake_row;
        } else if (dir == 'l') {
            --snake_col;
        } else {
            ++snake_col;
        }
        map[snake_row][snake_col] = SNAKE;

        print_map(map);
    }

    printf("Chomp!\n");

    return 0;
}

/**
 * Initialises the given `map` such that all tiles are `NOT_VISITED`
 * 
 * Parameters:
 *     map - The map to initialise
 * 
 * Returns:
 *     Nothing
 */
void initialise_map(enum land map[SIZE][SIZE]) {
    for (int row = 0; row < SIZE; ++row) {
        for (int col = 0; col < SIZE; ++col) {
            map[row][col] = NOT_VISITED;
        }
    }
}

/**
 * Prints the given `map` such that all enum values are printed as nice
 * characters.
 * 
 * Parameters:
 *     map - The map to print out
 * 
 * Returns:
 *     Nothing
 */
void print_map(enum land map[SIZE][SIZE]) {
    for (int row = 0; row < SIZE; ++row) {
        for (int col = 0; col < SIZE; ++col) {
            if (map[row][col] == NOT_VISITED) {
                printf(". ");
            } else if (map[row][col] == VISITED) {
                printf("- ");
            } else if (map[row][col] == SNAKE) {
                printf("S ");
            } else if (map[row][col] == APPLE) {
                printf("A ");
            }
        }
        printf("\n");
    }
}

Exercise
(●●◌)
:

Planter

Copy the program planter.c from the course account to your directory by typing (make sure you type the dot at the end):

cp ~dp1091/public_html/24T3/activities/planter/planter.c .

Complete the program planter.c! The program is a garden simulator that uses a 2D array, a 5x5 grid, to represent a garden.

The gardener will be represented by the # character and each round will appear on the first column of the row that is about to be planted.

The program should prompt the user to choose which type of flower that will be planted in each row of the garden. The user may also choose to plant nothing, represented by the . character.

Flowers take 3 rounds to bloom after they are planted. During the round, if the flower is still growing, it will be represented by a number that represents how many rounds are left for the flower to bloom. If the flower has already bloomed, it will be represented by the first letter of its name.

The garden should be printed after each round, updating how long is left for the flowers to bloom.

Once all flowers are planted, the program should wait for the growing flowers to bloom, printing Waiting for flowers to bloom... and the garden after each round.

You must use the provided struct garden to represent the flowers in the garden, the print_garden function to display the current state of the garden and the provided enum flowers to represent the different flowers.

Examples

dcc planter.c -o planter
./planter
Welcome to the planter!

# . . . . 
. . . . . 
. . . . . 
. . . . . 
. . . . . 

0. Nothing
1. Daisy
2. Rose
3. Tulip
Which Flower would you like to plant in this row? 3

3 3 3 3 3 
# . . . . 
. . . . . 
. . . . . 
. . . . . 

0. Nothing
1. Daisy
2. Rose
3. Tulip
Which Flower would you like to plant in this row? 0

2 2 2 2 2 
. . . . . 
# . . . . 
. . . . . 
. . . . . 

0. Nothing
1. Daisy
2. Rose
3. Tulip
Which Flower would you like to plant in this row? 1

1 1 1 1 1 
. . . . . 
3 3 3 3 3 
# . . . . 
. . . . . 

0. Nothing
1. Daisy
2. Rose
3. Tulip
Which Flower would you like to plant in this row? 2

T T T T T 
. . . . . 
2 2 2 2 2 
3 3 3 3 3 
# . . . . 

0. Nothing
1. Daisy
2. Rose
3. Tulip
Which Flower would you like to plant in this row? 0

T T T T T 
. . . . . 
1 1 1 1 1 
2 2 2 2 2 
. . . . . 

Waiting for flowers to bloom...

T T T T T 
. . . . . 
D D D D D 
1 1 1 1 1 
. . . . . 

Waiting for flowers to bloom...

T T T T T 
. . . . . 
D D D D D 
R R R R R 
. . . . . 

Assumptions/Restrictions/Clarifications

  • Assume you will only be given valid inputs.
  • The provided struct garden, enum flowers and print_garden should not be modified.
  • You may not assume a flower will always be chosen to be planted in a row, the user may choose to plant nothing.
New! You can run an automated code style checker using the following command:
1091 style planter.c
    

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

1091 autotest planter

When you are finished working on this exercise, you must submit your work by running give:

give dp1091 lab06_planter planter.c
    

You must run give before Monday 14 October 09:00 to obtain the marks for this lab exercise. Note that this is an individual exercise, the work you submit with give must be entirely your own.

Sample solution for planter.c
// planter.c 
// A program which lets you live out your dream of being a gardener.
// Written by Ibrahim Ghoneim 

/*

*/
#include <stdio.h>

#define GARDEN_ROWS 5
#define GARDEN_COLS 5
#define TRUE 1
#define FALSE 0

/*
Provided enum
*/
enum flowers {
    EMPTY,
    DAISY,
    ROSE,
    TULIP
};

/*
Provided struct
*/
struct garden {
    enum flowers flower;
    int bloom_countdown;
    int is_gardener;
};

/*
provided function prototypes
*/
void print_garden(struct garden garden[GARDEN_ROWS][GARDEN_COLS]);
int grow_garden(struct garden garden[GARDEN_ROWS][GARDEN_COLS]);

int main(void) {
    printf("Welcome to the planter!\n");
    struct garden garden[GARDEN_ROWS][GARDEN_COLS];

    // Double for loop to initialize the garden
    for (int i = 0; i < GARDEN_ROWS; i++) {
        for (int j = 0; j < GARDEN_COLS; j++) {
            garden[i][j].flower = EMPTY;
            garden[i][j].bloom_countdown = 0;
            garden[i][j].is_gardener = FALSE;
        }
    }
    int choice;

    // Loop to plant flowers in the garden going row by row and planting the
    // same flower in each column
    for (int i = 0; i < GARDEN_ROWS; i++) {
        garden[i][0].is_gardener = TRUE;
        print_garden(garden);
        grow_garden(garden);
        printf(
            "0. Nothing\n"
            "1. Daisy\n"
            "2. Rose\n"
            "3. Tulip\n"
            "Which Flower would you like to plant in this row? "
        );
        scanf("%d", &choice);
        if (choice != EMPTY) {
            for (int j = 0; j < GARDEN_COLS; j++) {
                garden[i][j].flower = choice;
                garden[i][j].bloom_countdown = 3;
            }
        }
        garden[i][0].is_gardener = FALSE;
    }

    print_garden(garden);
    // Loop to wait for the flowers to bloom, will keep looping until grow_garden
    // returns 0
    while (grow_garden(garden)) {
        printf("Waiting for flowers to bloom...\n");
        print_garden(garden);
    }
    return 0;
}

/*
    Decreases the bloom_countdown for all flowers in the garden
    Parameters:
        garden: a 2D array of struct garden
    Returns:
        int: returns 1 if a flower has grown, 0 otherwise
*/
int grow_garden(struct garden garden[GARDEN_ROWS][GARDEN_COLS]) {
    int flower_found = FALSE;
    for (int i = 0; i < GARDEN_ROWS; i++) {
        for (int j = 0; j < GARDEN_COLS; j++) {
            if (garden[i][j].bloom_countdown > 0) {
                garden[i][j].bloom_countdown--;
                flower_found = TRUE;
            }
        }
    }
    return flower_found;
}


////////////////////////////////////////////////////////////////////////////////
//////////////////// DO NOT MODIFY ANYTHING BELOW THIS LINE ////////////////////
////////////////////////////////////////////////////////////////////////////////

/*
    Prints the garden to the terminal
    Parameters:
        garden: a 2D array of struct garden
    Returns:
        void
*/
void print_garden(struct garden garden[GARDEN_ROWS][GARDEN_COLS]) {
    printf("\n");
    for (int i = 0; i < GARDEN_ROWS; i++) {
        for (int j = 0; j < GARDEN_COLS; j++) {
            if (garden[i][j].is_gardener) {
                printf("# ");
            } else if (garden[i][j].flower == EMPTY) {
                printf(". ");
            } else if (garden[i][j].bloom_countdown > 0) {
                printf("%d ", garden[i][j].bloom_countdown);
            } else if (garden[i][j].flower == DAISY) {
                printf("D ");
            } else if (garden[i][j].flower == ROSE) {
                printf("R ");
            } else if (garden[i][j].flower == TULIP) {
                printf("T ");
            } else {
                printf(". ");
            }
        }
        printf("\n");
    }
    printf("\n");
}

Exercise
(●●◌)
:

Palindrome

A palindrome is a sequence which is the same forwards as backwards.

Write a program, palindrome.c, which reads a string and tests if it is a palindrome.

For example:

./palindrome
Enter a string: kayak
String is a palindrome
./palindrome
Enter a string: canoe
String is not a palindrome
./palindrome
Enter a string: if if fi fi
String is a palindrome
./palindrome
Enter a string: if if if fi
String is not a palindrome

Hint: don't use scanf, use fgets to read the string.

Note, your program needs to read only one line - it doesn't have to read until the end of input.

You can assume the line contains at most 4096 characters.

New! You can run an automated code style checker using the following command:
1091 style palindrome.c
    

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

1091 autotest palindrome

When you are finished working on this exercise, you must submit your work by running give:

give dp1091 lab06_palindrome palindrome.c
    

You must run give before Monday 14 October 09:00 to obtain the marks for this lab exercise. Note that this is an individual exercise, the work you submit with give must be entirely your own.

Sample solution for palindrome.c
// Read a string and then print the letters one per line
// written by Andrew Taylor andrewt@cse.unsw.edu.au
// April 2018 as a COMP1511 lab exercise
//

#include <stdio.h>

#define MAXLINE 5000

int is_palindrome(char line[]);

int main(void) {
    char line[MAXLINE] = {0};
    printf("Enter a string: ");
    fgets(line, MAXLINE, stdin);

    if (is_palindrome(line)) {
        printf("String is a palindrome\n");
    } else{
        printf("String is not a palindrome\n");
    }

    return 0;
}

// return 1 is line is palindromic, 0 otherwise
// line is terminated by either '\n' or '\0'
// an empty line is considered a palindrome
int is_palindrome(char line[]) {
    int right = 0;
    while (line[right] != '\0' && line[right] != '\n') {
        right =  right + 1;
    }

    right = right - 1;

    int left = 0;
    while (left < right) {
        if (line[left] != line[right]) {
            return 0;
        }
        left = left + 1;
        right = right - 1;
    }

    return 1;
}

Exercise
(●●●)
:

Remove any duplicate values from an array and write the result into another array

Write a C function that removes duplicate elements from an array, by copying the non-duplicate values to a second array, i.e. only the first occurrence of any value should be copied.

Place your answer in a file named remove_duplicates_function.c

Your function should take three parameters: the length of source array, the source array itself, and the destination array. It must have this prototype:

int remove_duplicates(int length, int source[length], int destination[length]);

Your function should return a single integer: the number of elements copied to the destination array.

For example, if the source array contains these 6 elements:

3, 1, 4, 1, 5, 9

Your function should copy these 5 values to the destination array:

3, 1, 4, 5, 9

Your function should return the integer 5, because there were 5 values copied -- the second occurrence of the digit 1 was not copied.

Assumptions/Restrictions/Clarifications

  • You can assume the source array only contains positive integers.
  • You can assume the source array contains at least one integer.
  • You can assume that the destination array will always be large enough to fit all of the copied values.
  • You cannot assume anything about the number of duplicates, i.e. there may not be any duplicates, or conversely, the entire array may be duplicates.
  • Your function should return a single integer.
  • Your function should not change the array it is given.
  • Your function should not call scanf (or getchar or fgets).
  • Your function should not print anything. It should not call printf.
  • Your submitted file may contain a main function. It will not be tested or marked.

Write a C function that removes duplicate elements from an array, by copying the non-duplicate values to a second array, i.e. only the first occurrence of any value should be copied.

Place your answer in a file named remove_duplicates_function.c

Your function should take three parameters: the length of source array, the source array itself, and the destination array. It must have this prototype:

int remove_duplicates(int length, int source[length], int destination[length]);

Your function should return a single integer: the number of elements copied to the destination array.

For example, if the source array contains these 6 elements:

3, 1, 4, 1, 5, 9

Your function should copy these 5 values to the destination array:

3, 1, 4, 5, 9

Your function should return the integer 5, because there were 5 values copied -- the second occurrence of the digit 1 was not copied.

Assumptions/Restrictions/Clarifications

  • You can assume the source array only contains positive integers.
  • You can assume the source array contains at least one integer.
  • You can assume that the destination array will always be large enough to fit all of the copied values.
  • You cannot assume anything about the number of duplicates, i.e. there may not be any duplicates, or conversely, the entire array may be duplicates.
  • Your function should return a single integer.
  • Your function should not change the array it is given.
  • Your function should not call scanf (or getchar or fgets).
  • Your function should not print anything. It should not call printf.
  • Your submitted file may contain a main function. It will not be tested or marked.
New! You can run an automated code style checker using the following command:
1091 style remove_duplicates_function.c
    

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

1091 autotest remove_duplicates_function

When you are finished working on this exercise, you must submit your work by running give:

give dp1091 lab06_remove_duplicates_function remove_duplicates_function.c
    

You must run give before Monday 14 October 09:00 to obtain the marks for this lab exercise. Note that this is an individual exercise, the work you submit with give must be entirely your own.

Sample solution for remove_duplicates_function.c
int remove_duplicates(int length, int source[length], int destination[length]) {

    // Go through each element in the `source` array
    int destination_upto = 0;
    int source_upto = 0;
    while (source_upto < length) {
        // Check it against every other element we've seen so far.
        int duplicate = 0;
        int checking = 0;
        while (checking < source_upto && duplicate == 0) {
            if (source[source_upto] == source[checking]) {
                duplicate = 1;
            }
            checking = checking + 1;
        }

        if (!duplicate) {
            destination[destination_upto] = source[source_upto];
            destination_upto = destination_upto + 1;
        }

        source_upto = source_upto + 1;
    }
    return destination_upto;
}

Exercise
(●●●)
:

Find the Largest Sum of Numbers in a Z Shape

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

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

You are to implement the largest_z_sum function which should return the sum of values forming the shape of the letter 'Z' in a square 2D array.

A Z shape is made up of three lines of equal length. Two of these lines are horizontal and one is diagonal. The length of the three lines must be equal but can range from 3 up to the size of the array. Only correctly oriented Z shapes are valid - Z shapes with a northwest/southeast diagonal are not valid.

The 2D square array may contain any positive or negative integers.

You can assume that the side length of the 2D square array will always be greater than or equal to 3.

You can assume that the side length of the 2D array will never be greater than

  1. The file largest_z_sum.c contains a main function which reads values into a square 2D array and calls largest_z_sum.

Examples

dcc largest_z_sum.c -o largest_z_sum
./largest_z_sum
Enter 2D array side length: 3
Enter 2D array values:
1 1 1
1 1 1
1 1 1
The largest z sum is 7.
./largest_z_sum
Enter 2D array side length: 5
Enter 2D array values:
1  2  3  4  5
6  7  8  9  10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25
The largest z sum is 169.
./largest_z_sum
Enter 2D array side length: 5
Enter 2D array values:
 28 -47 -40  29  49
 26 -42 -37  48  1
-36  50  41 -24 -33
 41  25 -39  39  48
 14 -26 -46 -3  -29
The largest z sum is 153.
./largest_z_sum
Enter 2D array side length: 5
Enter 2D array values:
1  1  1  1  1
1  1  1  1  1
99 99 99 1  1
1  99 1  1  1
99 99 99 1  1
The largest z sum is 693.

In the first example, there is only one possible Z sum of size 3.

The Z in the example input is underlined below for your reference:

1 1 1
1 1 1
1 1 1

In the second example, the Z of size 5 starting from (0, 0) is used to form the largest sum of:

1 + 2 + 3 + 4 + 5 + 9 + 13 + 17 + 21 + 22 + 23 + 24 + 25 = 169

The Z in the example input is underlined below for your reference:

1  2  3  4  5
6  7  8  9  10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25

In the third example, the Z of size 4 starting from (0, 1) is used to form the largest sum of:

-47 - 40 + 29 + 49 + 48 + 41 + 25 - 39 + 39 + 48 = 153

The Z in the example input is underlined below for your reference:

 28 -47 -40  29  49
 26 -42 -37  48  1
-36  50  41 -24 -33
 41  25 -39  39  48
 14 -26 -46 -3  -29

In the fourth example, the Z of size 3 starting from (2, 0) is used to form the largest sum of:
99 + 99 + 99 + 99 + 99 + 99 + 99 = 693
The Z in the example input is underlined below for your reference:

1  1  1  1  1
1  1  1  1  1
99 99 99 1  1
1  99 1  1  1
99 99 99 1  1
New! You can run an automated code style checker using the following command:
1091 style largest_z_sum.c
    

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

1091 autotest largest_z_sum

When you are finished working on this exercise, you must submit your work by running give:

give dp1091 lab06_largest_z_sum largest_z_sum.c
    

You must run give before Monday 14 October 09:00 to obtain the marks for this lab exercise. Note that this is an individual exercise, the work you submit with give must be entirely your own.

Sample solution for largest_z_sum.c
// Find the largest sum of numbers in a z shape.

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

#define MAX_SIZE 100

int largest_z_sum(int size, int array[MAX_SIZE][MAX_SIZE]);

// DO NOT CHANGE THIS MAIN FUNCTION
int main(void) {
    int array[MAX_SIZE][MAX_SIZE];

    // Get the array size.
    int size;
    printf("Enter 2D array side length: ");
    scanf("%d", &size);
    assert(size >= 3);

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

    printf("The largest z sum is %d.\n", largest_z_sum(size, array));

    return 0;
}

// Return the largest sum of numbers in a z shape.
int largest_z_sum(int size, int array[MAX_SIZE][MAX_SIZE]) {
    int curr_size = 3;

    // Appropriate initial value for max_sum. Most basic z.
    int max_sum = array[0][0] + array[0][1] + array[0][2]
                              + array[1][1]
                + array[2][0] + array[2][1] + array[2][2];

    while (curr_size <= size) {
        int z_possible_y = 0;
        while (z_possible_y <= size - curr_size) {
            int z_possible_x = 0;
            while (z_possible_x <= size - curr_size) {

                // Consider (z_possible_y, z_possible_x) to be top left corner
                // of candidate z shape of curr_size sidelength.
                
                // Calculate sum of the top row of the z.
                int top_row_sum = 0;
                int i = 0;
                while (i < curr_size - 1) { // -1 to prevent intersection point being double counted.
                    top_row_sum += array[z_possible_y][z_possible_x + i];
                    i++;
                }

                // Calculate the sum of the diagonal.
                int diagonal_sum = 0;
                i = 0;
                while (i < curr_size) {
                    diagonal_sum += array[z_possible_y + i][z_possible_x + (curr_size - 1) - i];
                    i++;
                }


                // Calculate sum of the bottom row.
                int bottom_row_sum = 0;
                i = 1; // 1 initial value to prevent intersection point being double counted.
                while (i < curr_size) {
                    bottom_row_sum += array[z_possible_y + (curr_size - 1)][z_possible_x + i];
                    i++;
                }

                int total_sum = top_row_sum + diagonal_sum + bottom_row_sum;
                if (total_sum > max_sum) {
                    max_sum = total_sum;
                }

                z_possible_x++;
            }

            z_possible_y++;
        }

        curr_size++;
    }
    return max_sum;
}

Submission

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

You only need to do this if the exercise specifies a give command, otherwise - the exercise is not worth marks.

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 8 Monday 9:00am to submit your work.

You cannot obtain marks by e-mailing your code to tutors or lecturers.

You check the files you have submitted here.

Automarking will be run by the lecturer several days after the submission deadline, using test cases different to those autotest runs for you. (Hint: do your own testing as well as running autotest.)

After automarking is run by the lecturer you can view your results here. The resulting mark will also be available via give's web interface.

Lab Marks

When all components of a lab are automarked you should be able to view the the marks via give's web interface or by running this command on a CSE machine:

1091 classrun -sturec

Generative AI Permission Level

In completing this assessment, you are permitted to use standard editing and referencing functions in the software you use to complete your assessment. These functions are described below. You must not use any functions that generate or paraphrase passages of text or other media, whether based on your own work or not.

If your Convenor has concerns that your submission contains passages of AI-generated text or media, you may be asked to account for your work. If you are unable to satisfactorily demonstrate your understanding of your submission, you may be referred to UNSW Conduct & Integrity Office for investigation for academic misconduct and possible penalties.

DPST1091/CPTG1391 Specific Information

You are permitted to use the tools dcc-help to help you understand the error messages you may get when compiling the code you have written.

You are permitted to use autotest-help to help you understand why your code may not be passing the automated tests.

You are not permitted to submit code generated by automatic AI tools such as Github Copilot, ChatGPT, Google Bard in DPST1091/CPTG1391/COMP1511 for assignments. Submitting code generated by Github Copilot, ChatGPT, Google Bard and similar tools will be treated as plagiarism.

Our reasoning behind our decisions:

Systems such as Github Copilot and ChatGPT based on large language models or other generative artificial intelligence techniques, look likely to become heavily used by programmers. However, you need a good understanding of the language you are coding in and the systems involved before you can effectively use these tools. Using these tools to generate code for DPST1091/CPTG1391/COMP1511 instead of writing the code yourself will hinder your learning.