Theorem: ZMod.sum_mul_div_add_sum_mul_div_eq_mul
File: Mathlib/NumberTheory/LegendreSymbol/GaussEisensteinLemmas.lean

tactic: have hswap :
  ((Ico 1 (q / 2).succ ×ˢ Ico 1 (p / 2).succ).filter fun x : ℕ × ℕ => x.2 * q ≤ x.1 * p).card =
    ((Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ).filter fun x : ℕ × ℕ =>
      x.1 * q ≤ x.2 * p).card :=
  card_equiv (Equiv.prodComm _ _)
    (fun ⟨_, _⟩ => by
      simp (config := { contextual := true }) only [mem_filter, and_self_iff, Prod.swap_prod_mk,
        forall_true_iff, mem_product, Equiv.prodComm_apply, and_assoc, and_left_comm])
state_before: p q : ℕ
hp : Fact (Nat.Prime p)
hq0 : ↑q ≠ 0
⊢ ∑ a ∈ Ico 1 (p / 2).succ, a * q / p + ∑ a ∈ Ico 1 (q / 2).succ, a * p / q = p / 2 * (q / 2)
state_after: p q : ℕ
hp : Fact (Nat.Prime p)
hq0 : ↑q ≠ 0
hswap :
  (filter (fun x => x.2 * q ≤ x.1 * p) (Ico 1 (q / 2).succ ×ˢ Ico 1 (p / 2).succ)).card =
    (filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ)).card
⊢ ∑ a ∈ Ico 1 (p / 2).succ, a * q / p + ∑ a ∈ Ico 1 (q / 2).succ, a * p / q = p / 2 * (q / 2)

tactic: have hdisj :
  Disjoint ((Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ).filter fun x : ℕ × ℕ => x.2 * p ≤ x.1 * q)
    ((Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ).filter fun x : ℕ × ℕ => x.1 * q ≤ x.2 * p) := by
  apply disjoint_filter.2 fun x hx hpq hqp => ?_
  have hxp : x.1 < p := lt_of_le_of_lt
    (show x.1 ≤ p / 2 by simp_all only [Nat.lt_succ_iff, mem_Ico, mem_product])
    (Nat.div_lt_self hp.1.pos (by decide))
  have : (x.1 : ZMod p) = 0 := by
    simpa [hq0] using congr_arg ((↑) : ℕ → ZMod p) (le_antisymm hpq hqp)
  apply_fun ZMod.val at this
  rw [val_cast_of_lt hxp, val_zero] at this
  simp only [this, nonpos_iff_eq_zero, mem_Ico, one_ne_zero, false_and_iff, mem_product] at hx
state_before: p q : ℕ
hp : Fact (Nat.Prime p)
hq0 : ↑q ≠ 0
hswap :
  (filter (fun x => x.2 * q ≤ x.1 * p) (Ico 1 (q / 2).succ ×ˢ Ico 1 (p / 2).succ)).card =
    (filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ)).card
⊢ ∑ a ∈ Ico 1 (p / 2).succ, a * q / p + ∑ a ∈ Ico 1 (q / 2).succ, a * p / q = p / 2 * (q / 2)
state_after: p q : ℕ
hp : Fact (Nat.Prime p)
hq0 : ↑q ≠ 0
hswap :
  (filter (fun x => x.2 * q ≤ x.1 * p) (Ico 1 (q / 2).succ ×ˢ Ico 1 (p / 2).succ)).card =
    (filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ)).card
hdisj :
  Disjoint (filter (fun x => x.2 * p ≤ x.1 * q) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ))
    (filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ))
⊢ ∑ a ∈ Ico 1 (p / 2).succ, a * q / p + ∑ a ∈ Ico 1 (q / 2).succ, a * p / q = p / 2 * (q / 2)

tactic: have hunion :
    (((Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ).filter fun x : ℕ × ℕ => x.2 * p ≤ x.1 * q) ∪
      (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ).filter fun x : ℕ × ℕ => x.1 * q ≤ x.2 * p) =
    Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ :=
  Finset.ext fun x => by
    have := le_total (x.2 * p) (x.1 * q)
    simp only [mem_union, mem_filter, mem_Ico, mem_product]
    tauto
state_before: p q : ℕ
hp : Fact (Nat.Prime p)
hq0 : ↑q ≠ 0
hswap :
  (filter (fun x => x.2 * q ≤ x.1 * p) (Ico 1 (q / 2).succ ×ˢ Ico 1 (p / 2).succ)).card =
    (filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ)).card
hdisj :
  Disjoint (filter (fun x => x.2 * p ≤ x.1 * q) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ))
    (filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ))
⊢ ∑ a ∈ Ico 1 (p / 2).succ, a * q / p + ∑ a ∈ Ico 1 (q / 2).succ, a * p / q = p / 2 * (q / 2)
state_after: p q : ℕ
hp : Fact (Nat.Prime p)
hq0 : ↑q ≠ 0
hswap :
  (filter (fun x => x.2 * q ≤ x.1 * p) (Ico 1 (q / 2).succ ×ˢ Ico 1 (p / 2).succ)).card =
    (filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ)).card
hdisj :
  Disjoint (filter (fun x => x.2 * p ≤ x.1 * q) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ))
    (filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ))
hunion :
  filter (fun x => x.2 * p ≤ x.1 * q) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ) ∪
      filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ) =
    Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ
⊢ ∑ a ∈ Ico 1 (p / 2).succ, a * q / p + ∑ a ∈ Ico 1 (q / 2).succ, a * p / q = p / 2 * (q / 2)

tactic: rw [sum_Ico_eq_card_lt, sum_Ico_eq_card_lt, hswap, ← card_union_of_disjoint hdisj, hunion,
  card_product]
state_before: p q : ℕ
hp : Fact (Nat.Prime p)
hq0 : ↑q ≠ 0
hswap :
  (filter (fun x => x.2 * q ≤ x.1 * p) (Ico 1 (q / 2).succ ×ˢ Ico 1 (p / 2).succ)).card =
    (filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ)).card
hdisj :
  Disjoint (filter (fun x => x.2 * p ≤ x.1 * q) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ))
    (filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ))
hunion :
  filter (fun x => x.2 * p ≤ x.1 * q) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ) ∪
      filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ) =
    Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ
⊢ ∑ a ∈ Ico 1 (p / 2).succ, a * q / p + ∑ a ∈ Ico 1 (q / 2).succ, a * p / q = p / 2 * (q / 2)
state_after: p q : ℕ
hp : Fact (Nat.Prime p)
hq0 : ↑q ≠ 0
hswap :
  (filter (fun x => x.2 * q ≤ x.1 * p) (Ico 1 (q / 2).succ ×ˢ Ico 1 (p / 2).succ)).card =
    (filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ)).card
hdisj :
  Disjoint (filter (fun x => x.2 * p ≤ x.1 * q) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ))
    (filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ))
hunion :
  filter (fun x => x.2 * p ≤ x.1 * q) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ) ∪
      filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ) =
    Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ
⊢ (Ico 1 (p / 2).succ).card * (Ico 1 (q / 2).succ).card = p / 2 * (q / 2)

tactic: simp only [card_Ico, tsub_zero, succ_sub_succ_eq_sub]
state_before: p q : ℕ
hp : Fact (Nat.Prime p)
hq0 : ↑q ≠ 0
hswap :
  (filter (fun x => x.2 * q ≤ x.1 * p) (Ico 1 (q / 2).succ ×ˢ Ico 1 (p / 2).succ)).card =
    (filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ)).card
hdisj :
  Disjoint (filter (fun x => x.2 * p ≤ x.1 * q) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ))
    (filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ))
hunion :
  filter (fun x => x.2 * p ≤ x.1 * q) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ) ∪
      filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ) =
    Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ
⊢ (Ico 1 (p / 2).succ).card * (Ico 1 (q / 2).succ).card = p / 2 * (q / 2)
state_after: no goals

tactic: simp (config := { contextual := true }) only [mem_filter, and_self_iff, Prod.swap_prod_mk,
  forall_true_iff, mem_product, Equiv.prodComm_apply, and_assoc, and_left_comm]
state_before: p q : ℕ
hp : Fact (Nat.Prime p)
hq0 : ↑q ≠ 0
x✝ : ℕ × ℕ
fst✝ snd✝ : ℕ
⊢ (fst✝, snd✝) ∈ filter (fun x => x.2 * q ≤ x.1 * p) (Ico 1 (q / 2).succ ×ˢ Ico 1 (p / 2).succ) ↔
    (Equiv.prodComm ℕ ℕ) (fst✝, snd✝) ∈ filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ)
state_after: no goals

tactic: apply disjoint_filter.2 fun x hx hpq hqp => ?_
state_before: p q : ℕ
hp : Fact (Nat.Prime p)
hq0 : ↑q ≠ 0
hswap :
  (filter (fun x => x.2 * q ≤ x.1 * p) (Ico 1 (q / 2).succ ×ˢ Ico 1 (p / 2).succ)).card =
    (filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ)).card
⊢ Disjoint (filter (fun x => x.2 * p ≤ x.1 * q) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ))
    (filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ))
state_after: p q : ℕ
hp : Fact (Nat.Prime p)
hq0 : ↑q ≠ 0
hswap :
  (filter (fun x => x.2 * q ≤ x.1 * p) (Ico 1 (q / 2).succ ×ˢ Ico 1 (p / 2).succ)).card =
    (filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ)).card
x : ℕ × ℕ
hx : x ∈ Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ
hpq : x.2 * p ≤ x.1 * q
hqp : x.1 * q ≤ x.2 * p
⊢ False

tactic: have hxp : x.1 < p := lt_of_le_of_lt
  (show x.1 ≤ p / 2 by simp_all only [Nat.lt_succ_iff, mem_Ico, mem_product])
  (Nat.div_lt_self hp.1.pos (by decide))
state_before: p q : ℕ
hp : Fact (Nat.Prime p)
hq0 : ↑q ≠ 0
hswap :
  (filter (fun x => x.2 * q ≤ x.1 * p) (Ico 1 (q / 2).succ ×ˢ Ico 1 (p / 2).succ)).card =
    (filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ)).card
x : ℕ × ℕ
hx : x ∈ Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ
hpq : x.2 * p ≤ x.1 * q
hqp : x.1 * q ≤ x.2 * p
⊢ False
state_after: p q : ℕ
hp : Fact (Nat.Prime p)
hq0 : ↑q ≠ 0
hswap :
  (filter (fun x => x.2 * q ≤ x.1 * p) (Ico 1 (q / 2).succ ×ˢ Ico 1 (p / 2).succ)).card =
    (filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ)).card
x : ℕ × ℕ
hx : x ∈ Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ
hpq : x.2 * p ≤ x.1 * q
hqp : x.1 * q ≤ x.2 * p
hxp : x.1 < p
⊢ False

tactic: have : (x.1 : ZMod p) = 0 := by
  simpa [hq0] using congr_arg ((↑) : ℕ → ZMod p) (le_antisymm hpq hqp)
state_before: p q : ℕ
hp : Fact (Nat.Prime p)
hq0 : ↑q ≠ 0
hswap :
  (filter (fun x => x.2 * q ≤ x.1 * p) (Ico 1 (q / 2).succ ×ˢ Ico 1 (p / 2).succ)).card =
    (filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ)).card
x : ℕ × ℕ
hx : x ∈ Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ
hpq : x.2 * p ≤ x.1 * q
hqp : x.1 * q ≤ x.2 * p
hxp : x.1 < p
⊢ False
state_after: p q : ℕ
hp : Fact (Nat.Prime p)
hq0 : ↑q ≠ 0
hswap :
  (filter (fun x => x.2 * q ≤ x.1 * p) (Ico 1 (q / 2).succ ×ˢ Ico 1 (p / 2).succ)).card =
    (filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ)).card
x : ℕ × ℕ
hx : x ∈ Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ
hpq : x.2 * p ≤ x.1 * q
hqp : x.1 * q ≤ x.2 * p
hxp : x.1 < p
this : ↑x.1 = 0
⊢ False

tactic: apply_fun ZMod.val at this
state_before: p q : ℕ
hp : Fact (Nat.Prime p)
hq0 : ↑q ≠ 0
hswap :
  (filter (fun x => x.2 * q ≤ x.1 * p) (Ico 1 (q / 2).succ ×ˢ Ico 1 (p / 2).succ)).card =
    (filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ)).card
x : ℕ × ℕ
hx : x ∈ Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ
hpq : x.2 * p ≤ x.1 * q
hqp : x.1 * q ≤ x.2 * p
hxp : x.1 < p
this : ↑x.1 = 0
⊢ False
state_after: p q : ℕ
hp : Fact (Nat.Prime p)
hq0 : ↑q ≠ 0
hswap :
  (filter (fun x => x.2 * q ≤ x.1 * p) (Ico 1 (q / 2).succ ×ˢ Ico 1 (p / 2).succ)).card =
    (filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ)).card
x : ℕ × ℕ
hx : x ∈ Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ
hpq : x.2 * p ≤ x.1 * q
hqp : x.1 * q ≤ x.2 * p
hxp : x.1 < p
this : (↑x.1).val = val 0
⊢ False

tactic: rw [val_cast_of_lt hxp, val_zero] at this
state_before: p q : ℕ
hp : Fact (Nat.Prime p)
hq0 : ↑q ≠ 0
hswap :
  (filter (fun x => x.2 * q ≤ x.1 * p) (Ico 1 (q / 2).succ ×ˢ Ico 1 (p / 2).succ)).card =
    (filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ)).card
x : ℕ × ℕ
hx : x ∈ Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ
hpq : x.2 * p ≤ x.1 * q
hqp : x.1 * q ≤ x.2 * p
hxp : x.1 < p
this : (↑x.1).val = val 0
⊢ False
state_after: p q : ℕ
hp : Fact (Nat.Prime p)
hq0 : ↑q ≠ 0
hswap :
  (filter (fun x => x.2 * q ≤ x.1 * p) (Ico 1 (q / 2).succ ×ˢ Ico 1 (p / 2).succ)).card =
    (filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ)).card
x : ℕ × ℕ
hx : x ∈ Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ
hpq : x.2 * p ≤ x.1 * q
hqp : x.1 * q ≤ x.2 * p
hxp : x.1 < p
this : x.1 = 0
⊢ False

tactic: simp only [this, nonpos_iff_eq_zero, mem_Ico, one_ne_zero, false_and_iff, mem_product] at hx
state_before: p q : ℕ
hp : Fact (Nat.Prime p)
hq0 : ↑q ≠ 0
hswap :
  (filter (fun x => x.2 * q ≤ x.1 * p) (Ico 1 (q / 2).succ ×ˢ Ico 1 (p / 2).succ)).card =
    (filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ)).card
x : ℕ × ℕ
hx : x ∈ Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ
hpq : x.2 * p ≤ x.1 * q
hqp : x.1 * q ≤ x.2 * p
hxp : x.1 < p
this : x.1 = 0
⊢ False
state_after: no goals

tactic: simp_all only [Nat.lt_succ_iff, mem_Ico, mem_product]
state_before: p q : ℕ
hp : Fact (Nat.Prime p)
hq0 : ↑q ≠ 0
hswap :
  (filter (fun x => x.2 * q ≤ x.1 * p) (Ico 1 (q / 2).succ ×ˢ Ico 1 (p / 2).succ)).card =
    (filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ)).card
x : ℕ × ℕ
hx : x ∈ Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ
hpq : x.2 * p ≤ x.1 * q
hqp : x.1 * q ≤ x.2 * p
⊢ x.1 ≤ p / 2
state_after: no goals

tactic: decide
state_before: p q : ℕ
hp : Fact (Nat.Prime p)
hq0 : ↑q ≠ 0
hswap :
  (filter (fun x => x.2 * q ≤ x.1 * p) (Ico 1 (q / 2).succ ×ˢ Ico 1 (p / 2).succ)).card =
    (filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ)).card
x : ℕ × ℕ
hx : x ∈ Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ
hpq : x.2 * p ≤ x.1 * q
hqp : x.1 * q ≤ x.2 * p
⊢ 1 < 2
state_after: no goals

tactic: simpa [hq0] using congr_arg ((↑) : ℕ → ZMod p) (le_antisymm hpq hqp)
state_before: p q : ℕ
hp : Fact (Nat.Prime p)
hq0 : ↑q ≠ 0
hswap :
  (filter (fun x => x.2 * q ≤ x.1 * p) (Ico 1 (q / 2).succ ×ˢ Ico 1 (p / 2).succ)).card =
    (filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ)).card
x : ℕ × ℕ
hx : x ∈ Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ
hpq : x.2 * p ≤ x.1 * q
hqp : x.1 * q ≤ x.2 * p
hxp : x.1 < p
⊢ ↑x.1 = 0
state_after: no goals

tactic: have := le_total (x.2 * p) (x.1 * q)
state_before: p q : ℕ
hp : Fact (Nat.Prime p)
hq0 : ↑q ≠ 0
hswap :
  (filter (fun x => x.2 * q ≤ x.1 * p) (Ico 1 (q / 2).succ ×ˢ Ico 1 (p / 2).succ)).card =
    (filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ)).card
hdisj :
  Disjoint (filter (fun x => x.2 * p ≤ x.1 * q) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ))
    (filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ))
x : ℕ × ℕ
⊢ x ∈
      filter (fun x => x.2 * p ≤ x.1 * q) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ) ∪
        filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ) ↔
    x ∈ Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ
state_after: p q : ℕ
hp : Fact (Nat.Prime p)
hq0 : ↑q ≠ 0
hswap :
  (filter (fun x => x.2 * q ≤ x.1 * p) (Ico 1 (q / 2).succ ×ˢ Ico 1 (p / 2).succ)).card =
    (filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ)).card
hdisj :
  Disjoint (filter (fun x => x.2 * p ≤ x.1 * q) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ))
    (filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ))
x : ℕ × ℕ
this : x.2 * p ≤ x.1 * q ∨ x.1 * q ≤ x.2 * p
⊢ x ∈
      filter (fun x => x.2 * p ≤ x.1 * q) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ) ∪
        filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ) ↔
    x ∈ Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ

tactic: simp only [mem_union, mem_filter, mem_Ico, mem_product]
state_before: p q : ℕ
hp : Fact (Nat.Prime p)
hq0 : ↑q ≠ 0
hswap :
  (filter (fun x => x.2 * q ≤ x.1 * p) (Ico 1 (q / 2).succ ×ˢ Ico 1 (p / 2).succ)).card =
    (filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ)).card
hdisj :
  Disjoint (filter (fun x => x.2 * p ≤ x.1 * q) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ))
    (filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ))
x : ℕ × ℕ
this : x.2 * p ≤ x.1 * q ∨ x.1 * q ≤ x.2 * p
⊢ x ∈
      filter (fun x => x.2 * p ≤ x.1 * q) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ) ∪
        filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ) ↔
    x ∈ Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ
state_after: p q : ℕ
hp : Fact (Nat.Prime p)
hq0 : ↑q ≠ 0
hswap :
  (filter (fun x => x.2 * q ≤ x.1 * p) (Ico 1 (q / 2).succ ×ˢ Ico 1 (p / 2).succ)).card =
    (filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ)).card
hdisj :
  Disjoint (filter (fun x => x.2 * p ≤ x.1 * q) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ))
    (filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ))
x : ℕ × ℕ
this : x.2 * p ≤ x.1 * q ∨ x.1 * q ≤ x.2 * p
⊢ ((1 ≤ x.1 ∧ x.1 < (p / 2).succ) ∧ 1 ≤ x.2 ∧ x.2 < (q / 2).succ) ∧ x.2 * p ≤ x.1 * q ∨
      ((1 ≤ x.1 ∧ x.1 < (p / 2).succ) ∧ 1 ≤ x.2 ∧ x.2 < (q / 2).succ) ∧ x.1 * q ≤ x.2 * p ↔
    (1 ≤ x.1 ∧ x.1 < (p / 2).succ) ∧ 1 ≤ x.2 ∧ x.2 < (q / 2).succ

tactic: tauto
state_before: p q : ℕ
hp : Fact (Nat.Prime p)
hq0 : ↑q ≠ 0
hswap :
  (filter (fun x => x.2 * q ≤ x.1 * p) (Ico 1 (q / 2).succ ×ˢ Ico 1 (p / 2).succ)).card =
    (filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ)).card
hdisj :
  Disjoint (filter (fun x => x.2 * p ≤ x.1 * q) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ))
    (filter (fun x => x.1 * q ≤ x.2 * p) (Ico 1 (p / 2).succ ×ˢ Ico 1 (q / 2).succ))
x : ℕ × ℕ
this : x.2 * p ≤ x.1 * q ∨ x.1 * q ≤ x.2 * p
⊢ ((1 ≤ x.1 ∧ x.1 < (p / 2).succ) ∧ 1 ≤ x.2 ∧ x.2 < (q / 2).succ) ∧ x.2 * p ≤ x.1 * q ∨
      ((1 ≤ x.1 ∧ x.1 < (p / 2).succ) ∧ 1 ≤ x.2 ∧ x.2 < (q / 2).succ) ∧ x.1 * q ≤ x.2 * p ↔
    (1 ≤ x.1 ∧ x.1 < (p / 2).succ) ∧ 1 ≤ x.2 ∧ x.2 < (q / 2).succ
state_after: no goals