COMP1511 17s1 Introduction to Programming

### Objectives

In this Lab, you will practice:
• using complex if statements to control program execution
• using a while loop for repetition
• input & output of numerical values
• implementing simple numerical calculations

### Preparation

Before the lab you should re-read the relevant lecture slides and their accompanying examples. You should also have read the lab assessment guidelines.

### Getting Started

One member of your programming pair should login and run the following commands inside a Linux terminal

Create a new directory for this lab called `lab04` by typing:

```mkdir lab04
```
Change to this directory by typing:
```cd lab04
```

### Exercise: Three or Five

Write a program that three_five.c that reads a positive integer n and print all the positive integers < n divisible by 3 or 5.

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
```
``` ~cs1511/bin/autotest lab04 three_five.c
```
Sample solution for `three_five.c`
```// Written 26/3/2015
// by Andrew Taylor (andrewt@cse.unsw.edu.au)
// as a lab example for COMP1911
// Suggested  by  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: 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 if indicates if 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
```

``` ~cs1511/bin/autotest lab04 perfect.c
```
Sample solution for `perfect.c`
```// Test if a number is perfect
// Written 26/3/2015
// by Andrew Taylor (andrewt@cse.unsw.edu.au)
// as a lab example for COMP1911

#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: X Factor

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.

You are not permitted to use an array in this exercise.

```./x
Enter size: 5
*---*
-*-*-
--*--
-*-*-
*---*
./x
Enter size: 9
*-------*
-*-----*-
--*---*--
---*-*---
----*----
---*-*---
--*---*--
-*-----*-
*-------*
./x
Enter size: 15
*-------------*
-*-----------*-
--*---------*--
---*-------*---
----*-----*----
-----*---*-----
------*-*------
-------*-------
------*-*------
-----*---*-----
----*-----*----
---*-------*---
--*---------*--
-*-----------*-
*-------------*
```
``` ~cs1511/bin/autotest lab04 x.c
```
Sample solution for `x.c`
```// Written 14/3/2017 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 row, column;

printf("Enter size: ");

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

```

### Exercise: Plus

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

You can assume n is odd and >= 5.

Make your program match the examples below exactly.

You are not permitted to use an array in this exercise.

```./plus
Enter size: 7
---*---
---*---
---*---
*******
---*---
---*---
---*---
./plus
Enter size: 13
------*------
------*------
------*------
------*------
------*------
------*------
*************
------*------
------*------
------*------
------*------
------*------
------*------
```
``` ~cs1511/bin/autotest lab04 plus.c
```
Sample solution for `plus.c`
```// Written 14/3/2017 by Andrew Taylor (andrewt@unsw.edu.au)
// as a lab example for COMP1511

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

#include <stdio.h>

int main(void) {
int row, column;

printf("Enter size: ");

// 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 == size/2 || column == size/2) {
printf("*");
} else {
printf("-");
}
column = column + 1;
}
printf("\n");
row = row + 1;
}

return 0;
}

```

### Exercise: Chessboard

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

You can assume n is odd and >= 5.

Make your program match the examples below exactly.

You are not permitted to use an array in this exercise.

```./chessboard
Enter size: 5
-*-*-
*-*-*
-*-*-
*-*-*
-*-*-
./chessboard
Enter size: 7
-*-*-*-
*-*-*-*
-*-*-*-
*-*-*-*
-*-*-*-
*-*-*-*
-*-*-*-
./chessboard
Enter size: 17
-*-*-*-*-*-*-*-*-
*-*-*-*-*-*-*-*-*
-*-*-*-*-*-*-*-*-
*-*-*-*-*-*-*-*-*
-*-*-*-*-*-*-*-*-
*-*-*-*-*-*-*-*-*
-*-*-*-*-*-*-*-*-
*-*-*-*-*-*-*-*-*
-*-*-*-*-*-*-*-*-
*-*-*-*-*-*-*-*-*
-*-*-*-*-*-*-*-*-
*-*-*-*-*-*-*-*-*
-*-*-*-*-*-*-*-*-
*-*-*-*-*-*-*-*-*
-*-*-*-*-*-*-*-*-
*-*-*-*-*-*-*-*-*
-*-*-*-*-*-*-*-*-
```
``` ~cs1511/bin/autotest lab04 chessboard.c
```
Sample solution for `chessboard.c`
```// Written 14/3/2017 by Andrew Taylor (andrewt@unsw.edu.au)
// as a lab example for COMP1511

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

#include <stdio.h>

int main(void) {
int row, column;

printf("Enter size: ");

// 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) % 2 == 1) {
printf("*");
} else {
printf("-");
}
column = column + 1;
}
printf("\n");
row = row + 1;
}

return 0;
}

```

### Exercise: It's Prime

Write a program called prime_factors.c that reads a integer n from standard input and prints the decomposition of n into prime factors. If n is prime it instead should print a message indicating this. You may assume n > 2. Make your program match the examples below exactly.
```./prime_factors
Enter number: 6
The prime factorization of 6 is:
2 * 3 = 6
./prime_factors
Enter number: 30
The prime factorization of 30 is:
2 * 3 * 5 = 30
./prime_factors
Enter number: 22501
22501 is prime
./prime_factors
Enter number: 2048
The prime factorization of 2048 is:
2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 = 2048
./prime_factors
Enter number: 22500
The prime factorization of 22500 is:
2 * 2 * 3 * 3 * 5 * 5 * 5 * 5 = 22500
./prime_factors
Enter number: 22501
22501 is prime
```
Hint: prime_factors.c requires a complex flow of control. Sketch out on paper the structure of your program. Your tutor may ask to see this.

Hint: prime_factors.c requires a declaring a number of variables and thinking carefully about how they will be used (choose good names). If you don't have the right variables, you'll get stuck writing the if and while statements.

Hint: prime_factors.c will require difficult debugging - think about where you can printf statements to see the value of variables and understand what your program is doing.

You are not permitted to use an array in this exercise.

``` ~cs1511/bin/autotest lab04 prime_factors.c
```
Sample solution for `prime_factors.c`
```// Find prime factors of a number
// Written 26/3/2015
// by Andrew Taylor (andrewt@cse.unsw.edu.au)
// as a lab example for COMP1911

#include <stdio.h>

int main(int argc, char *argv[]) {
int number, n, nFactors;
int i;

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

// To find all prime factors of a number, we simply go through all
// numbers from 2 to the original number and see if the
// original numbers is divisible by any of them.
// We also need to take into account that there may be
// multiple prime factors of the
// same value, e.g. 12 = 2*2*3, so we have to keep dividing a number
// by a factor until it is no longer divisible.

i = 2;
nFactors = 0;
n = number;
while (i < number) {
if (n % i == 0) {
if (nFactors == 0) {
printf("The prime factorization of %d is:\n", number);
} else {
printf(" * ");
}
printf("%d", i);
n = n / i;
nFactors = nFactors + 1;
} else {
i = i + 1;
}
}
if (nFactors == 0) {
printf("%d is prime\n", number);
} else {
printf(" = %d\n", number);
}
return 0;
}

```

### Challenge Exercise: 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.

You are only permitted to use C language features covered in weeks 1-3 lectures. In particular, you are not permitted to use array(s).

Make your program match the examples below exactly.

You are not permitted to use an array in this exercise.

```./spiral
Enter size: 5
*****
----*
***-*
*---*
*****
./spiral
Enter size: 7
*******
------*
*****-*
*---*-*
*-***-*
*-----*
*******
./spiral
Enter size: 9
*********
--------*
*******-*
*-----*-*
*-***-*-*
*-*---*-*
*-*****-*
*-------*
*********
./spiral
Enter size: 17
*****************
----------------*
***************-*
*-------------*-*
*-***********-*-*
*-*---------*-*-*
*-*-*******-*-*-*
*-*-*-----*-*-*-*
*-*-*-***-*-*-*-*
*-*-*-*---*-*-*-*
*-*-*-*****-*-*-*
*-*-*-------*-*-*
*-*-*********-*-*
*-*-----------*-*
*-*************-*
*---------------*
*****************
```
Try to invent your own solution - don't google or ask others how do it. Tutors want to see your original work even if it only partly works

``` ~cs1511/bin/autotest lab04 spiral.c
```
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 EXIT_FAILURE;
}

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

```
Another solution for `spiral.c`
```// Prints an ascii spiral given a size >= 5
// Written 19/3/2017
// by Evan Kohilas (z5114986@unsw.edu.au)

/*
* Example for size = 17
* row, section: ... : formula
*  0, 0: ***************** :"*-"x0 + "*"x17 + "-*"x0
*  1, 0: ----------------* :"*-"x0 + "-"x15 + "-*"x1
*  2, 1: ***************-* :"*-"x0 + "*"x15 + "-*"x1
*  3, 1: *-------------*-* :"*-"x1 + "-"x11 + "-*"x2
*  4, 2: *-***********-*-* :"*-"x1 + "*"x11 + "-*"x2
*  5, 2: *-*---------*-*-* :"*-"x2 + "-"x7  + "-*"x3
*  6, 3: *-*-*******-*-*-* :"*-"x2 + "*"x7  + "-*"x3
*  7, 3: *-*-*-----*-*-*-* :"*-"x3 + "-"x3  + "-*"x4
*  8, 4: *-*-*-***-*-*-*-* :"*-"x3 + "*"x3  + "-*"x4
*  9, 5: *-*-*-*---*-*-*-* :"*-"x4 + "-"x1  + "-*"x4
* 10, 5: *-*-*-*****-*-*-* :"*-"x3 + "*"x5  + "-*"x3
* 11, 6: *-*-*-------*-*-* :"*-"x3 + "-"x5  + "-*"x3
* 12, 6: *-*-*********-*-* :"*-"x2 + "*"x9  + "-*"x2
* 13, 7: *-*-----------*-* :"*-"x2 + "-"x9  + "-*"x2
* 14, 7: *-*************-* :"*-"x1 + "*"x13 + "-*"x1
* 15, 8: *---------------* :"*-"x1 + "-"x13 + "-*"x1
* 16, 8: ***************** :"*-"x0 + "*"x17 + "-*"x0
*/

#include <stdio.h>

int main(void){

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

int i = 0;

int offset;
if (size % 4 == 3){
// if down spiral
offset = 1;
} else if (size % 4 == 1){
// if up spiral
offset = 0;
} else {
printf("WARNING: INVALID SIZE\n");
offset = 0;
}

int mid = size/2 + offset;
int mid_section = size/4 + offset;
int max_section = size/2;

int row = 0;
while (row < size){

int section;
if (row < mid) {
section = row/2;
} else if (row == mid){
section = mid_section;
} else if (row > mid) {
section = (row + 1)/2;
} else {
printf("WARNING: UNKNOWN CASE\n");
section = 0;
}

if (row == 0){
// first row

i = 0;
while (i < size){
printf("*");
i += 1;
}

} else if (row == 1){
// second row

i = 0;
while (i < (size - 1)){
printf("-");
i += 1;
}
printf("*");

} else if ((section < mid_section) && (row % 2 == 0)) {
// even rows before middle

//left
i = 0;
while (i < (section - 1)) {
printf("*-");
i += 1;
}

//middle
i = 0;
while (i < ((size - 2) - ((section - 1) * 4))) {
printf("*");
i += 1;
}

//right
i = 0;
while (i < section) {
printf("-*");
i += 1;
}

} else if ((section < mid_section) && (row % 2 != 0)) {
// odd rows before middle

//left
i = 0;
while (i < section) {
printf("*-");
i += 1;
}

//middle
i = 0;
while (i < ((size - 2) - (section * 4))) {
printf("-");
i += 1;
}

//right
i = 0;
while (i < (section + 1)) {
printf("-*");
i += 1;
}

} else if (section == mid_section) {
// middle row

//left
i = 0;
while (i < (section - 1)) {
printf("*-");
i += 1;
}

//middle
printf("***");

//right
i = 0;
while (i < (section - offset)) {
printf("-*");
i += 1;
}

} else if ((section > mid_section) && (row % 2 != 0)) {
// even rows after middle

//left
i = 0;
while (i < (max_section - section + 1)) {
printf("*-");
i += 1;
}

//middle
i = 0;
while (i < ((section - mid_section - 1)*4 + 1 + offset*2)) {
printf("-");
i += 1;
}

//right
i = 0;
while (i < (max_section - section + 1)) {
printf("-*");
i += 1;
}

} else if ((section > mid_section) && (row % 2 == 0)) {
// odd rows after middle

//left
i = 0;
while (i < (max_section - section)) {
printf("*-");
i += 1;
}

//middle
i = 0;
while (i < ((section - mid_section)*4 + 1 + offset*2)) {
printf("*");
i += 1;
}

//right
i = 0;
while (i < (max_section - section)) {
printf("-*");
i += 1;
}

} else {
// unknown cases
printf(">>> WARNING: UNKNOWN ROW CASE <<<");
}

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

return 0;

}

```

### Challenge Exercise: Decimal Spiral

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.

You are only permitted to use C language features covered in weeks 1-3 lectures. In particular, you are not permitted to use array(s).

Make your program match the examples below exactly.

You are not permitted to use an array in this exercise.

```./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
```
Try to invent your own solution - don't google or ask others how do it. Tutors want to see your original work even if it only partly works - this is a really hard problem.

``` ~cs1511/bin/autotest lab04 decimal_spiral.c
```
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 EXIT_FAILURE;
}

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

```

### Submission/Assessment

When you are satisfied with your work, ask your tutor to assess it. You also need to submit your work electronically by typing (run this command in the `lab04` directory):
```give cs1511 lab04 three_five.c perfect.c x.c plus.c chessboard.c prime_factors.c spiral.c decimal_spiral.c
```
Submit the challenge exercises only if you attempt them.

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

Remember the lab assessment guidelines - if you don't finish the exercises you can finish them in your own time, submit them by Monday 11:00am using `give` and ask your tutor to assess them at the start of the following lab.

Either or both members of a programming pair can submit the work (make sure each program lists both of you as authors in the header comment).