# Lab 9: List Induction Practice
## Problem 1: Warm-Up
### 1. Proof Sketch
- We know `l` is an arbitrary list.
- `l` can be either empty or non-empty, and `l` can contain inner lists (a list of lists).
- In function `tails`, lists are being `cons`ed to more lists, making a list of lists. Therefore, the length of said list would be the number of lists inside of it.
- Now, we would analyze the case of `l` being empty, and prove the equivalence between both sides for this case.
- For function `length`, the empty case would return `0`.
- For function `tails`, the empty case would return a list containing one empty list.
- For the non-empty list case, we would evaluate as usual until we cannot proceed further and then use the induction hypothesis to prove equivalence.
- For function `length`, the non-empty case would return `(+ 1 (length tail))`.
- For function `tails`, the non-empty case would return `(cons l (tails tail))`.
### 2. Formal Proof
**Claim**: For all lists `l`, `(length (tails l))` ≡ `(+ 1 (length l))`.
_Proof_. Let `l` be an arbitrary list. We prove this claim by induction on `l`.
Either `l` is empty or non-empty.
- **`l` is empty**.
The left-hand side, `(length (tails '()))`, evaluates as follows:
```racket
(length (tails '()))
-->* (length '('()))
-->* (+ 1 (length '()))
-->* (+ 1 0)
--> 1
```
The right-hand side, `(+ 1 (length '()))`, evaluates as follows:
``` racket
(+ 1 (length '()))
-->* (+ 1 0)
--> 1
```
- **`l` is non-empty**: Let `tail` be the tail of `l`. We assume our induction hypothesis:
**Induction Hypothesis**: `(length (tails tail))` ≡ `(+ 1 (length tail))`.
We must prove:
**Goal**: `(length (tails l))` ≡ `(+ 1 (length l))`.
The left-hand side, `(length (tails l))`, evaluates as follows:
```racket
(length (tails l))
-->* (length (cons l (tails tail)))
```
`(cons l (tails tail))` is a list with `l` as the head and `(tails tail)` as the tail. Then we have:
```racket
-->* (+ 1 (length (tails tail)))
```
The right hand side, `(+ 1 (length l))`, evaluates as follows:
```racket
(+ 1 (length l))
-->* (+ 1 (+ 1 (length tail)))
```
By our induction hypothesis:
`(+ 1 (length (tails tail)))` ≡ `(+ 1 (+ 1 (length tail)))`.
`(+ 1 (+ 1 (length tail)))` ≡ `(+ 1 (+ 1 (length tail)))`.
Therefore, the left-hand side steps to the value that the right-hand side steps to.
□
## Problem 2: A World Apart
### 1. Proof Sketch
- We know that `l` is an arbitrary list.
- `l` can be either empty or non-empty.
- Now, we would analyze the case of `l` being empty, and prove the equivalence between both sides for this case.
- For function `list-inc`, the empty case would return `'()`.
- For function `sum`, the empty case would return `0`.
- For a non-empty list, we would evaluate both sides as usual until we cannot proceed any furhter. Then, we need to use the induction hypothesis to prove equivalence.
- For function `list-inc`, the non-empty case would return `(cons (+ 1 head) (list-inc tail))`, essentially adding `1` to every element in `l`.
- For function `sum`, the non-empty case would return `(+ head (sum tail))`.
### 2. Formal Proof
**Claim**: For any list of numbers `l`, `(sum (list-inc l))` ≡ `(+ (length l) (sum l))`.
_Proof_. Let `l` be an arbitrary list. We prove this claim by induction on `l`.
Because `l` is a list, `l` is either empty or non-empty.
- **l is empty**.
The left-hand side, `(sum (list-inc '()))`, evaluates as follows:
```racket
(sum (list-inc '()))
-->* (sum '())
-->* 0
```
The right-hand side, `(+ (length '()) (sum '()))`, evaluates as follows:
```racket
(+ (length '()) (sum '()))
-->* (+ 0 (sum '()))
-->* (+ 0 0)
--> 0
```
- **l is non-empty**. Let `head` and `tail` be the head and tail of `l`, respectively. We assume our induction hypothesis:
**Induction Hypothesis**: `(sum (list-inc tail))` ≡ `(+ (length tail) (sum tail))`.
We must prove:
**Goal**: `(sum (list-inc l))` ≡ `(+ (length l) (sum l))`.
The left-hand side, `(sum (list-inc l))`, evaluates as follows:
```racket
(sum (list-inc l))
-->* (sum (cons (+ 1 head) (list-inc tail)))
```
`(cons (+ 1 head) (list-inc tail))` is a list with `(+ 1 head)` as the head and `(list-inc tail)` as the tail.
```racket
-->* (+ (+ 1 head) (sum (list-inc tail)))
-->* (+ 1 (+ head (sum (list-inc tail))))
```
The final step of evaluation comes from the commutative property of addition: `(1 + x)` + `y` = `1` + `(x + y)`.
The right-hand side, `(+ (length l) (sum l))`, evaluates as follows:
```racket
(+ (length l) (sum l))
-->* (+ (+ 1 (length tail)) (sum l))
-->* (+ (+ 1 (length tail)) (+ head (sum tail)))
-->* (+ 1 (+ (length tail) (+ head (sum tail))))
-->* (+ 1 (+ head (+ (length tail) (sum tail))))
```
The final two steps of evaluation come from the commutative property of addition: `(1 + x)` + `y` = `1` + `(x + y)`.
By our induction hypothesis:
`(+ 1 (+ head (sum (list-inc tail))))` ≡ `(+ 1 (+ head (+ (length tail) (sum tail))))`.
`(+ 1 (+ head (+ (length tail) (sum tail))))` ≡ `(+ 1 (+ head (+ (length tail) (sum tail))))`.
Therefore, the left-hand side steps to the value that the right-hand side steps to.
□
## Problem 3: Building Up Facts
1. `rev`:
```racket
(define rev
(lambda (l)
(match l
['() '()]
[(cons head tail) (snoc (rev tail) head)])))
```
2. **Claim (Snoc Length)**: For all lists `l` and values `v`, `(length (snoc l v))` ≡ `(+ 1 (length l))`.
_Proof_. Let `l` be an arbitrary list, and let `v` be an arbitrary value. We prove this claim by induction on `l`.
Either `l` is empty or non-empty.
- **`l` is empty**.
The left-hand side, `(length (snoc '() v))` evaluates as follows:
```racket
(length (snoc '() v))
-->* (length (list v))
--> (length '(v))
-->* (+ 1 (length '()))
-->* (+ 1 0)
--> 1
```
The right-hand side, `(+ 1 (length '()))`, evaluates as follows:
```racket
(+ 1 (length '()))
-->* (+ 1 0)
--> 1
```
- **`l` is nonempty**. Let `head` and `tail` be the head and tail of the list, respectively. We assume our induction hypothesis:
**Induction Hypothesis**: `(length (snoc tail v))` ≡ `(+ 1 (length tail))`.
We must prove:
**Goal**: `(length (snoc l v))` ≡ `(+ 1 (length l))`.
The left-hand side, `(length (snoc l v))`, evaluates as follows:
```racket
(length (snoc l v))
-->* (length (cons (car l) (snoc (cdr l) v)))
-->* (length (cons head (snoc tail v)))
```
`(cons head (snoc tail v))` is a list with `head` as the head and `(snoc tail v)` as the tail.
```racket
-->* (+ 1 (length (snoc tail v)))
```
The right-hand side, `(+ 1 (length l))`, evaluates as follows:
```racket
(+ 1 (length l))
-->* (+ 1 (+ 1 (length tail)))
```
By our induction hypothesis:
`(+ 1 (length (snoc tail v)))` ≡ `(+ 1 (+ 1 (length tail)))`.
`(+ 1 (+ 1 (length tail)))` ≡ `(+ 1 (+ 1 (length tail)))`
Therefore, the left-hand side steps to the same value that the right-hand side steps to.
□
3. **Claim (Rev Length)**: For all lists `l`, `(length (rev l))` ≡ `(length l)`.
_Proof_. Let `l` be an arbitrary list. We prove this claim by induction on `l`.
Either `l` is empty or non-empty.
- **`l` is empty**.
The left-hand side evaluates as follows:
```racket
(length (rev '()))
-->* (length '())
-->* 0
```
The right-hand side evaluates as follows:
```racket
(length '())
-->* 0
```
- **`l` is non-empty**. Let `head` and `tail` be the head tail of the list, respectively. We assume our induction hypothesis:
**Induction Hypothesis**: `(length (rev tail))` ≡ `(length tail)`.
We must prove:
**Goal**: `(length (rev l))` ≡ `(length l)`.
The left-hand side evaluates as follows:
```racket
(length (rev l))
-->* (length (snoc (rev tail) head))
-->* (+ 1 (length (rev tail)))
```
The last step of the evaluation was derived using the Snoc Length property: `(length (snoc l v))` ≡ `(+ 1 (length l))`.
The right-hand side evaluates as follows:
```racket
(length l)
-->* (+ 1 (length tail))
```
By our induction hypothesis:
`(+ 1 (length (rev tail)))` ≡ `(+ 1 (length tail))`.
`(+ 1 (length tail))` ≡ `(+ 1 (length tail))`.
Therefore, the left-hand side steps to the same value that the right-hand side steps to.
□