Theorem: Finset.card_div_mul_le_card_div_mul_card_div
File: Mathlib/Combinatorics/Additive/PluenneckeRuzsa.lean

tactic: rw [← card_product (A / B), ← mul_one ((A / B) ×ˢ (B / C)).card]
state_before: α : Type u_1
inst✝¹ : CommGroup α
inst✝ : DecidableEq α
A✝ B✝ C✝ A B C : Finset α
⊢ (A / C).card * B.card ≤ (A / B).card * (B / C).card
state_after: α : Type u_1
inst✝¹ : CommGroup α
inst✝ : DecidableEq α
A✝ B✝ C✝ A B C : Finset α
⊢ (A / C).card * B.card ≤ ((A / B) ×ˢ (B / C)).card * 1

tactic: refine card_mul_le_card_mul (fun b ac ↦ ac.1 * ac.2 = b) (fun x hx ↦ ?_)
  fun x _ ↦ card_le_one_iff.2 fun hu hv ↦
    ((mem_bipartiteBelow _).1 hu).2.symm.trans ?_
state_before: α : Type u_1
inst✝¹ : CommGroup α
inst✝ : DecidableEq α
A✝ B✝ C✝ A B C : Finset α
⊢ (A / C).card * B.card ≤ ((A / B) ×ˢ (B / C)).card * 1
state_after: case refine_1
α : Type u_1
inst✝¹ : CommGroup α
inst✝ : DecidableEq α
A✝ B✝ C✝ A B C : Finset α
x : α
hx : x ∈ A / C
⊢ B.card ≤ (bipartiteAbove (fun b ac => ac.1 * ac.2 = b) ((A / B) ×ˢ (B / C)) x).card

case refine_2
α : Type u_1
inst✝¹ : CommGroup α
inst✝ : DecidableEq α
A✝ B✝ C✝ A B C : Finset α
x : α × α
x✝ : x ∈ (A / B) ×ˢ (B / C)
a✝ b✝ : α
hu : a✝ ∈ bipartiteBelow (fun b ac => ac.1 * ac.2 = b) (A / C) x
hv : b✝ ∈ bipartiteBelow (fun b ac => ac.1 * ac.2 = b) (A / C) x
⊢ x.1 * x.2 = b✝

tactic: obtain ⟨a, ha, c, hc, rfl⟩ := mem_div.1 hx
state_before: case refine_1
α : Type u_1
inst✝¹ : CommGroup α
inst✝ : DecidableEq α
A✝ B✝ C✝ A B C : Finset α
x : α
hx : x ∈ A / C
⊢ B.card ≤ (bipartiteAbove (fun b ac => ac.1 * ac.2 = b) ((A / B) ×ˢ (B / C)) x).card

case refine_2
α : Type u_1
inst✝¹ : CommGroup α
inst✝ : DecidableEq α
A✝ B✝ C✝ A B C : Finset α
x : α × α
x✝ : x ∈ (A / B) ×ˢ (B / C)
a✝ b✝ : α
hu : a✝ ∈ bipartiteBelow (fun b ac => ac.1 * ac.2 = b) (A / C) x
hv : b✝ ∈ bipartiteBelow (fun b ac => ac.1 * ac.2 = b) (A / C) x
⊢ x.1 * x.2 = b✝
state_after: case refine_1.intro.intro.intro.intro
α : Type u_1
inst✝¹ : CommGroup α
inst✝ : DecidableEq α
A✝ B✝ C✝ A B C : Finset α
a : α
ha : a ∈ A
c : α
hc : c ∈ C
hx : a / c ∈ A / C
⊢ B.card ≤ (bipartiteAbove (fun b ac => ac.1 * ac.2 = b) ((A / B) ×ˢ (B / C)) (a / c)).card

case refine_2
α : Type u_1
inst✝¹ : CommGroup α
inst✝ : DecidableEq α
A✝ B✝ C✝ A B C : Finset α
x : α × α
x✝ : x ∈ (A / B) ×ˢ (B / C)
a✝ b✝ : α
hu : a✝ ∈ bipartiteBelow (fun b ac => ac.1 * ac.2 = b) (A / C) x
hv : b✝ ∈ bipartiteBelow (fun b ac => ac.1 * ac.2 = b) (A / C) x
⊢ x.1 * x.2 = b✝

tactic: refine card_le_card_of_injOn (fun b ↦ (a / b, b / c)) (fun b hb ↦ ?_) fun b₁ _ b₂ _ h ↦ ?_
state_before: case refine_1.intro.intro.intro.intro
α : Type u_1
inst✝¹ : CommGroup α
inst✝ : DecidableEq α
A✝ B✝ C✝ A B C : Finset α
a : α
ha : a ∈ A
c : α
hc : c ∈ C
hx : a / c ∈ A / C
⊢ B.card ≤ (bipartiteAbove (fun b ac => ac.1 * ac.2 = b) ((A / B) ×ˢ (B / C)) (a / c)).card

case refine_2
α : Type u_1
inst✝¹ : CommGroup α
inst✝ : DecidableEq α
A✝ B✝ C✝ A B C : Finset α
x : α × α
x✝ : x ∈ (A / B) ×ˢ (B / C)
a✝ b✝ : α
hu : a✝ ∈ bipartiteBelow (fun b ac => ac.1 * ac.2 = b) (A / C) x
hv : b✝ ∈ bipartiteBelow (fun b ac => ac.1 * ac.2 = b) (A / C) x
⊢ x.1 * x.2 = b✝
state_after: case refine_1.intro.intro.intro.intro.refine_1
α : Type u_1
inst✝¹ : CommGroup α
inst✝ : DecidableEq α
A✝ B✝ C✝ A B C : Finset α
a : α
ha : a ∈ A
c : α
hc : c ∈ C
hx : a / c ∈ A / C
b : α
hb : b ∈ B
⊢ (fun b => (a / b, b / c)) b ∈ bipartiteAbove (fun b ac => ac.1 * ac.2 = b) ((A / B) ×ˢ (B / C)) (a / c)

case refine_1.intro.intro.intro.intro.refine_2
α : Type u_1
inst✝¹ : CommGroup α
inst✝ : DecidableEq α
A✝ B✝ C✝ A B C : Finset α
a : α
ha : a ∈ A
c : α
hc : c ∈ C
hx : a / c ∈ A / C
b₁ : α
x✝¹ : b₁ ∈ ↑B
b₂ : α
x✝ : b₂ ∈ ↑B
h : (fun b => (a / b, b / c)) b₁ = (fun b => (a / b, b / c)) b₂
⊢ b₁ = b₂

case refine_2
α : Type u_1
inst✝¹ : CommGroup α
inst✝ : DecidableEq α
A✝ B✝ C✝ A B C : Finset α
x : α × α
x✝ : x ∈ (A / B) ×ˢ (B / C)
a✝ b✝ : α
hu : a✝ ∈ bipartiteBelow (fun b ac => ac.1 * ac.2 = b) (A / C) x
hv : b✝ ∈ bipartiteBelow (fun b ac => ac.1 * ac.2 = b) (A / C) x
⊢ x.1 * x.2 = b✝

tactic: rw [mem_bipartiteAbove]
state_before: case refine_1.intro.intro.intro.intro.refine_1
α : Type u_1
inst✝¹ : CommGroup α
inst✝ : DecidableEq α
A✝ B✝ C✝ A B C : Finset α
a : α
ha : a ∈ A
c : α
hc : c ∈ C
hx : a / c ∈ A / C
b : α
hb : b ∈ B
⊢ (fun b => (a / b, b / c)) b ∈ bipartiteAbove (fun b ac => ac.1 * ac.2 = b) ((A / B) ×ˢ (B / C)) (a / c)
state_after: case refine_1.intro.intro.intro.intro.refine_1
α : Type u_1
inst✝¹ : CommGroup α
inst✝ : DecidableEq α
A✝ B✝ C✝ A B C : Finset α
a : α
ha : a ∈ A
c : α
hc : c ∈ C
hx : a / c ∈ A / C
b : α
hb : b ∈ B
⊢ (fun b => (a / b, b / c)) b ∈ (A / B) ×ˢ (B / C) ∧
    ((fun b => (a / b, b / c)) b).1 * ((fun b => (a / b, b / c)) b).2 = a / c

tactic: exact ⟨mk_mem_product (div_mem_div ha hb) (div_mem_div hb hc), div_mul_div_cancel' _ _ _⟩
state_before: case refine_1.intro.intro.intro.intro.refine_1
α : Type u_1
inst✝¹ : CommGroup α
inst✝ : DecidableEq α
A✝ B✝ C✝ A B C : Finset α
a : α
ha : a ∈ A
c : α
hc : c ∈ C
hx : a / c ∈ A / C
b : α
hb : b ∈ B
⊢ (fun b => (a / b, b / c)) b ∈ (A / B) ×ˢ (B / C) ∧
    ((fun b => (a / b, b / c)) b).1 * ((fun b => (a / b, b / c)) b).2 = a / c
state_after: no goals

tactic: exact div_right_injective (Prod.ext_iff.1 h).1
state_before: case refine_1.intro.intro.intro.intro.refine_2
α : Type u_1
inst✝¹ : CommGroup α
inst✝ : DecidableEq α
A✝ B✝ C✝ A B C : Finset α
a : α
ha : a ∈ A
c : α
hc : c ∈ C
hx : a / c ∈ A / C
b₁ : α
x✝¹ : b₁ ∈ ↑B
b₂ : α
x✝ : b₂ ∈ ↑B
h : (fun b => (a / b, b / c)) b₁ = (fun b => (a / b, b / c)) b₂
⊢ b₁ = b₂
state_after: no goals

tactic: exact ((mem_bipartiteBelow _).1 hv).2
state_before: case refine_2
α : Type u_1
inst✝¹ : CommGroup α
inst✝ : DecidableEq α
A✝ B✝ C✝ A B C : Finset α
x : α × α
x✝ : x ∈ (A / B) ×ˢ (B / C)
a✝ b✝ : α
hu : a✝ ∈ bipartiteBelow (fun b ac => ac.1 * ac.2 = b) (A / C) x
hv : b✝ ∈ bipartiteBelow (fun b ac => ac.1 * ac.2 = b) (A / C) x
⊢ x.1 * x.2 = b✝
state_after: no goals