DUE: 11:59 pm on Monday, December 8. No late days may be used!
- DUE: 11:59 pm on Monday, December 8. No late days may be used!
- Goals of This Assignment
- Specification
- Testing
- Submission
Goals of This Assignment
In this assignment, you’ll practice thinking recursively through writing six recursive functions across a range of difficulties.
Tools for Completing This Assignment
- Recursive programming and backtracking
- Working with Data Structures
- Unit Testing
Git
You should keep track of your code for this assignment using git. Review the instructions for setting up a git repository here. There are not specific checkpoints at which you should make a commit. Instead, you should commit and push your changes each time you make substantial progress. A good rule of thumb is to make a commit each time you finish one of the required functions.
You will submit as part of your solution a screenshot of your commit history. The image should show at minimum 5 commits to receive the full 5 points. You are welcome to make more.
Collaboration Policy
You cannot collaborate with anyone on this assignment. All code you write must be your own, and you may not discuss the assignment with other students. Please refer to the Collaboration & Academic Misconduct portion of the syllabus for further details.
Style & Design Policy
There is no style and design portion of the grade for this assignment, but you should still aim to follow the best practices you’ve learned thus far.
Specification
For this assignment, you will have some flexibility in terms of which problems to complete. Below you will find three categories of problems:
- Easier (6 total options)
- More difficult (4 total options)
- Most difficult (3 total options)
Each problem asks you to write a recursive function. The function signature should exactly match the function signature given in the problem. This may mean you need to write some recursive helper functions in order to complete a problem. Helper functions should be private static and add the word Helper to the function name. All of these functions should be written in a file called RecursivePractice.java.
You will complete 6 recursive functions for this assignment. You may choose which problems to complete, following these requirements:
- 3 of the problems should be from the “Easier” category
- 2 of the problems should be from the “More difficult” category
- 1 of the problems should be from the “Most difficult” category
Note Solutions using any kind of iteration will be given no credit.
Easier Problems
countSubstrings
Function Signature: public static int countSubstrings(String word, String substring)
Problem Description: Given a word and a substring, count how many times the substring appears in the word.
For example, in the word “banana”, the substring “na” appears two times, with “banana” and “banana”, so countSubstrings would return 2.
Similarly, the substring “ana” also appears twice in “banana”, with “banana” and “banana”. Note that this means we can have overlaps between the starts of our substrings (don’t worry, this actually makes the problem easier).
You may assume that both word and substring are not null and have positive lengths. You may also assume that both strings are all lowercase.
convertIntToString
Function Signature: public static String convertIntToString(int x)
Problem Description: Given an integer x, convert it into a String representation.
To do this recursively, you should process x digit by digit. You will find the ASCII table of values useful for converting int to char and you may use the method Character.toString() to convert from char to String.
If x is negative, you should maintain this in the String representation.
digitMatch
Function signature: public static int digitMatch(int x, int y)
Problem Description: Given two integers x and y, count the number of digits they have in common.
Two digits match if they are equal in 1) value and 2) position (relative to the end of the number). In other words, the function should compare the last digits of each number, followed by the second-to-last digits, then the third-to-last digits, and so forth, counting how many pairs match.
For example, digitMatch(1072503891, 62530841) would return 4.
1 0 7 2 5 0 3 8 9 1
| | | | | | | |
6 2 5 3 0 8 4 1
You may assume that x and y are non-negative numbers with no leading zeroes.
sumReciprocalsBetween
Function Signature: public static double sumReciprocalsBetween(int lower, int upper)
Problem Description: Given two integers lower and upper, sum the reciprocals between the two. In math, we would write this problem as \(\sum_{i=lower}^{upper}\frac{1}{i}\).
For example, sumReciprocalsBetween(1,3) returns 1.8333... because 1 + 1/2 + 1/3 = 1.8333....
If either bound is less than or equal to 0, or if the upper bound is less than the lower bound throw an IllegalArgumentException.
writeBinary
Function Signature: public static void writeBinary(int x)
Problem Description: Given an integer x, write its binary (base-2) representation to the console.
For example, the binary representation of 44 is 101100.
If x is less than 0, throw an IllegalArgumentException.
multiplyOdds
Function Signature: public static int multiplyOdds(int n)
Problem Description: Given an integer n, return the product of the first n odd integers.
For example, multiplyOdds(1) returns 1 and multiplyOdds(4) returns 105 because 1 * 3 * 5 * 7 = 105.
If n is less than or equal to 0, throw an IllegalArgumentException.
More Difficult Problems
findSecondLargest
Function Signature: public static int findSecondLargest(int[] arr)
Problem Description: Given an array of integers, find the second largest number in the array.
Note that if the largest number appears multiple times, the second largest is considered to be the same as the largest number. For example, the second largest number of [7, 1, 7] is 7.
You may assume that the array is not null and has at least 2 different elements in it.
collatz
Function Signature: public static boolean collatz(int n)
Problem Description: Given an integer n, determine whether or not the number will ever reach 1 by following the steps of the Collatz Conjecture.
The Collatz Conjecture is an unsolved problem in mathematics which states that every positive integer can be transformed into 1 by doing the following:
- If
nis even, the next term will ben / 2 - If
nis odd, the next term will be3 * n + 1 - Repeat until the term becomes 1
If a value of n is ever repeated in this process, then there is a cycle and it is impossible to reach the value 1. If such a case is detected, the function returns false. Otherwise, if the value reaches 1, return true.
For example, collatz(10) returns true and the sequence of computations which leads to this is as follows:
10 -> 10 / 2 -> 5
5 -> 5 * 3 + 1 -> 16
16 -> 16 / 2 -> 8
8 -> 8 / 2 -> 4
4 -> 4 / 2 -> 2
2 -> 2 / 2 -> 1
1 -> return true
Hint Think about what data type you could add as a parameter to a helper function to help you track previously seen elements.
Exception This problem is exempt from the 100% line coverage requirement for testing!
permutation
Function Signature: public static double permutation(int n, int r)
Problem Description: Given two integers n and r, compute the number of unique permutations of r items from a group of n items.
For given values of n and r, this value P(n, r) can be computed as follows: \(P(n, r) = \frac{n!}{(n - r)!}\)
For example, permutation(7, 4) should return 840.0.
If n is less than r, or either value is less than 0, throw an IllegalArgumentException.
Hint Think about how the call permutation(7, 4) relates to the call permuttaion(6, 3).
recamans
Function Signature: public static int recamans(int n)
Problem Description: Given an integer n, compute the nth term in Recamán’s sequence.
If n is less than 0, throw an IllegalArgumentException.
Recamán’s sequence is defined as follows:
\[a_{n} = \begin{cases} 0 & \text{if } n = 0 \\ a_{n-1} - n & \text{if } a_{n-1} - n > 0 \text{ and is not already in the sequence} \\ a_{n-1} + n & \text{ otherwise} \end{cases}\]Hint Think about what data type you could add as a parameter to a helper function to help you track previously seen elements.
Most Difficult Problems
subsetsOfSize
Function Signature: public static void subsetsOfSize(ArrayList<String> list, int size)
Problem Description: Given a list of strings and a size, print out every sub-list of that size that could be created from elements of the given list.
For example, given the list [Banana, Mango, Pineapple, Strawberry] and a size 2, the output would be:
[Banana, Mango]
[Banana, Pineapple]
[Banana, Strawberry]
[Mango, Pineapple]
[Mango, Strawberry]
[Pineapple, Strawberry]
The order in which you show the sub-lists does not matter, and the order of the elements of each sub-list also does not matter. The key thing is that the function should produce the correct overall set of sub-lists as its output.
You may assume that the list is not null, that the list contains no duplicates, and that the size is at least 1 and no larger than the size of the list.
maxSum
Function Signature: public static int maxSum(ArrayList<Integer> list, int limit)
Problem Description: Given a list of integers and a limit, find the maximum sum that can be computed by adding elements of the list without exceeding the limit.
For example, given the list [7, 30, 8, 22, 6, 1, 14] and the limit of 19, the maximum sum that can be generated that does not exceed the limit is 16. This is achieved by adding 7, 8, and 1.
If the list is empty, or if the limit is not a positive integer, or all of the lists values exceed the limit, return 0.
Each index’s element in the list can be added to the sum only once, but the same number value might occur more than once in a list, in which case each occurrence might be added to the sum. For example, if the list is [6, 2, 1] you may us up to one 6 in the sum, but if the list is [6, 2, 1, 6] you may use up to two sixes.
You may assume that all values in the list are nonnegative. Your method may alter the contents of the list as it executes, but it should be restored to its original state before your method returns. Do not use any loops.
waysToClimb
Function Signature: public static int waysToClimb(int n)
Problem Description: Given an integer n representing an amount of stairs to climb, calculate the number of ways to climb the stairs taking either 1 or 2 steps at a time.
If n is less than or equal to 0, throw an IllegalArgumentException.
For example, if there are four stairs, it returns 5 as there are the following options:
1, 1, 1, 1
1, 1, 2
1, 2, 1
2, 1, 1
2, 2
Hint You may find it helpful to write out the possibilities by hand for several small examples. Look for patterns you can take advantage of.
Testing
We expect you to write unit tests using JUnit for every recursive function in RecursivePractice.java in a file called RecursiveTesting.java. We will run your tests in addition to our own to verify your code works. To earn full points on testing, you must:
- Write at least 3 tests for each function you implement
- Achieve 100% line-based code coverage for each function you implement (including private helper functions which are tested implicitly)
Submission
Submit the files RecursivePractice.java and RecursiveTesting.java which should contain all your recursively implemented functions and their associated tests, respectively. Finally, submit a screenshot of your git log history.
Ensure that your files do not have a package header! Specifically, the first lines of your file should not read package xyz or similar.
Please find these files locally on your file system. You should select each of the files and upload them as files (not as a directory, and preferably not as a .zip either). If you need help, please reach out on Ed or in Office Hours.