l3lab/ntp-mathlib huggingface dataset:
theorem ext_smul {w₁ w₂ : NormalWord d} (i : ι)
    (h : CoprodI.of (φ i w₁.head) • w₁.toWord =
         CoprodI.of (φ i w₂.head) • w₂.toWord) :
    w₁ = w₂ := by
  rcases w₁ with ⟨w₁, h₁, hw₁⟩
  rcases w₂ with ⟨w₂, h₂, hw₂⟩
  dsimp at *
  rw [smul_eq_iff_eq_inv_smul, ← mul_smul] at h
  subst h
  simp only [← map_inv, ← map_mul] at hw₁
  have : h₁⁻¹ * h₂ = 1 := eq_one_of_smul_normalized w₂ (h₁⁻¹ * h₂) hw₂ hw₁
  

Proof state:
case mk.mk
ι : Type u_1
G : ι → Type u_2
H : Type u_3
K : Type u_4
inst✝⁴ : Monoid K
inst✝³ : (i : ι) → Group (G i)
inst✝² : Group H
φ : (i : ι) → H →* G i
d : Transversal φ
inst✝¹ : DecidableEq ι
inst✝ : (i : ι) → DecidableEq (G i)
i : ι
h₁ : H
w₂ : Word fun i => G i
h₂ : H
hw₂ : ∀ (i : ι) (g : G i), { fst := i, snd := g } ∈ w₂.toList → g ∈ Transversal.set d i
hw₁✝ :
  ∀ (i_1 : ι) (g : G i_1),
    { fst := i_1, snd := g } ∈ (((CoprodI.of ((φ i) h₁))⁻¹ * CoprodI.of ((φ i) h₂)) • w₂).toList →
      g ∈ Transversal.set d i_1
hw₁ :
  ∀ (i_1 : ι) (g : G i_1),
    { fst := i_1, snd := g } ∈ (CoprodI.of ((φ i) (h₁⁻¹ * h₂)) • w₂).toList → g ∈ Transversal.set d i_1
this : h₁⁻¹ * h₂ = 1
⊢ { toWord := ((CoprodI.of ((φ i) h₁))⁻¹ * CoprodI.of ((φ i) h₂)) • w₂, head := h₁, normalized := hw₁✝ } =
    { toWord := w₂, head := h₂, normalized := hw₂ }

Next tactic:
rw [inv_mul_eq_one] at this
theorem ext_smul {w₁ w₂ : NormalWord d} (i : ι)
    (h : CoprodI.of (φ i w₁.head) • w₁.toWord =
         CoprodI.of (φ i w₂.head) • w₂.toWord) :
    w₁ = w₂ := by
  rcases w₁ with ⟨w₁, h₁, hw₁⟩
  rcases w₂ with ⟨w₂, h₂, hw₂⟩
  dsimp at *
  rw [smul_eq_iff_eq_inv_smul, ← mul_smul] at h
  subst h
  simp only [← map_inv, ← map_mul] at hw₁
  have : h₁⁻¹ * h₂ = 1 := eq_one_of_smul_normalized w₂ (h₁⁻¹ * h₂) hw₂ hw₁
  rw [inv_mul_eq_one] at this; 

Proof state:
case mk.mk
ι : Type u_1
G : ι → Type u_2
H : Type u_3
K : Type u_4
inst✝⁴ : Monoid K
inst✝³ : (i : ι) → Group (G i)
inst✝² : Group H
φ : (i : ι) → H →* G i
d : Transversal φ
inst✝¹ : DecidableEq ι
inst✝ : (i : ι) → DecidableEq (G i)
i : ι
h₁ : H
w₂ : Word fun i => G i
h₂ : H
hw₂ : ∀ (i : ι) (g : G i), { fst := i, snd := g } ∈ w₂.toList → g ∈ Transversal.set d i
hw₁✝ :
  ∀ (i_1 : ι) (g : G i_1),
    { fst := i_1, snd := g } ∈ (((CoprodI.of ((φ i) h₁))⁻¹ * CoprodI.of ((φ i) h₂)) • w₂).toList →
      g ∈ Transversal.set d i_1
hw₁ :
  ∀ (i_1 : ι) (g : G i_1),
    { fst := i_1, snd := g } ∈ (CoprodI.of ((φ i) (h₁⁻¹ * h₂)) • w₂).toList → g ∈ Transversal.set d i_1
this : h₁ = h₂
⊢ { toWord := ((CoprodI.of ((φ i) h₁))⁻¹ * CoprodI.of ((φ i) h₂)) • w₂, head := h₁, normalized := hw₁✝ } =
    { toWord := w₂, head := h₂, normalized := hw₂ }

Next tactic:
subst this
theorem ext_smul {w₁ w₂ : NormalWord d} (i : ι)
    (h : CoprodI.of (φ i w₁.head) • w₁.toWord =
         CoprodI.of (φ i w₂.head) • w₂.toWord) :
    w₁ = w₂ := by
  rcases w₁ with ⟨w₁, h₁, hw₁⟩
  rcases w₂ with ⟨w₂, h₂, hw₂⟩
  dsimp at *
  rw [smul_eq_iff_eq_inv_smul, ← mul_smul] at h
  subst h
  simp only [← map_inv, ← map_mul] at hw₁
  have : h₁⁻¹ * h₂ = 1 := eq_one_of_smul_normalized w₂ (h₁⁻¹ * h₂) hw₂ hw₁
  rw [inv_mul_eq_one] at this; subst this
  

Proof state:
case mk.mk
ι : Type u_1
G : ι → Type u_2
H : Type u_3
K : Type u_4
inst✝⁴ : Monoid K
inst✝³ : (i : ι) → Group (G i)
inst✝² : Group H
φ : (i : ι) → H →* G i
d : Transversal φ
inst✝¹ : DecidableEq ι
inst✝ : (i : ι) → DecidableEq (G i)
i : ι
h₁ : H
w₂ : Word fun i => G i
hw₂ : ∀ (i : ι) (g : G i), { fst := i, snd := g } ∈ w₂.toList → g ∈ Transversal.set d i
hw₁✝ :
  ∀ (i_1 : ι) (g : G i_1),
    { fst := i_1, snd := g } ∈ (((CoprodI.of ((φ i) h₁))⁻¹ * CoprodI.of ((φ i) h₁)) • w₂).toList →
      g ∈ Transversal.set d i_1
hw₁ :
  ∀ (i_1 : ι) (g : G i_1),
    { fst := i_1, snd := g } ∈ (CoprodI.of ((φ i) (h₁⁻¹ * h₁)) • w₂).toList → g ∈ Transversal.set d i_1
⊢ { toWord := ((CoprodI.of ((φ i) h₁))⁻¹ * CoprodI.of ((φ i) h₁)) • w₂, head := h₁, normalized := hw₁✝ } =
    { toWord := w₂, head := h₁, normalized := hw₂ }

Next tactic:
simp
/-- A constructor that multiplies a `NormalWord` by an element, with condition to make
sure the underlying list does get longer.  -/
@[simps!]
noncomputable def cons {i} (g : G i) (w : NormalWord d) (hmw : w.fstIdx ≠ some i)
    (hgr : g ∉ (φ i).range) : NormalWord d :=
  letI n := (d.compl i).equiv (g * (φ i w.head))
  letI w' := Word.cons (n.2 : G i) w.toWord hmw
    (mt (coe_equiv_snd_eq_one_iff_mem _ (d.one_mem _)).1
      (mt (mul_mem_cancel_right (by 

Proof state:
ι : Type u_1
G : ι → Type u_2
H : Type u_3
K : Type u_4
inst✝⁴ : Monoid K
inst✝³ : (i : ι) → Group (G i)
inst✝² : Group H
φ : (i : ι) → H →* G i
d : Transversal φ
inst✝¹ : DecidableEq ι
inst✝ : (i : ι) → DecidableEq (G i)
i : ι
g : G i
w : NormalWord d
hmw : Word.fstIdx w.toWord ≠ some i
hgr : g ∉ MonoidHom.range (φ i)
n : ↑↑(MonoidHom.range (φ i)) × ↑(Transversal.set d i) :=
  (equiv (_ : IsComplement (↑(MonoidHom.range (φ i))) (Transversal.set d i))) (g * (φ i) w.head)
⊢ (φ i) w.head ∈ MonoidHom.range (φ i)

Next tactic:
simp
/-- A constructor that multiplies a `NormalWord` by an element, with condition to make
sure the underlying list does get longer.  -/
@[simps!]
noncomputable def cons {i} (g : G i) (w : NormalWord d) (hmw : w.fstIdx ≠ some i)
    (hgr : g ∉ (φ i).range) : NormalWord d :=
  letI n := (d.compl i).equiv (g * (φ i w.head))
  letI w' := Word.cons (n.2 : G i) w.toWord hmw
    (mt (coe_equiv_snd_eq_one_iff_mem _ (d.one_mem _)).1
      (mt (mul_mem_cancel_right (by simp)).1 hgr))
  { toWord := w'
    head := (MonoidHom.ofInjective (d.injective i)).symm n.1
    normalized := fun i g hg => by
      

Proof state:
ι : Type u_1
G : ι → Type u_2
H : Type u_3
K : Type u_4
inst✝⁴ : Monoid K
inst✝³ : (i : ι) → Group (G i)
inst✝² : Group H
φ : (i : ι) → H →* G i
d : Transversal φ
inst✝¹ : DecidableEq ι
inst✝ : (i : ι) → DecidableEq (G i)
i✝ : ι
g✝ : G i✝
w : NormalWord d
hmw : Word.fstIdx w.toWord ≠ some i✝
hgr : g✝ ∉ MonoidHom.range (φ i✝)
n : ↑↑(MonoidHom.range (φ i✝)) × ↑(Transversal.set d i✝) :=
  (equiv (_ : IsComplement (↑(MonoidHom.range (φ i✝))) (Transversal.set d i✝))) (g✝ * (φ i✝) w.head)
w' : Word G := Word.cons (↑n.2) w.toWord hmw (_ : ¬↑n.2 = 1)
i : ι
g : G i
hg : { fst := i, snd := g } ∈ w'.toList
⊢ g ∈ Transversal.set d i

Next tactic:
simp only [Word.cons, mem_cons, Sigma.mk.inj_iff] at hg
/-- A constructor that multiplies a `NormalWord` by an element, with condition to make
sure the underlying list does get longer.  -/
@[simps!]
noncomputable def cons {i} (g : G i) (w : NormalWord d) (hmw : w.fstIdx ≠ some i)
    (hgr : g ∉ (φ i).range) : NormalWord d :=
  letI n := (d.compl i).equiv (g * (φ i w.head))
  letI w' := Word.cons (n.2 : G i) w.toWord hmw
    (mt (coe_equiv_snd_eq_one_iff_mem _ (d.one_mem _)).1
      (mt (mul_mem_cancel_right (by simp)).1 hgr))
  { toWord := w'
    head := (MonoidHom.ofInjective (d.injective i)).symm n.1
    normalized := fun i g hg => by
      simp only [Word.cons, mem_cons, Sigma.mk.inj_iff] at hg
      

Proof state:
ι : Type u_1
G : ι → Type u_2
H : Type u_3
K : Type u_4
inst✝⁴ : Monoid K
inst✝³ : (i : ι) → Group (G i)
inst✝² : Group H
φ : (i : ι) → H →* G i
d : Transversal φ
inst✝¹ : DecidableEq ι
inst✝ : (i : ι) → DecidableEq (G i)
i✝ : ι
g✝ : G i✝
w : NormalWord d
hmw : Word.fstIdx w.toWord ≠ some i✝
hgr : g✝ ∉ MonoidHom.range (φ i✝)
n : ↑↑(MonoidHom.range (φ i✝)) × ↑(Transversal.set d i✝) :=
  (equiv (_ : IsComplement (↑(MonoidHom.range (φ i✝))) (Transversal.set d i✝))) (g✝ * (φ i✝) w.head)
w' : Word G := Word.cons (↑n.2) w.toWord hmw (_ : ¬↑n.2 = 1)
i : ι
g : G i
hg :
  i = i✝ ∧
      HEq g ↑((equiv (_ : IsComplement (↑(MonoidHom.range (φ i✝))) (Transversal.set d i✝))) (g✝ * (φ i✝) w.head)).2 ∨
    { fst := i, snd := g } ∈ w.toList
⊢ g ∈ Transversal.set d i

Next tactic:
rcases hg with ⟨rfl, hg | hg⟩
/-- A constructor that multiplies a `NormalWord` by an element, with condition to make
sure the underlying list does get longer.  -/
@[simps!]
noncomputable def cons {i} (g : G i) (w : NormalWord d) (hmw : w.fstIdx ≠ some i)
    (hgr : g ∉ (φ i).range) : NormalWord d :=
  letI n := (d.compl i).equiv (g * (φ i w.head))
  letI w' := Word.cons (n.2 : G i) w.toWord hmw
    (mt (coe_equiv_snd_eq_one_iff_mem _ (d.one_mem _)).1
      (mt (mul_mem_cancel_right (by simp)).1 hgr))
  { toWord := w'
    head := (MonoidHom.ofInjective (d.injective i)).symm n.1
    normalized := fun i g hg => by
      simp only [Word.cons, mem_cons, Sigma.mk.inj_iff] at hg
      rcases hg with ⟨rfl, hg | hg⟩
      · 

Proof state:
case inl.intro.refl
ι : Type u_1
G : ι → Type u_2
H : Type u_3
K : Type u_4
inst✝⁴ : Monoid K
inst✝³ : (i : ι) → Group (G i)
inst✝² : Group H
φ : (i : ι) → H →* G i
d : Transversal φ
inst✝¹ : DecidableEq ι
inst✝ : (i : ι) → DecidableEq (G i)
w : NormalWord d
i : ι
g : G i
hmw : Word.fstIdx w.toWord ≠ some i
hgr : g ∉ MonoidHom.range (φ i)
n : ↑↑(MonoidHom.range (φ i)) × ↑(Transversal.set d i) :=
  (equiv (_ : IsComplement (↑(MonoidHom.range (φ i))) (Transversal.set d i))) (g * (φ i) w.head)
w' : Word G := Word.cons (↑n.2) w.toWord hmw (_ : ¬↑n.2 = 1)
β : Type u_2
⊢ ↑((equiv (_ : IsComplement (↑(MonoidHom.range (φ i))) (Transversal.set d i))) (g * (φ i) w.head)).2 ∈
    Transversal.set d i

Next tactic:
simp
/-- A constructor that multiplies a `NormalWord` by an element, with condition to make
sure the underlying list does get longer.  -/
@[simps!]
noncomputable def cons {i} (g : G i) (w : NormalWord d) (hmw : w.fstIdx ≠ some i)
    (hgr : g ∉ (φ i).range) : NormalWord d :=
  letI n := (d.compl i).equiv (g * (φ i w.head))
  letI w' := Word.cons (n.2 : G i) w.toWord hmw
    (mt (coe_equiv_snd_eq_one_iff_mem _ (d.one_mem _)).1
      (mt (mul_mem_cancel_right (by simp)).1 hgr))
  { toWord := w'
    head := (MonoidHom.ofInjective (d.injective i)).symm n.1
    normalized := fun i g hg => by
      simp only [Word.cons, mem_cons, Sigma.mk.inj_iff] at hg
      rcases hg with ⟨rfl, hg | hg⟩
      · simp
      · 

Proof state:
case inr
ι : Type u_1
G : ι → Type u_2
H : Type u_3
K : Type u_4
inst✝⁴ : Monoid K
inst✝³ : (i : ι) → Group (G i)
inst✝² : Group H
φ : (i : ι) → H →* G i
d : Transversal φ
inst✝¹ : DecidableEq ι
inst✝ : (i : ι) → DecidableEq (G i)
i✝ : ι
g✝ : G i✝
w : NormalWord d
hmw : Word.fstIdx w.toWord ≠ some i✝
hgr : g✝ ∉ MonoidHom.range (φ i✝)
n : ↑↑(MonoidHom.range (φ i✝)) × ↑(Transversal.set d i✝) :=
  (equiv (_ : IsComplement (↑(MonoidHom.range (φ i✝))) (Transversal.set d i✝))) (g✝ * (φ i✝) w.head)
w' : Word G := Word.cons (↑n.2) w.toWord hmw (_ : ¬↑n.2 = 1)
i : ι
g : G i
h✝ : { fst := i, snd := g } ∈ w.toList
⊢ g ∈ Transversal.set d i

Next tactic:
exact w.normalized _ _ (by assumption)
/-- A constructor that multiplies a `NormalWord` by an element, with condition to make
sure the underlying list does get longer.  -/
@[simps!]
noncomputable def cons {i} (g : G i) (w : NormalWord d) (hmw : w.fstIdx ≠ some i)
    (hgr : g ∉ (φ i).range) : NormalWord d :=
  letI n := (d.compl i).equiv (g * (φ i w.head))
  letI w' := Word.cons (n.2 : G i) w.toWord hmw
    (mt (coe_equiv_snd_eq_one_iff_mem _ (d.one_mem _)).1
      (mt (mul_mem_cancel_right (by simp)).1 hgr))
  { toWord := w'
    head := (MonoidHom.ofInjective (d.injective i)).symm n.1
    normalized := fun i g hg => by
      simp only [Word.cons, mem_cons, Sigma.mk.inj_iff] at hg
      rcases hg with ⟨rfl, hg | hg⟩
      · simp
      · exact w.normalized _ _ (by 

Proof state:
ι : Type u_1
G : ι → Type u_2
H : Type u_3
K : Type u_4
inst✝⁴ : Monoid K
inst✝³ : (i : ι) → Group (G i)
inst✝² : Group H
φ : (i : ι) → H →* G i
d : Transversal φ
inst✝¹ : DecidableEq ι
inst✝ : (i : ι) → DecidableEq (G i)
i✝ : ι
g✝ : G i✝
w : NormalWord d
hmw : Word.fstIdx w.toWord ≠ some i✝
hgr : g✝ ∉ MonoidHom.range (φ i✝)
n : ↑↑(MonoidHom.range (φ i✝)) × ↑(Transversal.set d i✝) :=
  (equiv (_ : IsComplement (↑(MonoidHom.range (φ i✝))) (Transversal.set d i✝))) (g✝ * (φ i✝) w.head)
w' : Word G := Word.cons (↑n.2) w.toWord hmw (_ : ¬↑n.2 = 1)
i : ι
g : G i
h✝ : { fst := i, snd := g } ∈ w.toList
⊢ { fst := i, snd := g } ∈ w.toList

Next tactic:
assumption
/-- Given a pair `(head, tail)`, we can form a word by prepending `head` to `tail`, but
putting head into normal form first, by making sure it is expressed as an element
of the base group multiplied by an element of the transversal. -/
noncomputable def rcons (i : ι) (p : Pair d i) : NormalWord d :=
  letI n := (d.compl i).equiv p.head
  let w := (Word.equivPair i).symm { p.toPair with head := n.2 }
  { toWord := w
    head := (MonoidHom.ofInjective (d.injective i)).symm n.1
    normalized := fun i g hg => by
        

Proof state:
ι : Type u_1
G : ι → Type u_2
H : Type u_3
K : Type u_4
inst✝⁴ : Monoid K
inst✝³ : (i : ι) → Group (G i)
inst✝² : Group H
φ : (i : ι) → H →* G i
d : Transversal φ
inst✝¹ : DecidableEq ι
inst✝ : (i : ι) → DecidableEq (G i)
i✝ : ι
p : Pair d i✝
n : ↑↑(MonoidHom.range (φ i✝)) × ↑(Transversal.set d i✝) :=
  (equiv (_ : IsComplement (↑(MonoidHom.range (φ i✝))) (Transversal.set d i✝))) p.head
w : Word fun i => G i :=
  (Word.equivPair i✝).symm
    (let src := p.toPair;
    { head := ↑n.2, tail := src.tail, fstIdx_ne := (_ : Word.fstIdx src.tail ≠ some i✝) })
i : ι
g : G i
hg : { fst := i, snd := g } ∈ w.toList
⊢ g ∈ Transversal.set d i

Next tactic:
dsimp at hg
/-- Given a pair `(head, tail)`, we can form a word by prepending `head` to `tail`, but
putting head into normal form first, by making sure it is expressed as an element
of the base group multiplied by an element of the transversal. -/
noncomputable def rcons (i : ι) (p : Pair d i) : NormalWord d :=
  letI n := (d.compl i).equiv p.head
  let w := (Word.equivPair i).symm { p.toPair with head := n.2 }
  { toWord := w
    head := (MonoidHom.ofInjective (d.injective i)).symm n.1
    normalized := fun i g hg => by
        dsimp at hg
        

Proof state:
ι : Type u_1
G : ι → Type u_2
H : Type u_3
K : Type u_4
inst✝⁴ : Monoid K
inst✝³ : (i : ι) → Group (G i)
inst✝² : Group H
φ : (i : ι) → H →* G i
d : Transversal φ
inst✝¹ : DecidableEq ι
inst✝ : (i : ι) → DecidableEq (G i)
i✝ : ι
p : Pair d i✝
n : ↑↑(MonoidHom.range (φ i✝)) × ↑(Transversal.set d i✝) :=
  (equiv (_ : IsComplement (↑(MonoidHom.range (φ i✝))) (Transversal.set d i✝))) p.head
w : Word fun i => G i :=
  (Word.equivPair i✝).symm
    (let src := p.toPair;
    { head := ↑n.2, tail := src.tail, fstIdx_ne := (_ : Word.fstIdx src.tail ≠ some i✝) })
i : ι
g : G i
hg :
  { fst := i, snd := g } ∈
    ((Word.equivPair i✝).symm
        { head := ↑((equiv (_ : IsComplement (↑(MonoidHom.range (φ i✝))) (Transversal.set d i✝))) p.head).2,
          tail := p.tail, fstIdx_ne := (_ : Word.fstIdx p.tail ≠ some i✝) }).toList
⊢ g ∈ Transversal.set d i

Next tactic:
rw [Word.equivPair_symm, Word.mem_rcons_iff] at hg
/-- Given a pair `(head, tail)`, we can form a word by prepending `head` to `tail`, but
putting head into normal form first, by making sure it is expressed as an element
of the base group multiplied by an element of the transversal. -/
noncomputable def rcons (i : ι) (p : Pair d i) : NormalWord d :=
  letI n := (d.compl i).equiv p.head
  let w := (Word.equivPair i).symm { p.toPair with head := n.2 }
  { toWord := w
    head := (MonoidHom.ofInjective (d.injective i)).symm n.1
    normalized := fun i g hg => by
        dsimp at hg
        rw [Word.equivPair_symm, Word.mem_rcons_iff] at hg
        

Proof state:
ι : Type u_1
G : ι → Type u_2
H : Type u_3
K : Type u_4
inst✝⁴ : Monoid K
inst✝³ : (i : ι) → Group (G i)
inst✝² : Group H
φ : (i : ι) → H →* G i
d : Transversal φ
inst✝¹ : DecidableEq ι
inst✝ : (i : ι) → DecidableEq (G i)
i✝ : ι
p : Pair d i✝
n : ↑↑(MonoidHom.range (φ i✝)) × ↑(Transversal.set d i✝) :=
  (equiv (_ : IsComplement (↑(MonoidHom.range (φ i✝))) (Transversal.set d i✝))) p.head
w : Word fun i => G i :=
  (Word.equivPair i✝).symm
    (let src := p.toPair;
    { head := ↑n.2, tail := src.tail, fstIdx_ne := (_ : Word.fstIdx src.tail ≠ some i✝) })
i : ι
g : G i
hg :
  { fst := i, snd := g } ∈
      { head := ↑((equiv (_ : IsComplement (↑(MonoidHom.range (φ i✝))) (Transversal.set d i✝))) p.head).2,
            tail := p.tail, fstIdx_ne := (_ : Word.fstIdx p.tail ≠ some i✝) }.tail.toList ∨
    g ≠ 1 ∧
      ∃ (h : i✝ = i),
        g =
          h ▸
            { head := ↑((equiv (_ : IsComplement (↑(MonoidHom.range (φ i✝))) (Transversal.set d i✝))) p.head).2,
                tail := p.tail, fstIdx_ne := (_ : Word.fstIdx p.tail ≠ some i✝) }.head
⊢ g ∈ Transversal.set d i

Next tactic:
rcases hg with hg | ⟨_, rfl, rfl⟩
/-- Given a pair `(head, tail)`, we can form a word by prepending `head` to `tail`, but
putting head into normal form first, by making sure it is expressed as an element
of the base group multiplied by an element of the transversal. -/
noncomputable def rcons (i : ι) (p : Pair d i) : NormalWord d :=
  letI n := (d.compl i).equiv p.head
  let w := (Word.equivPair i).symm { p.toPair with head := n.2 }
  { toWord := w
    head := (MonoidHom.ofInjective (d.injective i)).symm n.1
    normalized := fun i g hg => by
        dsimp at hg
        rw [Word.equivPair_symm, Word.mem_rcons_iff] at hg
        rcases hg with hg | ⟨_, rfl, rfl⟩
        · 

Proof state:
case inl
ι : Type u_1
G : ι → Type u_2
H : Type u_3
K : Type u_4
inst✝⁴ : Monoid K
inst✝³ : (i : ι) → Group (G i)
inst✝² : Group H
φ : (i : ι) → H →* G i
d : Transversal φ
inst✝¹ : DecidableEq ι
inst✝ : (i : ι) → DecidableEq (G i)
i✝ : ι
p : Pair d i✝
n : ↑↑(MonoidHom.range (φ i✝)) × ↑(Transversal.set d i✝) :=
  (equiv (_ : IsComplement (↑(MonoidHom.range (φ i✝))) (Transversal.set d i✝))) p.head
w : Word fun i => G i :=
  (Word.equivPair i✝).symm
    (let src := p.toPair;
    { head := ↑n.2, tail := src.tail, fstIdx_ne := (_ : Word.fstIdx src.tail ≠ some i✝) })
i : ι
g : G i
hg :
  { fst := i, snd := g } ∈
    { head := ↑((equiv (_ : IsComplement (↑(MonoidHom.range (φ i✝))) (Transversal.set d i✝))) p.head).2, tail := p.tail,
          fstIdx_ne := (_ : Word.fstIdx p.tail ≠ some i✝) }.tail.toList
⊢ g ∈ Transversal.set d i

Next tactic:
exact p.normalized _ _ hg
/-- Given a pair `(head, tail)`, we can form a word by prepending `head` to `tail`, but
putting head into normal form first, by making sure it is expressed as an element
of the base group multiplied by an element of the transversal. -/
noncomputable def rcons (i : ι) (p : Pair d i) : NormalWord d :=
  letI n := (d.compl i).equiv p.head
  let w := (Word.equivPair i).symm { p.toPair with head := n.2 }
  { toWord := w
    head := (MonoidHom.ofInjective (d.injective i)).symm n.1
    normalized := fun i g hg => by
        dsimp at hg
        rw [Word.equivPair_symm, Word.mem_rcons_iff] at hg
        rcases hg with hg | ⟨_, rfl, rfl⟩
        · exact p.normalized _ _ hg
        · 

Proof state:
case inr.intro.intro
ι : Type u_1
G : ι → Type u_2
H : Type u_3
K : Type u_4
inst✝⁴ : Monoid K
inst✝³ : (i : ι) → Group (G i)
inst✝² : Group H
φ : (i : ι) → H →* G i
d : Transversal φ
inst✝¹ : DecidableEq ι
inst✝ : (i : ι) → DecidableEq (G i)
i : ι
p : Pair d i
n : ↑↑(MonoidHom.range (φ i)) × ↑(Transversal.set d i) :=
  (equiv (_ : IsComplement (↑(MonoidHom.range (φ i))) (Transversal.set d i))) p.head
w : Word fun i => G i :=
  (Word.equivPair i).symm
    (let src := p.toPair;
    { head := ↑n.2, tail := src.tail, fstIdx_ne := (_ : Word.fstIdx src.tail ≠ some i) })
left✝ :
  (_ : i = i) ▸
      { head := ↑((equiv (_ : IsComplement (↑(MonoidHom.range (φ i))) (Transversal.set d i))) p.head).2, tail := p.tail,
          fstIdx_ne := (_ : Word.fstIdx p.tail ≠ some i) }.head ≠
    1
⊢ (_ : i = i) ▸
      { head := ↑((equiv (_ : IsComplement (↑(MonoidHom.range (φ i))) (Transversal.set d i))) p.head).2, tail := p.tail,
          fstIdx_ne := (_ : Word.fstIdx p.tail ≠ some i) }.head ∈
    Transversal.set d i

Next tactic:
simp
theorem rcons_injective {i : ι} : Function.Injective (rcons (d := d) i) := by
  

Proof state:
ι : Type u_1
G : ι → Type u_2
H : Type u_3
K : Type u_4
inst✝⁴ : Monoid K
inst✝³ : (i : ι) → Group (G i)
inst✝² : Group H
φ : (i : ι) → H →* G i
d : Transversal φ
inst✝¹ : DecidableEq ι
inst✝ : (i : ι) → DecidableEq (G i)
i : ι
⊢ Injective (rcons i)

Next tactic:
rintro ⟨⟨head₁, tail₁⟩, _⟩ ⟨⟨head₂, tail₂⟩, _⟩
theorem rcons_injective {i : ι} : Function.Injective (rcons (d := d) i) := by
  rintro ⟨⟨head₁, tail₁⟩, _⟩ ⟨⟨head₂, tail₂⟩, _⟩
  

Proof state:
case mk.mk.mk.mk
ι : Type u_1
G : ι → Type u_2
H : Type u_3
K : Type u_4
inst✝⁴ : Monoid K
inst✝³ : (i : ι) → Group (G i)
inst✝² : Group H
φ : (i : ι) → H →* G i
d : Transversal φ
inst✝¹ : DecidableEq ι
inst✝ : (i : ι) → DecidableEq (G i)
i : ι
head₁ : G i
tail₁ : Word fun i => G i
fstIdx_ne✝¹ : Word.fstIdx tail₁ ≠ some i
normalized✝¹ :
  ∀ (i_1 : ι) (g : G i_1),
    { fst := i_1, snd := g } ∈ { head := head₁, tail := tail₁, fstIdx_ne := fstIdx_ne✝¹ }.tail.toList →
      g ∈ Transversal.set d i_1
head₂ : G i
tail₂ : Word fun i => G i
fstIdx_ne✝ : Word.fstIdx tail₂ ≠ some i
normalized✝ :
  ∀ (i_1 : ι) (g : G i_1),
    { fst := i_1, snd := g } ∈ { head := head₂, tail := tail₂, fstIdx_ne := fstIdx_ne✝ }.tail.toList →
      g ∈ Transversal.set d i_1
⊢ rcons i { toPair := { head := head₁, tail := tail₁, fstIdx_ne := fstIdx_ne✝¹ }, normalized := normalized✝¹ } =
      rcons i { toPair := { head := head₂, tail := tail₂, fstIdx_ne := fstIdx_ne✝ }, normalized := normalized✝ } →
    { toPair := { head := head₁, tail := tail₁, fstIdx_ne := fstIdx_ne✝¹ }, normalized := normalized✝¹ } =
      { toPair := { head := head₂, tail := tail₂, fstIdx_ne := fstIdx_ne✝ }, normalized := normalized✝ }

Next tactic:
simp only [rcons, NormalWord.mk.injEq, EmbeddingLike.apply_eq_iff_eq,
    Word.Pair.mk.injEq, Pair.mk.injEq, and_imp]
theorem rcons_injective {i : ι} : Function.Injective (rcons (d := d) i) := by
  rintro ⟨⟨head₁, tail₁⟩, _⟩ ⟨⟨head₂, tail₂⟩, _⟩
  simp only [rcons, NormalWord.mk.injEq, EmbeddingLike.apply_eq_iff_eq,
    Word.Pair.mk.injEq, Pair.mk.injEq, and_imp]
  

Proof state:
case mk.mk.mk.mk
ι : Type u_1
G : ι → Type u_2
H : Type u_3
K : Type u_4
inst✝⁴ : Monoid K
inst✝³ : (i : ι) → Group (G i)
inst✝² : Group H
φ : (i : ι) → H →* G i
d : Transversal φ
inst✝¹ : DecidableEq ι
inst✝ : (i : ι) → DecidableEq (G i)
i : ι
head₁ : G i
tail₁ : Word fun i => G i
fstIdx_ne✝¹ : Word.fstIdx tail₁ ≠ some i
normalized✝¹ :
  ∀ (i_1 : ι) (g : G i_1),
    { fst := i_1, snd := g } ∈ { head := head₁, tail := tail₁, fstIdx_ne := fstIdx_ne✝¹ }.tail.toList →
      g ∈ Transversal.set d i_1
head₂ : G i
tail₂ : Word fun i => G i
fstIdx_ne✝ : Word.fstIdx tail₂ ≠ some i
normalized✝ :
  ∀ (i_1 : ι) (g : G i_1),
    { fst := i_1, snd := g } ∈ { head := head₂, tail := tail₂, fstIdx_ne := fstIdx_ne✝ }.tail.toList →
      g ∈ Transversal.set d i_1
⊢ ↑((equiv (_ : IsComplement (↑(MonoidHom.range (φ i))) (Transversal.set d i))) head₁).2 =
      ↑((equiv (_ : IsComplement (↑(MonoidHom.range (φ i))) (Transversal.set d i))) head₂).2 →
    tail₁ = tail₂ →
      ((equiv (_ : IsComplement (↑(MonoidHom.range (φ i))) (Transversal.set d i))) head₁).1 =
          ((equiv (_ : IsComplement (↑(MonoidHom.range (φ i))) (Transversal.set d i))) head₂).1 →
        head₁ = head₂ ∧ tail₁ = tail₂

Next tactic:
intro h₁ h₂ h₃