Week 03 Laboratory Sample Solutions

Objectives

  • implementing simple numerical calculations
  • using complex if statements to control program execution
  • using while loops for repetition

Preparation

Before the lab you should re-read the relevant lecture slides and their accompanying examples.

Getting Started

Exercise — in pairs:
Ordering Three Integers

Write a C program order3.c using if statements (no loops) that reads 3 integers and prints them from smallest to largest.

Your program should behave exactly like this example:

./order3
Enter integer: 23
Enter integer: 5
Enter integer: 27
The integers in order are: 5 23 27
./order3
Enter integer: 3
Enter integer: 6
Enter integer: 27
The integers in order are: 3 6 27
./order3
Enter integer: 9
Enter integer: 8
Enter integer: 7
The integers in order are: 7 8 9
You can assume the user supplies 3 integers. You do not have to check the return value from scanf.
New! You can run an automated code style checker using the following command:
1511 style order3.c

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

1511 autotest order3

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

give cs1511 lab03_order3 order3.c

Note, even though this is a pair exercise, you both must run give from your own account before Friday 08 March 20:00 to obtain the marks for this lab exercise.

Sample solution for order3.c
// Modified 3/3/2018 by Andrew Taylor (andrewt@unsw.edu.au)
// as a lab example for COMP1511

// Print 3 integers in non-decreasing order

#include <stdio.h>

int main(void) {
    int a, b, c;
    int tmp;

    printf("Enter integer: ");
    if (scanf("%d", &a) != 1) {
        return 1; // EXIT_FAILURE would be more portable
    }

    printf("Enter integer: ");
    if (scanf("%d", &b) != 1) {
        return 1;
    }

    printf("Enter integer: ");
    if (scanf("%d", &c) != 1) {
        return 1;
    }

    // a, b, c can be in any order

    // swap a & b if they are not in order
    if (a > b) {
        tmp = b;
        b = a;
        a = tmp;
    }

    // swap a & c if they are not in order
    if (a > c) {
        tmp = c;
        c = a;
        a = tmp;
    }

    // a must be the smallest now

    // swap b & c if they are not in order
    if (b > c) {
        tmp = c;
        c = b;
        b = tmp;
    }

    // a, b, c now in  order

    printf("The integers in order are: %d %d %d\n", a, b, c);

    return 0;
}

Exercise — in pairs:
Countdown

We use loops in C to do things multiple times. Here is an example of a loop that prints all the numbers from 1 to 17 on a new line in ascending order:

//initialise counter to 1
int counter = 1; 
// loop until not <= 17
while (counter <= 17) { // Have printed all numbers between 1 and counter
    // print counter
    printf("%d\n", counter);
    // increment counter
    counter = counter + 1; 
} // counter == 18

In this exercise you will use a loop to print a countdown from 10 to 0. Start by creating a file called countdown.c, and copying the above code. Modify this code so that the loop counts down from 10 until 0.

Example

./countdown
10
9
8
7
6
5
4
3
2
1
0
New! You can run an automated code style checker using the following command:
1511 style countdown.c

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

1511 autotest countdown

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

give cs1511 lab03_countdown countdown.c

Note, even though this is a pair exercise, you both must run give from your own account before Friday 08 March 20:00 to obtain the marks for this lab exercise.

Sample solution for countdown.c
// Count down from 10 to 0, using a loop.
// 2017-08-10   Alex Linker <{a.linker, z5061930}@unsw.edu.au>
//              Jashank Jeremy <{jashankj, z5017851}@cse.unsw.edu.au>
// 2020-02-27	Edited by Marc Chee to add Carroll Morgan's commenting

#include <stdio.h>

int main(int argc, char *argv[]) {
    // For this loop, we have a counter, which we'll call `num`.
    int num = 10;

    // And, as long as `num` is greater than or equal to zero:
    while (num >= 0) { // Have printed all numbers strictly between 10 and num.
        // We print out the counter ---
        printf("%d\n", num);
        
        // --- and subtract one from it.
        num = num - 1;
    } // num = -1

    return 0;
}

Exercise — in pairs:
Three or Five

Write a program three_five.c that reads a positive integer n and print all the positive integers < n divisible by 3 or 5. All of the numbers printed should be in ascending order.

For example:

 ./three_five
Enter number: 10
3
5
6
9
./three_five
Enter number: 30
3
5
6
9
10
12
15
18
20
21
24
25
27
New! You can run an automated code style checker using the following command:
1511 style three_five.c

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

1511 autotest three_five

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

give cs1511 lab03_three_five three_five.c

Note, even though this is a pair exercise, you both must run give from your own account before Friday 08 March 20:00 to obtain the marks for this lab exercise.

Sample solution for three_five.c
// Written 16/3/2018
// by Andrew Taylor (andrewt@cse.unsw.edu.au)
// as a lab example for COMP1511
// Suggested by a https://projecteuler.net/ problem

// Print multiples of 3 or 5 < n

#include <stdio.h>

int main(void) {
    int number, i;

    printf("Enter number: ");
    scanf("%d", &number);

    i = 1;
    while (i < number) {
        if (i % 3 == 0 || i % 5 == 0) {
            printf("%d\n", i);
        }
        i = i + 1;
    }

    return 0;
}

Exercise — in pairs:
Are You Perfect

Write a program perfect.c that reads a positive integer n from standard input and prints all the factors of n, their sum and indicates whether n is a perfect number.
 ./perfect
Enter number: 6
The factors of 6 are:
1
2
3
6
Sum of factors = 12
6 is a perfect number
./perfect
Enter number: 1001
The factors of 1001 are:
1
7
11
13
77
91
143
1001
Sum of factors = 1344
1001 is not a perfect number
New! You can run an automated code style checker using the following command:
1511 style perfect.c

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

1511 autotest perfect

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

give cs1511 lab03_perfect perfect.c

Note, even though this is a pair exercise, you both must run give from your own account before Friday 08 March 20:00 to obtain the marks for this lab exercise.

Sample solution for perfect.c
// Test if a number is perfect
// Written 26/3/2017
// by Andrew Taylor (andrewt@unsw.edu.au)
// as a lab example for COMP1511

#include <stdio.h>

int main(void) {
    int number, sum, i;

    printf("Enter number: ");

    scanf("%d", &number);

    printf("The factors of %d are:\n", number);

    i = 1;
    sum = 0;
    while (i <= number) {
        if ((number % i) == 0 ) {
            printf("%d\n", i);
            sum = sum + i;
        }
        i = i + 1;
    }

    printf("Sum of factors = %d\n", sum);

    if (number == (sum - number)) {
        printf("%d is a perfect number\n", number);
    } else {
        printf("%d is not a perfect number\n", number);
    }

    return 0;
}

Exercise — in pairs:
Draw a Hollow Triangle

Write a program called hollow_triangle.c that reads an integer n from standard input. and prints a pattern of asterisks forming a hollow triangle.

You can assume n is greater than 3.

Make your program match the examples below exactly.

Note: you are not permitted to use an array in this exercise.

dcc hollow_triangle.c -o hollow_triangle
./hollow_triangle 
Enter size: 4
*
**
* *
****
./hollow_triangle 
Enter size: 5
*
**
* *
*  *
*****
./hollow_triangle
Enter size: 8
*
**
* *
*  *
*   *
*    *
*     *
********
./hollow_triangle
Enter size: 11
*
**
* *
*  *
*   *
*    *
*     *
*      *
*       *
*        *
***********
New! You can run an automated code style checker using the following command:
1511 style hollow_triangle.c

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

1511 autotest hollow_triangle

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

give cs1511 lab03_hollow_triangle hollow_triangle.c

Note, even though this is a pair exercise, you both must run give from your own account before Saturday 23 March 17:00 to obtain the marks for this lab exercise.

Sample solution for hollow_triangle.c
// Written 14/3/2018 by Andrew Taylor (andrewt@unsw.edu.au)
// as a test for COMP1511
// Print a hollow triangle

#include <stdio.h>

int main(void) {

    int size;
    printf("Enter size: ");
    scanf("%d", &size);

    int row = 1;
    while (row <= size) {
        int col = 1;
        while (col <= row) {
            // row == size gives horizontal line
            // row == col gives diagonal line
            // col == 1 gives vertical line
            if (row == size || col == 1 || row == col) {
                printf("*");
            } else {
                printf(" ");
            }
            col = col + 1;
        }
        printf("\n");
        row = row + 1;
    }

    return 0;
}

Exercise — in pairs:
Draw an X

Write a program called x.c that reads an integer n from standard input, and prints an nxn pattern of asterisks and dashes in the shape of an "X".

You can assume n is odd and >= 5.

Make your program match the examples below exactly.

This exercise is designed to give you practice with while loops, if statements and some mathematical operators. Do not use arrays for this exercise!

Note: you are not permitted to use an array in this exercise.

./x
Enter size: 5
*---*
-*-*-
--*--
-*-*-
*---*
./x
Enter size: 9
*-------*
-*-----*-
--*---*--
---*-*---
----*----
---*-*---
--*---*--
-*-----*-
*-------*
./x
Enter size: 15
*-------------*
-*-----------*-
--*---------*--
---*-------*---
----*-----*----
-----*---*-----
------*-*------
-------*-------
------*-*------
-----*---*-----
----*-----*----
---*-------*---
--*---------*--
-*-----------*-
*-------------*
New! You can run an automated code style checker using the following command:
1511 style x.c

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

1511 autotest x

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

give cs1511 lab03_x x.c

Note, even though this is a pair exercise, you both must run give from your own account before Friday 08 March 20:00 to obtain the marks for this lab exercise.

Sample solution for x.c
// Written 14/3/2018 by Andrew Taylor (andrewt@unsw.edu.au)
// as a lab example for COMP1511

// Print an nxn "x" pattern of asterisks and spaces
//
// For example here is the output for n == 9
//
// *-------*
// -*-----*-
// --*---*--
// ---*-*---
// ----*----
// ---*-*---
// --*---*--
// -*-----*-
// *-------*

#include <stdio.h>

int main(void) {
    int size, n_numbers_read;
    int row, column;

    printf("Enter size: ");
    n_numbers_read = scanf("%d", &size);

    if (n_numbers_read != 1) {
        // scanf failed to read a number
        return 1;
    }

    if (size < 5 || size % 2 != 1) {
        printf("Error: size has to be odd and >= 5.\n");
        return 1;
    }

    row = 0;
    while (row < size) {
        column = 0;
        while (column < size) {
            if (row == column || row == size - (column + 1)) {
                printf("*");
            } else {
                printf("-");
            }
            column = column + 1;
        }
        printf("\n");
        row = row + 1;
    }

    return 0;
}

Challenge Exercise — individual:
Ordering Three Integers Without If Statements

Write a C program order3_challenge1.c that reads 3 integers and prints them from smallest to largest.

You are not permitted to use if statements.

You are not permitted to use loops (e.g. while).

You are not permitted to call functions other than printf and scanf. For example, you are not permitted to use functions from the math library.

You are not permitted to use printf inside expressions - you can only use printf as a statement (the way it has been used in lectures).

You are not permitted to assign variables inside expressions - you can only assign variables as a statement (the way it has been done in lectures).

For example, both of these are invalid:

(a < b) && printf("a"); // invalid

(a < b) && (a = b); // invalid

You can use printf to print the value of an expression, in other words you can have an expression inside printf.

You are only permitted to use parts of C covered in the weeks 1 and 2 lectures. For example, you are not permitted to use the ternary ?: operator. You are not permitted to use arrays. You are not permitted to define functions.

You should invent your own solution - don't just google or ask others how do it!

Your program should behave exactly like this example:

./order3_challenge1
Enter integer: 23
Enter integer: 5
Enter integer: 27
The integers in order are: 5 23 27
./order3_challenge1
Enter integer: 3
Enter integer: 6
Enter integer: 27
The integers in order are: 3 6 27
./order3_challenge1
Enter integer: 9
Enter integer: 8
Enter integer: 7
The integers in order are: 7 8 9
This is more puzzle than a programming exercise.

Try to invent your own solution - don't google or ask others how do it.

Autotest is available to help you test your program - but it doesn't check that your code meets the above restrictions.

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

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

1511 autotest order3_challenge1

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

give cs1511 lab03_order3_challenge1 order3_challenge1.c

You must run give before Friday 08 March 20: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 order3_challenge1.c
// Modified 3/3/2018 by Andrew Taylor (andrewt@unsw.edu.au)
// as a lab example for COMP1511

// Print 3 integers in non-decreasing order
// without using functions: if/while or other control statements, ?:
// using only  C covered in the first 2 weeks of COMP1511 lectures

// This is a puzzle not a programming exercises

#include <stdio.h>

int main(void) {
    int a, b, c;
    int tmp;

    printf("Enter integer: ");
    scanf("%d", &a);

    printf("Enter integer: ");
    scanf("%d", &b);

    printf("Enter integer: ");
    scanf("%d", &c);

    tmp = b;
    b = a - (1 - (a > b)) * (a - b);
    a = a - (1 - (a < tmp)) * (a - tmp);
    tmp = c;
    c = a - (1 - (a > c)) * (a - c);
    a = a - (1 - (a < tmp)) * (a - tmp);
    tmp = c;
    c = b - (1 - (b > c)) * (b - c);
    b = b - (1 - (b < tmp)) * (b - tmp);

    printf("The integers in order are: %d %d %d\n", a, b, c);

    return 0;
}
Alternative solution for order3_challenge1.c
// Modified 3/3/2018 by Andrew Taylor (andrewt@unsw.edu.au)
// as a lab example for COMP1511

// Print 3 integers in non-decreasing order
// without using functions: if/while or other control statements, ?:
// using only  C covered in the first 2 weeks of COMP1511 lectures

// This is a puzzle not a programming exercises

#include <stdio.h>

int main(void) {
    int a, b, c;
    int tmp;

    printf("Enter integer: ");
    if (scanf("%d", &a) != 1) {
        return 1; // EXIT_FAILURE would be more portable
    }

    printf("Enter integer: ");
    if (scanf("%d", &b) != 1) {
        return 1;
    }

    printf("Enter integer: ");
    if (scanf("%d", &c) != 1) {
        return 1;
    }

    tmp = b;
    b = a - (1 - (a > b)) * (a - b);
    a = a - (1 - (a < tmp)) * (a - tmp);
    tmp = c;
    c = a - (1 - (a > c)) * (a - c);
    a = a - (1 - (a < tmp)) * (a - tmp);
    tmp = c;
    c = b - (1 - (b > c)) * (b - c);
    b = b - (1 - (b < tmp)) * (b - tmp);

    printf("The integers in order are: %d %d %d\n", a, b, c);

    return 0;
}

Challenge Exercise — individual:
Ordering Three Integers Without If Statements and With Only 3 Variables

Write a C program order3_challenge2.c that reads 3 integers and prints them from smallest to largest.

You are only permitted to have 3 variables in your program and they must be of type int.

The restrictions of the previous challenge exercise also apply.

You are not permitted to use if statements.

You are not permitted to use loops (e.g. while).

You are not permitted to call functions other than printf and scanf. For example, you are not permitted to use functions from the math library.

You are not permitted to use printf inside expressions - you can only use printf as a statement (the way it has been used in lectures).

You are not permitted to assign variables inside expressions - you can only assign variables as a statement (the way it has been done in lectures).

For example, both of these are invalid:

(a < b) && printf("a"); // invalid

(a < b) && (a = b); // invalid

You can use printf to print the value of an expression, in other words you can have an expression inside printf.

You are only permitted to use parts of C covered in the weeks 1 and 2 lectures. For example, you are not permitted to use the ternary ?: operator. You are not permitted to use arrays. You are not permitted to define functions.

You should invent your own solution - don't just google or ask others how do it!

Your program should behave exactly like this example:

./order3_challenge2
Enter integer: 23
Enter integer: 5
Enter integer: 27
The integers in order are: 5 23 27
./order3_challenge2
Enter integer: 3
Enter integer: 6
Enter integer: 27
The integers in order are: 3 6 27
./order3_challenge2
Enter integer: 9
Enter integer: 8
Enter integer: 7
The integers in order are: 7 8 9
This is much more puzzle than a programming exercise.

Try to invent your own solution - don't google or ask others how do it.

Autotest is available to help you test your program - but it doesn't check that your code meets the above restrictions.

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

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

1511 autotest order3_challenge2

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

give cs1511 lab03_order3_challenge2 order3_challenge2.c

You must run give before Friday 08 March 20: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 order3_challenge2.c
// Modified 3/3/2018 by Andrew Taylor (andrewt@unsw.edu.au)
// as a lab example for COMP1511

// Print 3 integers in non-decreasing order
// without using: functions, if/while or other control statements, ?:
// using only  C covered in the first 2 weeks of COMP1511 lectures
// and only using 3 int variables

// This is a puzzle not a programming exercises

#include <stdio.h>

int main(void) {
    int a, b, c;

    printf("Enter integer: ");
    scanf("%d", &a);

    printf("Enter integer: ");
    scanf("%d", &b);

    printf("Enter integer: ");
    scanf("%d", &c);

    printf("The integers in order are:");
    printf(" %d", a - (1 - (a < (b - (1 - (b < c)) * (b - c)))) * (a - (b - (1 - (b < c)) * (b - c))));
    printf(" %d", (a - (1 - (a < b)) * (a - b)) - (1 - ((a - (1 - (a < b)) * (a - b)) > (c - (1 - (c < (a - (1 - (a > b)) * (a - b)))) * (c - (a - (1 - (a > b)) * (a - b)))))) * ((a - (1 - (a < b)) * (a - b)) - (c - (1 - (c < (a - (1 - (a > b)) * (a - b)))) * (c - (a - (1 - (a > b)) * (a - b))))));
    printf(" %d", a - (1 - (a > (b - (1 - (b > c)) * (b - c)))) * (a - (b - (1 - (b > c)) * (b - c))));
    printf("\n");

    return 0;
}
Alternative solution for order3_challenge2.c
// Modified 3/3/2018 by Andrew Taylor (andrewt@unsw.edu.au)
// as a lab example for COMP1511

// Print 3 integers in non-decreasing order
// without using: functions, if/while or other control statements, ?:
// using only  C covered in the first 2 weeks of COMP1511 lectures
// and only using 3 int variables

// This is a puzzle not a programming exercises

#include <stdio.h>

int main(void) {
    int a, b, c;

    printf("Enter integer: ");
    if (scanf("%d", &a) != 1) {
        return 1; // EXIT_FAILURE would be more portable
    }

    printf("Enter integer: ");
    if (scanf("%d", &b) != 1) {
        return 1;
    }

    printf("Enter integer: ");
    if (scanf("%d", &c) != 1) {
        return 1;
    }

    printf("The integers in order are:");
    printf(" %d", a - (1 - (a < (b - (1 - (b < c)) * (b - c)))) * (a - (b - (1 - (b < c)) * (b - c))));
    printf(" %d", (a - (1 - (a < b)) * (a - b)) - (1 - ((a - (1 - (a < b)) * (a - b)) > (c - (1 - (c < (a - (1 - (a > b)) * (a - b)))) * (c - (a - (1 - (a > b)) * (a - b)))))) * ((a - (1 - (a < b)) * (a - b)) - (c - (1 - (c < (a - (1 - (a > b)) * (a - b)))) * (c - (a - (1 - (a > b)) * (a - b))))));
    printf(" %d", a - (1 - (a > (b - (1 - (b > c)) * (b - c)))) * (a - (b - (1 - (b > c)) * (b - c))));
    printf("\n");

    return 0;
}

Challenge Exercise — individual:
Spiral

Write a program called spiral.c that reads an integer n from standard input. and prints an nxn pattern of asterisks and dashes in the shape of a spiral.

You can assume n is odd and >= 5.

This exercise must be completed without arrays.

Make your program match the examples below exactly.

./spiral
Enter size: 5
*****
----*
***-*
*---*
*****
./spiral
Enter size: 7
*******
------*
*****-*
*---*-*
*-***-*
*-----*
*******
./spiral
Enter size: 9
*********
--------*
*******-*
*-----*-*
*-***-*-*
*-*---*-*
*-*****-*
*-------*
*********
./spiral
Enter size: 17
*****************
----------------*
***************-*
*-------------*-*
*-***********-*-*
*-*---------*-*-*
*-*-*******-*-*-*
*-*-*-----*-*-*-*
*-*-*-***-*-*-*-*
*-*-*-*---*-*-*-*
*-*-*-*****-*-*-*
*-*-*-------*-*-*
*-*-*********-*-*
*-*-----------*-*
*-*************-*
*---------------*
*****************
New! You can run an automated code style checker using the following command:
1511 style spiral.c

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

1511 autotest spiral

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

give cs1511 lab03_spiral spiral.c

You must run give before Friday 08 March 20: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 spiral.c
//spiral.c
//By Alex Rowell z5116848
//Written 20th/21st March 2017
//A program to print a spiral of stars

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


//A key part of this implementation is splitting the numbers into lines
//These are the straight lines of numbers, with the first number coming from the line before
//There are 4 cases to deal with each line based on which direction it would go when spiraling inwards
//(For the example below 'r' is for lines going right, 'd' for lines going down, 'u' for lines going up and 'l' for lines going left)
//eg.
// rrrrr
// ----d
// urr-d
// u---d
// lllld

int main(void) {
    int num;

    printf("Enter size: ");
    if (!scanf("%d", &num) || num % 2 == 0) {
        //Did not get a number or the number is even, exit
        return 1;
    }

    int row = 0;
    int col = 0;

    while (row < num) {
        col = 0;

        while (col < num) {
            if (row <= num/2 && row % 2 == 0 && col >= row - 1 && col <= num-row - 1) { //Line going to the right

                printf("*");

            } else if (row > num/2 && row % 2 == 0 && col <= row && col >= num - row - 1) { //Line going to the left

                printf("*");

            } else if (col <= num/2 && col % 2 == 0 && row >= col + 2 && row < num - col - 1) { //Line going upwards

                printf("*");

            } else if (col > num/2 && col % 2 == 0 && row <= col && row >= num - col) { //Line going downwards

                printf("*");

            } else { // Not part of any line

                printf("-");

            }

            col = col + 1;
        }
        printf("\n");
        row = row + 1;
    }

    return 0;
}

Extra-hard challenge: Decimal Spiral (individual - attempt if you dare)

Write a program called decimal_spiral.c that reads an integer n from standard input. and prints an nxn pattern of decimal digits and dashes in the shape of a spiral.

You can assume n is odd and >= 5.

This exercise must be done without arrays.

Make your program match the examples below exactly.

./decimal_spiral
Enter size: 5
65432
----1
210-0
3---9
45678
./decimal_spiral
Enter size: 7
0987654
------3
87654-2
9---3-1
0-012-0
1-----9
2345678
./decimal_spiral
Enter size: 9
876543210
--------9
8765432-8
9-----1-7
0-210-0-6
1-3---9-5
2-45678-4
3-------3
456789012
./decimal_spiral
Enter size: 15
654321098765432
--------------1
2109876543210-0
3-----------9-9
4-210987654-8-8
5-3-------3-7-7
6-4-87654-2-6-6
7-5-9---3-1-5-5
8-6-0-012-0-4-4
9-7-1-----9-3-3
0-8-2345678-2-2
1-9---------1-1
2-01234567890-0
3-------------9
456789012345678
New! You can run an automated code style checker using the following command:
1511 style decimal_spiral.c

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

1511 autotest decimal_spiral

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

give cs1511 lab03_decimal_spiral decimal_spiral.c

You must run give before Friday 08 March 20: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 decimal_spiral.c
//decimal_spiral.c
//By Alex Rowell z5116848
//Written 20th March 2017
//A program to print a spiral of numbers, with the numbers increasing as it spirals outwards

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


//These are for the direction of the current line being printed (to be explained below)
#define DIR_NONE 0
#define DIR_LEFT 1
#define DIR_RIGHT 2
#define DIR_UP 3
#define DIR_DOWN 4


//A key part of this implementation is splitting the numbers into lines
//These are the straight lines of numbers, with the first number coming from the line before
//There are 4 cases to deal with each line based on which direction it would go when spiraling inwards
//(For the example below 'r' is for lines going right, 'd' for lines going down, 'u' for lines going up and 'l' for lines going left)
//eg.
// rrrrr
// ----d
// urr-d
// u---d
// lllld

int main(void) {
    int num;

    printf("Enter size: ");
    if (!scanf("%d", &num) || num % 2 == 0) {
        //Did not get a number or the number is even, exit
        return 1;
    }


    // These are the sizes of the original lines, the right line starts
    // longer than the others since it doesn't have another direction that takes its first number
    // The up line starts shorter than the others since every time it gets to the upwards line the line
    // gets smaller
    int original_up_size = num - 3;
    int original_down_size = num - 1;
    int original_right_size = num + 1;
    int original_left_size = num - 1;



    //Determine the total number of numbers to write (so that it can count down)
    //This is done by simulating each side
    int total_stars = 0;

    int up_size = original_up_size;
    int down_size = original_down_size;
    int right_size = original_right_size;
    int left_size = original_left_size;

    while (up_size > 0) {
        total_stars = total_stars + up_size;
        up_size = up_size - 4; //Every go of the spiral, each side shrinks by 4
    }
    while (down_size > 0) {
        total_stars = total_stars + down_size;
        down_size = down_size - 4;
    }
    while (right_size > 0) {
        total_stars = total_stars + right_size;
        right_size = right_size - 4;
    }
    while (left_size > 0) {
        total_stars = total_stars + left_size;
        left_size = left_size - 4;
    }


    int row = 0;
    int col = 0;

    while (row < num) {
        col = 0;

        while (col < num) {

            int line_num = 0; // The number of line changes in the spiral before this line

            int offset = 0; // The number along the line this position is

            int line_dir = DIR_NONE; //The direction the line's going (or none if a dash should be printed)


            if (row <= num/2 && row % 2 == 0 && col >= row - 1 && col <= num-row - 1) { //Line going to the right
                line_dir = DIR_RIGHT;
                line_num = (row / 2 * 4);

                offset = col - row + 2;

            } else if (row > num/2 && row % 2 == 0 && col <= row && col >= num - row - 1) { //Line going to the left
                line_dir = DIR_LEFT;
                line_num = ((num-row-1)/2 * 4) + 2;

                offset = row - col;

            } else if (col <= num/2 && col % 2 == 0 && row >= col + 2 && row < num - col - 1) { //Line going upwards
                line_dir = DIR_UP;
                line_num = (col / 2 * 4) + 3;

                offset = num - col - 1 - row;
            } else if (col > num/2 && col % 2 == 0 && row <= col && row >= num - col) { //Line going downwards
                line_dir = DIR_DOWN;
                line_num = ((num-col-1)/2 * 4) + 1;

                offset = row - num + col + 1;
            }

            if (line_dir != DIR_NONE) {
                // Reset the number of stars in the first line of each type
                // For calculating the number to print out
                up_size = original_up_size;
                down_size = original_down_size;
                right_size = original_right_size;
                left_size = original_left_size;

                int num_so_far = 0; //The total numbers that have been printed so far in the spiral
                int i = 0;

                while (i < line_num) {
                    // Similar to calculating total number of numbers printed in the whole spiral
                    // but in this case only go up to the current line
                    if (i % 4 == 0) { // rightwards line
                        num_so_far = num_so_far + right_size;
                        right_size = right_size - 4;
                    } else if (i % 4 == 1) { // downwards line
                        num_so_far = num_so_far + down_size;
                        down_size = down_size - 4;
                    } else if (i % 4 == 2) { // leftwards line
                        num_so_far = num_so_far + left_size;
                        left_size = left_size - 4;
                    } else { // i % 4 == 3, upwards line
                        num_so_far = num_so_far + up_size;
                        up_size = up_size - 4;
                    }

                    i = i + 1;
                }

                num_so_far = num_so_far + offset; // Include the amount printed in the current line

                int to_print = total_stars - num_so_far; // Subtract num_so_far from total_stars as
                // the spiral should be counting down as it goes inwards
                printf("%d", to_print % 10); // Only take last digit of what to print

            } else {
                printf("-"); // Not part of spiral, just print a dash
            }
            col = col + 1;
        }
        printf("\n");
        row = row + 1;
    }

    return 0;
}
Alternative solution for decimal_spiral.c
// Draws a decimal spiral of size defined by the user. O(n^2)
// By Sabine Lim z5242579
// For COMP1511 Lab04

// The implementation consists of 2 parts:
// 1. Loop left to right, up to down, calling an isDigit function to
// know whether to print a digit or a dash for each coordinate
// 2. If a digit should be printed, call a getDigit function to
// calculate the digit to be printed

// The isDigit function is the same the code for the regular spiral, but
// instead of printing an asterisk it returns 1 to whatever code called it

// getDigit works by splitting the spiral into triangular quadrants
//
//   *******
// *  *****  *
// **  ***  **
// ***  *  ***
// **  ***  **
// *  *****  *
//   *******
//
// For the top quadrant, observe the following digits
//
// 6**************
// --------------*
// **0**********-*
// *-----------*-*
// *-**0******-*-*
// *-*-------*-*-*
// *-*-**6**-*-*-*
// *-*-*---*-*-*-*
// *-*-*-***-*-*-*
// *-*-*-----*-*-*
// *-*-*******-*-*
// *-*---------*-*
// *-***********-*
// *-------------*
// ***************
//
// The actual numbers at the location of these digits form a quadratic sequence
// 6  30  70  126
//  24  40  56
//    16  16
// Where the differences between the differences is 16.
// Using this, you can make a quadratic sequence for the top left corners
// of each box, and subtract the current column to find the digits for
// coordinates to the right
//
// You'll need to come up with a different quadratic equation for each quadrant
// Since there are 2 types of spiral (last digit in the centre, last digit
// off-centre, that's a total of 8 different quadratic equations
// Use the current column or current row accordingly to determine how much
// to add or subtract from the corner values

#include <stdio.h>

int abs(int i);
// Returns 0 if current coordinate is a dash, 1 for a digit
int isDigit(int size, int row, int col);
// Returns the integer at a specific coordinate on a box for a given size
int getDigit(int size, int row, int col);

int main() {
    int size = 0;
    printf("Enter size: ");
    scanf("%d", &size);
    int row = 0;
    while (row < size) {
        int col = 0;
        while (col < size) {
            if (isDigit(size, row, col) == 1) {
                if (row <= size / 2 && col < size / 2 && row == col + 1) {
                    // Special handling for box segments modified to be spirals
                    printf("%d", getDigit(size, row - 1, col - 1) % 10);
                } else {
                    printf("%d", getDigit(size, row, col) % 10);
                }
            } else {
                printf("-");
            }
            ++col;
        }
        printf("\n");
        ++row;
    }
    return 0;
}

int abs(int i) {
    if (i < 0) {
        i = -i;
    }
    return i;
}

int isDigit(int size, int row, int col) {
    // Absolute row distance from midpoint
    int rowDist = abs(row - size / 2);
    // Absolute column distance from midpoint
    int colDist = abs(col - size / 2);
    int isDigit = 0;
    if (size % 4 == 1) {
        // Type 1 spiral (digit in centre)
        if (row <= size / 2 && col < size / 2 && row == col + 1) {
            // Special handling to turn boxes into spirals
            if (rowDist % 2 == 0) {
                isDigit = 1;
            }
        } else if (colDist >= rowDist && colDist % 2 == 0) {
            isDigit = 1;
        } else if (colDist < rowDist && rowDist % 2 == 0) {
            isDigit = 1;
        }
    } else {
        // Type 2 spiral (no digit in centre)
        if (row <= size / 2 && col < size / 2 && row == col + 1) {
            // Special handling to turn boxes into spirals
            if (rowDist % 2 == 1) {
                isDigit = 1;
            }
        } else if (colDist >= rowDist && colDist % 2 == 1) {
            isDigit = 1;
        } else if (colDist < rowDist && rowDist % 2 == 1) {
            isDigit = 1;
        }
    }
    return isDigit;
}

int getDigit(int size, int row, int col) {
    // Row displacement from midpoint
    int rowDist = row - size / 2;
    // Absolute row distance from midpoint
    int absRowDist = abs(rowDist);
    // Column displacement from midpoint
    int colDist = col - size / 2;
    // Absolute column distance from midpoint
    int absColDist = abs(colDist);
    // Size of box current coordinate is on
    int subSize = 0;
    if (absRowDist >= absColDist) {
        subSize = 2 * absRowDist + 1;
    } else {
        subSize = 2 * absColDist + 1;
    }
    row = row - (size - subSize) / 2;
    col = col - (size - subSize) / 2;
    // Layer of current box. 0 is centre
    int layer = (subSize + 1) / 4;
    if (rowDist <= 0 && absRowDist >= absColDist) {
        // Top quadrant
        if (subSize % 4 == 1) {
            // Type 1 boxes
            return 8 * layer * layer + 8 * layer - col;
        } else {
            // Type 2 boxes
            return 8 * layer * layer - 2 - col;
        }
    } else if (colDist > 0 && absColDist > absRowDist) {
        // Right quadrant
        if (subSize % 4 == 1) {
            // Type 1 boxes
            return 8 * layer * layer + 4 * layer - row;
        } else {
            // Type 2 boxes
            return 8 * layer * layer - 4 * layer - row;
        }
    } else if (rowDist > 0 && absRowDist >= absColDist) {
        // Bottom quadrant
        if (subSize % 4 == 1) {
            // Type 1 boxes
            return 8 * layer * layer - 4 * layer + col;
        } else {
            // Type 2 boxes
            return 8 * layer * layer - 12 * layer + 4 + col;
        }
    } else {
        // Left quadrant
        if (subSize % 4 == 1) {
            // Type 1 boxes
            return 8 * layer * layer - 8 * layer + row;
        } else {
            // Type 2 boxes
            return 8 * layer * layer - 16 * layer + 6 + row;
        }
    }
}

Submission

When you are finished each exercises 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 3 Sunday 20:00 to submit your work.

You cannot obtain marks by e-mailing lab work 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 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)

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

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:

1511 classrun -sturec