l3lab/ntp-mathlib huggingface dataset:
theorem cons_prefix_iff : a :: l₁ <+: b :: l₂ ↔ a = b ∧ l₁ <+: l₂ := by
  constructor
  · rintro ⟨L, hL⟩
    simp only [cons_append] at hL
    injection hL with hLLeft hLRight
    

Proof state:
case mp.intro
α : Type u_1
β : Type u_2
l l₁ l₂ l₃ : List α
a b : α
m n : ℕ
L : List α
hLLeft : a = b
hLRight : l₁ ++ L = l₂
⊢ a = b ∧ l₁ <+: l₂

Next tactic:
exact ⟨hLLeft, ⟨L, hLRight⟩⟩
theorem cons_prefix_iff : a :: l₁ <+: b :: l₂ ↔ a = b ∧ l₁ <+: l₂ := by
  constructor
  · rintro ⟨L, hL⟩
    simp only [cons_append] at hL
    injection hL with hLLeft hLRight
    exact ⟨hLLeft, ⟨L, hLRight⟩⟩
  · 

Proof state:
case mpr
α : Type u_1
β : Type u_2
l l₁ l₂ l₃ : List α
a b : α
m n : ℕ
⊢ a = b ∧ l₁ <+: l₂ → a :: l₁ <+: b :: l₂

Next tactic:
rintro ⟨rfl, h⟩
theorem cons_prefix_iff : a :: l₁ <+: b :: l₂ ↔ a = b ∧ l₁ <+: l₂ := by
  constructor
  · rintro ⟨L, hL⟩
    simp only [cons_append] at hL
    injection hL with hLLeft hLRight
    exact ⟨hLLeft, ⟨L, hLRight⟩⟩
  · rintro ⟨rfl, h⟩
    

Proof state:
case mpr.intro
α : Type u_1
β : Type u_2
l l₁ l₂ l₃ : List α
a : α
m n : ℕ
h : l₁ <+: l₂
⊢ a :: l₁ <+: a :: l₂

Next tactic:
rwa [prefix_cons_inj]
theorem IsPrefix.map (h : l₁ <+: l₂) (f : α → β) : l₁.map f <+: l₂.map f := by
  

Proof state:
α : Type u_1
β : Type u_2
l l₁ l₂ l₃ : List α
a b : α
m n : ℕ
h : l₁ <+: l₂
f : α → β
⊢ List.map f l₁ <+: List.map f l₂

Next tactic:
induction' l₁ with hd tl hl generalizing l₂
theorem IsPrefix.map (h : l₁ <+: l₂) (f : α → β) : l₁.map f <+: l₂.map f := by
  induction' l₁ with hd tl hl generalizing l₂
  · 

Proof state:
case nil
α : Type u_1
β : Type u_2
l l₃ : List α
a b : α
m n : ℕ
f : α → β
l₂ : List α
h : [] <+: l₂
⊢ List.map f [] <+: List.map f l₂

Next tactic:
simp only [nil_prefix, map_nil]
theorem IsPrefix.map (h : l₁ <+: l₂) (f : α → β) : l₁.map f <+: l₂.map f := by
  induction' l₁ with hd tl hl generalizing l₂
  · simp only [nil_prefix, map_nil]
  · 

Proof state:
case cons
α : Type u_1
β : Type u_2
l l₃ : List α
a b : α
m n : ℕ
f : α → β
hd : α
tl : List α
hl : ∀ {l₂ : List α}, tl <+: l₂ → List.map f tl <+: List.map f l₂
l₂ : List α
h : hd :: tl <+: l₂
⊢ List.map f (hd :: tl) <+: List.map f l₂

Next tactic:
cases' l₂ with hd₂ tl₂
theorem IsPrefix.map (h : l₁ <+: l₂) (f : α → β) : l₁.map f <+: l₂.map f := by
  induction' l₁ with hd tl hl generalizing l₂
  · simp only [nil_prefix, map_nil]
  · cases' l₂ with hd₂ tl₂
    · 

Proof state:
case cons.nil
α : Type u_1
β : Type u_2
l l₃ : List α
a b : α
m n : ℕ
f : α → β
hd : α
tl : List α
hl : ∀ {l₂ : List α}, tl <+: l₂ → List.map f tl <+: List.map f l₂
h : hd :: tl <+: []
⊢ List.map f (hd :: tl) <+: List.map f []

Next tactic:
simpa only using eq_nil_of_prefix_nil h
theorem IsPrefix.map (h : l₁ <+: l₂) (f : α → β) : l₁.map f <+: l₂.map f := by
  induction' l₁ with hd tl hl generalizing l₂
  · simp only [nil_prefix, map_nil]
  · cases' l₂ with hd₂ tl₂
    · simpa only using eq_nil_of_prefix_nil h
    · 

Proof state:
case cons.cons
α : Type u_1
β : Type u_2
l l₃ : List α
a b : α
m n : ℕ
f : α → β
hd : α
tl : List α
hl : ∀ {l₂ : List α}, tl <+: l₂ → List.map f tl <+: List.map f l₂
hd₂ : α
tl₂ : List α
h : hd :: tl <+: hd₂ :: tl₂
⊢ List.map f (hd :: tl) <+: List.map f (hd₂ :: tl₂)

Next tactic:
rw [cons_prefix_iff] at h
theorem IsPrefix.map (h : l₁ <+: l₂) (f : α → β) : l₁.map f <+: l₂.map f := by
  induction' l₁ with hd tl hl generalizing l₂
  · simp only [nil_prefix, map_nil]
  · cases' l₂ with hd₂ tl₂
    · simpa only using eq_nil_of_prefix_nil h
    · rw [cons_prefix_iff] at h
      

Proof state:
case cons.cons
α : Type u_1
β : Type u_2
l l₃ : List α
a b : α
m n : ℕ
f : α → β
hd : α
tl : List α
hl : ∀ {l₂ : List α}, tl <+: l₂ → List.map f tl <+: List.map f l₂
hd₂ : α
tl₂ : List α
h : hd = hd₂ ∧ tl <+: tl₂
⊢ List.map f (hd :: tl) <+: List.map f (hd₂ :: tl₂)

Next tactic:
simp only [List.map_cons, h, prefix_cons_inj, hl, map]
theorem IsPrefix.filter_map (h : l₁ <+: l₂) (f : α → Option β) :
    l₁.filterMap f <+: l₂.filterMap f := by
  

Proof state:
α : Type u_1
β : Type u_2
l l₁ l₂ l₃ : List α
a b : α
m n : ℕ
h : l₁ <+: l₂
f : α → Option β
⊢ filterMap f l₁ <+: filterMap f l₂

Next tactic:
induction' l₁ with hd₁ tl₁ hl generalizing l₂
theorem IsPrefix.filter_map (h : l₁ <+: l₂) (f : α → Option β) :
    l₁.filterMap f <+: l₂.filterMap f := by
  induction' l₁ with hd₁ tl₁ hl generalizing l₂
  · 

Proof state:
case nil
α : Type u_1
β : Type u_2
l l₃ : List α
a b : α
m n : ℕ
f : α → Option β
l₂ : List α
h : [] <+: l₂
⊢ filterMap f [] <+: filterMap f l₂

Next tactic:
simp only [nil_prefix, filterMap_nil]
theorem IsPrefix.filter_map (h : l₁ <+: l₂) (f : α → Option β) :
    l₁.filterMap f <+: l₂.filterMap f := by
  induction' l₁ with hd₁ tl₁ hl generalizing l₂
  · simp only [nil_prefix, filterMap_nil]
  · 

Proof state:
case cons
α : Type u_1
β : Type u_2
l l₃ : List α
a b : α
m n : ℕ
f : α → Option β
hd₁ : α
tl₁ : List α
hl : ∀ {l₂ : List α}, tl₁ <+: l₂ → filterMap f tl₁ <+: filterMap f l₂
l₂ : List α
h : hd₁ :: tl₁ <+: l₂
⊢ filterMap f (hd₁ :: tl₁) <+: filterMap f l₂

Next tactic:
cases' l₂ with hd₂ tl₂
theorem IsPrefix.filter_map (h : l₁ <+: l₂) (f : α → Option β) :
    l₁.filterMap f <+: l₂.filterMap f := by
  induction' l₁ with hd₁ tl₁ hl generalizing l₂
  · simp only [nil_prefix, filterMap_nil]
  · cases' l₂ with hd₂ tl₂
    · 

Proof state:
case cons.nil
α : Type u_1
β : Type u_2
l l₃ : List α
a b : α
m n : ℕ
f : α → Option β
hd₁ : α
tl₁ : List α
hl : ∀ {l₂ : List α}, tl₁ <+: l₂ → filterMap f tl₁ <+: filterMap f l₂
h : hd₁ :: tl₁ <+: []
⊢ filterMap f (hd₁ :: tl₁) <+: filterMap f []

Next tactic:
simpa only using eq_nil_of_prefix_nil h
theorem IsPrefix.filter_map (h : l₁ <+: l₂) (f : α → Option β) :
    l₁.filterMap f <+: l₂.filterMap f := by
  induction' l₁ with hd₁ tl₁ hl generalizing l₂
  · simp only [nil_prefix, filterMap_nil]
  · cases' l₂ with hd₂ tl₂
    · simpa only using eq_nil_of_prefix_nil h
    · 

Proof state:
case cons.cons
α : Type u_1
β : Type u_2
l l₃ : List α
a b : α
m n : ℕ
f : α → Option β
hd₁ : α
tl₁ : List α
hl : ∀ {l₂ : List α}, tl₁ <+: l₂ → filterMap f tl₁ <+: filterMap f l₂
hd₂ : α
tl₂ : List α
h : hd₁ :: tl₁ <+: hd₂ :: tl₂
⊢ filterMap f (hd₁ :: tl₁) <+: filterMap f (hd₂ :: tl₂)

Next tactic:
rw [cons_prefix_iff] at h
theorem IsPrefix.filter_map (h : l₁ <+: l₂) (f : α → Option β) :
    l₁.filterMap f <+: l₂.filterMap f := by
  induction' l₁ with hd₁ tl₁ hl generalizing l₂
  · simp only [nil_prefix, filterMap_nil]
  · cases' l₂ with hd₂ tl₂
    · simpa only using eq_nil_of_prefix_nil h
    · rw [cons_prefix_iff] at h
      

Proof state:
case cons.cons
α : Type u_1
β : Type u_2
l l₃ : List α
a b : α
m n : ℕ
f : α → Option β
hd₁ : α
tl₁ : List α
hl : ∀ {l₂ : List α}, tl₁ <+: l₂ → filterMap f tl₁ <+: filterMap f l₂
hd₂ : α
tl₂ : List α
h : hd₁ = hd₂ ∧ tl₁ <+: tl₂
⊢ filterMap f (hd₁ :: tl₁) <+: filterMap f (hd₂ :: tl₂)

Next tactic:
rw [← @singleton_append _ hd₁ _, ← @singleton_append _ hd₂ _, filterMap_append,
        filterMap_append, h.left, prefix_append_right_inj]
theorem IsPrefix.filter_map (h : l₁ <+: l₂) (f : α → Option β) :
    l₁.filterMap f <+: l₂.filterMap f := by
  induction' l₁ with hd₁ tl₁ hl generalizing l₂
  · simp only [nil_prefix, filterMap_nil]
  · cases' l₂ with hd₂ tl₂
    · simpa only using eq_nil_of_prefix_nil h
    · rw [cons_prefix_iff] at h
      rw [← @singleton_append _ hd₁ _, ← @singleton_append _ hd₂ _, filterMap_append,
        filterMap_append, h.left, prefix_append_right_inj]
      

Proof state:
case cons.cons
α : Type u_1
β : Type u_2
l l₃ : List α
a b : α
m n : ℕ
f : α → Option β
hd₁ : α
tl₁ : List α
hl : ∀ {l₂ : List α}, tl₁ <+: l₂ → filterMap f tl₁ <+: filterMap f l₂
hd₂ : α
tl₂ : List α
h : hd₁ = hd₂ ∧ tl₁ <+: tl₂
⊢ filterMap f tl₁ <+: filterMap f tl₂

Next tactic:
exact hl h.right
@[simp]
theorem mem_inits : ∀ s t : List α, s ∈ inits t ↔ s <+: t
  | s, [] =>
    suffices s = nil ↔ s <+: nil by 

Proof state:
α : Type u_1
β : Type u_2
l l₁ l₂ l₃ : List α
a b : α
m n : ℕ
s : List α
this : s = [] ↔ s <+: []
⊢ s ∈ inits [] ↔ s <+: []

Next tactic:
simpa only [inits, mem_singleton]
@[simp]
theorem mem_inits : ∀ s t : List α, s ∈ inits t ↔ s <+: t
  | s, [] =>
    suffices s = nil ↔ s <+: nil by simpa only [inits, mem_singleton]
    ⟨fun h => h.symm ▸ prefix_refl [], eq_nil_of_prefix_nil⟩
  | s, a :: t =>
    suffices (s = nil ∨ ∃ l ∈ inits t, a :: l = s) ↔ s <+: a :: t by simpa
    ⟨fun o =>
      match s, o with
      | _, Or.inl rfl => ⟨_, rfl⟩
      | s, Or.inr ⟨r, hr, hs⟩ => by
        

Proof state:
α : Type u_1
β : Type u_2
l l₁ l₂ l₃ : List α
a✝ b : α
m n : ℕ
s✝ : List α
a : α
t : List α
o : s✝ = [] ∨ ∃ l, l ∈ inits t ∧ a :: l = s✝
s r : List α
hr : r ∈ inits t
hs : a :: r = s
⊢ s <+: a :: t

Next tactic:
let ⟨s, ht⟩ := (mem_inits _ _).1 hr
@[simp]
theorem mem_inits : ∀ s t : List α, s ∈ inits t ↔ s <+: t
  | s, [] =>
    suffices s = nil ↔ s <+: nil by simpa only [inits, mem_singleton]
    ⟨fun h => h.symm ▸ prefix_refl [], eq_nil_of_prefix_nil⟩
  | s, a :: t =>
    suffices (s = nil ∨ ∃ l ∈ inits t, a :: l = s) ↔ s <+: a :: t by simpa
    ⟨fun o =>
      match s, o with
      | _, Or.inl rfl => ⟨_, rfl⟩
      | s, Or.inr ⟨r, hr, hs⟩ => by
        let ⟨s, ht⟩ := (mem_inits _ _).1 hr
        

Proof state:
α : Type u_1
β : Type u_2
l l₁ l₂ l₃ : List α
a✝ b : α
m n : ℕ
s✝¹ : List α
a : α
t : List α
o : s✝¹ = [] ∨ ∃ l, l ∈ inits t ∧ a :: l = s✝¹
s✝ r : List α
hr : r ∈ inits t
hs : a :: r = s✝
s : List α
ht : r ++ s = t
⊢ s✝ <+: a :: t

Next tactic:
rw [← hs, ← ht]
@[simp]
theorem mem_inits : ∀ s t : List α, s ∈ inits t ↔ s <+: t
  | s, [] =>
    suffices s = nil ↔ s <+: nil by simpa only [inits, mem_singleton]
    ⟨fun h => h.symm ▸ prefix_refl [], eq_nil_of_prefix_nil⟩
  | s, a :: t =>
    suffices (s = nil ∨ ∃ l ∈ inits t, a :: l = s) ↔ s <+: a :: t by simpa
    ⟨fun o =>
      match s, o with
      | _, Or.inl rfl => ⟨_, rfl⟩
      | s, Or.inr ⟨r, hr, hs⟩ => by
        let ⟨s, ht⟩ := (mem_inits _ _).1 hr
        rw [← hs, ← ht]; 

Proof state:
α : Type u_1
β : Type u_2
l l₁ l₂ l₃ : List α
a✝ b : α
m n : ℕ
s✝¹ : List α
a : α
t : List α
o : s✝¹ = [] ∨ ∃ l, l ∈ inits t ∧ a :: l = s✝¹
s✝ r : List α
hr : r ∈ inits t
hs : a :: r = s✝
s : List α
ht : r ++ s = t
⊢ a :: r <+: a :: (r ++ s)

Next tactic:
exact ⟨s, rfl⟩
@[simp]
theorem mem_inits : ∀ s t : List α, s ∈ inits t ↔ s <+: t
  | s, [] =>
    suffices s = nil ↔ s <+: nil by simpa only [inits, mem_singleton]
    ⟨fun h => h.symm ▸ prefix_refl [], eq_nil_of_prefix_nil⟩
  | s, a :: t =>
    suffices (s = nil ∨ ∃ l ∈ inits t, a :: l = s) ↔ s <+: a :: t by simpa
    ⟨fun o =>
      match s, o with
      | _, Or.inl rfl => ⟨_, rfl⟩
      | s, Or.inr ⟨r, hr, hs⟩ => by
        let ⟨s, ht⟩ := (mem_inits _ _).1 hr
        rw [← hs, ← ht]; exact ⟨s, rfl⟩,
      fun mi =>
      match s, mi with
      | [], ⟨_, rfl⟩ => Or.inl rfl
      | b :: s, ⟨r, hr⟩ =>
        (List.noConfusion hr) fun ba (st : s ++ r = t) =>
          Or.inr <| by 

Proof state:
α : Type u_1
β : Type u_2
l l₁ l₂ l₃ : List α
a✝ b✝ : α
m n : ℕ
s✝ : List α
a : α
t : List α
mi : s✝ <+: a :: t
b : α
s r : List α
hr : b :: s ++ r = a :: t
ba : b = a
st : s ++ r = t
⊢ ∃ l, l ∈ inits t ∧ a :: l = b :: s

Next tactic:
rw [ba]
@[simp]
theorem mem_inits : ∀ s t : List α, s ∈ inits t ↔ s <+: t
  | s, [] =>
    suffices s = nil ↔ s <+: nil by simpa only [inits, mem_singleton]
    ⟨fun h => h.symm ▸ prefix_refl [], eq_nil_of_prefix_nil⟩
  | s, a :: t =>
    suffices (s = nil ∨ ∃ l ∈ inits t, a :: l = s) ↔ s <+: a :: t by simpa
    ⟨fun o =>
      match s, o with
      | _, Or.inl rfl => ⟨_, rfl⟩
      | s, Or.inr ⟨r, hr, hs⟩ => by
        let ⟨s, ht⟩ := (mem_inits _ _).1 hr
        rw [← hs, ← ht]; exact ⟨s, rfl⟩,
      fun mi =>
      match s, mi with
      | [], ⟨_, rfl⟩ => Or.inl rfl
      | b :: s, ⟨r, hr⟩ =>
        (List.noConfusion hr) fun ba (st : s ++ r = t) =>
          Or.inr <| by rw [ba]; 

Proof state:
α : Type u_1
β : Type u_2
l l₁ l₂ l₃ : List α
a✝ b✝ : α
m n : ℕ
s✝ : List α
a : α
t : List α
mi : s✝ <+: a :: t
b : α
s r : List α
hr : b :: s ++ r = a :: t
ba : b = a
st : s ++ r = t
⊢ ∃ l, l ∈ inits t ∧ a :: l = a :: s

Next tactic:
exact ⟨_, (mem_inits _ _).2 ⟨_, st⟩, rfl⟩
@[simp]
theorem mem_inits : ∀ s t : List α, s ∈ inits t ↔ s <+: t
  | s, [] =>
    suffices s = nil ↔ s <+: nil by simpa only [inits, mem_singleton]
    ⟨fun h => h.symm ▸ prefix_refl [], eq_nil_of_prefix_nil⟩
  | s, a :: t =>
    suffices (s = nil ∨ ∃ l ∈ inits t, a :: l = s) ↔ s <+: a :: t by 

Proof state:
α : Type u_1
β : Type u_2
l l₁ l₂ l₃ : List α
a✝ b : α
m n : ℕ
s : List α
a : α
t : List α
this : (s = [] ∨ ∃ l, l ∈ inits t ∧ a :: l = s) ↔ s <+: a :: t
⊢ s ∈ inits (a :: t) ↔ s <+: a :: t

Next tactic:
simpa
@[simp]
theorem mem_tails : ∀ s t : List α, s ∈ tails t ↔ s <:+ t
  | s, [] => by
    

Proof state:
α : Type u_1
β : Type u_2
l l₁ l₂ l₃ : List α
a b : α
m n : ℕ
s : List α
⊢ s ∈ tails [] ↔ s <:+ []

Next tactic:
simp only [tails, mem_singleton, suffix_nil]
@[simp]
theorem mem_tails : ∀ s t : List α, s ∈ tails t ↔ s <:+ t
  | s, [] => by
    simp only [tails, mem_singleton, suffix_nil]
  | s, a :: t => by
    

Proof state:
α : Type u_1
β : Type u_2
l l₁ l₂ l₃ : List α
a✝ b : α
m n : ℕ
s : List α
a : α
t : List α
⊢ s ∈ tails (a :: t) ↔ s <:+ a :: t

Next tactic:
simp only [tails, mem_cons, mem_tails s t]
@[simp]
theorem mem_tails : ∀ s t : List α, s ∈ tails t ↔ s <:+ t
  | s, [] => by
    simp only [tails, mem_singleton, suffix_nil]
  | s, a :: t => by
    simp only [tails, mem_cons, mem_tails s t];
    

Proof state:
α : Type u_1
β : Type u_2
l l₁ l₂ l₃ : List α
a✝ b : α
m n : ℕ
s : List α
a : α
t : List α
⊢ s = a :: t ∨ s <:+ t ↔ s <:+ a :: t

Next tactic:
exact
      show s = a :: t ∨ s <:+ t ↔ s <:+ a :: t from
        ⟨fun o =>
          match s, t, o with
          | _, t, Or.inl rfl => suffix_rfl
          | s, _, Or.inr ⟨l, rfl⟩ => ⟨a :: l, rfl⟩,
          fun e =>
          match s, t, e with
          | _, t, ⟨[], rfl⟩ => Or.inl rfl
          | s, t, ⟨b :: l, he⟩ => List.noConfusion he fun _ lt => Or.inr ⟨l, lt⟩⟩
theorem inits_cons (a : α) (l : List α) : inits (a :: l) = [] :: l.inits.map fun t => a :: t := by
  

Proof state:
α : Type u_1
β : Type u_2
l✝ l₁ l₂ l₃ : List α
a✝ b : α
m n : ℕ
a : α
l : List α
⊢ inits (a :: l) = [] :: map (fun t => a :: t) (inits l)

Next tactic:
simp
theorem tails_cons (a : α) (l : List α) : tails (a :: l) = (a :: l) :: l.tails := by 

Proof state:
α : Type u_1
β : Type u_2
l✝ l₁ l₂ l₃ : List α
a✝ b : α
m n : ℕ
a : α
l : List α
⊢ tails (a :: l) = (a :: l) :: tails l

Next tactic:
simp
@[simp]
theorem inits_append : ∀ s t : List α, inits (s ++ t) = s.inits ++ t.inits.tail.map fun l => s ++ l
  | [], [] => by 

Proof state:
α : Type u_1
β : Type u_2
l l₁ l₂ l₃ : List α
a b : α
m n : ℕ
⊢ inits ([] ++ []) = inits [] ++ map (fun l => [] ++ l) (tail (inits []))

Next tactic:
simp
@[simp]
theorem inits_append : ∀ s t : List α, inits (s ++ t) = s.inits ++ t.inits.tail.map fun l => s ++ l
  | [], [] => by simp
  | [], a :: t => by 

Proof state:
α : Type u_1
β : Type u_2
l l₁ l₂ l₃ : List α
a✝ b : α
m n : ℕ
a : α
t : List α
⊢ inits ([] ++ a :: t) = inits [] ++ map (fun l => [] ++ l) (tail (inits (a :: t)))

Next tactic:
simp[· ∘ ·]
@[simp]
theorem inits_append : ∀ s t : List α, inits (s ++ t) = s.inits ++ t.inits.tail.map fun l => s ++ l
  | [], [] => by simp
  | [], a :: t => by simp[· ∘ ·]
  | a :: s, t => by 

Proof state:
α : Type u_1
β : Type u_2
l l₁ l₂ l₃ : List α
a✝ b : α
m n : ℕ
a : α
s t : List α
⊢ inits (a :: s ++ t) = inits (a :: s) ++ map (fun l => a :: s ++ l) (tail (inits t))

Next tactic:
simp [inits_append s t, · ∘ ·]
@[simp]
theorem tails_append :
    ∀ s t : List α, tails (s ++ t) = (s.tails.map fun l => l ++ t) ++ t.tails.tail
  | [], [] => by 

Proof state:
α : Type u_1
β : Type u_2
l l₁ l₂ l₃ : List α
a b : α
m n : ℕ
⊢ tails ([] ++ []) = map (fun l => l ++ []) (tails []) ++ tail (tails [])

Next tactic:
simp
@[simp]
theorem tails_append :
    ∀ s t : List α, tails (s ++ t) = (s.tails.map fun l => l ++ t) ++ t.tails.tail
  | [], [] => by simp
  | [], a :: t => by 

Proof state:
α : Type u_1
β : Type u_2
l l₁ l₂ l₃ : List α
a✝ b : α
m n : ℕ
a : α
t : List α
⊢ tails ([] ++ a :: t) = map (fun l => l ++ a :: t) (tails []) ++ tail (tails (a :: t))

Next tactic:
simp
@[simp]
theorem tails_append :
    ∀ s t : List α, tails (s ++ t) = (s.tails.map fun l => l ++ t) ++ t.tails.tail
  | [], [] => by simp
  | [], a :: t => by simp
  | a :: s, t => by 

Proof state:
α : Type u_1
β : Type u_2
l l₁ l₂ l₃ : List α
a✝ b : α
m n : ℕ
a : α
s t : List α
⊢ tails (a :: s ++ t) = map (fun l => l ++ t) (tails (a :: s)) ++ tail (tails t)

Next tactic:
simp [tails_append s t]
theorem inits_eq_tails : ∀ l : List α, l.inits = (reverse <| map reverse <| tails <| reverse l)
  | [] => by 

Proof state:
α : Type u_1
β : Type u_2
l l₁ l₂ l₃ : List α
a b : α
m n : ℕ
⊢ inits [] = reverse (map reverse (tails (reverse [])))

Next tactic:
simp
theorem inits_eq_tails : ∀ l : List α, l.inits = (reverse <| map reverse <| tails <| reverse l)
  | [] => by simp
  | a :: l => by 

Proof state:
α : Type u_1
β : Type u_2
l✝ l₁ l₂ l₃ : List α
a✝ b : α
m n : ℕ
a : α
l : List α
⊢ inits (a :: l) = reverse (map reverse (tails (reverse (a :: l))))

Next tactic:
simp [inits_eq_tails l, map_eq_map_iff, reverse_map]
theorem tails_eq_inits : ∀ l : List α, l.tails = (reverse <| map reverse <| inits <| reverse l)
  | [] => by 

Proof state:
α : Type u_1
β : Type u_2
l l₁ l₂ l₃ : List α
a b : α
m n : ℕ
⊢ tails [] = reverse (map reverse (inits (reverse [])))

Next tactic:
simp
theorem tails_eq_inits : ∀ l : List α, l.tails = (reverse <| map reverse <| inits <| reverse l)
  | [] => by simp
  | a :: l => by 

Proof state:
α : Type u_1
β : Type u_2
l✝ l₁ l₂ l₃ : List α
a✝ b : α
m n : ℕ
a : α
l : List α
⊢ tails (a :: l) = reverse (map reverse (inits (reverse (a :: l))))

Next tactic:
simp [tails_eq_inits l, append_left_inj]
theorem inits_reverse (l : List α) : inits (reverse l) = reverse (map reverse l.tails) := by
  

Proof state:
α : Type u_1
β : Type u_2
l✝ l₁ l₂ l₃ : List α
a b : α
m n : ℕ
l : List α
⊢ inits (reverse l) = reverse (map reverse (tails l))

Next tactic:
rw [tails_eq_inits l]
theorem inits_reverse (l : List α) : inits (reverse l) = reverse (map reverse l.tails) := by
  rw [tails_eq_inits l]
  

Proof state:
α : Type u_1
β : Type u_2
l✝ l₁ l₂ l₃ : List α
a b : α
m n : ℕ
l : List α
⊢ inits (reverse l) = reverse (map reverse (reverse (map reverse (inits (reverse l)))))

Next tactic:
simp [reverse_involutive.comp_self, reverse_map]
theorem tails_reverse (l : List α) : tails (reverse l) = reverse (map reverse l.inits) := by
  

Proof state:
α : Type u_1
β : Type u_2
l✝ l₁ l₂ l₃ : List α
a b : α
m n : ℕ
l : List α
⊢ tails (reverse l) = reverse (map reverse (inits l))

Next tactic:
rw [inits_eq_tails l]
theorem tails_reverse (l : List α) : tails (reverse l) = reverse (map reverse l.inits) := by
  rw [inits_eq_tails l]
  

Proof state:
α : Type u_1
β : Type u_2
l✝ l₁ l₂ l₃ : List α
a b : α
m n : ℕ
l : List α
⊢ tails (reverse l) = reverse (map reverse (reverse (map reverse (tails (reverse l)))))

Next tactic:
simp [reverse_involutive.comp_self, reverse_map]
theorem map_reverse_inits (l : List α) : map reverse l.inits = (reverse <| tails <| reverse l) := by
  

Proof state:
α : Type u_1
β : Type u_2
l✝ l₁ l₂ l₃ : List α
a b : α
m n : ℕ
l : List α
⊢ map reverse (inits l) = reverse (tails (reverse l))

Next tactic:
rw [inits_eq_tails l]
theorem map_reverse_inits (l : List α) : map reverse l.inits = (reverse <| tails <| reverse l) := by
  rw [inits_eq_tails l]
  

Proof state:
α : Type u_1
β : Type u_2
l✝ l₁ l₂ l₃ : List α
a b : α
m n : ℕ
l : List α
⊢ map reverse (reverse (map reverse (tails (reverse l)))) = reverse (tails (reverse l))

Next tactic:
simp [reverse_involutive.comp_self, reverse_map]
theorem map_reverse_tails (l : List α) : map reverse l.tails = (reverse <| inits <| reverse l) := by
  

Proof state:
α : Type u_1
β : Type u_2
l✝ l₁ l₂ l₃ : List α
a b : α
m n : ℕ
l : List α
⊢ map reverse (tails l) = reverse (inits (reverse l))

Next tactic:
rw [tails_eq_inits l]
theorem map_reverse_tails (l : List α) : map reverse l.tails = (reverse <| inits <| reverse l) := by
  rw [tails_eq_inits l]
  

Proof state:
α : Type u_1
β : Type u_2
l✝ l₁ l₂ l₃ : List α
a b : α
m n : ℕ
l : List α
⊢ map reverse (reverse (map reverse (inits (reverse l)))) = reverse (inits (reverse l))

Next tactic:
simp [reverse_involutive.comp_self, reverse_map]
@[simp]
theorem length_tails (l : List α) : length (tails l) = length l + 1 := by
  

Proof state:
α : Type u_1
β : Type u_2
l✝ l₁ l₂ l₃ : List α
a b : α
m n : ℕ
l : List α
⊢ length (tails l) = length l + 1

Next tactic:
induction' l with x l IH
@[simp]
theorem length_tails (l : List α) : length (tails l) = length l + 1 := by
  induction' l with x l IH
  · 

Proof state:
case nil
α : Type u_1
β : Type u_2
l l₁ l₂ l₃ : List α
a b : α
m n : ℕ
⊢ length (tails []) = length [] + 1

Next tactic:
simp
@[simp]
theorem length_tails (l : List α) : length (tails l) = length l + 1 := by
  induction' l with x l IH
  · simp
  · 

Proof state:
case cons
α : Type u_1
β : Type u_2
l✝ l₁ l₂ l₃ : List α
a b : α
m n : ℕ
x : α
l : List α
IH : length (tails l) = length l + 1
⊢ length (tails (x :: l)) = length (x :: l) + 1

Next tactic:
simpa using IH
@[simp]
theorem length_inits (l : List α) : length (inits l) = length l + 1 := by 

Proof state:
α : Type u_1
β : Type u_2
l✝ l₁ l₂ l₃ : List α
a b : α
m n : ℕ
l : List α
⊢ length (inits l) = length l + 1

Next tactic:
simp [inits_eq_tails]
@[simp]
theorem nth_le_tails (l : List α) (n : ℕ) (hn : n < length (tails l)) :
    nthLe (tails l) n hn = l.drop n := by
  

Proof state:
α : Type u_1
β : Type u_2
l✝ l₁ l₂ l₃ : List α
a b : α
m n✝ : ℕ
l : List α
n : ℕ
hn : n < length (tails l)
⊢ nthLe (tails l) n hn = drop n l

Next tactic:
induction' l with x l IH generalizing n
@[simp]
theorem nth_le_tails (l : List α) (n : ℕ) (hn : n < length (tails l)) :
    nthLe (tails l) n hn = l.drop n := by
  induction' l with x l IH generalizing n
  · 

Proof state:
case nil
α : Type u_1
β : Type u_2
l l₁ l₂ l₃ : List α
a b : α
m n✝ n : ℕ
hn : n < length (tails [])
⊢ nthLe (tails []) n hn = drop n []

Next tactic:
simp
@[simp]
theorem nth_le_tails (l : List α) (n : ℕ) (hn : n < length (tails l)) :
    nthLe (tails l) n hn = l.drop n := by
  induction' l with x l IH generalizing n
  · simp
  · 

Proof state:
case cons
α : Type u_1
β : Type u_2
l✝ l₁ l₂ l₃ : List α
a b : α
m n✝ : ℕ
x : α
l : List α
IH : ∀ (n : ℕ) (hn : n < length (tails l)), nthLe (tails l) n hn = drop n l
n : ℕ
hn : n < length (tails (x :: l))
⊢ nthLe (tails (x :: l)) n hn = drop n (x :: l)

Next tactic:
cases n
@[simp]
theorem nth_le_tails (l : List α) (n : ℕ) (hn : n < length (tails l)) :
    nthLe (tails l) n hn = l.drop n := by
  induction' l with x l IH generalizing n
  · simp
  · cases n
    · 

Proof state:
case cons.zero
α : Type u_1
β : Type u_2
l✝ l₁ l₂ l₃ : List α
a b : α
m n : ℕ
x : α
l : List α
IH : ∀ (n : ℕ) (hn : n < length (tails l)), nthLe (tails l) n hn = drop n l
hn : zero < length (tails (x :: l))
⊢ nthLe (tails (x :: l)) zero hn = drop zero (x :: l)

Next tactic:
simp[nthLe_cons]
@[simp]
theorem nth_le_tails (l : List α) (n : ℕ) (hn : n < length (tails l)) :
    nthLe (tails l) n hn = l.drop n := by
  induction' l with x l IH generalizing n
  · simp
  · cases n
    · simp[nthLe_cons]
    · 

Proof state:
case cons.succ
α : Type u_1
β : Type u_2
l✝ l₁ l₂ l₃ : List α
a b : α
m n : ℕ
x : α
l : List α
IH : ∀ (n : ℕ) (hn : n < length (tails l)), nthLe (tails l) n hn = drop n l
n✝ : ℕ
hn : succ n✝ < length (tails (x :: l))
⊢ nthLe (tails (x :: l)) (succ n✝) hn = drop (succ n✝) (x :: l)

Next tactic:
simpa[nthLe_cons] using IH _ _
@[simp]
theorem nth_le_inits (l : List α) (n : ℕ) (hn : n < length (inits l)) :
    nthLe (inits l) n hn = l.take n := by
  

Proof state:
α : Type u_1
β : Type u_2
l✝ l₁ l₂ l₃ : List α
a b : α
m n✝ : ℕ
l : List α
n : ℕ
hn : n < length (inits l)
⊢ nthLe (inits l) n hn = take n l

Next tactic:
induction' l with x l IH generalizing n
@[simp]
theorem nth_le_inits (l : List α) (n : ℕ) (hn : n < length (inits l)) :
    nthLe (inits l) n hn = l.take n := by
  induction' l with x l IH generalizing n
  · 

Proof state:
case nil
α : Type u_1
β : Type u_2
l l₁ l₂ l₃ : List α
a b : α
m n✝ n : ℕ
hn : n < length (inits [])
⊢ nthLe (inits []) n hn = take n []

Next tactic:
simp