l3lab/ntp-mathlib huggingface dataset:
theorem range_eq_iSup {N} [Group N] (f : ∀ i, G i →* N) : (lift f).range = ⨆ i, (f i).range := by
  apply le_antisymm (lift_range_le _ f fun i => le_iSup (fun i => MonoidHom.range (f i)) i)
  apply iSup_le _
  rintro i _ ⟨x, rfl⟩
  

Proof state:
case intro
ι : Type u_1
M : ι → Type u_2
inst✝³ : (i : ι) → Monoid (M i)
N✝ : Type u_3
inst✝² : Monoid N✝
G : ι → Type u_4
inst✝¹ : (i : ι) → Group (G i)
N : Type u_5
inst✝ : Group N
f : (i : ι) → G i →* N
i : ι
x : G i
⊢ (f i) x ∈ MonoidHom.range (lift f)

Next tactic:
exact ⟨of x, by simp only [lift_of]⟩
theorem range_eq_iSup {N} [Group N] (f : ∀ i, G i →* N) : (lift f).range = ⨆ i, (f i).range := by
  apply le_antisymm (lift_range_le _ f fun i => le_iSup (fun i => MonoidHom.range (f i)) i)
  apply iSup_le _
  rintro i _ ⟨x, rfl⟩
  exact ⟨of x, by 

Proof state:
ι : Type u_1
M : ι → Type u_2
inst✝³ : (i : ι) → Monoid (M i)
N✝ : Type u_3
inst✝² : Monoid N✝
G : ι → Type u_4
inst✝¹ : (i : ι) → Group (G i)
N : Type u_5
inst✝ : Group N
f : (i : ι) → G i →* N
i : ι
x : G i
⊢ (lift f) (of x) = (f i) x

Next tactic:
simp only [lift_of]
/-- The empty reduced word. -/
@[simps]
def empty : Word M where
  toList := []
  ne_one := by 

Proof state:
ι : Type u_1
M : ι → Type u_2
inst✝¹ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝ : Monoid N
⊢ ∀ l ∈ [], l.snd ≠ 1

Next tactic:
simp
theorem fstIdx_ne_iff {w : Word M} {i} :
    fstIdx w ≠ some i ↔ ∀ l ∈ w.toList.head?, i ≠ Sigma.fst l :=
  not_iff_not.mp <| by 

Proof state:
ι : Type u_1
M : ι → Type u_2
inst✝¹ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝ : Monoid N
w : Word M
i : ι
⊢ ¬fstIdx w ≠ some i ↔ ¬∀ l ∈ List.head? w.toList, i ≠ l.fst

Next tactic:
simp [fstIdx]
instance (i : ι) : Inhabited (Pair M i) :=
  ⟨⟨1, empty, by 

Proof state:
ι : Type u_1
M : ι → Type u_2
inst✝¹ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝ : Monoid N
i : ι
⊢ fstIdx empty ≠ some i

Next tactic:
tauto
/-- Construct a new `Word` without any reduction. The underlying list of
`cons m w _ _` is `⟨_, m⟩::w`  -/
@[simps]
def cons {i} (m : M i) (w : Word M) (hmw : w.fstIdx ≠ some i) (h1 : m ≠ 1) : Word M :=
  { toList := ⟨i, m⟩ :: w.toList,
    ne_one := by
      

Proof state:
ι : Type u_1
M : ι → Type u_2
inst✝² : (i : ι) → Monoid (M i)
N : Type u_3
inst✝¹ : Monoid N
inst✝ : (i : ι) → DecidableEq (M i)
i : ι
m : M i
w : Word M
hmw : fstIdx w ≠ some i
h1 : m ≠ 1
⊢ ∀ l ∈ { fst := i, snd := m } :: w.toList, l.snd ≠ 1

Next tactic:
simp only [List.mem_cons]
/-- Construct a new `Word` without any reduction. The underlying list of
`cons m w _ _` is `⟨_, m⟩::w`  -/
@[simps]
def cons {i} (m : M i) (w : Word M) (hmw : w.fstIdx ≠ some i) (h1 : m ≠ 1) : Word M :=
  { toList := ⟨i, m⟩ :: w.toList,
    ne_one := by
      simp only [List.mem_cons]
      

Proof state:
ι : Type u_1
M : ι → Type u_2
inst✝² : (i : ι) → Monoid (M i)
N : Type u_3
inst✝¹ : Monoid N
inst✝ : (i : ι) → DecidableEq (M i)
i : ι
m : M i
w : Word M
hmw : fstIdx w ≠ some i
h1 : m ≠ 1
⊢ ∀ (l : (i : ι) × M i), l = { fst := i, snd := m } ∨ l ∈ w.toList → l.snd ≠ 1

Next tactic:
rintro l (rfl | hl)
/-- Construct a new `Word` without any reduction. The underlying list of
`cons m w _ _` is `⟨_, m⟩::w`  -/
@[simps]
def cons {i} (m : M i) (w : Word M) (hmw : w.fstIdx ≠ some i) (h1 : m ≠ 1) : Word M :=
  { toList := ⟨i, m⟩ :: w.toList,
    ne_one := by
      simp only [List.mem_cons]
      rintro l (rfl | hl)
      

Proof state:
case inl
ι : Type u_1
M : ι → Type u_2
inst✝² : (i : ι) → Monoid (M i)
N : Type u_3
inst✝¹ : Monoid N
inst✝ : (i : ι) → DecidableEq (M i)
i : ι
m : M i
w : Word M
hmw : fstIdx w ≠ some i
h1 : m ≠ 1
⊢ { fst := i, snd := m }.snd ≠ 1
case inr
ι : Type u_1
M : ι → Type u_2
inst✝² : (i : ι) → Monoid (M i)
N : Type u_3
inst✝¹ : Monoid N
inst✝ : (i : ι) → DecidableEq (M i)
i : ι
m : M i
w : Word M
hmw : fstIdx w ≠ some i
h1 : m ≠ 1
l : (i : ι) × M i
hl : l ∈ w.toList
⊢ l.snd ≠ 1

Next tactic:
exact h1
/-- Construct a new `Word` without any reduction. The underlying list of
`cons m w _ _` is `⟨_, m⟩::w`  -/
@[simps]
def cons {i} (m : M i) (w : Word M) (hmw : w.fstIdx ≠ some i) (h1 : m ≠ 1) : Word M :=
  { toList := ⟨i, m⟩ :: w.toList,
    ne_one := by
      simp only [List.mem_cons]
      rintro l (rfl | hl)
      exact h1
      

Proof state:
case inr
ι : Type u_1
M : ι → Type u_2
inst✝² : (i : ι) → Monoid (M i)
N : Type u_3
inst✝¹ : Monoid N
inst✝ : (i : ι) → DecidableEq (M i)
i : ι
m : M i
w : Word M
hmw : fstIdx w ≠ some i
h1 : m ≠ 1
l : (i : ι) × M i
hl : l ∈ w.toList
⊢ l.snd ≠ 1

Next tactic:
exact w.ne_one l hl
@[simp]
theorem prod_rcons {i} (p : Pair M i) : prod (rcons p) = of p.head * prod p.tail :=
  if hm : p.head = 1 then by 

Proof state:
ι : Type u_1
M : ι → Type u_2
inst✝² : (i : ι) → Monoid (M i)
N : Type u_3
inst✝¹ : Monoid N
inst✝ : (i : ι) → DecidableEq (M i)
i : ι
p : Pair M i
hm : p.head = 1
⊢ prod (rcons p) = of p.head * prod p.tail

Next tactic:
rw [rcons, dif_pos hm, hm, MonoidHom.map_one, one_mul]
@[simp]
theorem prod_rcons {i} (p : Pair M i) : prod (rcons p) = of p.head * prod p.tail :=
  if hm : p.head = 1 then by rw [rcons, dif_pos hm, hm, MonoidHom.map_one, one_mul]
  else by 

Proof state:
ι : Type u_1
M : ι → Type u_2
inst✝² : (i : ι) → Monoid (M i)
N : Type u_3
inst✝¹ : Monoid N
inst✝ : (i : ι) → DecidableEq (M i)
i : ι
p : Pair M i
hm : ¬p.head = 1
⊢ prod (rcons p) = of p.head * prod p.tail

Next tactic:
rw [rcons, dif_neg hm, cons, prod, List.map_cons, List.prod_cons, prod]
theorem rcons_inj {i} : Function.Injective (rcons : Pair M i → Word M) := by
  

Proof state:
ι : Type u_1
M : ι → Type u_2
inst✝² : (i : ι) → Monoid (M i)
N : Type u_3
inst✝¹ : Monoid N
inst✝ : (i : ι) → DecidableEq (M i)
i : ι
⊢ Function.Injective rcons

Next tactic:
rintro ⟨m, w, h⟩ ⟨m', w', h'⟩ he
theorem rcons_inj {i} : Function.Injective (rcons : Pair M i → Word M) := by
  rintro ⟨m, w, h⟩ ⟨m', w', h'⟩ he
  

Proof state:
case mk.mk
ι : Type u_1
M : ι → Type u_2
inst✝² : (i : ι) → Monoid (M i)
N : Type u_3
inst✝¹ : Monoid N
inst✝ : (i : ι) → DecidableEq (M i)
i : ι
m : M i
w : Word M
h : fstIdx w ≠ some i
m' : M i
w' : Word M
h' : fstIdx w' ≠ some i
he : rcons { head := m, tail := w, fstIdx_ne := h } = rcons { head := m', tail := w', fstIdx_ne := h' }
⊢ { head := m, tail := w, fstIdx_ne := h } = { head := m', tail := w', fstIdx_ne := h' }

Next tactic:
by_cases hm : m = 1
theorem rcons_inj {i} : Function.Injective (rcons : Pair M i → Word M) := by
  rintro ⟨m, w, h⟩ ⟨m', w', h'⟩ he
  by_cases hm : m = 1 <;> 

Proof state:
case pos
ι : Type u_1
M : ι → Type u_2
inst✝² : (i : ι) → Monoid (M i)
N : Type u_3
inst✝¹ : Monoid N
inst✝ : (i : ι) → DecidableEq (M i)
i : ι
m : M i
w : Word M
h : fstIdx w ≠ some i
m' : M i
w' : Word M
h' : fstIdx w' ≠ some i
he : rcons { head := m, tail := w, fstIdx_ne := h } = rcons { head := m', tail := w', fstIdx_ne := h' }
hm : m = 1
⊢ { head := m, tail := w, fstIdx_ne := h } = { head := m', tail := w', fstIdx_ne := h' }

Next tactic:
by_cases hm' : m' = 1
theorem rcons_inj {i} : Function.Injective (rcons : Pair M i → Word M) := by
  rintro ⟨m, w, h⟩ ⟨m', w', h'⟩ he
  by_cases hm : m = 1 <;> 

Proof state:
case neg
ι : Type u_1
M : ι → Type u_2
inst✝² : (i : ι) → Monoid (M i)
N : Type u_3
inst✝¹ : Monoid N
inst✝ : (i : ι) → DecidableEq (M i)
i : ι
m : M i
w : Word M
h : fstIdx w ≠ some i
m' : M i
w' : Word M
h' : fstIdx w' ≠ some i
he : rcons { head := m, tail := w, fstIdx_ne := h } = rcons { head := m', tail := w', fstIdx_ne := h' }
hm : ¬m = 1
⊢ { head := m, tail := w, fstIdx_ne := h } = { head := m', tail := w', fstIdx_ne := h' }

Next tactic:
by_cases hm' : m' = 1
theorem rcons_inj {i} : Function.Injective (rcons : Pair M i → Word M) := by
  rintro ⟨m, w, h⟩ ⟨m', w', h'⟩ he
  by_cases hm : m = 1 <;> by_cases hm' : m' = 1
  · 

Proof state:
case pos
ι : Type u_1
M : ι → Type u_2
inst✝² : (i : ι) → Monoid (M i)
N : Type u_3
inst✝¹ : Monoid N
inst✝ : (i : ι) → DecidableEq (M i)
i : ι
m : M i
w : Word M
h : fstIdx w ≠ some i
m' : M i
w' : Word M
h' : fstIdx w' ≠ some i
he : rcons { head := m, tail := w, fstIdx_ne := h } = rcons { head := m', tail := w', fstIdx_ne := h' }
hm : m = 1
hm' : m' = 1
⊢ { head := m, tail := w, fstIdx_ne := h } = { head := m', tail := w', fstIdx_ne := h' }

Next tactic:
simp only [rcons, dif_pos hm, dif_pos hm'] at he
theorem rcons_inj {i} : Function.Injective (rcons : Pair M i → Word M) := by
  rintro ⟨m, w, h⟩ ⟨m', w', h'⟩ he
  by_cases hm : m = 1 <;> by_cases hm' : m' = 1
  · simp only [rcons, dif_pos hm, dif_pos hm'] at he
    

Proof state:
case pos
ι : Type u_1
M : ι → Type u_2
inst✝² : (i : ι) → Monoid (M i)
N : Type u_3
inst✝¹ : Monoid N
inst✝ : (i : ι) → DecidableEq (M i)
i : ι
m : M i
w : Word M
h : fstIdx w ≠ some i
m' : M i
w' : Word M
h' : fstIdx w' ≠ some i
hm : m = 1
hm' : m' = 1
he : w = w'
⊢ { head := m, tail := w, fstIdx_ne := h } = { head := m', tail := w', fstIdx_ne := h' }

Next tactic:
aesop
theorem rcons_inj {i} : Function.Injective (rcons : Pair M i → Word M) := by
  rintro ⟨m, w, h⟩ ⟨m', w', h'⟩ he
  by_cases hm : m = 1 <;> by_cases hm' : m' = 1
  · simp only [rcons, dif_pos hm, dif_pos hm'] at he
    aesop
  · 

Proof state:
case neg
ι : Type u_1
M : ι → Type u_2
inst✝² : (i : ι) → Monoid (M i)
N : Type u_3
inst✝¹ : Monoid N
inst✝ : (i : ι) → DecidableEq (M i)
i : ι
m : M i
w : Word M
h : fstIdx w ≠ some i
m' : M i
w' : Word M
h' : fstIdx w' ≠ some i
he : rcons { head := m, tail := w, fstIdx_ne := h } = rcons { head := m', tail := w', fstIdx_ne := h' }
hm : m = 1
hm' : ¬m' = 1
⊢ { head := m, tail := w, fstIdx_ne := h } = { head := m', tail := w', fstIdx_ne := h' }

Next tactic:
exfalso
theorem rcons_inj {i} : Function.Injective (rcons : Pair M i → Word M) := by
  rintro ⟨m, w, h⟩ ⟨m', w', h'⟩ he
  by_cases hm : m = 1 <;> by_cases hm' : m' = 1
  · simp only [rcons, dif_pos hm, dif_pos hm'] at he
    aesop
  · exfalso
    

Proof state:
case neg.h
ι : Type u_1
M : ι → Type u_2
inst✝² : (i : ι) → Monoid (M i)
N : Type u_3
inst✝¹ : Monoid N
inst✝ : (i : ι) → DecidableEq (M i)
i : ι
m : M i
w : Word M
h : fstIdx w ≠ some i
m' : M i
w' : Word M
h' : fstIdx w' ≠ some i
he : rcons { head := m, tail := w, fstIdx_ne := h } = rcons { head := m', tail := w', fstIdx_ne := h' }
hm : m = 1
hm' : ¬m' = 1
⊢ False

Next tactic:
simp only [rcons, dif_pos hm, dif_neg hm'] at he
theorem rcons_inj {i} : Function.Injective (rcons : Pair M i → Word M) := by
  rintro ⟨m, w, h⟩ ⟨m', w', h'⟩ he
  by_cases hm : m = 1 <;> by_cases hm' : m' = 1
  · simp only [rcons, dif_pos hm, dif_pos hm'] at he
    aesop
  · exfalso
    simp only [rcons, dif_pos hm, dif_neg hm'] at he
    

Proof state:
case neg.h
ι : Type u_1
M : ι → Type u_2
inst✝² : (i : ι) → Monoid (M i)
N : Type u_3
inst✝¹ : Monoid N
inst✝ : (i : ι) → DecidableEq (M i)
i : ι
m : M i
w : Word M
h : fstIdx w ≠ some i
m' : M i
w' : Word M
h' : fstIdx w' ≠ some i
hm : m = 1
hm' : ¬m' = 1
he :
  w =
    cons m' w' (_ : fstIdx { head := m', tail := w', fstIdx_ne := h' }.tail ≠ some i)
      (_ : ¬{ head := m', tail := w', fstIdx_ne := h' }.head = 1)
⊢ False

Next tactic:
rw [he] at h
theorem rcons_inj {i} : Function.Injective (rcons : Pair M i → Word M) := by
  rintro ⟨m, w, h⟩ ⟨m', w', h'⟩ he
  by_cases hm : m = 1 <;> by_cases hm' : m' = 1
  · simp only [rcons, dif_pos hm, dif_pos hm'] at he
    aesop
  · exfalso
    simp only [rcons, dif_pos hm, dif_neg hm'] at he
    rw [he] at h
    

Proof state:
case neg.h
ι : Type u_1
M : ι → Type u_2
inst✝² : (i : ι) → Monoid (M i)
N : Type u_3
inst✝¹ : Monoid N
inst✝ : (i : ι) → DecidableEq (M i)
i : ι
m : M i
w : Word M
m' : M i
w' : Word M
h' : fstIdx w' ≠ some i
hm : m = 1
hm' : ¬m' = 1
h :
  fstIdx
      (cons m' w' (_ : fstIdx { head := m', tail := w', fstIdx_ne := h' }.tail ≠ some i)
        (_ : ¬{ head := m', tail := w', fstIdx_ne := h' }.head = 1)) ≠
    some i
he :
  w =
    cons m' w' (_ : fstIdx { head := m', tail := w', fstIdx_ne := h' }.tail ≠ some i)
      (_ : ¬{ head := m', tail := w', fstIdx_ne := h' }.head = 1)
⊢ False

Next tactic:
exact h rfl
theorem rcons_inj {i} : Function.Injective (rcons : Pair M i → Word M) := by
  rintro ⟨m, w, h⟩ ⟨m', w', h'⟩ he
  by_cases hm : m = 1 <;> by_cases hm' : m' = 1
  · simp only [rcons, dif_pos hm, dif_pos hm'] at he
    aesop
  · exfalso
    simp only [rcons, dif_pos hm, dif_neg hm'] at he
    rw [he] at h
    exact h rfl
  · 

Proof state:
case pos
ι : Type u_1
M : ι → Type u_2
inst✝² : (i : ι) → Monoid (M i)
N : Type u_3
inst✝¹ : Monoid N
inst✝ : (i : ι) → DecidableEq (M i)
i : ι
m : M i
w : Word M
h : fstIdx w ≠ some i
m' : M i
w' : Word M
h' : fstIdx w' ≠ some i
he : rcons { head := m, tail := w, fstIdx_ne := h } = rcons { head := m', tail := w', fstIdx_ne := h' }
hm : ¬m = 1
hm' : m' = 1
⊢ { head := m, tail := w, fstIdx_ne := h } = { head := m', tail := w', fstIdx_ne := h' }

Next tactic:
exfalso
theorem rcons_inj {i} : Function.Injective (rcons : Pair M i → Word M) := by
  rintro ⟨m, w, h⟩ ⟨m', w', h'⟩ he
  by_cases hm : m = 1 <;> by_cases hm' : m' = 1
  · simp only [rcons, dif_pos hm, dif_pos hm'] at he
    aesop
  · exfalso
    simp only [rcons, dif_pos hm, dif_neg hm'] at he
    rw [he] at h
    exact h rfl
  · exfalso
    

Proof state:
case pos.h
ι : Type u_1
M : ι → Type u_2
inst✝² : (i : ι) → Monoid (M i)
N : Type u_3
inst✝¹ : Monoid N
inst✝ : (i : ι) → DecidableEq (M i)
i : ι
m : M i
w : Word M
h : fstIdx w ≠ some i
m' : M i
w' : Word M
h' : fstIdx w' ≠ some i
he : rcons { head := m, tail := w, fstIdx_ne := h } = rcons { head := m', tail := w', fstIdx_ne := h' }
hm : ¬m = 1
hm' : m' = 1
⊢ False

Next tactic:
simp only [rcons, dif_pos hm', dif_neg hm] at he
theorem rcons_inj {i} : Function.Injective (rcons : Pair M i → Word M) := by
  rintro ⟨m, w, h⟩ ⟨m', w', h'⟩ he
  by_cases hm : m = 1 <;> by_cases hm' : m' = 1
  · simp only [rcons, dif_pos hm, dif_pos hm'] at he
    aesop
  · exfalso
    simp only [rcons, dif_pos hm, dif_neg hm'] at he
    rw [he] at h
    exact h rfl
  · exfalso
    simp only [rcons, dif_pos hm', dif_neg hm] at he
    

Proof state:
case pos.h
ι : Type u_1
M : ι → Type u_2
inst✝² : (i : ι) → Monoid (M i)
N : Type u_3
inst✝¹ : Monoid N
inst✝ : (i : ι) → DecidableEq (M i)
i : ι
m : M i
w : Word M
h : fstIdx w ≠ some i
m' : M i
w' : Word M
h' : fstIdx w' ≠ some i
hm : ¬m = 1
hm' : m' = 1
he :
  cons m w (_ : fstIdx { head := m, tail := w, fstIdx_ne := h }.tail ≠ some i)
      (_ : ¬{ head := m, tail := w, fstIdx_ne := h }.head = 1) =
    w'
⊢ False

Next tactic:
rw [← he] at h'
theorem rcons_inj {i} : Function.Injective (rcons : Pair M i → Word M) := by
  rintro ⟨m, w, h⟩ ⟨m', w', h'⟩ he
  by_cases hm : m = 1 <;> by_cases hm' : m' = 1
  · simp only [rcons, dif_pos hm, dif_pos hm'] at he
    aesop
  · exfalso
    simp only [rcons, dif_pos hm, dif_neg hm'] at he
    rw [he] at h
    exact h rfl
  · exfalso
    simp only [rcons, dif_pos hm', dif_neg hm] at he
    rw [← he] at h'
    

Proof state:
case pos.h
ι : Type u_1
M : ι → Type u_2
inst✝² : (i : ι) → Monoid (M i)
N : Type u_3
inst✝¹ : Monoid N
inst✝ : (i : ι) → DecidableEq (M i)
i : ι
m : M i
w : Word M
h : fstIdx w ≠ some i
m' : M i
w' : Word M
hm : ¬m = 1
h' :
  fstIdx
      (cons m w (_ : fstIdx { head := m, tail := w, fstIdx_ne := h }.tail ≠ some i)
        (_ : ¬{ head := m, tail := w, fstIdx_ne := h }.head = 1)) ≠
    some i
hm' : m' = 1
he :
  cons m w (_ : fstIdx { head := m, tail := w, fstIdx_ne := h }.tail ≠ some i)
      (_ : ¬{ head := m, tail := w, fstIdx_ne := h }.head = 1) =
    w'
⊢ False

Next tactic:
exact h' rfl
theorem rcons_inj {i} : Function.Injective (rcons : Pair M i → Word M) := by
  rintro ⟨m, w, h⟩ ⟨m', w', h'⟩ he
  by_cases hm : m = 1 <;> by_cases hm' : m' = 1
  · simp only [rcons, dif_pos hm, dif_pos hm'] at he
    aesop
  · exfalso
    simp only [rcons, dif_pos hm, dif_neg hm'] at he
    rw [he] at h
    exact h rfl
  · exfalso
    simp only [rcons, dif_pos hm', dif_neg hm] at he
    rw [← he] at h'
    exact h' rfl
  · 

Proof state:
case neg
ι : Type u_1
M : ι → Type u_2
inst✝² : (i : ι) → Monoid (M i)
N : Type u_3
inst✝¹ : Monoid N
inst✝ : (i : ι) → DecidableEq (M i)
i : ι
m : M i
w : Word M
h : fstIdx w ≠ some i
m' : M i
w' : Word M
h' : fstIdx w' ≠ some i
he : rcons { head := m, tail := w, fstIdx_ne := h } = rcons { head := m', tail := w', fstIdx_ne := h' }
hm : ¬m = 1
hm' : ¬m' = 1
⊢ { head := m, tail := w, fstIdx_ne := h } = { head := m', tail := w', fstIdx_ne := h' }

Next tactic:
have : m = m' ∧ w.toList = w'.toList := by
      simpa [cons, rcons, dif_neg hm, dif_neg hm', true_and_iff, eq_self_iff_true, Subtype.mk_eq_mk,
        heq_iff_eq, ← Subtype.ext_iff_val] using he
theorem rcons_inj {i} : Function.Injective (rcons : Pair M i → Word M) := by
  rintro ⟨m, w, h⟩ ⟨m', w', h'⟩ he
  by_cases hm : m = 1 <;> by_cases hm' : m' = 1
  · simp only [rcons, dif_pos hm, dif_pos hm'] at he
    aesop
  · exfalso
    simp only [rcons, dif_pos hm, dif_neg hm'] at he
    rw [he] at h
    exact h rfl
  · exfalso
    simp only [rcons, dif_pos hm', dif_neg hm] at he
    rw [← he] at h'
    exact h' rfl
  · have : m = m' ∧ w.toList = w'.toList := by
      

Proof state:
ι : Type u_1
M : ι → Type u_2
inst✝² : (i : ι) → Monoid (M i)
N : Type u_3
inst✝¹ : Monoid N
inst✝ : (i : ι) → DecidableEq (M i)
i : ι
m : M i
w : Word M
h : fstIdx w ≠ some i
m' : M i
w' : Word M
h' : fstIdx w' ≠ some i
he : rcons { head := m, tail := w, fstIdx_ne := h } = rcons { head := m', tail := w', fstIdx_ne := h' }
hm : ¬m = 1
hm' : ¬m' = 1
⊢ m = m' ∧ w.toList = w'.toList

Next tactic:
simpa [cons, rcons, dif_neg hm, dif_neg hm', true_and_iff, eq_self_iff_true, Subtype.mk_eq_mk,
        heq_iff_eq, ← Subtype.ext_iff_val] using he
theorem rcons_inj {i} : Function.Injective (rcons : Pair M i → Word M) := by
  rintro ⟨m, w, h⟩ ⟨m', w', h'⟩ he
  by_cases hm : m = 1 <;> by_cases hm' : m' = 1
  · simp only [rcons, dif_pos hm, dif_pos hm'] at he
    aesop
  · exfalso
    simp only [rcons, dif_pos hm, dif_neg hm'] at he
    rw [he] at h
    exact h rfl
  · exfalso
    simp only [rcons, dif_pos hm', dif_neg hm] at he
    rw [← he] at h'
    exact h' rfl
  · have : m = m' ∧ w.toList = w'.toList := by
      simpa [cons, rcons, dif_neg hm, dif_neg hm', true_and_iff, eq_self_iff_true, Subtype.mk_eq_mk,
        heq_iff_eq, ← Subtype.ext_iff_val] using he
    

Proof state:
case neg
ι : Type u_1
M : ι → Type u_2
inst✝² : (i : ι) → Monoid (M i)
N : Type u_3
inst✝¹ : Monoid N
inst✝ : (i : ι) → DecidableEq (M i)
i : ι
m : M i
w : Word M
h : fstIdx w ≠ some i
m' : M i
w' : Word M
h' : fstIdx w' ≠ some i
he : rcons { head := m, tail := w, fstIdx_ne := h } = rcons { head := m', tail := w', fstIdx_ne := h' }
hm : ¬m = 1
hm' : ¬m' = 1
this : m = m' ∧ w.toList = w'.toList
⊢ { head := m, tail := w, fstIdx_ne := h } = { head := m', tail := w', fstIdx_ne := h' }

Next tactic:
rcases this with ⟨rfl, h⟩
theorem rcons_inj {i} : Function.Injective (rcons : Pair M i → Word M) := by
  rintro ⟨m, w, h⟩ ⟨m', w', h'⟩ he
  by_cases hm : m = 1 <;> by_cases hm' : m' = 1
  · simp only [rcons, dif_pos hm, dif_pos hm'] at he
    aesop
  · exfalso
    simp only [rcons, dif_pos hm, dif_neg hm'] at he
    rw [he] at h
    exact h rfl
  · exfalso
    simp only [rcons, dif_pos hm', dif_neg hm] at he
    rw [← he] at h'
    exact h' rfl
  · have : m = m' ∧ w.toList = w'.toList := by
      simpa [cons, rcons, dif_neg hm, dif_neg hm', true_and_iff, eq_self_iff_true, Subtype.mk_eq_mk,
        heq_iff_eq, ← Subtype.ext_iff_val] using he
    rcases this with ⟨rfl, h⟩
    

Proof state:
case neg.intro
ι : Type u_1
M : ι → Type u_2
inst✝² : (i : ι) → Monoid (M i)
N : Type u_3
inst✝¹ : Monoid N
inst✝ : (i : ι) → DecidableEq (M i)
i : ι
m : M i
w : Word M
h✝ : fstIdx w ≠ some i
w' : Word M
h' : fstIdx w' ≠ some i
hm : ¬m = 1
h : w.toList = w'.toList
he : rcons { head := m, tail := w, fstIdx_ne := h✝ } = rcons { head := m, tail := w', fstIdx_ne := h' }
hm' : ¬m = 1
⊢ { head := m, tail := w, fstIdx_ne := h✝ } = { head := m, tail := w', fstIdx_ne := h' }

Next tactic:
congr
theorem rcons_inj {i} : Function.Injective (rcons : Pair M i → Word M) := by
  rintro ⟨m, w, h⟩ ⟨m', w', h'⟩ he
  by_cases hm : m = 1 <;> by_cases hm' : m' = 1
  · simp only [rcons, dif_pos hm, dif_pos hm'] at he
    aesop
  · exfalso
    simp only [rcons, dif_pos hm, dif_neg hm'] at he
    rw [he] at h
    exact h rfl
  · exfalso
    simp only [rcons, dif_pos hm', dif_neg hm] at he
    rw [← he] at h'
    exact h' rfl
  · have : m = m' ∧ w.toList = w'.toList := by
      simpa [cons, rcons, dif_neg hm, dif_neg hm', true_and_iff, eq_self_iff_true, Subtype.mk_eq_mk,
        heq_iff_eq, ← Subtype.ext_iff_val] using he
    rcases this with ⟨rfl, h⟩
    congr
    

Proof state:
case neg.intro.e_tail
ι : Type u_1
M : ι → Type u_2
inst✝² : (i : ι) → Monoid (M i)
N : Type u_3
inst✝¹ : Monoid N
inst✝ : (i : ι) → DecidableEq (M i)
i : ι
m : M i
w : Word M
h✝ : fstIdx w ≠ some i
w' : Word M
h' : fstIdx w' ≠ some i
hm : ¬m = 1
h : w.toList = w'.toList
he : rcons { head := m, tail := w, fstIdx_ne := h✝ } = rcons { head := m, tail := w', fstIdx_ne := h' }
hm' : ¬m = 1
⊢ w = w'

Next tactic:
exact Word.ext _ _ h
theorem mem_rcons_iff {i j : ι} (p : Pair M i) (m : M j) :
    ⟨_, m⟩ ∈ (rcons p).toList ↔ ⟨_, m⟩ ∈ p.tail.toList ∨
      m ≠ 1 ∧ (∃ h : i = j, m = h ▸ p.head) := by
  

Proof state:
ι : Type u_1
M : ι → Type u_2
inst✝² : (i : ι) → Monoid (M i)
N : Type u_3
inst✝¹ : Monoid N
inst✝ : (i : ι) → DecidableEq (M i)
i j : ι
p : Pair M i
m : M j
⊢ { fst := j, snd := m } ∈ (rcons p).toList ↔
    { fst := j, snd := m } ∈ p.tail.toList ∨ m ≠ 1 ∧ ∃ (h : i = j), m = h ▸ p.head

Next tactic:
simp only [rcons._eq_1, cons._eq_1, ne_eq]
theorem mem_rcons_iff {i j : ι} (p : Pair M i) (m : M j) :
    ⟨_, m⟩ ∈ (rcons p).toList ↔ ⟨_, m⟩ ∈ p.tail.toList ∨
      m ≠ 1 ∧ (∃ h : i = j, m = h ▸ p.head) := by
  simp only [rcons._eq_1, cons._eq_1, ne_eq]
  

Proof state:
ι : Type u_1
M : ι → Type u_2
inst✝² : (i : ι) → Monoid (M i)
N : Type u_3
inst✝¹ : Monoid N
inst✝ : (i : ι) → DecidableEq (M i)
i j : ι
p : Pair M i
m : M j
⊢ { fst := j, snd := m } ∈
      (if h : p.head = 1 then p.tail
        else
          { toList := { fst := i, snd := p.head } :: p.tail.toList,
            ne_one := (_ : ∀ l ∈ { fst := i, snd := p.head } :: p.tail.toList, l.snd ≠ 1),
            chain_ne :=
              (_ : List.Chain' (fun l l' => l.fst ≠ l'.fst) ({ fst := i, snd := p.head } :: p.tail.toList)) }).toList ↔
    { fst := j, snd := m } ∈ p.tail.toList ∨ ¬m = 1 ∧ ∃ (h : i = j), m = h ▸ p.head

Next tactic:
by_cases hij : i = j
theorem mem_rcons_iff {i j : ι} (p : Pair M i) (m : M j) :
    ⟨_, m⟩ ∈ (rcons p).toList ↔ ⟨_, m⟩ ∈ p.tail.toList ∨
      m ≠ 1 ∧ (∃ h : i = j, m = h ▸ p.head) := by
  simp only [rcons._eq_1, cons._eq_1, ne_eq]
  by_cases hij : i = j
  · 

Proof state:
case pos
ι : Type u_1
M : ι → Type u_2
inst✝² : (i : ι) → Monoid (M i)
N : Type u_3
inst✝¹ : Monoid N
inst✝ : (i : ι) → DecidableEq (M i)
i j : ι
p : Pair M i
m : M j
hij : i = j
⊢ { fst := j, snd := m } ∈
      (if h : p.head = 1 then p.tail
        else
          { toList := { fst := i, snd := p.head } :: p.tail.toList,
            ne_one := (_ : ∀ l ∈ { fst := i, snd := p.head } :: p.tail.toList, l.snd ≠ 1),
            chain_ne :=
              (_ : List.Chain' (fun l l' => l.fst ≠ l'.fst) ({ fst := i, snd := p.head } :: p.tail.toList)) }).toList ↔
    { fst := j, snd := m } ∈ p.tail.toList ∨ ¬m = 1 ∧ ∃ (h : i = j), m = h ▸ p.head

Next tactic:
subst i
theorem mem_rcons_iff {i j : ι} (p : Pair M i) (m : M j) :
    ⟨_, m⟩ ∈ (rcons p).toList ↔ ⟨_, m⟩ ∈ p.tail.toList ∨
      m ≠ 1 ∧ (∃ h : i = j, m = h ▸ p.head) := by
  simp only [rcons._eq_1, cons._eq_1, ne_eq]
  by_cases hij : i = j
  · subst i
    

Proof state:
case pos
ι : Type u_1
M : ι → Type u_2
inst✝² : (i : ι) → Monoid (M i)
N : Type u_3
inst✝¹ : Monoid N
inst✝ : (i : ι) → DecidableEq (M i)
j : ι
m : M j
p : Pair M j
⊢ { fst := j, snd := m } ∈
      (if h : p.head = 1 then p.tail
        else
          { toList := { fst := j, snd := p.head } :: p.tail.toList,
            ne_one := (_ : ∀ l ∈ { fst := j, snd := p.head } :: p.tail.toList, l.snd ≠ 1),
            chain_ne :=
              (_ : List.Chain' (fun l l' => l.fst ≠ l'.fst) ({ fst := j, snd := p.head } :: p.tail.toList)) }).toList ↔
    { fst := j, snd := m } ∈ p.tail.toList ∨ ¬m = 1 ∧ ∃ (h : j = j), m = h ▸ p.head

Next tactic:
by_cases hm : m = p.head