APSC142 EngLinks Workshop Solutions

EngLinks APSC 142 Workshop
Part 1 (Solutions)
1
Variable Types, Declarations, and Expressions
Constants
Constants using a directive are defined like so:
#define VARIABLENAME 12345
Anytime VARIABLENAME is referred to, the program will substitute 12345.
Data Types
char: Stores characters as ASCII codes (‘a’, ‘b’, ‘c’, etc.)
int: Stores integers (1, 2345, -1235, etc.)
long: Stores larger integers (1234518348284, 18384872776463, -383847274742, etc.)
float: Stores floating point numbers (1.5, 4948.00, -382.583, etc.)
When mixing datatypes, such as assigning a float value (i.e. 43.23) to an integer variable, the
compiler will convert the value’s type to match the variable’s type. In this case, 43.23 would be
converted to an integer, and become 43, before it is assigned and stored.
You can also cast variables, like so:
int k = (int)43.23;
which will convert 43.23 to an integer before it is stored.
Declaring Variables
Variables can be declared like so:
int variable_name;
And then initialized like so:
variable_name = 12345;
Or, declared and initialized in the same line like so:
int variable_name = 12345;
Expressions
Using operators and operands, we can combine values and assign them to a variable. These
expressions can include variables and numerical values, as well as any of the following: +,-,*,/,%, (,
). Expressions follow the BEDMAS (brackets, exponents, divide, multiply, add, subtract) order of
operations. For example, the following code would assign k the value of 25.
int i = 100;
int k = (i + 100) / 8;
We can also use assignment operators such as +=, -=, *=, or /=. The expression k = 100 * k; is the
same as k *= k;. Additionally, we can simply use ++, -- after a variable like so:
2
k++;
to increment a variable by one. Using the -- decrements the variable by one.
Screen output
Text can be displayed on the EV3 robot’s screen like so:
displayTextLine(4, “Distance away is: %d”, distance);
where the first argument is the line you wish to display the output on, the second argument is the
display string, and the third argument is a variable you wanted to display. The %d is a format
specifier, which basically specifies that it wants to display distance as an integer. Other format
specifiers include %f, %c, and %e, among others.
Question 1:
In the box below, show the screen output that would be produced by this program (i.e. account for
integer arithmetic and any rounding truncation):
task main()
{
int k;
float x;
x = 13.7;
k = x;
displayTextLine(0, “%d, %0.1f”, k, x);
k = k/3;
x = k*3;
displayTextLine(1, “%d, %0.1f”, k, x);
}
Answer 1:
13, 13.7
4, 12.0
Question 2:
In the box below, show the screen output that would be produced by this program (i.e., account for
integer arithmetic and any rounding truncation):
task main()
{
int i = 5, j = 2, k;
float x = 6.3, y;
displayTextLine(0, “%d, %0.3f”, i, x);
k = i/j;
y = (float)i/(float)j;
displayTexxtLine(1, “%d, %0.3f”, k, y);
}
3
Answer 2:
5, 6.300
2, 2.500
Question 3:
In the box below, show the screen output that would be produced by the following program.
task main()
{
int i, j, temp;
i = 1;
j = 2;
displayTextLine(0, "i=%d, j=%d", i, j);
temp = i;
i = j;
j = temp;
displayTextLine(1, "i=%d, j=%d", i, j);
}
Answer 3:
i=1, j=2
i=2, j=1
4
Conditionals
Condition statements are either true or false, and can be used like so:
if (distance > 25)
{
//do stuff
}
In the above example, the program will only execute whatever is between the brackets, on the
condition that the distance variable is greater than 25. “>” is a relational operator, relating the
variable to the number. Other relational operators include: ==, <=, >=, !=, <. You can use other
conditions as well, like so:
if(distance > 25)
{
//do stuff
}
else if(distance < 10)
{
//do other stuff
}
else
{
//do other other stuff
}
In the above example, it will check the first condition, and if that doesn’t hold, it will check the
second example. If neither holds, it will automatically execute whatever is in the “else” block. You
can also use logical operators such as || (or), or && (and) to check for more conditions like so:
if(distance > 25 && distance < 100)
{
//do stuff
}
Switch-case statements can also be used, which look like this:
switch(counter)
{
case 0:
//do stuff
break;
case 1:
//do other stuff
break;
}
In the above example, counter is a variable that the switch-case statement will check. Based on the
value of counter, different parts of the code will execute. In this case, if counter is 0, the block
directly below case 0 will execute. If counter is 1, the block directly below case 1 will execute. Keep
in mind that the break; command is important and must be placed at the end of each “case” block.
5
Loops
There are three types of loops in C: while, do/while, and for.
While loops
A while loop is used like so:
while(condition)
{
//do stuff
}
A while loop will check the condition, and execute the block of code within the brackets if the
condition is true. The loop will continue checking and executing the code until the condition is false,
in which case the loop ends.
Do-while loops
A do/while loop is used like so:
do
{
//do stuff
} while(condition)
In the case of a do-while loop, the block of code between the brackets will be executed first, before
the condition is checked. Note that this is different from a while loop, in that a while loop checks the
condition first, before executing the code.
For loops
A for loop is used like so:
for(int k = 0; k < 100; k++)
{
//do stuff
}
where the first expression initializes a variable that will be used like a counter, the second
expression specifies the termination condition, and the last expression specifies how the variable is
modified after each loop. Note that in the example above, the variable is declared and initialized
within the loop. It can also be declared outside the loop like so:
int k;
for(k = 0; k < 100; k++)
{
//do stuff
}
6
Question 4:
In the box below, show the screen output that would be produced by this program:
task main()
{
int nums[5] = {1,7,5,9,6};
int j;
int highsum = 0;
int lowsum = 0;
for(j=0; j<5; j++)
{
if(nums[j]<=5)
lowsum += nums[j];
else
highsum += nums[j];
}
displayTextLine(0, "low sum = %d", lowsum);
displayTextLine(1, "high sum = %d", highsum);
}
Answer 4:
low sum = 6
high sum = 22
Question 5:
Write a program that calculates values of the polynomial y = 3x3 – 5x2 + 100x – 17 at x = 0, x=0.2,
x=0.4, … , x=4.0 (that is, for values of x separated by 0.2 between a start value of 0 and an end value
of 4.0). The y-values that are between -17 and +60, inclusive, are considered mid-range; the values
that are greater than 60 are considered high and the values that are lower than -17 are considered
low. Your program should determine and then display how many of the x-values in [0,4] evaluate to
high y-values, how many evaluate to mid-range y-values and how many evaluate to low y-values.
7
Answer 5:
task main()
{
int low = 0, mid = 0, high = 0;
float y;
float x = 0;
for(x = 0; x <= 4; x += 0.2)
{
y = (3*x*x*x) - (5*x*x) + (100*x) - 17;
if(y >= -16 && y <= 60)
mid++;
else if(y > 60)
high++;
else
low++;
}
displayTextLine(0, "high values: %d", high);
displayTextLine(1, "mid values: %d", mid);
displayTextLine(2, "low values: %d", low);
}
Question 6:
Write a program that calculates values of the polynomial y = 9x3 – 2x2 + 44x – 15 at x = 0, x = 0.4, x =
0.8, … , x = 4.0 (that is, for values of x separated by 0.4 between a start value of 0 and an end value of
4.0). The y-values that are between -5 and +20, inclusive, are considered typical and the values that
are greater than 60 or less than -20 are considered extreme. Your program should determine and
then display how many of the x-values in [0,4] evaluate to typically –values and how many evaluate
to extreme y-values.
Answer 6:
task main()
{
int y, x;
int typ = 0; ext = 0;
for(x = 0; x <= 4; x += 0.4)
{
y = (9*x*x*x) - (2*x*x) + 44*x) - 15;
if(y >= -5 && y <= 20)
typ++;
else if(y,-20||y>60);
ext++;
}
displayTextLine(0, "Typical = %d", typ);
displayTextLine(1, "Extreme = %d", ext);
}
8
Arrays
1-D Arrays
Arrays are used to store multiple objects of the same type, and can be thought of as a list. By using
an array, you can store related values in one variable without having to declare a new variable for
each object. For example:
float marks[5];
declares an array of 5 variables of type int, that are all contained under the variable “marks”. To
access an object stored in an array, use the variable name and its index like so:
marks[3];
The above line would access the 4th element in the array. This is because arrays are zero-indexed,
meaning the first element in the array is stored at index 0. You can also initialize an array like so:
float marks[5] = {80.32, 63.71, 84.1, 77.0, 86.4};
which would store the objects like this:
marks[0]
marks[1]
marks[2]
marks[3]
marks[4]
80.32
63.71
84.1
77.0
86.4
You can fill an array using a loop like so:
int values[5];
for(int i = 0; i < 5; i++)
{
marks[i] = i*5;
}
which is usually good if you want to fill an array with numbers with a regular pattern. You can also
access elements with a loop like so:
int values[5] = {123, 48, 2, 88, 9};
for(int i = 0; i < 5; i++)
{
displayTextLine(i, "The value is: %d", values[i]);
}
2-D Arrays
2-D arrays are very similar to 1-D arrays, except it can be thought of as more like a matrix or a table,
than a list. 2-D arrays can be declared like so:
int values[3][3];
and initialized like so:
int values[3][3] = {{1, 4, 6}, {5, 7, 9}, {2, 8, 0}};
9
which would store the objects like this:
values[x][0]
values[x][1]
values[x][2]
values[0][x]
1
4
6
values[1][x]
5
7
9
values[2][x]
2
8
0
You can fill an array using a loop like so:
int values[3][3];
for(int i = 0; i < 3; i++)
{
for(int j = 0; j < 3; j++)
{
values[i][j] = i*j;
}
}
which again, is usually good if you want to fill an array with numbers with a regular pattern. You
can also access elements with a loop like so:
int values[3][3];
int sum = 0;
int i, j;
for(i = 0; i < 3; i++)
{
for(j = 0; j < 3; j++)
{
sum += values[i][j];
}
}
10
Question 7:
In the box below, show the screen output that would be produced by this program:
task main()
{
int matrix[4][4] = {{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 16}};
int i, j, line = 0;
for(i = 1; i < 4; i = i + 2)
{
for(j = 0; j < 4; j = j + 2);
{
displayTextLine(line, "%d", matrix[i][j]);
line++;
}
}
}
Answer 7:
5
7
13
15
Question 8:
In the box below, show the screen output tha would be produced by the following program.
task main()
{
int i;
int arr[6];
}
for(i = 0; i < 6; i++)
{
arr[i] = i+i;
}
for(i=0; i < 6; i+=3)
{
displayTextLine(i, "array[%d] = %d", i, arr[i+1]);
}
11
Answer 8:
array[0] = 2
array[3] = 8
Functions
A function is a subprogram with its own declarations and statements, that is typically meant to
perform a specific task. The advantage of using functions is that they can be used multiple times in
the same program, and can be quite versatile if written properly. For example, you could write a
drive function for the EV3 robots, that accepts speed and duration arguments, allowing you to call
the drive function multiple times to drive for different durations at different speeds. Functions can
accept many parameters, but can only return at most one value. A function can be declared like so:
int add_numbers(int num1, int num2);
In this example, the function returns an integer, is named “add_numbers”, and takes two integers as
parameters. A function’s parameters can be declared with both variable types and names, or just
variable types. The above line is sometimes called a function prototype, and would be placed at the
top of your program, before task main(). This is because the C compiler reads through the program
line by line, top to bottom, and if you call a function in your task main() but haven’t declared it yet,
the compiler won’t know what you’re talking about and return an error. To actually write a
function, you would leave the function prototype at the beginning of your program, and then define
it after the task main() like so:
int add_numbers(int num1, int num2)
{
int sum;
sum = num1 + num2;
return sum;
}
Note that there is a semicolon after the function prototype, but no semicolon in your function
declaration. In the above example, the add_numbers function takes two integers as parameters,
adds them together, and then returns the result. Note the“return sums;” line, which specifies that
the function will return the value of sum, back to wherever the function was called. At least one
return line is necessary in any function that has been declared to return a value. Multiple return
lines can be placed in different loops or conditions, allowing the function to return a different result
based on different circumstances. Once the program reaches a return line, it automatically ends the
function and goes back to wherever the function was called. Parameters can be of any type, and you
can return any type you choose. You can even choose not to return anything at all, in which case you
would return type “void” like so:
void drive(int speed, int duration);
Note that in a void function, there is no return line.
To call a function, you would do it like so:
12
task main()
{
int x = 3;
int y = 5;
int z;
}
z = add_numbers(x, y);
Using the add_numbers function from above, this function call would call add_numbers, passing x as
num1 and y as num2. Sum would then be returned and stored in z. Note that x and y are not altered
by the function. You can also pass by reference. If we alter our add_numbers function like so:
void add_numbers(int num1, int num2, int &sum)
{
int sum;
sum = num1 + num2;
}
And call it like so:
task main()
{
int x = 3;
int y = 5;
int z;
add_numbers(x, y, &z);
}
x and y will not be altered, but z will. This is because adding the ampersand in front of the variable
passes the address of the variable, instead of the value stored in the variable. When we pass z by
reference to add_numbers, sum has the same address as z. As a result, when we execute the line
sum = num1 + num2, the result is stored in both sum, as well as z.
Variable Scope
The scope of a variable defines where the variable is accessible. A variable declared within a
function, called a local variable, is only accessible within that function. Conversely, a variable
declared outside any function is called a global variable, and can be accessed anywhere. For
example, when you declare a variable “x” within a function definition, your task main() will not
recognize it if you try to access it. In fact, if you were to declare a variable “x” within your task
main(), it would be separate from the one within the function – “x” could represent two different
values within your program, depending on the scope that you are accessing it in.
Question 9:
In the box below, write a function that returns the minimum value of two passed-in integer
variables. The function prototype is given below:
int findmin(int val1, int val2);
13
Answer 9:
int findmin(int val1, int val2)
{
int min = val1;
if(val2 < val1)
{
min = val2;
}
return min;
}
Question 10:
In the box below, show the screen output that would be produced by this program:
void testPassByRef(int, int &);
task main()
{
int i=5, j=2;
displayTextLine(0, "%d, %d", i, j);
testPassByRef(i,j);
displayTextLine(2, "%d, %d", i, j);
}
void teestPassByRef(int x, int &y)
{
x++;
y++;
displayTextLine(1, "%d, %d", x, y);
}
Answer 10:
5, 2
6, 3
5, 3
14
Functions and Arrays
In standard C, you can pass a 1-D array to a function like so:
int function(int var1[]);
However, in RobotC you must create an array type that corresponds to the type and size of array
you want to pass, using the keyword typedef, like so:
typedef int 1DArray[50];
In this example, it would define an array type for an array with 50 integers. To use this array type,
you would declare a function like so:
int function(1DArray var1);
Notice that in standard C, an array size does not need to be specified, but in RobotC, your type
definition must specify a size.
In standard C, you can pass a 2-D array to a function like so:
int function(int var1[][5]);
In RobotC, again, you must again create an array type that corresponds to the type and size of array
you want to pass, using the keyword typedef, like so:
typedef int 2DArray[5][5];
and use it like so:
int function(2DArray var1);
Note that in standard C, you can leave the first dimension blank, but you must specify a size for the
second dimension. In RobotC, you must specify a size for both dimensions. Keep in mind that arrays
(both 1D and 2D) are automatically passed by reference. Functions also cannot return arrays.
Question 11:
Professors for a new course will be using the following marking scheme:
If a student gets 50%
or more on final exam
If student gets less
than 50% on final
exam
Final exam
50
65
Project
35
20
Quiz
15
15
Final exam marks were recorded out of 100, project marks out of 30 and quiz marks out of 4. Write
a function getMarks() that will calculate the final mark of each student. The function has the
following parameters: one-dimensional arrays exam, project, quiz, which store the marks for each
of the N students, and one-dimensional array finalMark which will store the calculated percentage
marks for each of the N students, where N is no more than 10,000. You may assume that N is a
symbolic constant that has been defined at the top of the program and that a type definition
15
typedef float Grades1D[10000];
has been given at the top of the program. Your function will also return the number of students
whose final mark is less than 50%.
Assume that in the main function, the list of grades for exams, projects, and quizzes have been
stored in arrays studentExam[N], studentProj[N], studentQuiz[N], and that you will store the
final marks in array studentMark[N].
Fill the boxes provided to:
A. Show a function call from main() to the getMarks() function. Store the return value of
getMarks() into a variable of type int local to main() called numFailures.
B. Show the function definition (body) of the getMarks() function, including the function
header.
Answer 11:
A:
numFailures = getMarks(studentExam, studentProj, studentQuiz, studentMark);
B:
int getMarks(Grades1D exam, Grades1D project, Grades1D quiz, Grades1D finalMark)
{
int failed = 0;
int i;
for(i = 0; i < N; i++)
{
if(exam[i] < 50)
{
finalMark[i] = exam[i]*0.65 + project[i]*0.2 + quiz[i]*0.15;
failed++;
}
else
{
finalMark[i] = exam[i]*0.5 * project[i]*0.35 + quiz[i]*0.15;
}
return failed;
}
}
16
Question 12:
You are part of a landmine clearing agency whose job is to remove mines from previous civil wars
to make the area safe for civilians. You have a map of the area which is represented as a 2-D array.
Each element of the array gives the number of mines in that area for the map. For example, the
value 5 at row 4, column 6 means that there are 5 mines in that area that have to be removed.
However, a map has been discovered that is also a map of the same minefield. It is suspected that
one area has a different number of mines. Your job is to write a program that will compare both
maps and find the difference between the maps (if there is a difference).
The map array types are declared using the typedef statement
typedef int Int2D[255][255];
Your main program will call the following function:
int findMapDifference(Int2d map1, Int2d map2, int &row, int &col)
If there is an element of one array that differs from the corresponding element of the other array
(that is, if the maps are different), then the function returns the value true (that is, 1), and the row
and column of the different element are passed back through the parameters &row and &col. If the
elements are the same(i.e., the mapsa re the same), then the function returns the value false (i.e., 0),
and the row and column parameters are not changed.
NOTE: There will be at most one element in the two arrays that are different (that is, there is only
one area that is different between the two maps).
Complete the main() program and findMapDifference() function on the following page. the
main() program must call the function and then report the result by printing to the screen the
(row, column) position of the difference if found, otherwise it should report “NO DIFFFERENCE”.
17
Answer 12:
A:
#define ROWS 255
#define COLS 255
typedef int Int2D[255][255];
int findMapDifference(int2D map1, Int2D map2, int &row, int &col);
task main()
{
int ourMap[255][255];
int foundMap[255][255];
int result, row, col;
//Assume the map arrays are filled from a file here
fill(ourMap, "map1.txt");
fill(foundMap, "map2.txt");
//Call the funciton and report the results
result = findMapDifference(ourMap, foundMap, &row, &col);
}
if(result == 1)
{
displayTextLine(0, "Row: %d, Column: %d", row, col);
}
else
{
displayTextLine(0, "NO DIFFERENCE");
}
B:
int findMapDifference(int2D map1, Int2D map2, int &row, int &col)
{
int i, j;
for(i = 0; i < rows; i++)
{
for(j = 0; j < cols; j++)
{
if(map1[i][j] != map2[i][j])
{
row = i;
col = j;
return 1;
}
}
}
18
return 0;
}
Question 13:
Professor Smarts takes liquid level measurements of a chemical process. She takes each
measurement twice and then performs some analysis on her readings. Help Professor Smarts by
writing a function getLevels that has the following parameters:




Two arrays of floats, list1 and list2, that store the two lists of measurements
An array of floats low that will hold the lower of the two measurements from list1 and list2
an integer n that indicates the size of the arrays
An integer low1 that is passed by reference (described below)
The function getLevels should work as follows:



Compare each element of list1 to the corresponding element of list2 and put the lower
value in the array lows in the same index).
Count how many times a lower value comes from list1 and store that in low1.
Count the number of times that the value at a given index of list1 was within 0.01 of the
value of the element at the same index of list2. The function should return this value.
Assume that this type definition has been given at the top of the program
typedef float Float1D[100];
Assume that in the task main, the list of measurements are stored in arrays levels1[100] and
levels2[100], the list of low values will be stored in array lowVals[100], and the number of times a
low value comes from levels1 will be stored in a variable called numLow1.
Fill out the boxes provided to:
A. Show a function call from main() to the getLevel function. Store the returned value of
getlevels into a variable of type int local to main() called numClose.
B. Write the getLevels function
Answer 13:
A:
int numClose = getLevels(levels1, levels2, lowVals, n, low1)
19
B:
int getLevels(Float1D list1, Float1D list2, Float1D lowVals, int n, int &low1)
{
low1 = 0;
int close = 0;
for(int i = 0; i < n; i++)
{
lowVals[i] = list1[i];
if(list2[i] < list1[i])
{
lowVals[i] = list2[i];
}
if(lowVals[i] == list1[i])
{
low1++;
}
if(abs(list1[i] - list2[i]) < 0.01)
{
close++;
}
}
}
return close;
20
EngLinks APSC 142 Workshop
Part 2 (Solutions)
21
Sorting and Searching
Although there are many different sorting algorithms in APSC142 we focus on the sequential sort,
and the bubble sort.
Selection Sort
The selection sort finds the smallest element in the array, and swaps it with the first element, so
that it will be in the correct location. It then sorts the rest of the array starting at the second
element, swapping that with the next smallest element, and so on. Here is one way to implement a
selection sort:
void selectionSort(Array1D nums, int size)
{
int i, j, m_index;
//outer loop performs N-1 passes
for (i = 0; i < size - 1; i++)
{
// inner loop: scan the unsorted part to find min
m_index = i;
for (j = i + 1; j < size; j++)
{
if (nums[j] < nums[m_index])
m_index = j;
}
if (i != m_index)
swap(i, m_index, nums);
}
}
In this example, a swap function would also need to be written. This swap function would simply
take the elements in the array at the two indices passed to it, and swap them.
22
Bubble Sort
A bubble sort starts at the bottom, and swaps adjacent array elements to place the smaller one,
farther up top, and then continues up the array. This repeats from the bottom in subsequent passes
until no more swaps are needed. Here is one way to implement a bubble sort:
void bubbleSort(Array1D nums, int size)
{
// outer loop to perform N-1 passes
for (i=0; i < size-1; i++)
{
// keep track of whether a swap occurred
swapped = 0;
/* inner loop to go from bottom to top while
swapping elements */
for (j=size-1; j > i; j--)
{
if (nums[j] < nums[j-1])
{
swap(j, j-1, nums);
swapped = 1;
}
}
if (swapped == 0)
break;
}
}
Linear Search
A linear search searches through an array, in order, until either you find the value you were looking
for, or you reach the end of the array. Here is one way to implement a search function:
int linSearch(int target, 1DIntArray nums, int N)
{
for(int i = 0; i < N; i++)
{
if(nums[i] == target)
{
return nums[i];
}
}
return -1;
}
Binary Search
If an array is sorted, a binary search can be used, and is much faster. A binary search checks the
middle element of an array first, and compares it to the value we are searching for. If the middle
element is larger than the value we are searching for, it will search the lower half of the array.
23
Otherwise, it will search the upper half. This repeats until either the element is found, or we are
sure the element is not in the array. Here is one way to implement a binary search:
int binarySearch(int target, 1DIntArray nums, int size)
{
int first = 0, last = size-1, mid;
while (first <= last )
{
mid = (first + last) / 2;
if (target == nums[mid])
return mid;
else if ( target < nums[mid])
last = mid - 1;
else
first = mid + 1;
}
return -1;
}
Question 14:
The 2-D array stdMarks contains the information of 200 students in a first year course. The first
column of the array has the student number, the second column the student mark in the midterm
and the third column contains the student mark in the final exam. Write a program that uses a
Bubble Sort to sort the rows of the array in descending order according to the student tmark in the
final. A small example of the array contents before and after sorting is shown below:
Display the contents of the first row after sorting. Write your full program in task main(0 without
using any functions.
Hint: perform the sort (as in the 1D array case) by looping through the elements of the 3rd column
of the array stdMarks, and if the swap condition is satisfied, then use a for loop to swap all the
elements of the current row with the previous row.
24
Answer 14:
#define ROWS 200
#define COLS 3
task main()
{
int stdMarks[ROWS][COLS] = {{200, 33, 55}, {201, 26, 28},
{202, 24, 32}, {203, 30, 58},
...array definition completed};
int length = 200;
int temp;
for(int i = 0; i < length; i++)
{
for(int j = length-1; j > i; j--)
{
if(stdMarks[j][2] < stdMarks[j-1][2];
{
for(int k = 0; k < 3; k++)
{
temp = stdMarks[j][k];
stdMarks[j][k] = stdMarks[j-1][k];
stdMarks[j-1][k] = temp;
}
}
}
}
}
displayTextLine(0, "Student Number: %d", stdMarks[0][0]);
displayTextLine(1, "Midterm: %d", stdMarks[0][1]);
displayTextLine(2, "Final %d", stdMarks[0][2]);
Question 15:
Daily maximum temperatures in degrees centigrade for February 2014 in Kingston were recorded,
as follows:
1.9, 1.4, -4.1, -5.8, -7.2, -7, -8.3, -7, -8, -7.2, -12.6, -8.4, -4.3, -0.1, -18, -9.2, -11.1, -1.6, -3.7, 2.1, 4.8, 3.8,
0.7, -6.2, -7.4, -8.4, -8.2, -12.6
The values are in order by date from Feb. 1 to Feb. 28.
The temperatures are entered in a one-dimensional array, max_temps, in a C program. Complete
the program to do the following:
A. Calculate the average temperature, avg, in task main, where avg is obtained by summing
over all temperature values (Ti, i=0,…,N-1) and dividing by the total number of values (N):
25
𝑁−1
1
𝑎𝑣𝑔 = ∑ 𝑇𝑖
𝑁
𝑖=0
B. Display the average value on the LCD screen
C. Find the median temperature value: The median value of an array, is the value in the middle
of the sorted array; for example the meian of {3, 5, 6, 9, 12} is 6 and the median of {1.2, 1.8,
3.6, 4.2, 4.9, 6.4} is the average of the two values in the middle: (3.6+4.2)/2 = 3.9. To find the
median value of max_temps:
 copy the array max_temps into a second array sorted_temmps; pass
sorted_temps to the function sortArray to sort the temperature values from
minimum to maximum (use selection sort or bubble sort)
 In task main, find the median value from the sorted array; include code to find the
median if the number of values, N, in the array is odd or even, where:
i. if N is odd, find the middle index of the array and get he value at that
position
ii. If N is even, find the two middle indices and average the values in those
positions
D. Display the median temperature on the LCD screen
Complete the skeleton code given on the following two pages.
26
Answer 15:
#define N 28
typedef float Float1D[31];
//add function prototypes
void sortArray(Float1D temps);
void swap(int ind_1, int ind_2, Float1D list);
task main()
{
//variable declarations - declare any other variables used in the program
float max_temps[] = {1.9, 1.4, -4.1, -5.8, -7.2, -7, -8.3, -7,
-8, -7.2, -12.6, -8.4, -4.3, -0.1, -18,
-9.2, -11.1,-1.6, -3.7, 2.1, 4.8, 3.8,
0.7, -6.2, -7.4, -8.4, -8.2, -12.6}
float sorted_temps[N];
float total = 0;
float average;
float median;
int i, j, middle_element;
//calculate and display the average temperature
for(i = 0; i < N; i++)
{
total += max_temps[i];
}
average = total/N;
displayTextLine(0, "Average: %0.2f", average);
//copy the values in max_temps into sorted_temps and call sortArray
for(j = 0; j < N; j++)
{
sorted_temps[j] = max_temps[j];
}
sortArray(sorted_temps);
// find the median value if N is even or odd and display the median value on the LCD
screen
if(N%2 == 0)
{
median = (sorted_temps[N/2] + sorted_temps[(N/2)-1])/2;
}
else
}
middle_element = N/2 ;
median = sorted_temps[middle_element];
}
displayTextLine(1, "Median: %0.2f", median);
27
}
/*complete the function sortArray and swap to do a selection or
bubble sort*/
void sortArray(Float1D temps)
{
//declare two loop counters, (i,j) and variable to hold index of min value
int i, j, minIndex;
//sort array from min to max
for(i = 0; i < N-1; i++)
{
minIndex = i;
for(j = i+1; j < N; j++)
{
if(temps[j] < temps[minIndex])
{
minIndex = j;
}
}
//call swap if minIndex!=i (outer loop counter)
if(minIndex != i)
{
swap(i, minIndex, temps);
}
}
}
void swap(int ind_1, int ind_2, Float1D list)
{
int temp = list[ind_1];
list[ind_1] = list[ind_2];
list[ind_2] = temp;
}
28
Numerical Methods
Monte Carlo Integration
Monte Carlo integration is a method of approximating a definite integral. You specify an upper
bound on a function y given an interval of x, and create a rectangle within the interval of x from the
x-axis to the upper bound on y. You then generate a certain number of random x and y values
within this rectangle, and keep track of the number of times the (x,y) point is under the curve of the
function y. To approximate the definite integral, you simply multiply the area of the rectangle with
the ratio of (x,y) points below the curve, and the total number of (x,y) points generated. Here is one
way to implement this numerical method:
int N = 1000;
int hits = 0;
int x_lower = 2;
int x_upper = 6;
int y_upper = 4;
int area_rectangle = (x_upper - x_lower)*(y_upper);
for(int i = 0; i < N; i++)
{
int x = rand() % ((x_upper-x_lower+1) + x_lower);
int y = rand() % (y_upper+1);
if(y < (-x*x))
{
hits++;
}
}
integral = are_rectangle * (hits / N);
Keep in mind that this particular implementation will only work for a curve that is purely positive.
Numerical Precision
Although we count in base 10 (digits from 0 – 9), computers us base 2 (digits from 0-1). This can
lead to problems when converting between decimal (base 10), and binary (base 2). For example,
when we convert 27.25 to binary, we get 11011.01, and there is no error. However, if we want to
represent 27.24 in binary using only 4 bits after the decimal, we get 11011.0011. When you convert
that back to decimal, we get 27.1875, leading to an error of 0.0525. This error (called quantization
error) can be reduced by using more bits, but there is always a limit to the number of bits we can
use to represent numbers, and as a result, there will typically be some error when doing
calculations with a computer. Other sources of error include round-off error, overflow/underflow,
and truncation error.
Gaussian Elimination
As we learned in APSC174, we can use Gaussian elimination to solve systems of linear equations.
The method involves putting the system of linear equations into an augmented matrix, putting it
29
into row echelon form, and then back-substituting to solve for your unknowns. Here is a way to
implement Gaussian elimination for a system of three equations and three unknowns:
typedef float 2DFloatArray[3][4];
task main()
{
int i, n=3;
float eqns[3][4] = {{10, -8, 0, 40},
{-8, 20, -6, 0},
{0, -6, 10, -20}};
}
forwardElimination(eqns, n);
backSubstitution(eqns, n);
void forwardElimination(2DFloatArray eqns, int n)
{
float ratio;
}
for(int i = 0; i < n; i++)
{
for(int j = i+1; j M n; j++)
{
ratio = a[j][i]/a[i][i];
for(k = i; k < n; k++)
{
a[j][k] -= ratio * a[i][k];
}
}
}
void backSubstitution(2DFloatArray eqns, int n)
{
for(int i = n-1; i >= 0; i--)
{
a[i][n] = a[i][n]/a[i][i];
a[i][i] = 1;
for(j = i-1; j >= 0; j--)
{
a[j][n] -= a[j][i] * a[i][n];
a[j][i] = 0;
}
}
}
30
Question 16:
Write a program that calculates the Riemann integration of the function 3x2 – 5 from x = 0 to x = 10:



Compute the integration as the summation of the rectangles with width 0.5 and height f(xn),
where xn is the midpoint of the corresponding rectangle.
Display the result on line 4 using 3 decimal points
Hint: the grid points are x=0.25, x=0.75, x=1.25, … , x=9.75.
Answer 16:
task main()
{
float x, sum = 0;
for(x = 0.25, x < 10, x += 0.5)
sum = sum + ((3*x*x) - 5) * 0.5;
displayTextLine(3, "%0.3f", sum);
}
Question 17:
We have a function f(x) and we want to approximate it using an nth-order polynomial:
𝑓(𝑥) = 𝑓0 + 𝑓1 𝑥 + 𝑓2 𝑥 2 + ⋯ + 𝑓𝑛 𝑥 𝑛
One such approximation is given by the Taylor series expansion:
𝑁
𝑓 (𝑘) (𝑥) 𝑘
𝑓(𝑥) ≈ ∑
𝑥
𝑘!
𝑘=0
where



f(k)(x) is the kth derivative of the function f(x)
k! = k*(k-1)*(k-2)*….*3*2*2
For example: 0!=1
1!=1 2!=2*1=2
3!=3*2*1
4!=4*3*2*1
The Taylor series expansion of the cos(x) function is given by:
𝑁
cos(𝑥) ≈ ∑
𝑘=0
(−1)𝑁 2𝑁
−1𝑘 2𝑘
𝑥2 𝑥4
𝑥 = 1 − + − ⋯+
𝑥
(2𝑁)!
2𝑘!
2! 4!
Problem: RobotC has an internal function called cos(x) to compute the cosine function.



Write a program that will compute the value of cos(x) for x=5 using the series provided
above.
Your program will stop when your approximation is within 0.001 of the real value provided
by the internal function.
Also, display the value of k at which this condition is satisfied.
31
Answer 17:
task main()
{
int k = 1;
float sum = 1;
float x = 5;
int sign = -1;
float exp = 1;
float fact = 1;
while(abs(sum - cos(x)) > 0.001)
{
fact = 1;
exp = x*x*exp;
for(int i = 1; i <= k*2; i++)
{
fact = fact*i;
}
sum = sum + exp/fact*sign;
sign = -sign;
k += 1;
}
}
displayTextLine(2, "%d", k-1);
Question 18:
The acceleration of a small rocket was measured using an accelerometer. It was found that the
acceleration could be modeled using the equation: 𝑎(𝑡) = √𝑡 + 0.05𝑡. When the rocket reached a
maximum acceleration of 15m/s2 the acceleration dropped to zero, The acceleration profile is
shown below:
32
Complete the code on the following pages to:
A. Find the time in seconds at which the rocket reaches maximum acceleration
B. Determine the velocity of the rocket at 10 second intervals from t=0s to t=120s, (i.e.,
velocity at 10s, 20s, …, 120s) and store the values in an array rocketVelocity[n], where n is
the number of values to be stored. To find the velocities calculate the definite integral of the
acceleration function; use Riemann sum integration with a step size of 1 second. (Note: after
the acceleration drops to zero, the rocket is ravelling at constant velocity.)
Answer 18:
task main()
{
float accel, time, maxAccelTime;
float rocketVelocity[12];
time = 0; //Set initial time to zero
accel = 0; //Initialize acceleration value
//declare any other variables used in your program
int i;
float area;
// find maxAccelTime = time at which acceleration equals 15 m/s*s
maxAccelTime = (-(-2.5) - sqrt(2.5*2.5 - 4*225/400))/(2/400);
//display maxAccelTime on LCD screen
displayTextLine(0, "Max Accel Time: %0.2f", maxAccelTime);
//integrate accel function using Reimann sum to get velocity up to t=120s
//store velocity value at each 10 second interval in rocketVelocity[i]
area = 0;
i = 0;
for(i = 1; i <= 12; i++)
{
area += (sqrt(i*10) + 0.05*i*10)*10;
rocketVelocity[i-1] = area;
}
//display value of final velocity on LCD screen
displayTextLine(1, "Final velocity: %0.2f", rocketVelocity[11]);
33
EV3 Robots
The following C and RobotC functions should be provided with the exam:
motor[]
sgn(float x)
setMotorSpeed[]
sqrt(float x)
SensorType[]
exp(float x)
SensorValue[]
wait1Msec(int msecs)
SensorEV3_Color
sleep(int msecs)
SensorEV3_Sound
playTone(int freq, byte 10msec_tics)
getColorName(int sensor)
setPixel(int x, int y)
abs(float val)
clearPixel(int x, int y)
cos(float radians)
displayTextline(int line, “ “, …)
sin(float radians)
eraseDisplay();
Setting a motor speed can be done either using the motor letter (A-D) like so:
motor[motorA] = 30;
or the motor number (0-3) like so:
motor[0] = 30;
Using Sensors
Below is a list of the most common sensors and their corresponding sensor types:
Sensor
Sensor Type
Ultrasonic (range)
sensorEV3_Ulrasonic
Sound
sensorSoundDBA
Colour
sensorEV3_Color
Touch
sensorTouch
Sensor types are defined using the port number (S1-S4) like so:
SensorType[S1] =sensorTouch ;
If using the light sensor to check colours, you will have to specify the sensortype, as well as the
sensor mode like so:
SensorMode[S1] = modeEV3Color_Color;
34
Screen Pixel Drawing
2D arrays can be used to draw images on the EV3 robot’s’ screen. . The EV3 robot’s screen is 178
rows by 128 columns, and position (0,0) starts in the bottom left corner, with (177,127) in the top
right corner. Using the command setPixel(i,j) draws a black pixel as point (i,j) on the screen. Using
the command clearPixel(i,j) clears a pixel displayed at that point and returns it back to the typical
green. To display an image on the screen, we can use a 2D array of 0s and 1s in the shape of the
image we want to display. We can then loop through the array, setting all the 1s, and clearing all the
0s, to draw our image. We can display a simple “+” image in the upper left corner of the EV3 robot’s
screen like so:
byte pixels[5][5] =
{{0,0,1,0,0},
{0,0,1,0,0},
{1,1,1,1,1},
{0,0,1,0,0},
{0,0,1,0,0}};
for(i=0; i < ROWS; i++)
{
for(j=0; j < COLS; j++)
{
if(pixels[i][j] == 0)
clearPixel(j, 127-i);
else if(pixels[i][j] == 1)
setPixel(j, 127-i);
}
}
Notice that when setting and clearing pixels, we use “127 – i”, and not just i. This is because in the
array, higher indices move lower through the image. However on the screen, higher numbers
represent higher pixels. As a result, we use the –i to ensure the image is drawn in the correct
orientation. We can change where the image is drawn, by adding offsets. In the example above, the
top left of the image corresponds to the top left of the EV3 robot’s screen. However, if we wanted to
align the top left of the image closer to the middle of the screen, we could do something like this:
byte pixels[5][5] =
{{0,0,1,0,0},
{0,0,1,0,0},
{1,1,1,1,1},
{0,0,1,0,0},
{0,0,1,0,0}};
int x_offset = 90;
int y_offset = 60;
for(i=0; i < ROWS; i++)
{
for(j=0; j < COLS; j++)
{
if(pixels[i][j] == 0)
clearPixel(x_offset + j, 127 – (y_offset + i));
35
else if(pixels[i][j] == 1)
setPixel(90+ j, 60 - i);
}
}
In this example, the first (top left) pixel will be drawn at (90, 67), and the rest will proceed from
there.
Question 19:
A robot is placed in a hallway of white and black tiles of unequal length. The robot is placed on the
first tile which is assumed to be white. The last tile is also white followed by an obstructing wall.
Write a robotC program that will make the robot drive down the hallway and stop before or when it
hits the wall. Once it reaches the wall, the robot will display the number of black tiles encounter
along the way. If you wish to use any sensor, please use the following directions:




The ultrasonic sensor is connected to port S2 & the colour sensor is connected to
port S3.
The touch sensors are connected to port S1 and port S4.
The motors are connected to motorA and motorD.
Use any combination of sensors that can achieve the task demanded above.
36
Answer 19:
#define lightThreshold 40
void Drive(int speed);
task main()
{
//GIVEN DECLARATIONS
int lightVal, sonarVal, currentTile = 0, numberOfTiles = 0;
SensorType[S2] = sensorEV3_Ultrasonic;
SensorType[S3] = sensorEV3_Color;
SensorType[S1] = sensorTouch;
SensorType[S4] = sensorTouch;
while(SensorValue[S1] == 0 && SensorValue[S4] == 0)
{
lightVal = SensorValue[S3];
if(lightVal < 40 && currentTile > 40)
{
numberOfTiles++;
}
currentTile = lightVal;
wait1Msec(100);
}
Drive(0);
displayTextLine(0, "%d black tiles", numberOfTiles);
}
void Drive(int speed)
{
motor[motorA] = speed;
motor[motorD] = speed;
}
Question 20:
A robot is placed inside an arena that is delimited by a black tape. The arena is filled with grey tiles.
Program a game that will make the robot stay inside the arena while counting how many times it
crossed the grey tiles. The robot will stop if the player claps or whistles. (You are provided with the
function void Rotate(int speed, int degrees) that makes the robot rotate with the specified
degrees at the speed given.)
37
Specifications:







The Light sensor is attached to port S1
The Sound sensor is attached to port S2
The black tape has a reflected light level of 20
The grey tiles have a reflected light level of 40
The white ground has a reflected light level of 60
The clap/whistle level is measured at 65
The motors are on motorA and motorD
38
Answer 20:
void Rotate(int speed, int degrees);
task main()
{
//GIVEN DECLARATIONS
int lightval, currentTile = 0, numberoftiles = 0;
SensorType[S1] = sensorEV3_Color;
SensorType[S2] = sensorSoundDBA;
motor[motorA] = 20;
motor[motorD] = 20;
while(SensorValue[S2] < 65)
{
lightval = sensorValue[S1];
if(lightval == 20)
{
Rotate(90,20);
}
else if(lightval == 40 && currentTile != 1)
{
numberoftiles++;
currentTile = 1;
displayTextLine(0, "%d", numberoftiles);
}
if(lightval == 60)
{
currentTile = 0;
}
}
motor[motorA] = 0;
motor[motorD] = 0;
}