-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
290 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
/- # Problem 56 | ||
Let us call a binary tree symmetric if you can draw a vertical line through the root node and then the right subtree is the mirror image of the left subtree. Write a predicate symmetric/1 to check whether a given binary tree is symmetric. Hint: Write a predicate mirror/2 first to check whether one tree is the mirror image of another. We are only interested in the structure, not in the contents of the nodes. | ||
-/ | ||
|
||
inductive BinTree (α : Type) where | ||
| empty : BinTree α | ||
| node : α → BinTree α → BinTree α → BinTree α | ||
deriving Repr | ||
|
||
def leaf {α : Type} (a : α) : BinTree α := .node a .empty .empty | ||
|
||
/-- This is used to display `#check` results -/ | ||
@[app_unexpander BinTree.node] | ||
def leaf.unexpander : Lean.PrettyPrinter.Unexpander | ||
| `($_ $a BinTree.empty BinTree.empty) => `(leaf $a) | ||
| _ => throw () | ||
|
||
/-- Use `leaf` to display `#eval` results -/ | ||
def BinTree.toString {α : Type} [ToString α] (t : BinTree α) : String := | ||
match t with | ||
| .node v .empty .empty => s!"leaf {v}" | ||
| .node v l r => s!"BinTree.node {v} ({toString l}) ({toString r})" | ||
| .empty => "empty" | ||
|
||
variable {α : Type} | ||
|
||
def BinTree.mirror (s t : BinTree α) : Bool := | ||
-- sorry | ||
match s, t with | ||
| .empty, .empty => true | ||
| .node _ a b, .node _ x y => mirror a y && mirror b x | ||
| _, _ => false | ||
-- sorry | ||
|
||
def BinTree.isSymmetric (t : BinTree α) : Bool := | ||
-- sorry | ||
match t with | ||
| .empty => true | ||
| .node _ l r => mirror l r | ||
-- sorry | ||
|
||
-- The following codes are for test and you should not edit these. | ||
|
||
#guard BinTree.isSymmetric (leaf 'x') | ||
|
||
#guard ! BinTree.isSymmetric (BinTree.node 'x' (leaf 'x') BinTree.empty) | ||
|
||
#guard BinTree.isSymmetric (BinTree.node 'x' (leaf 'x') (leaf 'x')) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
/- # Problem 57 | ||
Use the predicate add/3, developed in chapter 4 of the course, to write a predicate to construct a binary search tree from a list of integer numbers. | ||
-/ | ||
|
||
inductive BinTree (α : Type) where | ||
| empty : BinTree α | ||
| node : α → BinTree α → BinTree α → BinTree α | ||
|
||
def leaf {α : Type} (a : α) : BinTree α := .node a .empty .empty | ||
|
||
/-- This is used to display `#check` results -/ | ||
@[app_unexpander BinTree.node] | ||
def leaf.unexpander : Lean.PrettyPrinter.Unexpander | ||
| `($_ $a BinTree.empty BinTree.empty) => `(leaf $a) | ||
| _ => throw () | ||
|
||
/-- Use `leaf` to display `#eval` results -/ | ||
def BinTree.toString {α : Type} [ToString α] (t : BinTree α) : String := | ||
match t with | ||
| .node v .empty .empty => s!"leaf {v}" | ||
| .node v l r => s!"BinTree.node {v} ({toString l}) ({toString r})" | ||
| .empty => "empty" | ||
|
||
instance {α : Type} [ToString α] : ToString (BinTree α) := ⟨BinTree.toString⟩ | ||
|
||
variable {α : Type} | ||
|
||
instance [Ord α] : Max α where | ||
max x y := | ||
match compare x y with | ||
| .lt => y | ||
| _ => x | ||
|
||
def BinTree.max [Ord α] (t : BinTree α) : Option α := | ||
match t with | ||
| .empty => none | ||
| .node v l r => | ||
let left_max := (max l).getD v | ||
let right_max := (max r).getD v | ||
some <| [v, left_max, right_max].foldl Max.max v | ||
|
||
def BinTree.searchTree [Ord α] (t : BinTree α) : Bool := | ||
-- sorry | ||
match t with | ||
| .empty => true | ||
| .node v l r => | ||
let left_max := (max l).getD v | ||
let right_max := (max r).getD v | ||
match compare left_max v, compare v right_max with | ||
| _, .gt => false | ||
| .gt, _ => false | ||
| _, _ => searchTree l && searchTree r | ||
-- sorry | ||
|
||
def BinTree.searchTreeFromList [Ord α] (xs : List α) : BinTree α := | ||
-- sorry | ||
xs.foldl insert BinTree.empty | ||
where | ||
insert : BinTree α → α → BinTree α | ||
| .empty, x => leaf x | ||
| .node v l r, x => | ||
match compare x v with | ||
| .lt => BinTree.node v (insert l x) r | ||
| _ => BinTree.node v l (insert r x) | ||
-- sorry | ||
|
||
-- The following codes are for test and you should not edit these. | ||
|
||
#guard BinTree.node 3 (.node 2 (leaf 1) .empty) (.node 5 .empty (leaf 7)) |>.searchTree | ||
|
||
#guard BinTree.searchTreeFromList [3, 2, 5, 7, 1] |>.searchTree |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
/- # Problem 58 | ||
Apply the generate-and-test paradigm to construct all symmetric, completely balanced binary trees with a given number of nodes. | ||
-/ | ||
|
||
/-- binary tree -/ | ||
inductive BinTree (α : Type) where | ||
| empty : BinTree α | ||
| node : α → BinTree α → BinTree α → BinTree α | ||
|
||
def leaf {α : Type} (a : α) : BinTree α := .node a .empty .empty | ||
|
||
variable {α : Type} [ToString α] | ||
|
||
def String.addIndent (s : String) (depth : Nat) : String := | ||
Nat.repeat (fun s => " " ++ s) depth s | ||
|
||
def BinTree.toString (tree : BinTree α) : String := | ||
aux tree 2 | ||
where | ||
aux (tree : BinTree α) (depth : Nat) : String := | ||
match tree with | ||
| .node v .empty .empty => s!"leaf {v}" | ||
| .node v l r => | ||
let ls := aux l (depth + 2) | ||
let rs := aux r (depth + 2) | ||
s!".node {v}\n" ++ s!"{ls}\n".addIndent depth ++ s!"{rs}\n".addIndent depth | ||
| .empty => "empty" | ||
|
||
instance {α : Type} [ToString α] : ToString (BinTree α) := ⟨BinTree.toString⟩ | ||
|
||
#eval BinTree.node 3 (.node 2 (leaf 1) .empty) (.node 5 .empty (leaf 7)) | ||
|
||
#eval BinTree.node 'x' (leaf 'x') (leaf 'x') | ||
|
||
#eval BinTree.node 'x' .empty (leaf 'x') | ||
|
||
#eval BinTree.node 'x' (leaf 'x') .empty | ||
|
||
/-- monad instance of `List` -/ | ||
instance : Monad List where | ||
pure := @List.pure | ||
bind := @List.bind | ||
map := @List.map | ||
|
||
/-- construct all balanced binary trees which contains `x` elements -/ | ||
partial def cbalTree (x : Nat) : List (BinTree Unit) := | ||
-- sorry | ||
match x with | ||
| 0 => [.empty] | ||
| n + 1 => do | ||
let q := n / 2 | ||
let r := n % 2 | ||
let indices := List.range (q+r+1) |>.drop q | ||
let i ← indices | ||
let left ← cbalTree i | ||
let right ← cbalTree (n - i) | ||
pure (BinTree.node () left right) | ||
-- sorry | ||
|
||
def BinTree.mirror (s t : BinTree α) : Bool := | ||
match s, t with | ||
| .empty, .empty => true | ||
| .node _ a b, .node _ x y => mirror a y && mirror b x | ||
| _, _ => false | ||
|
||
def BinTree.isSymmetric (t : BinTree α) : Bool := | ||
match t with | ||
| .empty => true | ||
| .node _ l r => mirror l r | ||
|
||
/-- construct all balanced, symmetric binary trees with given number of elements -/ | ||
def symCbalTrees (n : Nat) : List (BinTree Unit) := | ||
-- sorry | ||
cbalTree n |>.filter BinTree.isSymmetric | ||
-- sorry | ||
|
||
-- The following codes are for test and you should not edit these. | ||
|
||
#guard (symCbalTrees 5).length = 2 | ||
#guard (symCbalTrees 6).length = 0 | ||
#guard (symCbalTrees 7).length = 1 | ||
#guard (symCbalTrees 8).length = 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
/- # Problem 59 | ||
Construct height-balanced binary trees. | ||
-/ | ||
|
||
/-- binary tree -/ | ||
inductive BinTree (α : Type) where | ||
| empty : BinTree α | ||
| node : α → BinTree α → BinTree α → BinTree α | ||
|
||
deriving Repr | ||
|
||
def leaf {α : Type} (a : α) : BinTree α := .node a .empty .empty | ||
|
||
variable {α : Type} [ToString α] | ||
|
||
def BinTree.height (t : BinTree α) : Nat := | ||
match t with | ||
| .empty => 0 | ||
| .node _ l r => 1 + max l.height r.height | ||
|
||
/-- monad instance of `List` -/ | ||
instance : Monad List where | ||
pure := @List.pure | ||
bind := @List.bind | ||
map := @List.map | ||
|
||
/-- construct all balanced binary trees which contains `x` elements -/ | ||
partial def cbalTree (x : Nat) : List (BinTree Unit) := | ||
-- sorry | ||
match x with | ||
| 0 => [.empty] | ||
| n + 1 => do | ||
let q := n / 2 | ||
let r := n % 2 | ||
let indices := List.range (q+r+1) |>.drop q | ||
let i ← indices | ||
let left ← cbalTree i | ||
let right ← cbalTree (n - i) | ||
pure (BinTree.node () left right) | ||
-- sorry | ||
|
||
variable {β : Type} | ||
|
||
def List.product (as : List α) (bs : List β) : List (α × β) := do | ||
let a ← as | ||
let b ← bs | ||
return (a, b) | ||
|
||
/-- construct all balanced binary trees whose hight is `height`. -/ | ||
def hbalTrees (height : Nat) : List (BinTree Unit) := | ||
-- sorry | ||
match height with | ||
| 0 => [.empty] | ||
| 1 => [leaf ()] | ||
| h + 2 => | ||
let t1s := hbalTrees (h + 1) | ||
let t2s := hbalTrees h | ||
let ts := List.product t1s t2s ++ List.product t2s t1s | ||
ts.map fun (t1, t2) => BinTree.node () t1 t2 | ||
-- sorry | ||
|
||
-- The following codes are for test and you should not edit these. | ||
|
||
#guard (hbalTrees 2 |>.length) = 2 | ||
#guard (hbalTrees 3 |>.length) = 4 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
leanprover/lean4:v4.11.0-rc3 | ||
leanprover/lean4:v4.11.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters