Skip to content

Instantly share code, notes, and snippets.

@huynhtrankhanh
Created October 18, 2021 16:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save huynhtrankhanh/dff7036a45073735305caedc891dedf2 to your computer and use it in GitHub Desktop.
Save huynhtrankhanh/dff7036a45073735305caedc891dedf2 to your computer and use it in GitHub Desktop.
import tactic.norm_num
import tactic.unfold_cases
import tactic.nth_rewrite
import tactic.linarith
universe u
inductive bracket_t
| left
| right
inductive balanced : list bracket_t → Prop
| empty : balanced []
| wrap (initial : list bracket_t) : balanced initial → balanced ([bracket_t.left] ++ initial ++ [bracket_t.right])
| append (initial1 initial2 : list bracket_t) : balanced initial1 → balanced initial2 → balanced (initial1 ++ initial2)
def balance_factor : ∀ length : ℕ, ∀ string : list bracket_t, ℤ
| 0 _ := 0
| _ [] := 0
| (n + 1) (bracket_t.left::rest) := 1 + balance_factor n rest
| (n + 1) (bracket_t.right::rest) := -1 + balance_factor n rest
def balance_factor_predicate (string : list bracket_t) := balance_factor string.length string = 0 ∧ ∀ n : ℕ, n < string.length → 0 ≤ balance_factor n string
def chop_head : list bracket_t → list bracket_t
| [] := []
| (head::rest) := rest
def chop_other_end : list bracket_t → list bracket_t
| [] := []
| (head::rest) := if rest.length = 0 then [] else head::chop_other_end rest
noncomputable def meaningless_element : bracket_t := @classical.choice bracket_t begin
exact nonempty.intro bracket_t.left,
end
noncomputable def get_head : list bracket_t → bracket_t
| [] := meaningless_element
| (head::rest) := head
noncomputable def get_tail : list bracket_t → bracket_t
| [] := meaningless_element
| (head::rest) := if rest.length = 0 then head else get_tail rest
lemma reconstitute : ∀ string : list bracket_t, 0 < string.length → chop_other_end string ++ [get_tail string] = string
| [] h := begin
rw (show ([] : list bracket_t).length = 0, by refl) at h,
norm_num at h,
end
| (head::tail) h := begin
rw chop_other_end,
rw get_tail,
split_ifs,
have := list.length_eq_zero.mp h_1,
rw this,
rw list.nil_append,
rw list.cons_append,
rw list.cons_inj,
exact reconstitute tail begin
exact pos_iff_ne_zero.mpr h_1,
end,
end
def chop_both_ends : list bracket_t → list bracket_t
| string := chop_head (chop_other_end string)
lemma head_open : ∀ string : list bracket_t, ∀ head : bracket_t, balance_factor_predicate (head::string) → head = bracket_t.left
| string head h := begin
cases head,
refl,
rw balance_factor_predicate at h,
have := h.right 1 begin
rw list.length_cons,
exact if h' : string.length = 0 then begin
have h2 := list.eq_nil_of_length_eq_zero h',
rw h2 at h,
rw (show [bracket_t.right].length = 1, by refl) at h,
have := h.left,
rw balance_factor at this,
rw balance_factor at this,
norm_num at this,
end else begin
have := pos_iff_ne_zero.mpr h',
exact nat.succ_lt_succ_iff.mpr this,
end,
end,
rw balance_factor at this,
cases string,
rw balance_factor at this,
norm_num at this,
cases string_hd,
rw balance_factor at this,
norm_num at this,
rw balance_factor at this,
norm_num at this,
end
lemma ignores_garbage_left : ∀ z : list bracket_t, balance_factor z.length z = balance_factor z.length (z ++ [bracket_t.left])
| [] := begin
rw (show ([] : list bracket_t).length = 0, by refl),
rw list.nil_append,
rw [balance_factor, balance_factor],
end
| (bracket_t.left::rest) := begin
rw (show (bracket_t.left::rest).length = rest.length + 1, by refl),
rw list.cons_append,
rw [balance_factor, balance_factor],
rw ignores_garbage_left rest,
end
| (bracket_t.right::rest) := begin
rw (show (bracket_t.right::rest).length = rest.length + 1, by refl),
rw list.cons_append,
rw [balance_factor, balance_factor],
rw ignores_garbage_left rest,
end
lemma minus_one : ∀ z : list bracket_t, (balance_factor (z ++ [bracket_t.right]).length (z ++ [bracket_t.right]) = balance_factor z.length z - 1)
| [] := begin
rw list.nil_append,
rw (show [bracket_t.right].length = 1, by refl),
rw (show ([] : list bracket_t).length = 0, by refl),
rw balance_factor,
rw balance_factor,
norm_num,
end
| (bracket_t.left::rest) := begin
rw list.cons_append,
rw (show (bracket_t.left :: (rest ++ [bracket_t.right])).length = (rest ++ [bracket_t.right]).length + 1, by refl),
rw balance_factor,
have := minus_one rest,
rw this,
rw (show (bracket_t.left :: rest).length = rest.length + 1, by refl),
rw balance_factor,
norm_num,
end
| (bracket_t.right::rest) := begin
rw list.cons_append,
rw (show (bracket_t.right :: (rest ++ [bracket_t.right])).length = (rest ++ [bracket_t.right]).length + 1, by refl),
rw balance_factor,
have := minus_one rest,
rw this,
rw (show (bracket_t.right :: rest).length = rest.length + 1, by refl),
rw balance_factor,
rw int.sub_eq_add_neg,
rw int.sub_eq_add_neg,
rw (int.add_assoc _ _ _).symm,
end
lemma ignores_garbage : ∀ n_n : ℕ, ∀ z : list bracket_t, n_n < z.length → balance_factor n_n (z ++ [bracket_t.right]) = balance_factor n_n z
| 0 anything h := begin
cases anything,
rw list.nil_append,
rw balance_factor,
rw balance_factor,
rw list.cons_append,
rw balance_factor,
rw balance_factor,
end
| anything [] h := begin
rw (show ([] : list bracket_t).length = 0, by refl) at h,
exact false.elim ((not_lt_of_ge anything.zero_le) h),
end
| (n + 1) (bracket_t.left::rest) h := begin
rw [list.cons_append, balance_factor, balance_factor],
rw (show (bracket_t.left::rest).length = rest.length + 1, by refl) at h,
rw ignores_garbage n rest (nat.lt_of_succ_lt_succ h),
end
| (n + 1) (bracket_t.right::rest) h := begin
rw [list.cons_append, balance_factor, balance_factor],
rw (show (bracket_t.right::rest).length = rest.length + 1, by refl) at h,
rw ignores_garbage n rest (nat.lt_of_succ_lt_succ h),
end
lemma ignores_garbage' : ∀ z : list bracket_t, balance_factor z.length z = balance_factor z.length (z ++ [bracket_t.right])
| [] := begin
rw (show ([] : list bracket_t).length = 0, by refl),
rw list.nil_append,
rw [balance_factor, balance_factor],
end
| (bracket_t.left::rest) := begin
rw (show (bracket_t.left::rest).length = rest.length + 1, by refl),
rw list.cons_append,
rw [balance_factor, balance_factor],
rw ignores_garbage' rest,
end
| (bracket_t.right::rest) := begin
rw (show (bracket_t.right::rest).length = rest.length + 1, by refl),
rw list.cons_append,
rw [balance_factor, balance_factor],
rw ignores_garbage' rest,
end
lemma sandwich1 (rest2 : list bracket_t) : ∀ rest1 : list bracket_t, balance_factor (rest1 ++ bracket_t.left :: rest2).length (rest1 ++ bracket_t.left :: rest2) = balance_factor (rest1 ++ rest2).length (rest1 ++ rest2) + 1
| [] := begin
rw list.nil_append,
rw list.nil_append,
rw (show (bracket_t.left::rest2).length = rest2.length + 1, by refl),
rw balance_factor,
rw int.add_comm,
end
| (bracket_t.left::rest) := begin
rw list.cons_append,
rw (show (bracket_t.left :: (rest ++ bracket_t.left :: rest2)).length = (rest ++ bracket_t.left :: rest2).length + 1, by refl),
rw balance_factor,
rw sandwich1 rest,
rw list.cons_append,
rw (show (bracket_t.left :: (rest ++ rest2)).length = (rest ++ rest2).length + 1, by refl),
rw balance_factor,
rw add_assoc,
end
| (bracket_t.right::rest) := begin
rw list.cons_append,
rw (show (bracket_t.right :: (rest ++ bracket_t.left :: rest2)).length = (rest ++ bracket_t.left :: rest2).length + 1, by refl),
rw balance_factor,
rw sandwich1 rest,
rw list.cons_append,
rw (show (bracket_t.right :: (rest ++ rest2)).length = (rest ++ rest2).length + 1, by refl),
rw balance_factor,
rw add_assoc,
end
lemma sandwich2 (rest2 : list bracket_t) : ∀ rest1 : list bracket_t, balance_factor (rest1 ++ bracket_t.right :: rest2).length (rest1 ++ bracket_t.right :: rest2) = balance_factor (rest1 ++ rest2).length (rest1 ++ rest2) - 1
| [] := begin
rw list.nil_append,
rw list.nil_append,
rw (show (bracket_t.right::rest2).length = rest2.length + 1, by refl),
rw balance_factor,
rw int.add_comm,
norm_num,
end
| (bracket_t.left::rest) := begin
rw list.cons_append,
rw (show (bracket_t.left :: (rest ++ bracket_t.right :: rest2)).length = (rest ++ bracket_t.right :: rest2).length + 1, by refl),
rw balance_factor,
rw sandwich2 rest,
rw list.cons_append,
rw (show (bracket_t.left :: (rest ++ rest2)).length = (rest ++ rest2).length + 1, by refl),
rw balance_factor,
rw [int.sub_eq_add_neg, int.sub_eq_add_neg],
rw add_assoc,
end
| (bracket_t.right::rest) := begin
rw list.cons_append,
rw (show (bracket_t.right :: (rest ++ bracket_t.right :: rest2)).length = (rest ++ bracket_t.right :: rest2).length + 1, by refl),
rw balance_factor,
rw sandwich2 rest,
rw list.cons_append,
rw (show (bracket_t.right :: (rest ++ rest2)).length = (rest ++ rest2).length + 1, by refl),
rw balance_factor,
rw [int.sub_eq_add_neg, int.sub_eq_add_neg],
rw add_assoc,
end
lemma append_add_balance_factor : ∀ a b : list bracket_t, balance_factor a.length a + balance_factor b.length b = balance_factor ((a ++ b).length) (a ++ b)
| [] [] := begin
rw (show ([] : list bracket_t) ++ [] = [], by refl),
rw (show ([] : list bracket_t).length = 0, by refl),
rw balance_factor,
norm_num,
end
| [] anything := begin
rw (show ([] : list bracket_t).length = 0, by refl),
rw (show ([] : list bracket_t) ++ anything = anything, by refl),
rw balance_factor,
norm_num,
end
| anything [] := begin
rw (show ([] : list bracket_t).length = 0, by refl),
rw (show anything ++ ([] : list bracket_t) = anything, by exact list.append_nil anything),
rw balance_factor,
norm_num,
end
| (head1::rest1) (head2::rest2) := begin
cases head1,
repeat {
cases head2,
repeat {
rw (show ∀ x : bracket_t, (x::rest1).length = rest1.length + 1, begin intro, refl, end),
rw (show ∀ x : bracket_t, (x::rest2).length = rest2.length + 1, begin intro, refl, end),
rw balance_factor,
rw balance_factor,
try { rw sandwich1, },
try { rw sandwich2, },
rw list.cons_append,
rw (show ∀ x : bracket_t, ∀ y : list bracket_t, (x::y).length = y.length + 1, begin intros, refl end),
rw balance_factor,
rw (append_add_balance_factor rest1 rest2).symm,
try { rw int.sub_eq_add_neg, },
nth_rewrite 2 int.add_comm,
nth_rewrite 0 int.add_assoc,
nth_rewrite 0 int.add_assoc,
nth_rewrite 1 (int.add_assoc _ _ _).symm,
},
},
end
lemma tail_close : ∀ string : list bracket_t, ∀ tail : bracket_t, balance_factor_predicate (string ++ [tail]) → tail = bracket_t.right
| string tail h := begin
cases tail,
{
rw balance_factor_predicate at h,
cases h,
have := h_right string.length begin
rw list.length_append,
rw (show [bracket_t.left].length = 1, by refl),
exact nat.lt_succ_self _,
end,
rw (ignores_garbage_left string).symm at this,
rw (append_add_balance_factor string [bracket_t.left]).symm at h_left,
rw (show [bracket_t.left].length = 1, by refl) at h_left,
rw balance_factor at h_left,
rw balance_factor at h_left,
norm_num at h_left,
have h1 := eq_sub_of_add_eq h_left,
norm_num at h1,
rw h1 at this,
norm_num at this,
},
refl,
end
lemma ignores_garbage'' : ∀ a b : list bracket_t, ∀ n : ℕ, n ≤ a.length → balance_factor n (a ++ b) = balance_factor n a
| a b 0 h := begin
generalize : a ++ b = x,
cases x,
repeat {
cases a,
repeat {
rw balance_factor,
}
},
end
| a b (n + 1) h := begin
generalize_hyp h1 : a ++ b = x,
cases x,
repeat {
cases a,
repeat {
rw balance_factor,
}
},
cases a_hd,
rw balance_factor,
rw (show ∀ a : bracket_t, ∀ b : list bracket_t, (a::b).length = b.length + 1, by begin intros, refl, end) at h,
have := ignores_garbage'' a_tl b n (nat.le_of_succ_le_succ h),
rw list.cons_append at h1,
exact false.elim (list.cons_ne_nil _ _ h1),
exact false.elim (list.cons_ne_nil _ _ h1),
rw (show ([] : list bracket_t).length = 0, by refl) at h,
have := nat.succ_pos n,
have : false := nat.lt_le_antisymm this h,
exact false.elim this,
cases x_hd,
{
cases a_hd,
{
rw balance_factor,
rw balance_factor,
rw list.cons_append at h1,
rw (list.cons.inj_eq bracket_t.left (a_tl ++ b) bracket_t.left x_tl) at h1,
rw h1.right.symm,
rw (show ∀ a : bracket_t, ∀ b : list bracket_t, (a::b).length = b.length + 1, by begin intros, refl, end) at h,
have := ignores_garbage'' a_tl b n (nat.le_of_succ_le_succ h),
rw this,
},
{
rw h1.symm,
rw list.cons_append,
rw balance_factor,
rw balance_factor,
rw (show ∀ a : bracket_t, ∀ b : list bracket_t, (a::b).length = b.length + 1, by begin intros, refl, end) at h,
have := ignores_garbage'' a_tl b n (nat.le_of_succ_le_succ h),
rw this,
},
},
rw h1.symm,
rw list.cons_append,
cases a_hd,
repeat {
rw balance_factor,
rw balance_factor,
rw (show ∀ a : bracket_t, ∀ b : list bracket_t, (a::b).length = b.length + 1, by begin intros, refl, end) at h,
have := ignores_garbage'' a_tl b n (nat.le_of_succ_le_succ h),
rw this,
},
end
lemma decompose : ∀ a b : list bracket_t, ∀ n : ℕ, ¬(n ≤ a.length) → balance_factor n (a ++ b) = balance_factor a.length a + balance_factor (n - a.length) b
| a b 0 h := begin
have h1 := nat.zero_le a.length,
have := lt_or_eq_of_le h1,
cases this,
exact false.elim (h h1),
rw this.symm,
norm_num,
generalize : a ++ b = x,
have : ∀ x : list bracket_t, balance_factor 0 x = 0 := begin
intro x,
cases x,
rw balance_factor,
cases x_hd,
repeat {
rw balance_factor,
},
end,
rw this,
rw this,
rw this,
norm_num,
end
| a b (n + 1) h := begin
cases a,
{
rw list.nil_append,
rw (show ([] : list bracket_t).length = 0, by refl),
norm_num,
rw balance_factor,
},
{
rw list.cons_append,
rw (show (a_hd :: a_tl).length = a_tl.length + 1, by refl),
cases a_hd,
repeat {
rw balance_factor,
rw nat.succ_sub_succ n a_tl.length,
rw balance_factor,
rw (show ∀ a : bracket_t, ∀ b : list bracket_t, (a::b).length = b.length + 1, by begin intros, refl, end) at h,
have : n ≤ a_tl.length → n.succ ≤ a_tl.length.succ := begin
intro h,
exact nat.succ_le_succ h,
end,
have : ¬n.succ ≤ a_tl.length.succ → ¬n ≤ a_tl.length := begin
intros h h1,
have := this h1,
exact false.elim (h this),
end,
have := this h,
have := decompose a_tl b n this,
rw this,
rw int.add_assoc,
}
},
end
lemma append_nonnegative_condition : ∀ a b : list bracket_t, (∀ n : ℕ, n ≤ a.length → 0 ≤ balance_factor n a) → (∀ n : ℕ, n ≤ b.length → 0 ≤ balance_factor n b) → (∀ n : ℕ, n ≤ (a ++ b).length → 0 ≤ balance_factor n (a ++ b)) := begin
intros a b h1 h2 n h3,
exact if h : n ≤ a.length then begin
have h4 := h1 n h,
have := ignores_garbage'' a b n,
rw this,
exact h4,
exact h,
end else begin
rw decompose a b n h,
have := h1 a.length (nat.le_refl _),
rw list.length_append a b at h3,
have := (@nat.sub_le_sub_right_iff n (a.length + b.length) a.length (le_self_add)).mpr h3,
rw (norm_num.sub_nat_pos (a.length + b.length) a.length b.length rfl) at this,
have := h2 (n - a.length) this,
exact add_nonneg (by tauto) (by tauto),
end,
end
lemma balance_factor_append : ∀ a b : list bracket_t, balance_factor_predicate a → balance_factor_predicate b → balance_factor_predicate (a ++ b) := begin
intros a b h1 h2,
rw balance_factor_predicate at h1,
rw balance_factor_predicate at h2,
rw balance_factor_predicate,
split,
rw (append_add_balance_factor _ _).symm,
rw [h1.left, h2.left],
norm_num,
intros n h,
exact append_nonnegative_condition a b begin
intros n h,
have := lt_or_eq_of_le h,
cases this,
exact h1.right n this,
rw this,
apply le_of_lt_or_eq,
right,
exact h1.left.symm,
end begin
intros n h,
have := lt_or_eq_of_le h,
cases this,
exact h2.right n this,
rw this,
apply le_of_lt_or_eq,
right,
exact h2.left.symm,
end n (le_of_lt h),
end
lemma balanced_implies_balance_factor (string : list bracket_t) : balanced string → balance_factor_predicate string := begin
intro h,
induction h with z x c v b q w e r,
rw balance_factor_predicate,
rw (show ([] : list bracket_t).length = 0, by refl),
rw balance_factor,
split,
refl,
intro n,
intro absurdity,
exact false.elim ((not_lt_of_ge n.zero_le) absurdity),
rw balance_factor_predicate,
rw list.append_assoc,
rw list.cons_append,
rw list.nil_append,
rw (show (bracket_t.left :: (z ++ [bracket_t.right])).length = (z ++ [bracket_t.right]).length + 1, by refl),
rw balance_factor,
split,
rw minus_one z,
rw balance_factor_predicate at c,
rw c.left,
norm_num,
intro n,
intro h,
rw balance_factor_predicate at c,
have h1 := c.right,
induction n,
rw balance_factor,
have ha := n_ih (nat.lt_trans (nat.lt_succ_self n_n) h),
rw balance_factor,
have hb := h1 n_n,
exact if cond : n_n < z.length then begin
have hc := hb cond,
have hd := c.left,
rw ignores_garbage n_n z cond,
have := le_trans hc (le_of_lt (int.lt_succ_self (balance_factor n_n z))),
rw (show (balance_factor n_n z).succ = 1 + balance_factor n_n z, begin
rw add_comm,
refl,
end) at this,
exact this,
end else begin
have := (add_lt_add_iff_right 1).mp h,
rw list.length_append z [bracket_t.right] at this,
rw (show [bracket_t.right].length = 1, by refl) at this,
have := nat.le_of_lt_succ this,
have := lt_or_eq_of_le this,
cases this,
exact false.elim (cond this_1),
rw this_1,
rw (ignores_garbage' z).symm,
rw c.left,
norm_num,
end,
exact balance_factor_append v b e r,
end
def dropN : ∀ string : list bracket_t, ∀ n : ℕ, list bracket_t
| [] _ := []
| x 0 := x
| (head::tail) (n + 1) := dropN tail n
def takeN : ∀ string : list bracket_t, ∀ n : ℕ, list bracket_t
| [] _ := []
| _ 0 := []
| (head::tail) (n + 1) := head::takeN tail n
lemma takeN_calc : ∀ string : list bracket_t, ∀ n : ℕ, balance_factor n string = balance_factor (takeN string n).length (takeN string n)
| [] x := begin
cases x,
rw balance_factor,
have : takeN [] 0 = [] := by refl,
rw this,
norm_num,
rw balance_factor,
rw balance_factor,
rw takeN,
norm_num,
rw balance_factor,
norm_num,
end
| x 0 := begin
have : balance_factor 0 x = 0 := begin
cases x,
rw balance_factor,
rw balance_factor,
end,
rw this,
have : takeN x 0 = [] := begin
cases x,
refl,
rw takeN,
end,
rw this,
norm_num,
rw balance_factor,
end
| (head::tail) (n + 1) := begin
cases head,
repeat {
rw balance_factor,
rw takeN,
rw list.length_cons,
rw balance_factor,
have := takeN_calc tail n,
rw this,
},
end
lemma lt_of_ne : ∀ n : ℕ, n ≠ 0 → n ≠ 1 → 1 < n
| 0 h h' := false.elim (h rfl)
| 1 h h' := false.elim (h' rfl)
| (n + 2) h h' := by norm_num
lemma preserve_length : ∀ string : list bracket_t, ∀ n : ℕ, n ≤ string.length → (takeN string n).length = n
| [] x h := begin
have : takeN [] x = [] := begin
cases x,
refl,
refl,
end,
rw this,
norm_num,
norm_num at h,
exact h.symm,
end
| x 0 h := begin
have : takeN x 0 = [] := begin
cases x,
refl,
refl,
end,
rw this,
norm_num,
end
| (head::tail) (n + 1) h := begin
rw list.length_cons at h,
rw takeN,
rw list.length_cons,
rw nat.succ_inj',
have := preserve_length tail n begin
exact nat.succ_le_succ_iff.mp h,
end,
exact this,
end
lemma sane : ∀ string : list bracket_t, ∀ n x : ℕ, n < x → balance_factor n string = balance_factor n (takeN string x) := begin
intro string,
induction string with head tail sane,
intros a b c,
cases a,
rw balance_factor,
generalize : takeN list.nil b = h,
cases h,
rw balance_factor,
rw balance_factor,
rw balance_factor,
have : takeN [] b = [] := begin
cases b,
rw takeN,
norm_num at c,
rw takeN,
norm_num,
end,
rw this,
rw balance_factor,
intros a b c,
cases b,
norm_num at c,
rw takeN,
cases a,
rw balance_factor,
cases head,
rw balance_factor,
rw balance_factor,
cases head,
rw balance_factor,
rw balance_factor,
have := sane a b (nat.succ_lt_succ_iff.mp c),
rw this,
rw balance_factor,
rw balance_factor,
have := sane a b (nat.succ_lt_succ_iff.mp c),
rw this,
end
lemma balance_factor_implies_balanced : ∀ string : list bracket_t, balance_factor_predicate string → balanced string
| string := begin
intro h,
rw balance_factor_predicate at h,
cases h,
classical,
exact if hempty : string.length = 0 then begin
have := list.length_eq_zero.mp hempty,
rw this,
exact balanced.empty,
end else if hsingleton : string.length = 1 then begin
cases string,
exact balanced.empty,
cases string_tl,
norm_num at h_left,
cases string_hd,
rw balance_factor at h_left,
rw balance_factor at h_left,
norm_num at h_left,
rw balance_factor at h_left,
rw balance_factor at h_left,
norm_num at h_left,
rw list.length_cons at hsingleton,
rw list.length_cons at hsingleton,
norm_num at hsingleton,
end else if hnotequal : ∀ (n : ℕ), n < string.length → 0 < n → 0 < balance_factor n string then begin
have split_things : string = [get_head string] ++ chop_both_ends string ++ [get_tail string] := begin
clear_except hempty hsingleton,
cases string,
norm_num at hempty,
cases string_hd,
repeat {
rw get_head,
rw chop_both_ends,
rw chop_other_end,
rw get_tail,
split_ifs,
have : 1 < (bracket_t.left :: string_tl).length := begin
apply lt_of_ne, assumption, assumption,
end,
norm_num at this,
exact false.elim (ne_of_lt this h.symm),
rw chop_head,
rw list.append_assoc,
rw reconstitute string_tl (pos_iff_ne_zero.mpr h),
rw list.cons_append,
rw list.nil_append,
},
end,
have := head_open (chop_both_ends string ++ [get_tail string]) (get_head string) begin
rw list.singleton_append.symm,
rw (list.append_assoc _ _ _).symm,
rw split_things.symm,
rw balance_factor_predicate,
tauto,
end,
rw this at split_things,
clear this,
have := tail_close ([bracket_t.left] ++ chop_both_ends string) (get_tail string) begin
rw split_things.symm,
rw balance_factor_predicate,
tauto,
end,
rw this at split_things,
clear this,
rw split_things,
apply balanced.wrap _,
have := have wf : (chop_both_ends string).length < string.length, from begin
have : ∀ string : list bracket_t, 1 < string.length → (chop_both_ends string).length + 2 = string.length := begin
clear_except,
intros string h,
cases string,
norm_num at h,
rw chop_both_ends,
rw chop_other_end,
split_ifs,
have : string_tl = [] := list.length_eq_zero.mp h_1,
rw this at h,
norm_num at h,
rw chop_head,
have := reconstitute string_tl (pos_iff_ne_zero.mpr h_1),
norm_num,
conv begin
to_rhs,
rw this.symm,
end,
rw list.length_append,
norm_num,
end,
have := this string begin
apply lt_of_ne _ _ _, assumption, assumption,
end,
rw this.symm,
norm_num,
end, balance_factor_implies_balanced (chop_both_ends string) begin
rw balance_factor_predicate,
split,
have help := append_add_balance_factor ([bracket_t.left] ++ chop_both_ends string) [bracket_t.right],
rw split_things.symm at help,
rw (append_add_balance_factor [bracket_t.left] (chop_both_ends string)).symm at help,
norm_num at help,
rw balance_factor at help,
rw balance_factor at help,
rw balance_factor at help,
norm_num at help,
rw h_left at help,
exact help,
intros n limit,
have := hnotequal (n + 1) begin
have : ∀ string : list bracket_t, 1 < string.length → (chop_both_ends string).length + 2 = string.length := begin
clear_except,
intros string h,
cases string,
norm_num at h,
rw chop_both_ends,
rw chop_other_end,
split_ifs,
have : string_tl = [] := list.length_eq_zero.mp h_1,
rw this at h,
norm_num at h,
rw chop_head,
have := reconstitute string_tl (pos_iff_ne_zero.mpr h_1),
norm_num,
conv begin
to_rhs,
rw this.symm,
end,
rw list.length_append,
norm_num,
end,
have := this string begin
apply lt_of_ne _ _ _, assumption, assumption,
end,
rw this.symm,
apply nat.succ_lt_succ,
exact limit.trans (nat.lt_succ_self _),
end (nat.succ_pos n),
rw split_things at this,
rw list.append_assoc at this,
rw list.singleton_append at this,
rw balance_factor at this,
have := int.add_one_le_iff.mpr this,
norm_num at this,
have help := ignores_garbage n (chop_both_ends string) limit,
rw help at this,
exact this,
end,
exact this,
end else begin
push_neg at hnotequal,
cases hnotequal with x h1,
have hwellfounded := h1.left,
have := le_antisymm h1.right.right (h_right x h1.left),
have left := have wf : (takeN string x).length < string.length, from begin
clear_except hwellfounded,
induction string generalizing x,
norm_num at hwellfounded,
norm_num at hwellfounded,
norm_num,
cases x,
rw takeN,
norm_num,
rw takeN,
have := string_ih x (nat.succ_lt_succ_iff.mp hwellfounded),
norm_num,
exact this,
end, balance_factor_implies_balanced (takeN string x) begin
rw balance_factor_predicate,
split,
rw (takeN_calc _ _).symm,
exact this,
have := preserve_length string x (le_of_lt hwellfounded),
rw this,
intros n h',
have := h_right n (lt_trans h' hwellfounded),
rw (sane string n x h').symm,
exact this,
end,
have right := have wf : (dropN string x).length < string.length, from begin
have := h1.right.left,
clear_except hempty this,
induction string generalizing x this,
norm_num at hempty,
cases x,
exact false.elim (@nat.le_lt_antisymm 0 0 (rfl.ge) this),
rw dropN,
norm_num,
have to_split := em (string_tl.length = 0),
cases to_split,
rw to_split,
norm_num,
rw list.length_eq_zero.mp to_split,
have : dropN [] x = [] := begin
cases x, refl, rw dropN, clear_except,
exact nat.succ_ne_zero x,
end,
rw this,
norm_num,
have := string_ih to_split x,
have split2 := em (x = 0),
cases split2,
rw split2,
have : dropN string_tl 0 = string_tl := begin
cases string_tl,
refl, rw dropN,
end,
rw this,
exact lt_add_one (list.length string_tl),
have := (this (pos_iff_ne_zero.mpr split2)).trans (nat.lt_succ_self string_tl.length),
exact this,
end, balance_factor_implies_balanced (dropN string x) begin
rw balance_factor_predicate,
split,
have : ∀ string : list bracket_t, ∀ x : ℕ, takeN string x ++ dropN string x = string := begin
clear_except,
intros,
induction string generalizing x,
have : takeN [] x = [] := begin
cases x,
refl,
refl,
end,
rw this,
have : dropN [] x = [] := begin
cases x,
refl,
refl,
end,
rw this,
refl,
cases x,
rw takeN,
rw dropN,
rw list.nil_append,
rw takeN,
rw dropN,
rw list.cons_append,
rw list.cons_inj,
exact string_ih x,
end,
have : ∀ string : list bracket_t, ∀ x : ℕ, balance_factor (dropN string x).length (dropN string x) + balance_factor (takeN string x).length (takeN string x) = balance_factor string.length string := begin
clear_except this,
intros,
have destruct := (this string x).symm,
conv begin
to_rhs,
rw destruct,
end,
have := append_add_balance_factor (takeN string x) (dropN string x),
rw add_comm,
exact this,
end,
have := this string x,
rw h_left at this,
have help := takeN_calc string x,
rw (show balance_factor x string = 0, by assumption) at help,
rw help.symm at this,
norm_num at this,
exact this,
intros n h,
have := h_right (x + n),
have : ∀ string : list bracket_t, ∀ x : ℕ, x < string.length → (dropN string x).length = string.length - x := begin
clear_except,
intros string x h,
induction string generalizing x,
norm_num at h,
cases x,
rw dropN,
norm_num,
rw dropN,
rw list.length_cons,
rw list.length_cons at h,
have := string_ih x (nat.succ_lt_succ_iff.mp h),
rw this,
have := nat.succ_sub_succ string_tl.length x,
rw this,
end,
rw this string x hwellfounded at h,
clear this,
have := this (nat.add_lt_of_lt_sub_left h),
have help : ∀ string : list bracket_t, ∀ x n : ℕ, balance_factor (takeN string x).length (takeN string x) + balance_factor n (dropN string x) = balance_factor (x + n) string := begin
clear_except,
intros,
induction string generalizing x n,
have : takeN [] x = [] := begin
cases x,
refl,
refl,
end,
rw this,
have : dropN [] x = [] := begin
cases x,
refl,
refl,
end,
rw this,
norm_num,
have : ∀ x : ℕ, balance_factor x [] = 0 := begin
clear_except,
intros,
cases x,
refl,
refl,
end,
rw this,
rw this,
rw this,
norm_num,
cases x,
rw takeN,
rw dropN,
norm_num,
rw balance_factor,
rw takeN,
rw dropN,
rw nat.succ_add,
cases string_hd,
rw balance_factor,
norm_num,
rw balance_factor,
have := string_ih x n,
rw this.symm,
have := int.add_assoc 1 (balance_factor (takeN string_tl x).length (takeN string_tl x)) (balance_factor n (dropN string_tl x)),
conv begin
to_lhs,
rw this,
end,
rw balance_factor,
norm_num,
rw balance_factor,
rw int.add_assoc,
have := string_ih x n,
rw this,
end,
rw (help string x n).symm at this,
rw ((show balance_factor x string = 0, by assumption).symm.trans (takeN_calc string x)).symm at this,
norm_num at this,
exact this,
end,
have goal := balanced.append _ _ left right,
have : ∀ string : list bracket_t, ∀ x : ℕ, takeN string x ++ dropN string x = string := begin
clear_except,
intros,
induction string generalizing x,
have : takeN [] x = [] := begin
cases x,
refl,
refl,
end,
rw this,
have : dropN [] x = [] := begin
cases x,
refl,
refl,
end,
rw this,
refl,
cases x,
rw takeN,
rw dropN,
rw list.nil_append,
rw takeN,
rw dropN,
rw list.cons_append,
rw list.cons_inj,
exact string_ih x,
end,
have := this string x,
rw this at goal,
exact goal,
end,
end
using_well_founded {
rel_tac := λ_ _, `[exact ⟨_, inv_image.wf list.length nat.lt_wf⟩],
dec_tac := tactic.assumption }
lemma balanced_iff_balance_factor (string : list bracket_t) : balanced string ↔ balance_factor_predicate string := begin
split,
exact balanced_implies_balance_factor _,
exact balance_factor_implies_balanced _,
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment