Comp 110 Array Utility Functions

This project is due in two parts.

Part 1 of this problem set is a written test and edge case worksheet due by Wednesday September 26th at 11:59pm and will be handed in on Gradescope.

Part 2 of this problem set is a programming assignment due by Tuesday October, 2nd at 11:59pm, HOWEVER you are advised to attempt completing and submitting to the autograder functions1 through 5 before the quiz on Thursday. Time spent working through these functions is invaluable practice and preparation for the quiz.

Part 1. Test Cases Worksheet

Print out the following worksheet:

Ps2 Test Cases

Below are 9 function names and English descriptions of their purpose. Read the description of each and write two example use cases. The use case should be a valid call to the function, with necessary arguments, and the expected return value. Then write at least one edge case. A second edge case is optional but encouraged if there are edge cases related to more than one parameter.

1. count

Given an array of numbers and a number to search for, returns a count of the number of times the number occurs in the array.

Edge cases the grader tests:

count([], 1) -> 0
count([1], 2) -> 0

2. max

Given an array of numbers, returns the largest number in the array. When the array is empty, returns Number.MIN_VALUE.

Note: Number.MIN_VALUE is the number closest to zero that our language can represent (5 x 10^-324). It is not negative. Negative numbers are smaller than Number.MIN_VALUE.

Edge cases the grader tests:

max([]) -> Number.MIN_VALUE
max([-12, -10, -11]) -> -10
max([-1, 0.5, -2]) -> 0.5

3. has

Given an array of numbers and a number to search for, returns true when the number is an element of the array or false otherwise.

Edge cases the grader tests:

has([], 1) -> false

4. all

Given an array of numbers and a number to search for, returns true when every element in the array is equal to that number or false otherwise.

Edge cases the grader tests:

all([], 1) -> false

5. equals

Given two arrays of numbers, returns true when two arrays have the same elements in the same order. Two empty arrays are equal to one another.

Edge cases the grader tests:

equals([], [1]) -> false
equals([1], []) -> false
equals([1, 2], [1]) -> false
equals([1], [1, 2]) -> false
equals([], []) -> true

6. cycle

Given a number as an upper bound, and a count of elements to generate, generate an array that cycles from 1 to the upper bound with the correct length.

For example, if the cycle function is given 3 as an upper bound and a count of 7 would generate the following array:

[1, 2, 3, 1, 2, 3, 1]

When either the upper bound or the count is zero or negative, cycle returns an empty array.

Hint: How might the remainder operator help you here?

Edge cases the grader tests:

cycle(0, 3) -> []
cycle(3, -3) -> []

7. concat

Given two arrays, return a single array that contains all of the elements of the first array followed by all of the elements of the second array.

Concat should not modify either array parameter it is given.

Edge cases the grader tests:

concat([], []) -> []
concat([1], []) -> [1]
concat([], [1]) -> [1]
concat([1, 2], []) -> [1, 2]
concat([], [1, 2]) -> [1, 2]

8. sub

Given an array, a starting index, and an ending index, return an array that contains only the elements of the input array from start index to (end index - 1).

When the start index is negative, start from the beginning of the array.

When the end index is greater than the length of the array, end with the end of the array.

Edge cases the grader tests:

sub([1], -1, 0) -> []
sub([1], -1, 1) -> [1]
sub([1], 1, 2) -> []
sub([1], 2, 2) -> []
sub([], 0, 1) -> []

9. splice

Given an array we'll refer to as the first array, an integer index, and another array we'll refer to as second array, splice or "insert" the elements of the second array at the integer index of the first array.

For example, if the first array is [1, 9], the index is 1, and the second array is [4, 5], the splice function will return [1, 4, 5, 9].

If the index is less than zero, insert the second array before the first array.

If the index is greater than the length of the first array, append the second array to the first array.

Splice should not modify either array parameter it is given.

Hint: consider how you might call upon other functions you've written to simplify your job in splice.

Note: the order of the function parameters should be (1) the first array, (2) the integer index, and (3) the other array.

Edge cases the grader tests:

splice([1, 2], 0, []) -> [1, 2]
splice([1, 2], 1, []) -> [1, 2]
splice([1, 2], 2, []) -> [1, 2]
splice([], 0, [1, 2]) -> [1, 2]
splice([], 1, [1, 2]) -> [1, 2]
splice([], 2, [1, 2]) -> [1, 2]

Part 2. Implementation

Do not begin Part 2 until after you have completed the test cases worksheet for Part 1!

The UTAs are instructed not to help anyone with Part 2 unless they have example test cases to work with as is required in Part 1.

2.0. Starting the Dev Environment

As with in lecture, begin by opening up VSCode, ensuring your project is still open, and then running the following two commands in the VSCode Integrated Terminal:

  • npm run pull
  • npm start

This project's starter code can be found in ps02-array-utils. Your work will be completed in two files:

1. test-runner-app.ts - This is the file where you will add your test cases.

2. array-utils.ts - This is the file where you will define and export each of the functions from part 1.

2.1 Honor Code

Special honor code rule for this assignment! You are only allowed to use capabilities we've talked about in class. Specifically, you are not allowed to use any built-in methods of an array. You are not supposed to know what the preceding sentence means at this point in the semester, but if you attempt to find solutions to these functions on-line it is likely they will involve concepts we have not discussed in class yet. As such, as long as you only make use of capabilities we have talked about in class you will be just fine.

Add the following honor code header, and fill in your name and ONYEN, in both of the files: test-runner-app.ts and array-utils.ts:

/*
 *
 * Author:
 *
 * ONYEN:
 *
 * UNC Honor Pledge: I certify that no unauthorized assistance has been received
 * or given in the completion of this work. I certify that I understand and
 * could now rewrite on my own, without assistance from course staff,
 * the problem set code I am submitting.
 */

2.3 Implement the count Function

You will notice in test-runner-app.ts that the test cases provided as examples in the worksheet of Part 1 have been turned into actual test cases in the main function.

Additionally, in array-utils.ts, you'll notice we have defined and exported a skeleton count function for you. Your first task is to implement a version of the count function given the description in part 1.1.

Once you are passing all cases in your development environment and believe you have a working implementation of the count function, publish your project and submit for grading. You should pass the tests for count before continuing forward.

2.4 Implement the max function

Now you're ready to work on the max function!

Step 1) Begin in array-utils.ts by defining and exporting a max function with a skeleton implementation. Remember, a skeleton implementation of a function is a correct declaration whose body simply returns a dummy value of the correct return type.

Step 2) Switch back over to test-runner-app.ts. Import your max function so that you can call it from this file. Add the test cases you wrote out by hand in the Part 1 worksheet for the max function. Refer to count's test cases for inspiration.

Step 3) Now switch back to array-utils.ts and work on implementing a correct max function as per its description in Part 1.2. Once you have your test cases passing, try submitting to the autograder. If the autograder is failing on either use or edge cases, you should try to think of additional use or edge cases to test in your main function.

2.5 Implement the remaining functions

For each of the remaining functions in parts 1.3 through 1.9, follow the three steps above.

Note that for parts 1.3 through 1.5 the functions return booleans. To write a test for a boolean function, update your import statement in test-runner-app.ts to include the testBoolean function:

import { testNumber, testBoolean, testArray } from "./test-util";

Note that for any function that returns an array (for example, the cycle function) you will need to call the testArray function rather than the testNumber function to test your actual returned values against your expected return values.