LMU ☀️ CMSI 2120
DATA STRUCTURES
HOMEWORK #5 Due: 2022-11-22

Learning Objectives

With this assignment you will demonstrate:

Readings and Videos

Please:

Instructions

Work in teams of 1 to 2 students.

This assignment is a mix of programming and working-out-problems. Submit, to BrightSpace, a PDF document with your solutions as well as links to code on your GitHub repository. Make sure your document is beautiful. Because taking pride in one’s work is valued, poorly crafted submissions will necessarily be docked.

Your PDF submission should be generated from a source document written in a document preparation system such as LaTeX, Pages, or Word. Place your document source in the GitHub repository you have been using for this course. Submit only one submission per team. Some of the answers will be typed out completely, while others will be of the form “See <link>” where <link> is the full and complete URL on GitHub of your (runnable) solution.

Structure your repository, for now, as follows:

  .
  ├── README.md
  ├── .gitignore
  ├── homework1/
  │   └── (existing files from previous assignments)
  ├── homework2/
  │   └── (existing files from previous assignments)
  ├── homework3/
  │   └── (existing files from previous assignments)
  ├── homework4/
  │   └── (existing files from previous assignments)
  └── homework5/
      ├── README.md             (include all students’ names)
      ├── NeedlesslyRecursive.java
      ├── Sets.java
      ├── Homework5Test.java    (given to you below)
      └── (source code for your document, e.g. .tex, .docx, .pages, ...)

The Problems

  1. Write a Java interface called NeedlesslyRecursive with four static methods that implement recursive solutions to the following:
    1. The function $a$, defined as follows, where ($x$ and $y$ are BigIntegers):

      $\;\;\;\;a(x,y) = \begin{cases} y+1, & x = 0 \wedge y \geq 0 \\ a(x-1, 1), & x > 0 \wedge y = 0 \\ a(x-1, a(x, y-1)), & x > 0 \wedge y > 0 \end{cases}$

      Throw an exception if $x$ or $y$ is null or less than zero.
    2. A function that, when given an integer, returns the string containing the binary representation of the integer. For example, for 43, return "101011", and for -9 return "-1001".
    3. A function that takes in an integer $n$ and returns the largest integer less than or equal to $\log_3 n$.
    4. A function to compute $x^n$, where $x$ is a BigInteger and $n$ is an integer, using the famous algorithm that takes around $\log n$ steps, not $n$ steps.

    Place a comment at the top of your file stating that you know these methods would not ordinarily be written recursively, but that you are writing them recursively for practice. Submit this interface in the file NeedlesslyRecursive.java. A unit test has been provided to you at the bottom of this assignment page.

  2. The value of NeedlesslyRecursive.a(4, 2) has 19729 decimal digits, so running the recursive algorithm without memoization will never complete in the lifetime of our sun. But you can work out on paper (or a tablet or whiteboard) a concise expression for this exact value. Show it and its derivation. You may use the $\uparrow$ notation that appears on the course notes on Mathematics for Computer Science.
  3. We saw this function in class:

    $C(n,k) = \begin{cases} 1, & k = 0 \vee k = n \\ C(n-1,k-1)+C(n-1,k), & 0 < k < n\\ \end{cases}$

    It turns out you can also define it like this:

    $C(n,k) = \frac{n!}{k!(n-k)!}$

    Give the worst-case complexity of (a) the naïve recursive, (b) the non-recursive algorithms for computing $C(n,k)$. You may assume all values can fit in a single machine word, so your complexity measure can be a function of both $n$ and $k$.
  4. Draw detailed pictures of the progression of the following algorithms as they sort the array [81 9 17 21 20 8 2 5 1 83 23]. Give the same amount of detail as was given in the examples on the course notes on sorting. Work out your answers without the aid of a computer, using the computer only to check your work.
    1. Selection Sort
    2. Gnome Sort
    3. Insertion Sort
    4. Quick Sort (using first element as pivot)
    5. Merge Sort
    6. Heap Sort
    7. Radix Sort
  5. In your own words, but very, very, concisely, write a short one-sentence-fragment description for each of the following classifications of sorting algorithms: exchange, insertion, selection, merge, distribution, hybrid, concurrent, and impractical. Although brevity is important, make sure to capture the essence of each class.
  6. Write a Java interface called Sets with two static methods: one to return all subsets of a given generic set, and the other to return a sorted list of all values that are multiples of a given base from a set of integers. Use the unit tests below to both better understand the requirements and to of course test your solution. Pay attention to the restrictions shown in the unit tests (noting the security concerns). Please use Java’s built-in set, list, and sort functionality.
  7. For the following tree:

    anotherexampletree.png

    1. What is the size of this tree?
    2. How many edges does this tree have?
    3. What are the leaves?
    4. What are the children of D?
    5. What is the depth of G?
    6. What is the degree of G?
    7. What are the ancestors of G?
    8. What are the descendants of G?
    9. What are the nodes on level 3?
    10. What is the height of the tree?
    11. What is the width of the tree?
    12. What is the height of the node D?
    13. What is the simplest path from P to E?
    14. What is the degree of the tree?
    15. Enumerate the nodes in breadth-first order.
    16. Enumerate the nodes in depth-first order.
  8. Draw all 14 binary trees of size 4. Circle the ones that are complete trees.

Unit Tests

Please use this JUnit class as you develop your programming solutions for this assignment. And please add the files to your GitHub repository; I will be using them to check your work.

Homework5Test.java
import java.math.BigInteger;
import java.util.Set;
import java.util.HashSet;
import java.util.stream.IntStream;
import java.util.Collections;
import java.util.List;
import static java.util.stream.Collectors.toSet;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThrows;
import org.junit.jupiter.api.Test;

public class Homework5Test {

    @Test
    public void testBinaryString() {
        record Trial(int n, String expected) {
        }
        var trials = new Trial[] {
                new Trial(0, "0"),
                new Trial(1, "1"),
                new Trial(2, "10"),
                new Trial(3, "11"),
                new Trial(10, "1010"),
                new Trial(256, "100000000"),
                new Trial(257, "100000001"),
                new Trial(15378813, "111010101010100101111101"),
                new Trial(Integer.MAX_VALUE, "1111111111111111111111111111111"),
                new Trial(-1, "-1"),
                new Trial(-2, "-10"),
                new Trial(-35, "-100011"),
                new Trial(Integer.MIN_VALUE, "-10000000000000000000000000000000")
        };
        for (var trial : trials) {
            assertEquals(trial.expected, NeedlesslyRecursive.binaryString(trial.n));
        }
    }

    @Test
    public void testAckermann() {
        String[] bad = { "-1 3", "3 -10", "0 -1", "-1 -1" };
        String[] good = {
                "0 0 1", "0 9 10", "0 69 70", "1 0 2", "1 1 3", "1 9 11",
                "2 0 3", "2 3 9", "2 9 21", "3 0 5", "3 2 29", "3 9 4093",
                "4 0 13"
        };
        for (String s : bad) {
            var trial = s.split(" ");
            BigInteger x = new BigInteger(trial[0]);
            BigInteger y = new BigInteger(trial[1]);
            assertThrows(IllegalArgumentException.class,
                    () -> NeedlesslyRecursive.a(x, y));
        }
        for (String s : good) {
            var trial = s.split(" ");
            BigInteger x = new BigInteger(trial[0]);
            BigInteger y = new BigInteger(trial[1]);
            BigInteger expected = new BigInteger(trial[2]);
            assertEquals(expected, NeedlesslyRecursive.a(x, y));
        }
    }

    @Test
    public void testLog3() {
        assertEquals(0, NeedlesslyRecursive.log3(1));
        assertEquals(1, NeedlesslyRecursive.log3(3));
        assertEquals(1, NeedlesslyRecursive.log3(5));
        assertEquals(2, NeedlesslyRecursive.log3(9));
        assertEquals(1, NeedlesslyRecursive.log3(8));
        assertEquals(3, NeedlesslyRecursive.log3(80));
        assertEquals(4, NeedlesslyRecursive.log3(81));
        assertEquals(4, NeedlesslyRecursive.log3(242));
        assertEquals(5, NeedlesslyRecursive.log3(243));
        assertEquals(8, NeedlesslyRecursive.log3(19682));
        assertEquals(9, NeedlesslyRecursive.log3(19683));
    }

    @Test
    public void testPower() {
        var trials = new String[] {
                "0 5 0", "1 8 1", "9 3 729", "2 12 4096", "2 13 8192",
                "231 15 284563830596984699348644406569092951",
                "3 99 171792506910670443678820376588540424234035840667",
                "100 20 10000000000000000000000000000000000000000" };
        for (var trial : trials) {
            var values = trial.split(" ");
            BigInteger x = new BigInteger(values[0]);
            int n = Integer.parseInt(values[1]);
            BigInteger expected = new BigInteger(values[2]);
            assertEquals(expected, NeedlesslyRecursive.power(x, n));
        }
    }

    @Test
    public void testPowerSet() {
        assertEquals(Sets.powerSet(Set.of()),
                Set.of(Set.of()));
        assertEquals(Sets.powerSet(Set.of(1)),
                Set.of(Set.of(), Set.of(1)));
        assertEquals(Sets.powerSet(Set.of(1, 2)),
                Set.of(Set.of(), Set.of(1), Set.of(2), Set.of(1, 2)));
        assertEquals(Sets.powerSet(Set.of("A", "B", "C")),
                Set.of(Set.of(), Set.of("A"), Set.of("B"),
                        Set.of("A", "B"), Set.of("C"),
                        Set.of("A", "C"), Set.of("B", "C"),
                        Set.of("A", "B", "C")));
        assertThrows(IllegalArgumentException.class, () -> Sets.powerSet(
                IntStream.rangeClosed(1, 17).boxed().collect(toSet())));
    }

    @Test
    public void testMultiples() {
        assertEquals(Sets.multiples(Set.of(), 5), List.of());
        assertEquals(Sets.multiples(Set.of(3, 1, 8, 19), 5), List.of());
        assertEquals(Sets.multiples(Set.of(3, 800, 8, 19), 8), List.of(8, 800));
        assertEquals(Sets.multiples(Set.of(3, 800, 8, 19), 1), List.of(3, 8, 19, 800));
    }
}

Grading

You will be graded both on having reasonable and correct solutions to the problems, as well as how beautifully and consistently formatted your submitted document is presented. Your programming solutions will be grading for style and formatting as well as correctness, as usual.