-- Mathlib/Combinatorics/HalesJewett.lean
theorem exists_mono_homothetic_copy {M κ : Type*} [AddCommMonoid M] (S : Finset M) [Finite κ]
    (C : M → κ) : ∃ a > 0, ∃ (b : M) (c : κ), ∀ s ∈ S, C (a • s + b) = c

Proof state:
case intro.intro.intro.intro.refine_3.e_a
M : Type u_5
κ : Type u_6
inst✝¹ : AddCommMonoid M
S : Finset M
inst✝ : Finite κ
C : M → κ
ι : Type
_inst : Fintype ι
l : Line { x // x ∈ S } ι
c : κ
s : Finset ι := Finset.filter (fun i => l.idxFun i = none) Finset.univ
hs : s = Finset.filter (fun i => l.idxFun i = none) Finset.univ
x : M
xs : x ∈ S
⊢ s.card • x + ∑ i ∈ sᶜ, (Option.map (fun m => ↑m) (l.idxFun i)).getD 0 =
    ∑ i ∈ s, ↑(↑l ⟨x, xs⟩ i) + ∑ i ∈ sᶜ, ↑(↑l ⟨x, xs⟩ i)

Tactic:
congr 1

Result:
case intro.intro.intro.intro.refine_3.e_a.e_a
M : Type u_5
κ : Type u_6
inst✝¹ : AddCommMonoid M
S : Finset M
inst✝ : Finite κ
C : M → κ
ι : Type
_inst : Fintype ι
l : Line { x // x ∈ S } ι
c : κ
s : Finset ι := Finset.filter (fun i => l.idxFun i = none) Finset.univ
hs : s = Finset.filter (fun i => l.idxFun i = none) Finset.univ
x : M
xs : x ∈ S
⊢ s.card • x = ∑ i ∈ s, ↑(↑l ⟨x, xs⟩ i)

case intro.intro.intro.intro.refine_3.e_a.e_a
M : Type u_5
κ : Type u_6
inst✝¹ : AddCommMonoid M
S : Finset M
inst✝ : Finite κ
C : M → κ
ι : Type
_inst : Fintype ι
l : Line { x // x ∈ S } ι
c : κ
s : Finset ι := Finset.filter (fun i => l.idxFun i = none) Finset.univ
hs : s = Finset.filter (fun i => l.idxFun i = none) Finset.univ
x : M
xs : x ∈ S
⊢ ∑ i ∈ sᶜ, (Option.map (fun m => ↑m) (l.idxFun i)).getD 0 = ∑ i ∈ sᶜ, ↑(↑l ⟨x, xs⟩ i)

Proof state:
case intro.intro.intro.intro.refine_3.e_a.e_a
M : Type u_5
κ : Type u_6
inst✝¹ : AddCommMonoid M
S : Finset M
inst✝ : Finite κ
C : M → κ
ι : Type
_inst : Fintype ι
l : Line { x // x ∈ S } ι
c : κ
s : Finset ι := Finset.filter (fun i => l.idxFun i = none) Finset.univ
hs : s = Finset.filter (fun i => l.idxFun i = none) Finset.univ
x : M
xs : x ∈ S
⊢ s.card • x = ∑ i ∈ s, ↑(↑l ⟨x, xs⟩ i)

Tactic:
rw [← Finset.sum_const]

Result:
case intro.intro.intro.intro.refine_3.e_a.e_a
M : Type u_5
κ : Type u_6
inst✝¹ : AddCommMonoid M
S : Finset M
inst✝ : Finite κ
C : M → κ
ι : Type
_inst : Fintype ι
l : Line { x // x ∈ S } ι
c : κ
s : Finset ι := Finset.filter (fun i => l.idxFun i = none) Finset.univ
hs : s = Finset.filter (fun i => l.idxFun i = none) Finset.univ
x : M
xs : x ∈ S
⊢ ∑ _x ∈ s, x = ∑ i ∈ s, ↑(↑l ⟨x, xs⟩ i)

Proof state:
case intro.intro.intro.intro.refine_3.e_a.e_a
M : Type u_5
κ : Type u_6
inst✝¹ : AddCommMonoid M
S : Finset M
inst✝ : Finite κ
C : M → κ
ι : Type
_inst : Fintype ι
l : Line { x // x ∈ S } ι
c : κ
s : Finset ι := Finset.filter (fun i => l.idxFun i = none) Finset.univ
hs : s = Finset.filter (fun i => l.idxFun i = none) Finset.univ
x : M
xs : x ∈ S
i : ι
hi : i ∈ Finset.univ ∧ ¬l.idxFun i = none
⊢ (Option.map (fun m => ↑m) (l.idxFun i)).getD 0 = ↑(↑l ⟨x, xs⟩ i)

Tactic:
obtain ⟨y, hy⟩ := Option.ne_none_iff_exists.mp hi.right

Result:
case intro.intro.intro.intro.refine_3.e_a.e_a.intro
M : Type u_5
κ : Type u_6
inst✝¹ : AddCommMonoid M
S : Finset M
inst✝ : Finite κ
C : M → κ
ι : Type
_inst : Fintype ι
l : Line { x // x ∈ S } ι
c : κ
s : Finset ι := Finset.filter (fun i => l.idxFun i = none) Finset.univ
hs : s = Finset.filter (fun i => l.idxFun i = none) Finset.univ
x : M
xs : x ∈ S
i : ι
hi : i ∈ Finset.univ ∧ ¬l.idxFun i = none
y : { x // x ∈ S }
hy : some y = l.idxFun i
⊢ (Option.map (fun m => ↑m) (l.idxFun i)).getD 0 = ↑(↑l ⟨x, xs⟩ i)

Proof state:
case intro.intro.intro.intro.refine_3
M : Type u_5
κ : Type u_6
inst✝¹ : AddCommMonoid M
S : Finset M
inst✝ : Finite κ
C : M → κ
ι : Type
_inst : Fintype ι
l : Line { x // x ∈ S } ι
c : κ
hl : ∀ (x : { x // x ∈ S }), (fun v => C (∑ i : ι, ↑(v i))) (↑l x) = c
s : Finset ι := Finset.filter (fun i => l.idxFun i = none) Finset.univ
hs : s = Finset.filter (fun i => l.idxFun i = none) Finset.univ
x : M
xs : x ∈ S
⊢ C (s.card • x + ∑ i ∈ sᶜ, (Option.map (fun m => ↑m) (l.idxFun i)).getD 0) =
    (fun v => C (∑ i : ι, ↑(v i))) (↑l ⟨x, xs⟩)

Tactic:
clear hl

Result:
case intro.intro.intro.intro.refine_3
M : Type u_5
κ : Type u_6
inst✝¹ : AddCommMonoid M
S : Finset M
inst✝ : Finite κ
C : M → κ
ι : Type
_inst : Fintype ι
l : Line { x // x ∈ S } ι
c : κ
s : Finset ι := Finset.filter (fun i => l.idxFun i = none) Finset.univ
hs : s = Finset.filter (fun i => l.idxFun i = none) Finset.univ
x : M
xs : x ∈ S
⊢ C (s.card • x + ∑ i ∈ sᶜ, (Option.map (fun m => ↑m) (l.idxFun i)).getD 0) =
    (fun v => C (∑ i : ι, ↑(v i))) (↑l ⟨x, xs⟩)

Proof state:
case intro.intro
M : Type u_5
κ : Type u_6
inst✝¹ : AddCommMonoid M
S : Finset M
inst✝ : Finite κ
C : M → κ
ι : Type
_inst : Fintype ι
hι : ∀ (C : (ι → { x // x ∈ S }) → κ), ∃ l, Line.IsMono C l
⊢ ∃ a > 0, ∃ b c, ∀ s ∈ S, C (a • s + b) = c

Tactic:
specialize hι fun v => C <| ∑ i, v i

Result:
case intro.intro
M : Type u_5
κ : Type u_6
inst✝¹ : AddCommMonoid M
S : Finset M
inst✝ : Finite κ
C : M → κ
ι : Type
_inst : Fintype ι
hι : ∃ l, Line.IsMono (fun v => C (∑ i : ι, ↑(v i))) l
⊢ ∃ a > 0, ∃ b c, ∀ s ∈ S, C (a • s + b) = c

Proof state:
case intro.intro
M : Type u_5
κ : Type u_6
inst✝¹ : AddCommMonoid M
S : Finset M
inst✝ : Finite κ
C : M → κ
ι : Type
_inst : Fintype ι
hι : ∃ l, Line.IsMono (fun v => C (∑ i : ι, ↑(v i))) l
⊢ ∃ a > 0, ∃ b c, ∀ s ∈ S, C (a • s + b) = c

Tactic:
obtain ⟨l, c, hl⟩ := hι

Result:
case intro.intro.intro.intro
M : Type u_5
κ : Type u_6
inst✝¹ : AddCommMonoid M
S : Finset M
inst✝ : Finite κ
C : M → κ
ι : Type
_inst : Fintype ι
l : Line { x // x ∈ S } ι
c : κ
hl : ∀ (x : { x // x ∈ S }), (fun v => C (∑ i : ι, ↑(v i))) (↑l x) = c
⊢ ∃ a > 0, ∃ b c, ∀ s ∈ S, C (a • s + b) = c

Proof state:
case intro.intro.intro.intro.refine_3.e_a.e_a
M : Type u_5
κ : Type u_6
inst✝¹ : AddCommMonoid M
S : Finset M
inst✝ : Finite κ
C : M → κ
ι : Type
_inst : Fintype ι
l : Line { x // x ∈ S } ι
c : κ
s : Finset ι := Finset.filter (fun i => l.idxFun i = none) Finset.univ
hs : s = Finset.filter (fun i => l.idxFun i = none) Finset.univ
x : M
xs : x ∈ S
i : ι
hi : i ∈ s
⊢ x = ↑(↑l ⟨x, xs⟩ i)

Tactic:
rw [hs, Finset.mem_filter] at hi

Result:
case intro.intro.intro.intro.refine_3.e_a.e_a
M : Type u_5
κ : Type u_6
inst✝¹ : AddCommMonoid M
S : Finset M
inst✝ : Finite κ
C : M → κ
ι : Type
_inst : Fintype ι
l : Line { x // x ∈ S } ι
c : κ
s : Finset ι := Finset.filter (fun i => l.idxFun i = none) Finset.univ
hs : s = Finset.filter (fun i => l.idxFun i = none) Finset.univ
x : M
xs : x ∈ S
i : ι
hi : i ∈ Finset.univ ∧ l.idxFun i = none
⊢ x = ↑(↑l ⟨x, xs⟩ i)