LMU ☀️ CMSI 2120
DATA STRUCTURES
HOMEWORK #4 PARTIAL ANSWERS
  1. $\mathscr{P}(\{a,b,c\}) = \boxed{ \{ \varnothing, \{a\}, \{b\}, \{c\}, \{a,b\}, \{a,c\}, \{b,c\}, \{a,b,c\} \} }$
  2. There are $B_{10}$, specifically $\boxed{115975}$ , partitions of $\{1,2,3,4,5,6,7,8,9,10\}$.
  3. I'd say no. Let's take a simple example. Let $A = \{a\}$, $m = 1$, $n = 2$. Then $A^{m+n} = A^3 = \{(a,a,a)\}$, but $A^m \times A^n = A^1 \times A^2 = \{(a, (a, a))\}$. Whether you think $(a,a,a) = (a, (a, a))$ is a matter of preference, I suppose, but I think a 3-tuple is different from a 2-tuple whose second element is a 2-tuple. Saying they are not equal allows one to make a distinction between $((a, a), a)$ and $(a, (a, a))$, which might be convenient. However there is an argument for making them the same—it makes the product and power operations of sets behave the same as the corresponding operators on numbers. Either answer is acceptable provided you give your rationale.
  4. The composition function is $\boxed{\lambda (f,g). \lambda x. g(f(x))}$
  5. For the function f = λx. 4x–3x2 (which I found here):
    1. $f^0(0.01) = 0.01$
    2. $f^1(0.01) = 0.0397$
    3. $f^2(0.01) = 0.15407173$
    4. $f^5(0.01) = 0.1715191421091756109132737611936695015318486615246297164053309653$
    5. I don’t know what $f^{30}(0.01)$ is, but I do know it has 2,147,483,648 digits after its decimal point.
    6. To find the value of $f^{50}(0.01)$, according to Java, use JShell:
      var x = 0.01;
      for (var i = 0; i <= 50; i++) {
          System.out.printf("%2d %2.16f%n", i, x);
          x = 4*x - 3*x*x;
      }
      
      and got an answer of 1.3084580315967430. This value is probably nowhere near the actual value, since it is performing iterative computation with limited precision.
    7. Answers vary. On my middle daughter's TI-84 Plus, I got 0.3328104093. No doubt other calculators will give different results.
    8. $f^{75}(0.01)$ has 75,557,863,725,914,323,419,136 digits after the decimal point. 10 points is 0.13889 inches, so let's say that each digit is printed on 0.0193 square inches. So to print all those digits we would need about $1.45752052 \times 10^{21}$ square inches of paper. Really, really cheap printer paper has a thickness of 0.003 inches so we need a volume of $4.37256 \times 10^{18}$ cubic inches, or $7.16534 × 10^{13}$ cubic meters. This volume would cover the entire land area of earth with a height of about a half a meter, so this probably exceeds the volume of wood on the planet to produce the paper, not to mention the environmental catastrophe that would ensue if we managed to do it.
    9. I don't really know for sure, but I doubt that we'll ever know the first digit of the decimal expansion of $f^{100}(0.01)$, since unless you keep every digit of every iteration, the round-off errors will be magnified so much that your answer will be completely useless. There is really no way to store every digit even of $2^{80}$ let alone $2^{99}$. I don't know what fraction of the digits for partial results is sufficient just to get the first digit of the 100th iteration, but I think it is too high even for computation systems that will be in place 100 years from now. I could be wrong, as I am not a number theorist. If there was a way to figure this out, it would have to be via some indirect mechanism, but my gut feeling says no such approach exists.
  6. To determine the complexity, you can manually work out the number of stars printed for successive values of $n$ (or write code to count them). You will find:
    $n = 1 \;\longrightarrow\; 1$
    $n = 2 \;\longrightarrow\; 3$
    $n = 3 \;\longrightarrow\; 7$
    $n = 4 \;\longrightarrow\; 15$
    $n = 5 \;\longrightarrow\; 31$
    which suggests $T(n) = 2^n-1$, and in fact it is, because you could even be more precise and note the number of operations is $\sum_{i=1}^{n} 2^i$ which is $2^n-1$. This is in $\boxed{\Theta(2^n)}$
  7. The code does not terminate for $n > 1$ so $\boxed{\Theta(\infty)}$ .
  8. Outer loop runs $\sqrt n$ times. Inner loop runs $\log n$ times. Time complexity is $\boxed{\Theta(\sqrt{n} \log n)}$ .
  9. The code prints $1 + 2 + 4 + 8 + 16 + 32 + 64 + 128 + \ldots n$ stars. This series sums to $2n-1$, so the time complexity is $\boxed{\Theta(n)}$ .
  10. Outer loop runs $n^2$ times. Inner loop runs $\log n$ times. Time complexity is $\boxed{\Theta(n^2 \log n)}$ .
  11. This one was the hardest one, so let’s go through it in detail. First, note:
    When $i$ is 1, $j$ ranges through 1 (1 steps)
    When $i$ is 2, $j$ ranges through 1, 2 (2 steps)
    When $i$ is 3, $j$ ranges through 1, 2 (2 steps)
    When $i$ is 4, $j$ ranges through 1, 2, 4 (3 steps)
    When $i$ is 5, $j$ ranges through 1, 2, 4 (3 steps)
    When $i$ is 6, $j$ ranges through 1, 2, 4 (3 steps)
    When $i$ is 7, $j$ ranges through 1, 2, 4 (3 steps)
    When $i$ is 8, $j$ ranges through 1, 2, 4, 8 (4 steps)
    When $i$ is 9, $j$ ranges through 1, 2, 4, 8 (4 steps)
    ...
    When $i$ is 16, $j$ ranges through 1, 2, 4, 8, 16 (5 steps)
    When $i$ is 17, $j$ ranges through 1, 2, 4, 8, 16 (5 steps)
    ...
    When $i$ is 32, $j$ ranges through 1, 2, 4, 8, 16, 32 (6 steps)

    So the number of stars printed is:

    1+2+2+3+3+3+3+4+4+4+4+4+4+4+4+5+5+5+5+5+5+5+5+5+5+5+5+5+5+5+5+6+6+6...
    
    where there are $n$ terms in total. We can compute $T$ exactly! Note:

    $T(n) = \sum_{i=1}^n \log_2 i + 1$

    Now we need to figure out how to get the $\Theta$ in here. To do this, we need to find upper and lower bounds.

    The function $T$ is bounded above by $\lambda n. \sum_{i=1}^n 2 \log_2 i$, or $\lambda n. 2n \log n$. It is bounded below by $\lambda n. 0.5n \log n$ because half of that summation is, well, less that the full summation. Since we have $2n \log n$ as an upper bound and $0.5n \log n$ as a lower bound, we have $\boxed{\Theta(n \log n)}$

  12. The outer loop is executed $\log_4 n$ times. The inner loop is always executed exactly $n$ times, because $i$ never changes. Yes, you had to look rather carefully to notice that. This means the time complexity is $\boxed{\Theta(n \log n)}$ .
  13. The best case occurs then the $t$ is in the past and we never execute the inner loop. We still do $\log n$ time checks, though, so $\boxed{B(n) \in \Theta(\log n)}$ . In the worst case we print $n + \frac{n}{2} + \frac{n}{4} + \ldots + 1$ stars. therefore $\boxed{W(n) \in \Theta(n)}$ .
    There was a typo in the original assignment

    The assignment when first given had the outer loop copy-pasted from the previous problem, namely:

    for (var i = n; n >= 1; n /= 2) {
    

    In this case, we have the same situation as the previous problem, in which $i$ never changes, so the inner loop always has $n$ steps, with $\boxed{W(n) \in \Theta(n \log n)}$ .

  14. The best case occurs when we always have even values of $n$ during every recursive call, clearly we therefore have $\boxed{B(n) \in \Theta(\log n)}$ . In the worst case we still have the same number of recursive invocations; all we do is one extra multiplication in each. So $\boxed{W(n) \in \Theta(\log n)}$ .
  15. Recall the important note from our discussion of complexity analysis: “For unbounded values, like Java’s BigInteger or BigDecimal, the numbers themselves are collections and the number of bits [or digits] in the number becomes part of the problem input size.” Because the question referred to numbers of unbounded size, the “size of the input” is the number of bits (or digits) of the input numbers.
    $n$True input size
    (Digits)
    $2^n$True output size
    (Digits)
    5132 2 digits
    91512 3 digits
    2021048576 7 digits
    4021099511627776 13 digits
    70222 digits
    120337 digits
    10004302 digits
    999943010 digits
    For $\Theta$-analysis the base of the logs don’t matter (as $log_2$ and $log_{10}$ differ only by a constant). So if we do the same analysis with bits of a number, we get:
    $n$True input size
    (Bits)
    $2^n$True output size
    (Bits)
    $n$$\log n$$2^n$ $n = 2^{\log n}$
    So if the input has $k$ bits, the output has $2^k$ bits. So the time complexity is $\boxed{\Theta(2^n)}$
  16. Given $T(n) = n^3$ and $T(100)$ ops in 10 second. So: 1003 ops / 10 sec = 100000 ops/sec.
    1. $T(200) = 200^3$ ops. 8000000 ops / 100000 ops/sec = 80 sec
    2. A computer 10 times faster does 1000000 ops/sec. In 30 secs, it does 30000000 ops. We need to find the $k$ such that 30000000 = $k^3$, so $k = 30000000^{\frac{1}{3}} = $ 310.7
    3. Processing a $10^9$-element list means we need a computer that can do 1027/3600 ops/sec. To see how much faster this is than the original computer, we just divide the speeds: (1027 / 3600) / 105 = 1022 / 3600 which is 2.778×1018 times faster.
  17. We are given $T(n) = n \log n$, and $T(64)$ ops in 192 seconds. So (64 × 6) ops / 192 sec = 384 ops / 192 sec = 2 ops/sec.
    1. $T(128) = 128*7 = 896$ ops. Therefore, 896 ops / (2 ops/sec) = 448 seconds.
    2. A computer that is 8 times faster does 16 ops/sec, or 160 ops in 10 secs. We have to find the $k$ for which $k \log k$ = 160. That's pretty easy to get by trial and error; the value is 32.
    3. To process list of size 10 in one second requires a speed of 10 log 10 ops/sec or about 33.219 ops/sec, which is 16.6 times faster than the original computer.
  18. We are given $T(n) = 2n \log n$ and $T(32)$ ops in 160 seconds. So (2 × 32 × log(32)) ops / 160 sec = 320 ops / 160 sec = 2 ops/sec.
    1. $T(64)$ = (2 × 64 × 6) ops = 768 ops. Therefore 768 ops / 2 ops/sec = 384 secs.
    2. A computer 4 times faster does 8 ops/sec. To see how large of a list we can process in 16 seconds, we'd have 16 × 8 = 128 ops. We need the value of $k$ for which $2 k \log k$ = 128. This is easy to guess and check; the answer is 16.
  19. The exponential is actually smaller than the quadratic up through n=95. Starting with n=96, the values at the exponential function are much larger. I figured this out by graphing the function $\lambda n. 1.1^n - n^2$ Actually I put it into Wolfram Alpha and found the root to be 95.7168.
  20. Functions ordered by growth rate (slowest to fastest):

    $\lambda n . \frac{2}{n}$
    $\lambda n . 2$
    $\lambda n . \log{\sqrt{n}}$     (this is $0.5 \log n$)
    $\lambda n . 2 \log n$
    $\lambda n . \sqrt{n}$     (this is $n^{0.5}$)
    $\lambda n . n$
    $\lambda n . 2^{\log n}$     (this is just $n$)
    $\lambda n . n \log \log n$
    $\lambda n . n \log n$
    $\lambda n . \log n^n$     (this is $n \log n$)
    $\lambda n . n \log n^2$     (this is $2n \log n$)
    $\lambda n . n (\log n)^2$
    $\lambda n . n^{1.5}$
    $\lambda n . n^2$
    $\lambda n . n^2 \log n$
    $\lambda n . n^3$
    $\lambda n . 2^{n \div 2}$
    $\lambda n . 2^n$
    $\lambda n . (\log n)^n$     (grows faster than any constant to the $n$th power)
    $\lambda n . n!$
    $\lambda n . n^n$
    $\lambda n . 2^{n \cdot n}$