-- Mathlib/Algebra/Module/Torsion.lean
theorem exists_isTorsionBy {p : R} (hM : IsTorsion' M <| Submonoid.powers p) (d : ℕ) (hd : d ≠ 0)
    (s : Fin d → M) (hs : span R (Set.range s) = ⊤) :
    ∃ j : Fin d, Module.IsTorsionBy R M (p ^ pOrder hM (s j))

Proof state:
case h
R : Type u_1
M : Type u_2
inst✝³ : CommSemiring R
inst✝² : AddCommMonoid M
inst✝¹ : Module R M
inst✝ : (x : M) → Decidable (x = 0)
p : R
hM : IsTorsion' M ↥(Submonoid.powers p)
d : ℕ
hd : d ≠ 0
s : Fin d → M
hs : span R (Set.range s) = ⊤
oj : Option (Fin d) := List.argmax (fun i => pOrder hM (s i)) (List.finRange d)
hoj : oj.isSome = true
i : Fin d
⊢ p ^ pOrder hM (s (oj.get hoj)) • s i = 0

Tactic:
have : pOrder hM (s i) ≤ pOrder hM (s <| Option.get _ hoj) :=
  List.le_of_mem_argmax (List.mem_finRange i) (Option.get_mem hoj)

Result:
case h
R : Type u_1
M : Type u_2
inst✝³ : CommSemiring R
inst✝² : AddCommMonoid M
inst✝¹ : Module R M
inst✝ : (x : M) → Decidable (x = 0)
p : R
hM : IsTorsion' M ↥(Submonoid.powers p)
d : ℕ
hd : d ≠ 0
s : Fin d → M
hs : span R (Set.range s) = ⊤
oj : Option (Fin d) := List.argmax (fun i => pOrder hM (s i)) (List.finRange d)
hoj : oj.isSome = true
i : Fin d
this : pOrder hM (s i) ≤ pOrder hM (s (oj.get hoj))
⊢ p ^ pOrder hM (s (oj.get hoj)) • s i = 0

Proof state:
R : Type u_1
M : Type u_2
inst✝³ : CommSemiring R
inst✝² : AddCommMonoid M
inst✝¹ : Module R M
inst✝ : (x : M) → Decidable (x = 0)
p : R
hM : IsTorsion' M ↥(Submonoid.powers p)
d : ℕ
hd : d ≠ 0
s : Fin d → M
hs : span R (Set.range s) = ⊤
oj : Option (Fin d) := List.argmax (fun i => pOrder hM (s i)) (List.finRange d)
⊢ ∃ j, IsTorsionBy R M (p ^ pOrder hM (s j))

Tactic:
have hoj : oj.isSome :=
  Option.ne_none_iff_isSome.mp fun eq_none =>
    hd <| List.finRange_eq_nil.mp <| List.argmax_eq_none.mp eq_none

Result:
R : Type u_1
M : Type u_2
inst✝³ : CommSemiring R
inst✝² : AddCommMonoid M
inst✝¹ : Module R M
inst✝ : (x : M) → Decidable (x = 0)
p : R
hM : IsTorsion' M ↥(Submonoid.powers p)
d : ℕ
hd : d ≠ 0
s : Fin d → M
hs : span R (Set.range s) = ⊤
oj : Option (Fin d) := List.argmax (fun i => pOrder hM (s i)) (List.finRange d)
hoj : oj.isSome = true
⊢ ∃ j, IsTorsionBy R M (p ^ pOrder hM (s j))

Proof state:
case h
R : Type u_1
M : Type u_2
inst✝³ : CommSemiring R
inst✝² : AddCommMonoid M
inst✝¹ : Module R M
inst✝ : (x : M) → Decidable (x = 0)
p : R
hM : IsTorsion' M ↥(Submonoid.powers p)
d : ℕ
hd : d ≠ 0
s : Fin d → M
hs : span R (Set.range s) = ⊤
oj : Option (Fin d) := List.argmax (fun i => pOrder hM (s i)) (List.finRange d)
hoj : oj.isSome = true
⊢ IsTorsionBy R M (p ^ pOrder hM (s (oj.get hoj)))

Tactic:
rw [isTorsionBy_iff_torsionBy_eq_top, eq_top_iff, ← hs, Submodule.span_le,
  Set.range_subset_iff]

Result:
case h
R : Type u_1
M : Type u_2
inst✝³ : CommSemiring R
inst✝² : AddCommMonoid M
inst✝¹ : Module R M
inst✝ : (x : M) → Decidable (x = 0)
p : R
hM : IsTorsion' M ↥(Submonoid.powers p)
d : ℕ
hd : d ≠ 0
s : Fin d → M
hs : span R (Set.range s) = ⊤
oj : Option (Fin d) := List.argmax (fun i => pOrder hM (s i)) (List.finRange d)
hoj : oj.isSome = true
⊢ ∀ (y : Fin d), s y ∈ ↑(torsionBy R M (p ^ pOrder hM (s (oj.get hoj))))

Proof state:
case h
R : Type u_1
M : Type u_2
inst✝³ : CommSemiring R
inst✝² : AddCommMonoid M
inst✝¹ : Module R M
inst✝ : (x : M) → Decidable (x = 0)
p : R
hM : IsTorsion' M ↥(Submonoid.powers p)
d : ℕ
hd : d ≠ 0
s : Fin d → M
hs : span R (Set.range s) = ⊤
oj : Option (Fin d) := List.argmax (fun i => pOrder hM (s i)) (List.finRange d)
hoj : oj.isSome = true
i : Fin d
⊢ s i ∈ ↑(torsionBy R M (p ^ pOrder hM (s (oj.get hoj))))

Tactic:
change (p ^ pOrder hM (s (Option.get oj hoj))) • s i = 0

Result:
case h
R : Type u_1
M : Type u_2
inst✝³ : CommSemiring R
inst✝² : AddCommMonoid M
inst✝¹ : Module R M
inst✝ : (x : M) → Decidable (x = 0)
p : R
hM : IsTorsion' M ↥(Submonoid.powers p)
d : ℕ
hd : d ≠ 0
s : Fin d → M
hs : span R (Set.range s) = ⊤
oj : Option (Fin d) := List.argmax (fun i => pOrder hM (s i)) (List.finRange d)
hoj : oj.isSome = true
i : Fin d
⊢ p ^ pOrder hM (s (oj.get hoj)) • s i = 0

Proof state:
case h
R : Type u_1
M : Type u_2
inst✝³ : CommSemiring R
inst✝² : AddCommMonoid M
inst✝¹ : Module R M
inst✝ : (x : M) → Decidable (x = 0)
p : R
hM : IsTorsion' M ↥(Submonoid.powers p)
d : ℕ
hd : d ≠ 0
s : Fin d → M
hs : span R (Set.range s) = ⊤
oj : Option (Fin d) := List.argmax (fun i => pOrder hM (s i)) (List.finRange d)
hoj : oj.isSome = true
i : Fin d
this : pOrder hM (s i) ≤ pOrder hM (s (oj.get hoj))
⊢ p ^ pOrder hM (s (oj.get hoj)) • s i = 0

Tactic:
rw [← Nat.sub_add_cancel this, pow_add, mul_smul, pow_pOrder_smul, smul_zero]

Result:
no goals

Proof state:
case h
R : Type u_1
M : Type u_2
inst✝³ : CommSemiring R
inst✝² : AddCommMonoid M
inst✝¹ : Module R M
inst✝ : (x : M) → Decidable (x = 0)
p : R
hM : IsTorsion' M ↥(Submonoid.powers p)
d : ℕ
hd : d ≠ 0
s : Fin d → M
hs : span R (Set.range s) = ⊤
oj : Option (Fin d) := List.argmax (fun i => pOrder hM (s i)) (List.finRange d)
hoj : oj.isSome = true
⊢ ∀ (y : Fin d), s y ∈ ↑(torsionBy R M (p ^ pOrder hM (s (oj.get hoj))))

Tactic:
intro i

Result:
case h
R : Type u_1
M : Type u_2
inst✝³ : CommSemiring R
inst✝² : AddCommMonoid M
inst✝¹ : Module R M
inst✝ : (x : M) → Decidable (x = 0)
p : R
hM : IsTorsion' M ↥(Submonoid.powers p)
d : ℕ
hd : d ≠ 0
s : Fin d → M
hs : span R (Set.range s) = ⊤
oj : Option (Fin d) := List.argmax (fun i => pOrder hM (s i)) (List.finRange d)
hoj : oj.isSome = true
i : Fin d
⊢ s i ∈ ↑(torsionBy R M (p ^ pOrder hM (s (oj.get hoj))))

Proof state:
R : Type u_1
M : Type u_2
inst✝³ : CommSemiring R
inst✝² : AddCommMonoid M
inst✝¹ : Module R M
inst✝ : (x : M) → Decidable (x = 0)
p : R
hM : IsTorsion' M ↥(Submonoid.powers p)
d : ℕ
hd : d ≠ 0
s : Fin d → M
hs : span R (Set.range s) = ⊤
⊢ ∃ j, IsTorsionBy R M (p ^ pOrder hM (s j))

Tactic:
let oj := List.argmax (fun i => pOrder hM <| s i) (List.finRange d)

Result:
R : Type u_1
M : Type u_2
inst✝³ : CommSemiring R
inst✝² : AddCommMonoid M
inst✝¹ : Module R M
inst✝ : (x : M) → Decidable (x = 0)
p : R
hM : IsTorsion' M ↥(Submonoid.powers p)
d : ℕ
hd : d ≠ 0
s : Fin d → M
hs : span R (Set.range s) = ⊤
oj : Option (Fin d) := List.argmax (fun i => pOrder hM (s i)) (List.finRange d)
⊢ ∃ j, IsTorsionBy R M (p ^ pOrder hM (s j))

Proof state:
R : Type u_1
M : Type u_2
inst✝³ : CommSemiring R
inst✝² : AddCommMonoid M
inst✝¹ : Module R M
inst✝ : (x : M) → Decidable (x = 0)
p : R
hM : IsTorsion' M ↥(Submonoid.powers p)
d : ℕ
hd : d ≠ 0
s : Fin d → M
hs : span R (Set.range s) = ⊤
oj : Option (Fin d) := List.argmax (fun i => pOrder hM (s i)) (List.finRange d)
hoj : oj.isSome = true
⊢ ∃ j, IsTorsionBy R M (p ^ pOrder hM (s j))

Tactic:
use Option.get _ hoj

Result:
case h
R : Type u_1
M : Type u_2
inst✝³ : CommSemiring R
inst✝² : AddCommMonoid M
inst✝¹ : Module R M
inst✝ : (x : M) → Decidable (x = 0)
p : R
hM : IsTorsion' M ↥(Submonoid.powers p)
d : ℕ
hd : d ≠ 0
s : Fin d → M
hs : span R (Set.range s) = ⊤
oj : Option (Fin d) := List.argmax (fun i => pOrder hM (s i)) (List.finRange d)
hoj : oj.isSome = true
⊢ IsTorsionBy R M (p ^ pOrder hM (s (oj.get hoj)))