From 2e9f62cc98a3c6accf28bd4a7ef387d2e76c289b Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Mon, 16 Sep 2024 09:37:47 +1000 Subject: [PATCH] feat: List.replicate lemmas --- src/Init/Data/List/Lemmas.lean | 41 ++++++++++++++++++++++++++++++++++ src/Init/Data/Nat/Basic.lean | 4 ++++ src/Init/Data/Nat/Lemmas.lean | 3 --- 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/Init/Data/List/Lemmas.lean b/src/Init/Data/List/Lemmas.lean index b948d76a500a..83df4a173581 100644 --- a/src/Init/Data/List/Lemmas.lean +++ b/src/Init/Data/List/Lemmas.lean @@ -2323,6 +2323,47 @@ theorem bind_replicate {β} (f : α → List β) : (replicate n a).bind f = (rep @[simp] theorem isEmpty_replicate : (replicate n a).isEmpty = decide (n = 0) := by cases n <;> simp [replicate_succ] +/-- Every list is either empty, a non-empty `replicate`, or begins with a non-empty `replicate` +followed by a different element. -/ +theorem eq_replicate_or_eq_replicate_append_cons {α : Type _} (l : List α) : + (l = []) ∨ (∃ n a, l = replicate n a ∧ 0 < n) ∨ + (∃ n a b l', l = replicate n a ++ b :: l' ∧ 0 < n ∧ a ≠ b) := by + induction l with + | nil => simp + | cons x l ih => + right + rcases ih with rfl | ⟨n, a, rfl, h⟩ | ⟨n, a, b, l', rfl, h⟩ + · left + exact ⟨1, x, rfl, by decide⟩ + · by_cases h' : x = a + · subst h' + left + exact ⟨n + 1, x, rfl, by simp⟩ + · right + refine ⟨1, x, a, replicate (n - 1) a, ?_, by decide, h'⟩ + match n with | n + 1 => simp [replicate_succ] + · right + by_cases h' : x = a + · subst h' + refine ⟨n + 1, x, b, l', by simp [replicate_succ], by simp, h.2⟩ + · refine ⟨1, x, a, replicate (n - 1) a ++ b :: l', ?_, by decide, h'⟩ + match n with | n + 1 => simp [replicate_succ] + +/-- An induction principle for lists based on contiguous runs of identical elements. -/ +-- A `Sort _` valued version would require a different design. (And associated `@[simp]` lemmas.) +theorem replicateRecOn {α : Type _} {p : List α → Prop} (m : List α) + (h0 : p []) (hr : ∀ a n, 0 < n → p (replicate n a)) + (hi : ∀ a b n l, a ≠ b → 0 < n → p (b :: l) → p (replicate n a ++ b :: l)) : p m := by + rcases eq_replicate_or_eq_replicate_append_cons m with + rfl | ⟨n, a, rfl, hn⟩ | ⟨n, a, b, l', w, hn, h⟩ + · exact h0 + · exact hr _ _ hn + · have : (b :: l').length < m.length := by + simpa [w] using Nat.lt_add_of_pos_left hn + subst w + exact hi _ _ _ _ h hn (replicateRecOn (b :: l') h0 hr hi) +termination_by m.length + /-! ### reverse -/ @[simp] theorem length_reverse (as : List α) : (as.reverse).length = as.length := by diff --git a/src/Init/Data/Nat/Basic.lean b/src/Init/Data/Nat/Basic.lean index de6517016b55..6f0309b8757a 100644 --- a/src/Init/Data/Nat/Basic.lean +++ b/src/Init/Data/Nat/Basic.lean @@ -514,6 +514,10 @@ protected theorem add_lt_add_left {n m : Nat} (h : n < m) (k : Nat) : k + n < k protected theorem add_lt_add_right {n m : Nat} (h : n < m) (k : Nat) : n + k < m + k := Nat.add_comm k m ▸ Nat.add_comm k n ▸ Nat.add_lt_add_left h k +protected theorem lt_add_of_pos_left (h : 0 < k) : n < k + n := by + rw [Nat.add_comm] + exact Nat.add_lt_add_left h n + protected theorem lt_add_of_pos_right (h : 0 < k) : n < n + k := Nat.add_lt_add_left h n diff --git a/src/Init/Data/Nat/Lemmas.lean b/src/Init/Data/Nat/Lemmas.lean index 2d4908e48e0e..3bcade3e3763 100644 --- a/src/Init/Data/Nat/Lemmas.lean +++ b/src/Init/Data/Nat/Lemmas.lean @@ -84,9 +84,6 @@ protected theorem add_lt_add_of_lt_of_le {a b c d : Nat} (hlt : a < b) (hle : c a + c < b + d := Nat.lt_of_le_of_lt (Nat.add_le_add_left hle _) (Nat.add_lt_add_right hlt _) -protected theorem lt_add_of_pos_left : 0 < k → n < k + n := by - rw [Nat.add_comm]; exact Nat.lt_add_of_pos_right - protected theorem pos_of_lt_add_right (h : n < n + k) : 0 < k := Nat.lt_of_add_lt_add_left h