import subgroup.cyclic

namespace mygroup

open_locale classical

open mygroup mygroup.subgroup mygroup.quotient group_hom function set

namespace torsion

def torsion_set (G : Type) [comm_group G] := { g : G | order g ≠ 0 }

variables {G : Type} [comm_group G]

lemma torsion_set_def : torsion_set G = { g : G | order g ≠ 0 } := rfl
lemma mem_torsion_set_iff (g : G) : g ∈ torsion_set G ↔ order g ≠ 0 := iff.rfl

attribute [simp] mem_torsion_set_iff

lemma one_mem_torsion_set : (1 : G) ∈ torsion_set G :=
by rw [mem_torsion_set_iff, order_one_eq_one]; exact one_ne_zero

/-- Two elements of an abelian group with finite order multiplied is also an
  element of finite order -/
lemma ne_zero_order_mul_ne_zero {g h : G}
  (hg : order g ≠ 0) (hh : order h ≠ 0) : order (g * h) ≠ 0 :=
begin
  intro heq,
  rw order_eq_zero_iff at heq,
  rw ← zero_lt_iff_ne_zero at hg hh,
  apply heq (order g * order h),
    { apply mul_pos; simpa only [int.coe_nat_pos] },
    { rw [← group.mul_pow, mul_comm, group.pow_mul, pow_order_eq_one,
          group.one_pow, mul_comm, group.pow_mul, pow_order_eq_one,
          group.one_pow, group.mul_one] }
end

lemma mul_mem_torsion_set {g h : G}
  (hg : g ∈ torsion_set G) (hh : h ∈ torsion_set G) : g * h ∈ torsion_set G :=
ne_zero_order_mul_ne_zero hg hh

lemma inv_mem_torsion_set {g : G} (hg : g ∈ torsion_set G) :
  g⁻¹ ∈ torsion_set G :=
begin
  intro h,
  apply hg,
  rw order_eq_zero_iff at h ⊢,
  intros n hn hgn,
  exact h n hn
    (by rw [← group.pow_neg_one_inv, ← group.pow_mul, mul_comm, group.pow_mul, hgn]; simp),
end

/-- The torsion subgroup of an abelian group is the subgroup of all elements of
  finite order -/
def torsion_subgroup (G : Type) [comm_group G] : subgroup G :=
{ carrier := torsion_set G,
  one_mem' := one_mem_torsion_set,
  mul_mem' := λ _ _, mul_mem_torsion_set,
  inv_mem' := λ _, inv_mem_torsion_set }

lemma mem_torsion_subgroup_iff (g : G) : g ∈ torsion_subgroup G ↔ order g ≠ 0 := iff.rfl

attribute [simp] mem_torsion_subgroup_iff

end torsion

def torsion (G : Type) [comm_group G] : normal G :=
  normal.of_comm_subgroup $ torsion.torsion_subgroup G

-- Temporary (should infer from the fact that the normal subgroups form a complete lattice)
def normal.trivial {G : Type} [group G] : normal G :=
{ conj_mem' := λ _ hn _,
      by rw [(mem_trivial_carrier_iff _).mp hn, group.mul_one,
        group.mul_right_inv]; exact one_mem _, .. subgroup.trivial }

lemma normal.bot_eq_trivial {G : Type} [group G] :
  (⊥ : normal G) = normal.trivial :=
begin
  refine eq.symm (eq_bot_iff.2 $ λ x hx, _),
  change x = 1 at hx,
  exact hx.symm ▸ one_mem _,
end

lemma normal.mem_bot_iff {G : Type} [group G] {x : G} : x ∈ (⊥ : normal G) ↔ x = 1 :=
begin
  split, intro h,
    { rw [← mem_singleton_iff, ← bot_eq_singleton_one, bot_eq_trivial],
      rw normal.bot_eq_trivial at h, exact h },
    { rintro rfl, exact one_mem _ }
end

namespace torsion

variables {G : Type} [comm_group G]

@[simp] lemma mem_torsion_iff (g : G) : g ∈ torsion G ↔ order g ≠ 0 := iff.rfl

/-- The quotient of an abelian group by its torsion subgroup is also an
  abelian subgroup -/
instance : comm_group $ G /ₘ torsion G :=
  { mul_comm := λ a b,
      let ⟨g, hg⟩ := exists_mk a in
      let ⟨h, hh⟩ := exists_mk b in
      by rw [← hg, ← hh, quotient.coe_mul, group.mul_comm, ← quotient.coe_mul],
  .. show group (G /ₘ torsion G), by apply_instance } -- french quotes does not work

/-- The torsion of the quotient by the torsion is the trivial subgroup -/
lemma of_quotient_torsion_eq_bot : torsion (G /ₘ torsion G) = ⊥ :=
begin
  ext, rw [normal.mem_bot_iff], split,
    { intro h,
      rcases exists_mk g with ⟨g, rfl⟩,
      rw [← coe_one, mk_eq', group.one_inv, group.one_mul],
      intro hg, apply h,
      rw order_eq_zero_iff at hg ⊢,
      intros n hn hgn,
      rw [coe_pow, ← coe_one, mk_eq', group.one_inv,
        group.one_mul, mem_torsion_iff, ← zero_lt_iff_ne_zero] at hgn,
      refine hg (n * order (g ^ n)) (mul_pos hn $ int.coe_nat_pos.2 hgn) _,
      rw [mul_comm, group.pow_mul, pow_order_eq_one] },
    { rintro rfl, exact one_mem _ }
end

end torsion

end mygroup


/-
Copyright (c) 2019 Kenny Lau. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Kenny Lau
-/
import ring_theory.adjoin.basic
import data.mv_polynomial.rename
import data.polynomial.algebra_map

/-!
# Adjoining elements to form subalgebras: relation to polynomials

In this file we prove a few results representing `algebra.adjoin R s` as the range of
`mv_polynomial.aeval` or `polynomial.aeval`.

## Tags

adjoin, algebra, polynomials
-/

universes u v w

namespace algebra

open subsemiring submodule
variables (R : Type u) {A : Type v} (s : set A) [comm_semiring R] [comm_semiring A] [algebra R A]

theorem adjoin_eq_range :
  adjoin R s = (mv_polynomial.aeval (coe : s → A)).range :=
le_antisymm
  (adjoin_le $ λ x hx, ⟨mv_polynomial.X ⟨x, hx⟩, mv_polynomial.eval₂_X _ _ _⟩)
  (λ x ⟨p, (hp : mv_polynomial.aeval coe p = x)⟩, hp ▸ mv_polynomial.induction_on p
    (λ r, by { rw [mv_polynomial.aeval_def, mv_polynomial.eval₂_C],
               exact (adjoin R s).algebra_map_mem r })
    (λ p q hp hq, by rw alg_hom.map_add; exact subalgebra.add_mem _ hp hq)
    (λ p ⟨n, hn⟩ hp, by rw [alg_hom.map_mul, mv_polynomial.aeval_def _ (mv_polynomial.X _),
      mv_polynomial.eval₂_X]; exact subalgebra.mul_mem _ hp (subset_adjoin hn)))

lemma adjoin_range_eq_range_aeval {σ : Type*} (f : σ → A) :
  adjoin R (set.range f) = (mv_polynomial.aeval f).range :=
begin
  ext x,
  simp only [adjoin_eq_range, alg_hom.mem_range],
  split,
  { rintros ⟨p, rfl⟩,
    use mv_polynomial.rename (function.surj_inv (@@set.surjective_onto_range f)) p,
    rw [← alg_hom.comp_apply],
    refine congr_fun (congr_arg _ _) _,
    ext,
    simp only [mv_polynomial.rename_X, function.comp_app, mv_polynomial.aeval_X, alg_hom.coe_comp],
    simpa [subtype.ext_iff] using function.surj_inv_eq (@@set.surjective_onto_range f) i },
  { rintros ⟨p, rfl⟩,
    use mv_polynomial.rename (set.range_factorization f) p,
    rw [← alg_hom.comp_apply],
    refine congr_fun (congr_arg _ _) _,
    ext,
    simp only [mv_polynomial.rename_X, function.comp_app, mv_polynomial.aeval_X, alg_hom.coe_comp,
      set.range_factorization_coe] }
end

theorem adjoin_singleton_eq_range_aeval (x : A) : adjoin R {x} = (polynomial.aeval x).range :=
le_antisymm
  (adjoin_le $ set.singleton_subset_iff.2 ⟨polynomial.X, polynomial.eval₂_X _ _⟩)
  (λ y ⟨p, (hp : polynomial.aeval x p = y)⟩, hp ▸ polynomial.induction_on p
    (λ r, by { rw [polynomial.aeval_def, polynomial.eval₂_C],
               exact (adjoin R _).algebra_map_mem r })
    (λ p q hp hq, by rw alg_hom.map_add; exact subalgebra.add_mem _ hp hq)
    (λ n r ih, by { rw [pow_succ', ← mul_assoc, alg_hom.map_mul,
      polynomial.aeval_def _ polynomial.X, polynomial.eval₂_X],
      exact subalgebra.mul_mem _ ih (subset_adjoin rfl) }))

end algebra


import tactic.ring
import tactic.linarith
import data.rat.basic
import data.rat.cast

/- Section
1.4 An Application
-/

/-
Prove that there is no rational number whose square is 2
using the techniques introduced earlier.
-/

def even (a : ℤ) := ∃ b : ℤ, a = 2 * b
def odd (a : ℤ) := ∃ b : ℤ, a = 2 * b + 1

lemma not_even_is_odd (n : ℤ) : ¬ even n ↔ odd n :=
begin
    split,
    intro ha,
    have hb : n % 2 = 1,
        have hc : n % 2 = 0 ∨ n % 2 = 1,
            apply int.mod_two_eq_zero_or_one,
        cases hc with hx hy,
        exfalso,
        apply ha,
        existsi n / 2,
        rw int.mul_div_cancel_of_mod_eq_zero hx,
        assumption,
    have hc : (n - 1) % 2 = 0,
    have hd : n % 2 = 1 % 2, rw hb, refl,
        revert hd,
        rw int.mod_eq_mod_iff_mod_sub_eq_zero,
        intro h, assumption,
    existsi (n - 1) / 2,
    rw int.mul_div_cancel_of_mod_eq_zero hc,
    simp,

    intro ha,
    intro hb,
    cases ha with x hx,
    cases hb with y hy,
    have hc : n % 2 = 1,
        rw hx,
        rw [add_comm, int.add_mul_mod_self_left],
        refl,
    have hd : n % 2 = 0,
        rw hy, simp,
    have he : (1 : ℤ) = (0 : ℤ),
        rwa [←hc, ←hd],
    have hf : ¬ ( (1 : ℤ) = (0 : ℤ)), simp,
    exact hf he,
end

lemma gcdeven (n m : ℕ) : 2 ∣ nat.gcd (2 * n) (2 * m) :=
begin
    have ha : 2 ∣ 2 * n, existsi n, refl,
    have hb : 2 ∣ 2 * m, existsi m, refl,
    have hc : (2 ∣ 2 * n) → (2 ∣ 2 * m) → 2 ∣ nat.gcd (2 * n) (2 * m),
    exact nat.dvd_gcd,
    apply hc,
    repeat {assumption},
end
--#check gcdeven

/- Lemma
If $a$ is an integer, then $a$ is even if and only if $a^2$ is even.
-/
lemma times_even
  (a : ℤ) : even a ↔ even (a ^ 2) :=
begin
    split,
    intro h,
    have ha : ∃ b : ℤ, a = 2 * b, exact h,
    have hb : ∃ b : ℤ, a ^ 2 = 2 * b,
        cases ha with x hx,
        existsi 2 * x ^ 2,
        rw hx,
        ring,
    exact hb,

    intro h,
    apply classical.by_contradiction,
    intro ha,
    have hc : odd a,
        rw ←not_even_is_odd a,
        assumption,
    have hd : odd (a ^ 2),
        cases hc with x hx,
        existsi 2 * x ^ 2 + 2 * x,
        rw hx,
        ring,
    have he : ¬ even (a ^ 2),
        rw not_even_is_odd (a ^ 2),
        assumption,
    exact he h,
end

/- Theorem
There is no rational number whose square is 2.
-/
theorem rational_not_sqrt_two : ¬ ∃ r : ℚ, r ^ 2 = 2  :=
begin
    -- First show that p is even
    push_neg,
    intro r,
    -- Manipulate the fraction to have the properties desired
    have h : rat.mk (r.num) (r.denom) = r,
        apply rat.num_denom,
    rw ←h,
    intro hcon,
    -- The denominator must not be zero
    have hdnot0 : r.denom ≠ 0,
        intro ha,
        have hb : rat.mk (r.num) (r.denom) ^ 2 = 0,
            rw ha,
            refl,
        convert hb,
        rw hcon,
        simp,
        linarith,
    -- The numerator must also not be zero
    have hnnot0 : r.num ≠ 0,
        intro ha,
            have hb : rat.mk (r.num) (r.denom) ^ 2 = 0,
                rw ha,
                simp, refl,
            convert hb,
            rw hcon,
            simp,
            linarith,
    -- The fraction is in its lowest terms
    have hcop : nat.coprime (int.nat_abs r.num) r.denom,
        cases r with ha hb hc hd,
        exact hd,
    -- Now we can begin the actual proof...
    -- First show that r.num ^ 2 is even
    have hsqrneven : even (r.num ^ 2),
        existsi (r.denom : ℤ) ^ 2,
        have ha : r.num ^ 2 = r.num ^ 2 * 1,
            simp,
        rwa [ha, ←rat.mk_eq],
        convert hcon,
        repeat {rw pow_two},
        rw rat.mul_def,
        all_goals {try {simp, apply hdnot0,}},
        simp,
    -- Now we can use times_even to show r.num is even
    have hneven : even r.num, rw times_even, assumption,
    -- r.num is even → r.denom ^ 2 is also even
    have hsqrdeven : even (r.denom ^ 2),
        cases hneven with b ha,
        existsi b ^ 2,
        have hb : (2 * ↑(r.denom) ^ 2 = 4 * (b ^ 2)) → (↑(r.denom) ^ 2 = 2 * b ^ 2),
            have hβ : 4 * b ^ 2 = 2 * 2 * b ^ 2, refl,
            rw [hβ, ←sub_eq_zero],
            have hγ : 2 * ↑(r.denom) ^ 2 - 2 * 2 * b ^ 2 = 2 * (↑(r.denom) ^ 2 - 2 * b ^ 2), ring,
            rw [hγ, mul_eq_zero],
            intro hδ,
            cases hδ with hδ1 hδ2,
            exfalso,
            convert hδ1, simp, linarith,
            rw ←sub_eq_zero,
            assumption,
        rw hb,
        have hc : 4 * b ^ 2 = (2 * b) ^ 2,
            ring,
        rw [hc, ←ha],
    have hd : ↑r.denom * ↑r.denom = r.denom * r.denom, simp,
        have he : rat.mk (r.num ^ 2) (r.denom ^ 2) = 2,
            rw ←hcon,
            repeat {rw pow_two},
            rw rat.mul_def,
            repeat {simp, apply hdnot0,},
        have hf : rat.mk r.num r.denom = r.num / r.denom,
            exact rat.mk_eq_div (r.num) ↑(r.denom),
        have hg : 2 * (↑(r.denom) ^ 2) =  r.num ^ 2 * 1 → 2 * (↑(r.denom) * ↑(r.denom)) = r.num * r.num,
            repeat {rw pow_two},
            rw mul_one,
            intro hh,
            assumption,
        rw hg,
        rw ←rat.mk_eq,
        rw he,
        refl,
        simp,
        rw pow_two,
        intro hh,
        have hi : r.denom = 0,
            have hj : r.denom * r.denom = 0,
                rw ←hd,
                exact_mod_cast hh,
            rw nat.mul_eq_zero at hj,
            revert hj,
            simp,
        exfalso,
        exact hdnot0 hi,
    have hdeven : even r.denom, rw times_even, assumption,
    -- But that means r.num and r.denom are not coprimes
    have hncop : ¬ nat.coprime (int.nat_abs (r.num)) (r.denom),
        have ha : ¬ nat.coprime (int.nat_abs (r.num)) (r.denom) ↔ nat.gcd (int.nat_abs (r.num)) (r.denom) ≠ 1, refl,
        rw ha,
        cases hneven with k hk,
        cases hdeven with m hm,
        rw hk,
        have hb : int.nat_abs r.denom = 2 * (int.nat_abs m),
            rwa [hm, int.nat_abs_mul],
            refl,
        have hc : (r.denom : ℕ) = int.nat_abs r.denom, refl,
        rwa [hc, hb],
        have hd : int.nat_abs (2 * k) = 2 * int.nat_abs k, rw int.nat_abs_mul, refl,
        rw hd,
        intro he,
        have hf : ¬ (2 ∣ nat.gcd (2 * int.nat_abs k) (2 * int.nat_abs m)),
            rw he,
            simp,
            linarith,
        have hg : 2 ∣ nat.gcd (2 * int.nat_abs k) (2 * int.nat_abs m),
            apply gcdeven,
        exact hf hg,
    exact hncop hcop,
end


import group_theory.group_action
import group_theory.quotient_group
import data.zmod.basic
import data.fintype.card
import group_theory.sylow
import tactic
-- import algebra.group.conj

open equiv fintype finset mul_action function nat sylow
open subgroup quotient_group
universe u
variables {G : Type u} [group G]

open_locale classical

-- define a sylow subgroup given a prime p, and subgroup L
def is_sylow_subgroup [fintype G] (L : subgroup G) {p m n : ℕ} (hp : p.prime)
(hG : card G = p ^ n * m) (hndiv: ¬ p ∣ m) :=
  card L = p ^ n

lemma is_sylow_subgroup_def [fintype G] (L : subgroup G) {p m n : ℕ} (hp : p.prime)
(hG : card G = p ^ n * m) (hndiv: ¬ p ∣ m) : is_sylow_subgroup L hp hG hndiv ↔ (card L = p ^ n)
:= iff.rfl

-- TODO: think about using conjugation function
-- def conjugate (x y : G) := x⁻¹ * y * x

-- give the subgroup conjugate to subgroup L by g
def conjugate_subgroup (L : subgroup G) (g : G) : subgroup G :=
{ carrier := { c | ∃ h ∈ L, c = g⁻¹ * h * g },
  one_mem' :=
begin
  exact ⟨1, one_mem L, by simp⟩,
end,
  mul_mem' :=
begin
  rintros - - ⟨c, hc, rfl⟩ ⟨d, hd, rfl⟩,
  exact ⟨c * d, L.mul_mem hc hd, by group⟩,
end,
  inv_mem' :=
begin
  simp only [and_imp, exists_prop, set.mem_set_of_eq, exists_imp_distrib],
  intros x y hy hx,
  refine ⟨(g * x * g⁻¹)⁻¹, _, by group⟩,
  rw [hx, mul_assoc, mul_assoc, mul_assoc, mul_inv_self, mul_one, ← mul_assoc, mul_inv_self, one_mul],
  exact inv_mem L hy,
end }

lemma conjugate_subgroup_def (L : subgroup G) (x g : G) :
  x ∈ conjugate_subgroup L g ↔ x ∈  { c | ∃ h ∈ L, c = g⁻¹ * h * g } := iff.rfl

noncomputable def index_of_subgroup [fintype G] (L : subgroup G) : ℕ :=
  card G / card L

lemma index_of_subgroup_def [fintype G] (L : subgroup G) :
  index_of_subgroup L = card G / card L := rfl

-- this must already exist in mathlib - FIND IT!
lemma card_subgroup_pos [fintype G] (L : subgroup G) : 0 < card L :=
card_pos_iff.2 $ nonempty.intro ⟨1, L.one_mem⟩

-- lagranges theorem
lemma index_of_subgroup_def' [fintype G] (L : subgroup G) :
  index_of_subgroup L = card (quotient L) :=
begin
  rw [index_of_subgroup_def, card_eq_card_quotient_mul_card_subgroup L],
  rw [nat.mul_div_assoc _ (dvd_refl (card ↥L)), nat.div_self (card_subgroup_pos L)],
  simp,
end

-- this is Eric's proof, pull request 8382 quotient_group.eq_iff_coset_eq
lemma quotient_iff_set {y z : G} {L : subgroup G}
: @quotient_group.mk _ _ L y = quotient_group.mk z ↔ left_coset y L = left_coset z L :=
begin
  rw [←quotient_group.eq_class_eq_left_coset, ←quotient_group.eq_class_eq_left_coset],
  rw set.ext_iff,
  dsimp,
  split,
  { intros h z,
    exact eq.congr_right h,
    },
  intro h,
  exact (h y).mp rfl
end

-- think about replacing λ with a conjugation function
-- this may already exist
def subgroup_bijects_conjugate (L : subgroup G) (x : G) :
conjugate_subgroup L x ≃ L :=
{ to_fun := (λ y : conjugate_subgroup L x, ⟨x * y * x⁻¹,
begin
  rcases y with ⟨_, z, hz, rfl⟩,
  rw [subtype.coe_mk, mul_assoc, mul_assoc, mul_inv_self, mul_one, ← mul_assoc, mul_inv_self, one_mul],
  exact hz,
end⟩) ,
  inv_fun := (λ y : L, ⟨x⁻¹ * y * x, ⟨y, set_like.coe_mem y, rfl⟩⟩),
  left_inv :=
  begin
    rintro ⟨y, hy⟩,
    simp only [subtype.mk_eq_mk, subtype.coe_mk],
    group,
  end,
  right_inv :=
  begin
    rintro ⟨y, hy⟩,
    simp only [subtype.mk_eq_mk, subtype.coe_mk],
    group,
  end }

-- this index of a sylow subgroup is m
lemma sylow_subgroup_index [fintype G] {L : subgroup G} {p m n : ℕ}
(hp : p.prime) (hG : card G = p ^ n * m) (hndiv: ¬ p ∣ m) (h : is_sylow_subgroup L hp hG hndiv)
  : index_of_subgroup L = m :=
begin
  rw is_sylow_subgroup_def at h,
  rw [index_of_subgroup_def, hG, h, nat.mul_div_cancel_left _ (pow_pos (pos_of_gt hp.left) n)],
end

-- the index of a sylow subgroup is not divisible by prime p
lemma subgroup_index_not_conj_zero_wrt_p [fintype G] {L : subgroup G} {p m n : ℕ}
(hp : p.prime) (hG : card G = p ^ n * m) (hndiv: ¬ p ∣ m) (h : is_sylow_subgroup L hp hG hndiv)
  : ¬ index_of_subgroup L ≡ 0 [MOD p] :=
begin
  rw sylow_subgroup_index hp hG hndiv h,
  intro hn,
  apply hndiv,
  exact modeq.modeq_zero_iff.mp hn,
end

theorem sylow_two [fintype G] {p n m : ℕ} (L K : subgroup G)
(hp : p.prime) (hG : card G = p ^ n * m) (hndiv: ¬ p ∣ m)
( h₁ : is_sylow_subgroup L hp hG hndiv) (h₂ : is_sylow_subgroup K hp hG hndiv)
: ∃ g : G, conjugate_subgroup K g  = L :=
begin
  haveI : fact (p.prime) := ⟨ hp ⟩,
  have h₄ : index_of_subgroup L ≡ card (fixed_points K (quotient L)) [MOD p], {
    rw is_sylow_subgroup_def at h₂,
    rw index_of_subgroup_def',
    exact card_modeq_card_fixed_points p h₂,
  },
  have h₅ : 0 < card (fixed_points K (quotient L)), {
    apply lt_of_le_of_ne _ _, {
      exact le_of_not_gt (card ↥(fixed_points ↥K (quotient L))).not_lt_zero,
    }, {
      intro hn,
      apply subgroup_index_not_conj_zero_wrt_p hp hG hndiv h₁,
      rw hn,
      exact h₄,
    },
  },
  have h₆ : ∃ x : G, (conjugate_subgroup K x : set G) ⊆ L, {
    rw card_pos_iff at h₅,
    rcases h₅ with ⟨fp, hfp⟩,
    rw mul_action.mem_fixed_points at hfp,
    let x := quotient.out' fp,
    use x,
    rintro _ ⟨y, hy, rfl⟩,
    have h1 : y • fp = quotient_group.mk (y * x), {
      rw ← quotient.out_eq' fp,
      exact quotient.smul_mk L y x,
    },
    have h2 : @quotient_group.mk _ _ L (x⁻¹ * y * x) = quotient_group.mk 1, {
      rw [mul_assoc, ← quotient.smul_mk L x⁻¹ (y * x)],
      rw [← smul_left_cancel_iff x, smul_smul x x⁻¹ _, mul_inv_self, quotient.smul_mk, one_mul],
      rw [quotient.smul_mk, mul_one, ← h1],
      convert hfp ⟨y, hy⟩,
      exact quotient.out_eq' fp,
    },
    rw [quotient_iff_set, one_left_coset] at h2,
    rw ← h2,
    unfold left_coset,
    simp only [mul_inv_rev, set.mem_preimage, set.image_mul_left, set_like.mem_coe, inv_inv],
    rw [mul_assoc, mul_assoc, mul_assoc, ← mul_assoc x x⁻¹ (y * x)],
    rw [mul_inv_self, one_mul, ← mul_assoc, ← mul_assoc],
    simp [mul_left_inv, inv_mul_cancel_right, one_mem L],
  },
  have h₇ : ∀ x : G, card (conjugate_subgroup K x) = card L, {
    rw is_sylow_subgroup_def at h₁ h₂,
    intro x,
    rw [h₁, h₂.symm],
    apply fintype.card_congr,
    exact subgroup_bijects_conjugate K x,
  },
  apply exists.elim h₆,
  intros x hx,
  use x,
  rw set_like.ext'_iff,
  exact set.eq_of_subset_of_card_le hx (h₇ x).ge,
end