CSCI 150 - Discrete Mathematics
The math for computer science and every day...

Books and online resources (No textbook required)
Combinatorial Reasoning. Duane Detemple and William Webb.
Discrete Mathematics, An Open Introduction. Oscar Levin.
A Gentle Introduction to the Art of Mathematics. Joe Fields.
Discrete Mathematics Elementary and Beyond. Lázló Lovász, Jozsef Pelikán, and Katalin Vesztergombi.
Discrete Mathematics and its Applications. Rosen.
A First Course in Discrete Mathematics. Ian Anderson.
Discrete Mathematics for Computer Scientists. Cliff Stein, Robert Drysdale, and Kenneth Bogart.
How to Write Proofs.
Mathematics for Computer Science. Eric Lehman, Tom Leighton, and Albert Meyer.
Discrete and Combinatorial Mathematics. Ralph Grimaldi.
Essential Discrete Mathematics for Computer Science. Harry Lewis and Rachel Zax.

Extremely Important: All the documents posted on this website, including notes, lectures, and homework assignments, are subject to copyright. These document are the property of the author. It is ILLEGAL to distribute these documents or post them on ANY third party websites, such as coursehero, chegg, coursicle, studocu, studyblue, brainspace, kahoot, quizizz, reply, quizlet, tutor, stuvia, discord, youtube, facebook, instagram, X (twitter), etc... Really ANY website, including within the Hunter College domain. Any electronic document related to my courses (including pictures of documents you take yourself and any other sort of reproduction) that is accessible online must be on this site under www.cs.hunter.cuny.edu/~saad/

Instructional Team
The team consists of 16 people and one Guinea pig. Find us here.

Tutoring Schedule (mostly done by undergraduate TAs)
Find the schedule here (No more Navigate approintments, just walk in to Dolciani Math Learning Center on the 7th floor of East building)

Gradescope (for hw only)
Submit HW here

Recitations (Recitation instructors: Shayan, Arezoo, Daniel, Anthony)
Recitations will be added here on a regular basis. Each recitation instructor will use these as guide to cover what is appropriate given their recitation schedule.

Actual class notes for Spring 2024 (current offering, based on older lectures here)

PART I

Lecture 1 Ch. 1 Sections 1, 2, and 3.
- The general topics one might encounter in Discrete Math. Big ideas: combinatorics, number theory, proofs, set/relations/functions, graph theory, ...)
- Example questions and settings that people study and how they relate to above.
- The sum $1+2+\ldots+n=n(n+1)/2$ using a geometric proof.
- Planar graphs.

Lecture 2 Ch. 0 Sections 2, 3, and 6.
- The idea that counting reveals patterns and determines complexity of things we are dealing with.
- Counting: Euler's formula for planar graphs $v-e+f=2$.
- Counting: $1+2+\ldots+(n-1)$ is the number of pairs.
- Generalization to $a + (a+s) + (a+2s) + \ldots + b=\frac{a+b}{2}(\frac{b-a}{s}+1)$.
- Counting: permutations and $n!$.
- Sum and product notations $\Sigma$ and $\Pi$ (also seen as loops).

Lecture 3 Ch.0 Section 11, Ch. 1 Section 4.
- Manipluation of sum and product notation.
- Splitting sums and nested sums (also seen as nested loops).
- Snakes and Ladders (counting pairs).
- Addition rule and product rule.
- Students must read about sets (Ch. 0).

Lecture 4 Ch. 1 Section 4.
- Putting the product rule to work through examples.
- Practicing the product rule and overcounting.

Lecture 5 Ch. 2 Section 1, Section 6 first two pages.
- The 4 ways of selection: unordered/ordered, no repetition/repetition.
- $k$-permutations and $k$-combinations, with notation and formula.
- Selection with order and repetition: the $n^k$ formula.
- Some examples of counting with words.
- Application of the selection framework to counting problems should not be "literal".

Lecture 6 Ch. 1 Section 5, Ch.2 Section 4.
- $n$ choose 2 themes
- Handshake Lemma
- Making pairs vs. making teams

Lecture 7 Ch. 0 Section 11, Ch.2 Section 2 (excluding equivalence and partial order relations).
- Sets and their notation
- Subsets
- Intersection, union, product (relation to addition and product rules)
- The power set and the sum of binomial coefficients

Lecture 8 Ch. 2 Section 2 (first two pages).
- Functions
- Onto (surjection), one-to-one (injection), and bijection
- Significance of bijection (equal cardinality, inverse function)
- Quantifiers $\forall$, $\exists$, $\exists!$, and if-then $\Rightarrow$ (implies)
- How to show one-to-one and onto

Lecture 9 Ch. 2 Section 6.
- Counting with bijections
- Power sets $\rightarrow$ binary patterns
- Selecting $k$ from $n$ with repetition and no order $\rightarrow$ integer solutions to $x_1+x_2+\ldots+x_n=k, x_i\geq 0$

Lecture 10 Ch. 2 Section 5.
- Review/practice of functions: one-to-one, onto, bijection
- Review/practice of binary pattern problems
- An example of counting binary patterns with $n$ bits and $k$ 1s, and integer solutions to $x_1+x_2+\ldots +x_n=k$
- Pascal triangle, binomial coefficients, and their properties
- Binomial Theorem (without proof)

Lecture 11 Ch. 2 Sections 3 and 5.
- Binomial Theorem with proof
- Sum of binomial coefficients
- Alternating sum of binomial coefficients
- A fact about even and odd subsets
- Multinomials (Multinomial Theorem) and counting anagrams

PART II

Lecture 12 Ch. 3 Section 6 and 1st page of Section 7.
- Propositions and proofs
- Logical operators, Not $\neg$, And $\wedge$, Or $\vee$, Implication $\Rightarrow$
- Understanding implication (why $0\Rightarrow 0$ and $0\Rightarrow 1$ are true)
- Truth tables
- Different ways of saying $P\Rightarrow Q$ (or it's opposite)
- The contrapositive ($P\Rightarrow Q$ is equivalent to $\neg Q\Rightarrow\neg P$)

Lecture 13 Ch. 3 Section 6 and 1st page of Section 7.
- Contrapositive
- if and only if (iff), symbol $\Leftrightarrow$, (implication in both directions)
- Boolean functions and how to construct them with $\neg, \wedge, \vee$
- DeMorgan's Laws
- Commutative, Associative, and Distributive properties of $\wedge$ and $\vee$

Lecture 14 Ch. 3 Section 7.
- Properties of implication
- The three techniques: Direct proof, Contrapositive, Proof by contradiction
- Examples of each of the above, covering even/odd numbers, rational numbers, and $\sqrt{2}$

Lecture 15 Ch. 3 Sections 2, 3, and 7.
- Proof by contradiction $\neg P\Rightarrow$ False means that $P$ is true
- Technique: start with the negative of the statement, get to something false (called contradiction)
- Three examples of proof by contradiction, $\sqrt{2}$ is irrational, uncoverable grid, and primes are infinite

Lecture 16
- More proofs
- How to prove iff
- A summary of proof techniques, here

Lecture 17 Ch. 3 Section 8 (about countability).
- Hilbert's hotel (thought experiment)
- $S$ is countable iff ($S$ is finite or there is a bijection $f:S\rightarrow \mathbb{N}$)
- $S$ is countable iff there is a one-to-one function $f:S\rightarrow\mathbb{N}$
- S is countable iff elements can be ordered in such a way that every element has a finite rank
- $S$ is infinite and countable means $S$ and $\mathbb{N}$ have the same cardinality
- Subsets, Intersection, and Union of countable sets are countable

Lecture 18 Ch. 3 Section 8
- $\mathbb{Z}$ is countable
- The product of two countable sets is countable
- $\mathbb{Q}$ is countable (think of $\mathbb{Q}$ as a "subset" of $\mathbb{Z}\times\mathbb{N}$)
- $\mathbb{R}$ is uncountable (Cantor's diagonalization proof)
- The power set of a set $S$ is "bigger" than $S$, there is no bijection $f:S\rightarrow \mathcal{P}(S)$ (similar diagonalization proof is possible)

Lecture 19 Ch. 4 Sections 1, 2, 4, and 6
- Inclusion Exclusion
- General formula and proof
- The OR logic (for union)
- Divisibility example
- Good passwords example
- The lazy professor (read Section 3 for next time)

Lecture 20 Ch. 4 Sections 3 and 5, and parts of Section 8
- The Lazy professor revisited (derangments vs. permutations)
- Counting derangements using Inclusion-Exclusion
- Formula for derangements is $!n=n!\sum_{i=0}^n \frac{(-1)^i}{i!} \approx n!/e$
- Basic form of Pigeonhole with examples

Lecture 21 Ch. 4 Secrion 8
- Generalized Pigeonhole with $n$ objects and $m$ boxes
- The $\lceil m/n\rceil$ and $\lfloor(m-1)/n\rfloor +1$ formulas
- Examples of Pigeonhole
- The $m_1+m_2+\ldots+m_n-n+1$ variant form of Pigeonhole

Lecture 22 Ch. 5 is written differently from notes, so follow notes
- Proof by induction
- Base case, inductive hypothesis, induction step
- Examples of proof by induction

Lecture 23
- What can go wrong: no base case, inductive step does not work for all $k$, both ok but result is wrong
- Examples of what can go wrong
- Strong induction: inductive hypothesis $\wedge_{i\leq k}P(i)=P(k)\wedge P(k-1)\wedge\ldots$ as opposed to $P(k)$
- How many base cases are needed? (check values of $k$ for which inductive step actually works)
- Examples of strong induction

Lecture 24
- Induction and recurrences
- Examples of strong induction


PART III

Lecture 25 Ch. 6 Section 6
- Solving Linear Homogeneous Recurrences
- Recurrences of the form $a_n=Aa_{n-1}+Ba_{n-2}$
- The characteristic equation method

Lecture 26 Ch. 6 Sections 1, 2, 3, 4
- Counting by establishing a recurrence
- Name the quantity your counting, e.g. $a_n$, then express $a_n$ in terms of $a_{n-1}, a_{n-2}, \ldots$
- Cutting a place with lines
- Tiling with dominos
- Tower of Hanoi

Lecture 27 Ch.6 Sections 10, 11
- Generating functions
- Solving recurrences using the generating function method
- Solving recurrences asymptotically, e.g. Mergesort
- Divide-and-Conquer has recurrences of the form $T(n)=aT(n/b)+f(n)$

Lecture 28 Ch. 6 Section 12
- More on making homogeneous recurrences
- Solving characteristic equations of degree 3 by guessing one solution and factoring
- Catalan numbers and the recurrence $c_n=c_0c_{n-1}+c_1c_{n-2}+\ldots+c_{n-1}c_0$

Lecture 29 Ch. 7 Sections 1 and 2
- Divisibility, notation $a|b$
- Uniqueness of representation $b=aq+r$, where $0\leq r\lt a$
- $\gcd(a,b)$ and $\textrm{lcm}(a,b)$
- Finding $\gcd(a,b)$ by brute force and prime factorization
- Finding $\gcd(a,b)$ efficiently

Lecture 30 Ch. 7 Sections 3 and 4
- Extended Euclidean algorithm
- Euclidean alg $\Rightarrow \gcd(a,b)=ar+bs$, where $r,s\in\mathbb{Z}$
- Using $ar+bs=a(r+b)+b(s-a)$, we can say: $\gcd(a,b)=ar-bs$, where $r,s\in\mathbb{Z}_{\geq 0}$

Lecture 31 Ch. 7 Sections 5 and 9
- Coprimes: $gcd(a,b)=1\Leftrightarrow ar-bs=1$
- Inverse of $a$ modulo $n$ when $\gcd(a,n)=1$
- Finding the inverse of $a$ modulo $n$ using the extended Euclidean algorithm
- Modular arithmetic

Lecture 32 Ch. 2 Section 2
- Equivalence relation: reflexive, symmetric, transitive
- Classes of equivalence
- Congruence is an equivalent relation

Chapter 0
Read as much as possible from this as soon as you can. The topics of this chapter will be briefly covered as they come up. This chapter covers basic mathematical concepts that we will use at some point during the course. Make sure you are comfortable with most of these concepts.

Chapters 1 - 8 (main topics)
(1) Introduction
- Euler formula: v-e+f=2
- Why counting? (the lazy professor example)
- Basic examples of counting (snakes and ladders)
- Addition and multiplication rules
- Handshake lemma
- Generalization (n choose k)

(2) Counting
- Permutations
- Ordered selection
- n choose k
- Sets, relations, functions
- Onto functions and one-to-one correspondence (bijection)
- Equivalence relations and partial orders
- Anagrams and forming teams
- The binomial theorem and Pascal triangle
- Selection with repetition (ordered and non-ordered)

(3) What is a proof?
- The pigeonhole principle
- Primes are infinite
- A water juggling puzzle
- Proof by contradiction, by case analysis, by picture
- What are proofs?
- A false proof of Pythagoras
- Some logic, Boolean gates/functions
- What is implication?
- Proof by counter example, contradiction (again), contrapositive
- Self reference and diagonalization, the barber paradox
- Countable vs. uncountable

(4) Two useful principles
- The inclusion-exlusion principle, two sets
- What about more than two sets?
- The lazy professor revisited
- More examples of using inclusion-exclusion
- The pigeonhole principle revisited (generalized)
- Examples of using pigeonhole
- The birthday paradox
- Simplified Ramsey theory
- Proving program termination by Ramsey (and partial order)
(5) Inductive proofs
- A weird proof
- Proof by induction, definition
- Some false proofs
- Examples of proof by induction
- Rules of thumb for induction

(6) Recurrences
- What is a recurrence?
- Cutting the plane
- Towers of Hanoi
- Fibonacci
- Solution for a_n=Aa_{n-1}+Ba_{n-2}
- Generating functions
- Sorting
- Traveling in Manhattan and the Calatan numbers
- Stirling numbers
- Balls and bins (6 variantions)

(7) Number theory
- Divisibility and primes
- The Euclidean algorithm, why not brute force?
- The extended Euclidean algorithm
- Co-primes
- Fundamental theorem of arithmetic (uniqueness of prime factorization)
- Properties and distribution of primes
- Congruence as an equivalence relation
- Multiplicative inverses
- The Chinese remainder theorem
- Fermat's little theorem and primality testing
- Cryptography, breaking it by Chinese remaindering

(8) Graphs
- Vertices, edges, and connectivity
- Trees
- Counting trees
- Finding the best tree
- The traveling salesman problem
- Hamiltonian cycles and Eulerian walks
- Graph coloring and planarity

Note: While these notes reflect what is covered in class, they are far from being perfect (e.g. typos) or complete. But they should be self contained. They are intended for class use only. Many examples and explanations are actually taken from the above references, although no referencing is explicit within the text. Therefore, I emphasize that these notes are intended for class use only. For outside visitors of this page, please use them for your own benefit only. Do not distribute. No one should upload these documents on third party websites!

Homework (almost weekly, submitted through Gradescope, follow template in terms of number of pages and order of questions)
Homework 0 Due 1/31/2024
Homework 1 Due 2/7/2024
Homework 2 Due 2/14/2024
Homework 3 Due 2/22/2024
Homework 4 Due 2/29/2024

TEST 1 will be on Wed. March 6 in class from 1:30 to 3:00
Here's a sample TEST 1 and another from previous years
Test results

Homework 5 Due 3/13/2024
Homework 6 Due 3/20/2024
Homework 7 Due 3/28/2024
Homework 8 Due 4/3/2024

TEST 2 will be on Wed. April 10 in class from 1:30 to 3:00
Here are some sample questions for practice, and their answers.

Homework 9 Due 4/18/2024
Homework 10 Due 5/6/2024
Homework 11 (last homework) coming soon...

Solutions to homework and tests

Programming Explorations and Fun Activities (optional, only for those who are interested)
[Integer games]
- Write a function that takes a positive integer $n$ and outputs the Collatz sequence starting with $n$ and ending with $1$. Recall that, given a positive integer $n$, the next number is either $n/2$ if $n$ is even, or $3n+1$ if $n$ is odd. Example: 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1.
Additional idea: Replace the sequence by a binary sequence as follows: If the number goes up, place a 1, and if the number goes down, place a 0. The above sequence becomes: 1 0 0 1 0 0 0 1 0 0 0 0. Explore how different initial numbers lead to different binary patterns. How many 1s are there? What's the average distance between consecutive 1s? Etc...
- Write a function that takes a list of integers $(a_1, a_2, \ldots, a_n)$ of some length $n$ and outputs its Ducci sequence until $(0, 0, \ldots, 0)$ (such algorithm might not stop in general, but it will if $n=4$). Recall that $(a_1, a_2, \ldots, a_n)\rightarrow (|a_1-a_2|, |a_2-a_3|, \ldots, |a_n-a_1|)$. Example: $(1,2,3,4), (1, 1, 1, 3), (0,0,2,2), (0,2,0,2), (2,2,2,2), (0,0,0,0)$.
Additional idea: Find examples for $n\neq 4$ where the sequence never ends. For instance, experiment with $n=3$.

[Listing pairs]
Recall the socks example. Write a function that takes an integer $n$ and outputs all possible pairs; for instance, when $n=5$, the output should look like:

   x x - - -
   x - x - -
   x - - x -
   x - - - x
   
   - x x - -
   - x - x -
   - x - - x
   
   - - x x -
   - - x - x
   
   - - - x x
Additional idea: Can you modify the function to display only pairs that are at a minimum distance $d$? For instance, if the minimum distance is $d=2$, the above example for $n=5$ will become:
   x - x - -
   x - - x -
   x - - - x

   - x - x -
   - x - - x

   - - x - x
Explore how that changes the number of pairs from $n(n-1)/2$. Find a formula in terms of $n$ and $d$.

[Snakes and Ladders]
A snakes and ladders board can be encoded using an array $a[0\ldots n]$, where $a[0]=0$ and $a[n]=n$, and $a[i]=j$ for $0\lt i \lt n$ such that:
 $j\gt i$ means there is a ladder from square $i$ to square $j$, and
 $j\lt i$ means there is a snake with its head on $i$ and tail on $j$, and
 $j=i$ means that square $i$ is just a regular square.
Using such array, one can start at position $0$, and repeatedly obtain a random number in $[1,6]$ and advance the position by that number (if the new position is greater than $n$, the position is unchanged). When in position $i$, $a[i]$ is checked to see if one has to take a ladder or a snake (and update the position accordingly) or simply stay. Depending on the array $a$, one might have to repeatedly check $a[i]$ until $a[i]=i$ (for instance, if $a[i]=j$ and $a[j]=k$, etc...). When positision $n$ is reached, the game ends. Initialize the array $a[0\ldots n]$ to encode the board shown in Lecture 3, and simulate the snakes and ladders game multiple times to find the average number of turns needed to finish.
Additional idea: you can explore the average number of turns for a fixed number of snakes and ladders that are placed randomly, and compare that to a board that has none.

[The next permutation]
Write a function that, given a permutation of $(1,2,\ldots,n)$, will change it to the next permutation. For example, if the permutation is $(1,4,6,2,9,5,8,7,3)$ (here $n=9$), it will become $(1,4,6,2,9,7,3,5,8)$, which is the permutation that should appear next in "alphabetical order"; we call it lexicographic order. Here's an algorithm of how this may be done assuming the permutation is stored in an array.
1. Find the largest $i$ such that $a[i]\lt a[i+1]$
2. Find the largest $j$ such that $a[j]\gt a[i]$
3. If $i$ and $j$ are within bounds, swap $a[i]$ and $a[j]$
4. Reverse $a[i+1\ldots n-1]$
Additional idea: You can use this function to generate all anagrams of a given word $w$ (even when letters repeat). Simply replace $``\lt"$ with its appropriate meaning for letters. Alternatively, you could start with an array representing the word; for instance, "mathematics" corresponds to $[0,1,2,3,4,0,1,2,5,6,7]$. You can then output $w[a[0]], w[a[1]], \ldots, w[a[n-1]]$, and repeatedly obtain the next $a$ and output letters of $w$. You stop when you reach the original $a$ again.

[Integer solutions]
By now you know how to count the integer solutions to $x_1+x_2+\ldots+x_n=k$, where $x_i\in\{0,1,2,3,\ldots\}$. In this programming exercise, you will write a function to count the number of integer solutions when $x_i\in \{a,b\}$, where $0\leq a\lt b$ are two integers. Therefore, your function takes as parameters four integers $n$, $k$, $a$, and $b$, and returns the number of integer solutions to $x_1+x_2+\ldots+x_n=k$ if each $x_i\in\{a,b\}$. Hint: Making the function recursive is very helpful here. We are not after a closed form expression for the number, just a program to compute it. If we define this number of be $T(n,k)$, the following recurrence will help figure out the recursion: $T(n,k) = T(n-1, k-a) + T(n-1,k-b)$ (why?). Appropriate base cases must be used of course to stop the recursion.
Additional idea: Can you figure out what $T(n,k)$ is for special cases; for instance, what is $T(n,k)$ when $a=0$ and $b=1$? You are welcome to think about other special cases.
Extra idea: The recursive implementation, while easy, is not efficient. For instance, it recomputes the same quantities multiple times. Here's an example: Assume $a=0$ and $b=1$. Then, $T(n,k)=T(n-1,k)+T(n-1,k-1)$ $=[T(n-2,k)+T(n-2,k-1)]+[T(n-2,k-1)+T(n-2,k-2)]=\ldots$. You can see that $T(n-2,k-1)$ has already appeared twice. A more efficient implementation uses a two-dimensional array $T$ of size $(n+1)\times(k+1)$ to store computed values, where $T(i,j)$ is computed by accessing the pre-computed entries $T(i-1,j-a)$ and $T(i-1,j-b)$. Therefore, each entry is computed in terms of previously computed entries for smaller $i$ and $j$, starting with $T(0,0)$. When we find $T(n,k)$, we are done. This is the power of memoization!

[The Pascal triangle walk]
Given an integer $n\geq 0$, and two integers $a\geq 0$ and $b\geq 0$ such that $a+b>0$, start on the first number in the $n^{th}$ row of the Pascal triangle. Then move $a$ steps to the right, and $b$ steps diagonally up, to land on another number. Repeat this process until you exit the Pascal triangle. Write a function to compute the sum of all the numbers you land on before you exit. Find interesting patterns for special cases of $a$ and $b$. For instance, what do you get when $a=1$ and $b=0$, or when $a=0$ and $b=1$, or when $a=1$ and $b=1$? Avoid computing $\binom{n}{k}$ explicitly, so to compute the number that is $a$ steps away to the right and $b$ steps away up, update the current number by making appropriate multiplications and divisions. To do this, think about how to get the number that is one step away to the right, and how to get the number that is one step away up.
Extra idea: Instead of starting on the first number in row $n$, let $0\leq k\leq n$ be another integer input, and start on the $k^{th}$ number in row $n$. Experiment with different values of $n$ and $k$ for $a=0$ and $b=1$. What do you observe?

[Playing with arrays]
- Let $a$ be an array of integers of size $n$, where $a$ is supposed to encode a function $f:\{0,\ldots, n-1\}\rightarrow\{0,\ldots,n-1\}$. For instance, if $a[i]=j$, then this means $f(i)=j$. Write a function to test whether $f$ is one-to-one, and a function to test whether $f$ is onto. Extra idea: Given two such arrays $a$ and $b$ encoding functions $f$ and $g$, construct an array $c$ that represents $f \circ g$. Note $f\circ g(x)=f(g(x))$. Check the three properties: one-to-one, onto, and bijection. Which of them carry over; for instance, if $f$ and $g$ both satisfy a property, does that mean $f\circ g$ will? Similarly, if $f\circ g$ satisfies a property, does that mean either $f$ or $g$ must?
- Given an array $a$ as described above where all elements are in $\{0,\ldots,n-1\}$, imagine the following jumping game: start at 0 and move to $i=a[0]$. Then move to $j=a[i]$, and so on until you come back to 0 (you may never come back to 0). Write a function that determines whether the jumping game ends. Your function must always terminate with a decision. Extra challenge: what if your function cannot modify the array, and cannot use more than a constant amount of memory in addition to the array itself (so it cannot copy the array, for instance)?
- Write a function that takes a non-negative integer as input and returns an 0-1 array containing its binary representation (the same integer in base 2).

[Boolean functions]
Write a function that accepts an array of 8 bits $[b_0, b_1, ..., b_7]$, and outputs the Boolean function $f(x,y,z)$ corresponding to $f(0,0,0)=b_0, f(0,0,1)=b_1,\ldots, f(1,1,1)=b_7$. For example, if the array is $[0,0,0,1,0,1,1,1]$, the output will be: (~x /\ y /\ z) \/ (x /\ ~y /\ z) \/ (x /\ y /\ ~z) \/ (x /\ y /\ z).
Extra idea: choose whether to encode the function based on the number of 0s or the number of 1s, whichever leads to a smaller representation. For instance, if we have fewer zeros, then negate the array, obtain the Boolean function, and finally negate it (using DeMorgan's law). Here's an example: Given [0,1,1,1,0,1,1,1], we would negate this to get [1,0,0,0,1,0,0,0]. This gives the Boolean function (~x /\ ~y /\ ~z) \/ (x /\ ~y /\ ~z). Negating this, we get (x \/ y \/ z) /\ (~x \/ y \/ z).

[Prime numbers]
We have seen in class that primes are infinite. One interesting computer program is to generate all primes less than a given integer $n$. A simple way to do this is the sieve of Erathosthenes, which is essentially this: Start with an array $a[0...n-1]$ of all 1s and make $a[0]=a[1]=0$ indicating that 0 and 1 are not prime. The first prime is therefore 2, with $a[2]=1$ and let $p=2$. The program makes $a[i]=0$ for $i = 2p, 3p, 4p,\ldots$ i.e. every $i$ that is a multiple of $p$ (except $p$ itself), indicating that these numbers cannot be prime, and thus eliminating them. Then $p$ is updated by scanning the array to find the next prime, which is first number $i>p$ such that $a[i]$ is still 1. The process of elimination is repeated until the entire array has been scanned. Finally, $a[i]=1$ means that $i$ is prime for all $0\le i\le n-1$. Implement this idea. Note 1: For large $n$, this becomes not very practical in terms of memeory (but time is almost linear in $n$). Note 2: You can google the sieve of Erathosthenes to learn more about it and explore alternatives.

[Divisibility]
Write a function that accepts a positive integer $n$, and an array $p$ of length $k$, such that $p[0], p[1], \ldots, p[k-1]$ are all prime, and returns the number of integers in $\{1,2,\ldots, n\}$ that are divisible by any $p[i]$, $i=0,\ldots,k-1$. Explore three approaches:
- (Approach 1) The brute force approach: go through every integer $m$ in $\{1,\ldots,n\}$ and check if $m$ modulo $p[i]$ is 0 for any $i$. This essentially consists of two nested loops
    for m in range(1,n+1):
      for i in range(0,k):
        #check if m modulo some p[i] is zero and increment a count
This will be $O(nk)$ time, which is pretty slow especially when $n$ is large; for instance, try it on $n=1000000000$ (a billion) and $p=[2,3,5]$, and see how long it takes in seconds.
- (Approach 2) The inclusion-exclusion approach: For every non-empty subset S of $\{0,\ldots, k-1\}$, find $\Big\lfloor \frac{n}{\prod_{i\in S}p[i]}\Big\rfloor$ and sum these up with the appropriate sign. This is $O(k2^k)$ time, which is better if $k$ is less than logarithmic in $n$; for instance, if $k$ is just a constant like 3. The difficulty of this approach lies in being able to go through all subsets. One way to do this is to go through all numbers in $[1,2^k-1]$, convert each to its binary representation, and if the $i^{th}$ bit is 1, then $p[i]$ is included in the product.
- (Approach 3) If every $p[i]$, for $i=0,\ldots,k-1$, is a prime factor of $n$, find a very fast way of achieving the same task.

[Twos, Threes, and Fives]
Imagine a world where the prime numbers are only 2, 3, and 5. Then there is no 7, 11, 13, or even 14 (because $14=2\times7$ and there is no 7). Of course this makes no sense, but what if we want to generate all numbers that have no prime factors other than 2, 3, and 5? Here's how the list looks like: $1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, \ldots$
Using an array of size $n$, generate the first $n$ integers of this sequence. In other words, the first $n$ positive integers that are the product of just 2s, 3s, and 5s. Explore two approaches.
- (Approach 1) One way to do this is to go through the integers in $\mathbb{N}=\{1, 2, 3,\ldots\}$ one at a time and check for each whether it is a product of 2s, 3s, and 5s, until you fill the $n$ entries of the array.
- (Approach 2) A more efficient way is based on the following idea: Assume that you have generated the sequence up to some integer $m$ and you are about to generate the next integer, call it $w$. The integer $w$ must be either $2x$, $3y$, or $5z$, for some $x$, or $y$, or $z$ that has been generated already. Furthermore, $w$ must be the smallest such integer greater than $m$. Therefore, it is enough to know the smallest $x$ among those generated such that $2x\gt m$, and similarly, the smallest $y$ such that $3y\gt m$ and the smallest $z$ such that $5z\gt m$. So what if we just keep track of the indices of these three as we fill the array? Initially, $a[0]=1$, and the indices of $x$, $y$, and $z$ are all $0$, meaning $x=y=z=a[0]=1$. The next number of be generated is the smallest among $2x$, $3y$, and $5z$. It is obviously $2x=2$. So $a[1]=2$, and the index of $x$ is incremented by 1, making $x=a[1]=2$. There will be times where more than one among $x$, $y$, and $z$ can generate the next number $w$; for instance, when $2x=3y$ (what do we do?).

[Right triangles]
This problem was designed with the idea of pigeonhole in mind. In an $n\times n$ grid, place $2n-1$ points. Then three of the points must make a right triangle (can you prove this fact?). To encode the grid and the points, you may consider a two dimensional array of size $n\times n$ initialized to all 0s, and randomly make $2n-1$ of the entries 1s. Write a program to find a right triangle (three 1s that make a right triangle). You can output the right triangle in any way you want; for instance, you can display the grid with $2n-4$ points represented by "." and the three points of the right triangle by "o". Alternatively, you can simply output the coordinates of the three 1s making the right triangle. Hint: To find a right triangle, you should know that there must be one with two 1s in the same row and two 1s in the same column.
Additional ideas: Your algorithm to find a right triangle needs not be efficient. For instance, the two dimensional array occupies $O(n^2)$ memeory, even though only $2n-1$ points are needed. Furthermore, the search for the right triangle can be exhaustive. But how can we make the algorithm efficient? In addition, if one point moves, how can we find a new triangle quickly?
For an illustration of this, check here (make the width of your browser narrow to see the entire grid).

[Trominos]
A classical proof by induction establishes that a two dimensional array a of size $2^n\times2^n$ with one missing square can be tiled with L-shaped trominos. Look for this classical proof, which suggests how to tile the array with trominos. Then write a recursive function that takes $n$, $i$, $j$, $k$, and $l$ as parameters and returns the id of the tromino that covers $a[k,l]$ if $a[i,j]$ is the missing square. The requirement is that the function must return the same positive integer id for all squares that are covered by the same L-shaped tromino. If $(k,l)=(i,j)$, return 0. Remark: This is for those who want to experiment with a non-trivial handling of recursive information. I had to think about this one!

[Recurrence]
Write a function that takes the parameters $a_0$, $a_1$, $A$, $B$, and $n$ and returns $a_n$ assuming that $a_n$ satisfies the recurrence $a_n = Aa_{n-1} + Ba_{n-2}$. Make two version of this function, one recursive, and one that uses an array $a[0\ldots n]$. Compare the performance of the two functions in terms of running time on large values of $n$.
Extra idea: Use the characteristic equation method to find $a_n$.

[Euclidean Algorithm]
Implement the Euclidean algorithm: Given two integers $a$ and $b$, write a function that returns $\gcd(a,b)$.
(Approach 1) Use recursion: your implementation will rely on the idea that $\gcd(a,b)=gcd(b,a\bmod b)$, with the base case given when $b=0$.
(Approach 2) Use iteration: Keep two variables $a$ and $b$, and repeatedly make the change $a\leftarrow b$ and $b\leftarrow a\bmod b$, until $b$ becomes 0.
Extra Idea: Compute the greatest common divisor of multiple integers: The input to your function is an array of length $n$, and the function should return $\gcd(a[0], \ldots, a[n-1])$.
(Approach 1): Use the fact that $\gcd(a,b,c)=\gcd(\gcd(a,b),c)$.
(Approach 2): Generalize the Euclidean algorithm to handle $n$ integers (instead of just two). You start with the array $a[0\ldots n-1]$ such that $a[0]\gt a[1]\gt\ldots\gt a[n-1]$ (although this order is not really necessary), and two indices $i=0$ and $j=n-1$. Both $i$ and $j$ advance circularly throughout the execution of the algorithm. In other words, if we advance $i$, we make $i\leftarrow (i+1)\bmod n$. We then repeatedly perform the following. Find $a[i]\bmod a[j]$. If the result is non-zero, advance both $i$ and $j$ and write the result in $a[j]$. If the result is zero, only advance $i$ and do not change the array. When $i=j$, $a[i]$ holds the greatest common divisor. Try this algorithm when $n=2$ as well.

[Inverse]
Write a function that takes two positive integers $a$ and $n$ and returns the inverse of $a$ modulo $n$ if it exists. In other words, an integer $b$, such that $ab\equiv 1\ (\bmod n)$ (we typically denote $b$ by $a^{-1}$). If such an integer does not exist, your function can return 0.

[Program termination]
Implement the following program and run it several times and observe that it always terminates. In each iteration, print the tuple $(z,x)$ to observe that it's decreasing according to some partial order relation (which one?). Here's the pseudocode for the program (modify as needed):
x = rand(1, n)
y = rand(1, n)
z = rand(1, n)
while x>0 and y>0 and z>0
  control = rand(1,2)
  if control == 1
    x = rand(x, n)
    y = rand(y, n)
    z = z-1
  else
    y = rand(y, n)
    x = x-1

[Primality testing]
Implement the prime test algorithm based on Fermat's theorem to decide whether an integer $n$ is prime or not. Use repeated squaring and modulo $n$ calculations.

Grading policy
Homework 10% (almost weekly)
Test 1 25% (*)
Test 2 25% (*)
Final 40% (scheduled by Hunter College on 5/16/2024, 1:45 - 3:45)

(*) Date will be announced at least 10 days in advance. Given that lecture time is only 50 minutes (from 1:30 to 2:20), tests will use an extended class session from 1:30 to 3:00 to allow for more time.