l3lab/ntp-mathlib huggingface dataset:
lemma card_filter_le_iff (s : Multiset α) (P : α → Prop) [DecidablePred P] (n : ℕ) :
    card (s.filter P) ≤ n ↔ ∀ s' ≤ s, n < card s' → ∃ a ∈ s', ¬ P a := by
  fconstructor
  · intro H s' hs' s'_card
    by_contra! rid
    have card := card_le_of_le (monotone_filter_left P hs') |>.trans H
    exact s'_card.not_le (filter_eq_self.mpr rid ▸ card)
  · 

Proof state:
case mpr
α : Type u_1
β : Type v
γ : Type u_2
p : α → Prop
inst✝¹ : DecidablePred p
s : Multiset α
P : α → Prop
inst✝ : DecidablePred P
n : ℕ
⊢ (∀ s' ≤ s, n < card s' → ∃ a ∈ s', ¬P a) → card (filter P s) ≤ n

Next tactic:
contrapose!
lemma card_filter_le_iff (s : Multiset α) (P : α → Prop) [DecidablePred P] (n : ℕ) :
    card (s.filter P) ≤ n ↔ ∀ s' ≤ s, n < card s' → ∃ a ∈ s', ¬ P a := by
  fconstructor
  · intro H s' hs' s'_card
    by_contra! rid
    have card := card_le_of_le (monotone_filter_left P hs') |>.trans H
    exact s'_card.not_le (filter_eq_self.mpr rid ▸ card)
  · contrapose!
    

Proof state:
case mpr
α : Type u_1
β : Type v
γ : Type u_2
p : α → Prop
inst✝¹ : DecidablePred p
s : Multiset α
P : α → Prop
inst✝ : DecidablePred P
n : ℕ
⊢ n < card (filter P s) → ∃ s' ≤ s, n < card s' ∧ ∀ a ∈ s', P a

Next tactic:
exact fun H ↦ ⟨s.filter P, filter_le _ _, H, fun a ha ↦ (mem_filter.mp ha).2⟩
theorem filterMap_eq_filter : filterMap (Option.guard p) = filter p :=
  funext fun s =>
    Quot.inductionOn s fun l => congr_arg ofList <| by
      

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
p : α → Prop
inst✝ : DecidablePred p
s : Multiset α
l : List α
⊢ List.filterMap (Option.guard p) l = List.filter (fun b => decide (p b)) l

Next tactic:
rw [← List.filterMap_eq_filter]
theorem filterMap_eq_filter : filterMap (Option.guard p) = filter p :=
  funext fun s =>
    Quot.inductionOn s fun l => congr_arg ofList <| by
      rw [← List.filterMap_eq_filter]
      

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
p : α → Prop
inst✝ : DecidablePred p
s : Multiset α
l : List α
⊢ List.filterMap (Option.guard p) l = List.filterMap (Option.guard fun x => decide (p x) = true) l

Next tactic:
congr
theorem filterMap_eq_filter : filterMap (Option.guard p) = filter p :=
  funext fun s =>
    Quot.inductionOn s fun l => congr_arg ofList <| by
      rw [← List.filterMap_eq_filter]
      congr; 

Proof state:
case e_f
α : Type u_1
β : Type v
γ : Type u_2
p : α → Prop
inst✝ : DecidablePred p
s : Multiset α
l : List α
⊢ Option.guard p = Option.guard fun x => decide (p x) = true

Next tactic:
funext a
theorem filterMap_eq_filter : filterMap (Option.guard p) = filter p :=
  funext fun s =>
    Quot.inductionOn s fun l => congr_arg ofList <| by
      rw [← List.filterMap_eq_filter]
      congr; funext a; 

Proof state:
case e_f.h
α : Type u_1
β : Type v
γ : Type u_2
p : α → Prop
inst✝ : DecidablePred p
s : Multiset α
l : List α
a : α
⊢ Option.guard p a = Option.guard (fun x => decide (p x) = true) a

Next tactic:
simp
theorem filterMap_filter (f : α → Option β) (s : Multiset α) :
    filterMap f (filter p s) = filterMap (fun x => if p x then f x else none) s :=
  Quot.inductionOn s fun l => congr_arg ofList <| by 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
p : α → Prop
inst✝ : DecidablePred p
f : α → Option β
s : Multiset α
l : List α
⊢ List.filterMap f (List.filter (fun b => decide (p b)) l) = List.filterMap (fun x => if p x then f x else none) l

Next tactic:
simpa using List.filterMap_filter p f l
@[simp]
theorem countP_cons_of_pos {a : α} (s) : p a → countP p (a ::ₘ s) = countP p s + 1 :=
  Quot.inductionOn s <| by 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
p : α → Prop
inst✝ : DecidablePred p
a : α
s : Multiset α
⊢ ∀ (a_1 : List α), p a → countP p (a ::ₘ Quot.mk Setoid.r a_1) = countP p (Quot.mk Setoid.r a_1) + 1

Next tactic:
simpa using List.countP_cons_of_pos (p ·)
@[simp]
theorem countP_cons_of_neg {a : α} (s) : ¬p a → countP p (a ::ₘ s) = countP p s :=
  Quot.inductionOn s <| by 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
p : α → Prop
inst✝ : DecidablePred p
a : α
s : Multiset α
⊢ ∀ (a_1 : List α), ¬p a → countP p (a ::ₘ Quot.mk Setoid.r a_1) = countP p (Quot.mk Setoid.r a_1)

Next tactic:
simpa using List.countP_cons_of_neg (p ·)
theorem countP_cons (b : α) (s) : countP p (b ::ₘ s) = countP p s + if p b then 1 else 0 :=
  Quot.inductionOn s <| by 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
p : α → Prop
inst✝ : DecidablePred p
b : α
s : Multiset α
⊢ ∀ (a : List α), countP p (b ::ₘ Quot.mk Setoid.r a) = countP p (Quot.mk Setoid.r a) + if p b then 1 else 0

Next tactic:
simp [List.countP_cons]
@[simp]
theorem countP_add (s t) : countP p (s + t) = countP p s + countP p t := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
p : α → Prop
inst✝ : DecidablePred p
s t : Multiset α
⊢ countP p (s + t) = countP p s + countP p t

Next tactic:
simp [countP_eq_card_filter]
@[simp]
theorem countP_nsmul (s) (n : ℕ) : countP p (n • s) = n * countP p s := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
p : α → Prop
inst✝ : DecidablePred p
s : Multiset α
n : ℕ
⊢ countP p (n • s) = n * countP p s

Next tactic:
induction n
@[simp]
theorem countP_nsmul (s) (n : ℕ) : countP p (n • s) = n * countP p s := by
  induction n <;> 

Proof state:
case zero
α : Type u_1
β : Type v
γ : Type u_2
p : α → Prop
inst✝ : DecidablePred p
s : Multiset α
⊢ countP p (zero • s) = zero * countP p s

Next tactic:
simp [*, succ_nsmul', succ_mul, zero_nsmul]
@[simp]
theorem countP_nsmul (s) (n : ℕ) : countP p (n • s) = n * countP p s := by
  induction n <;> 

Proof state:
case succ
α : Type u_1
β : Type v
γ : Type u_2
p : α → Prop
inst✝ : DecidablePred p
s : Multiset α
n✝ : ℕ
n_ih✝ : countP p (n✝ • s) = n✝ * countP p s
⊢ countP p (succ n✝ • s) = succ n✝ * countP p s

Next tactic:
simp [*, succ_nsmul', succ_mul, zero_nsmul]
theorem card_eq_countP_add_countP (s) : card s = countP p s + countP (fun x => ¬p x) s :=
  Quot.inductionOn s fun l => by 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
p : α → Prop
inst✝ : DecidablePred p
s : Multiset α
l : List α
⊢ card (Quot.mk Setoid.r l) = countP p (Quot.mk Setoid.r l) + countP (fun x => ¬p x) (Quot.mk Setoid.r l)

Next tactic:
simp [l.length_eq_countP_add_countP p]
@[simp]
theorem countP_sub [DecidableEq α] {s t : Multiset α} (h : t ≤ s) :
    countP p (s - t) = countP p s - countP p t := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
p : α → Prop
inst✝¹ : DecidablePred p
inst✝ : DecidableEq α
s t : Multiset α
h : t ≤ s
⊢ countP p (s - t) = countP p s - countP p t

Next tactic:
simp [countP_eq_card_filter, h, filter_le_filter]
theorem countP_le_of_le {s t} (h : s ≤ t) : countP p s ≤ countP p t := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
p : α → Prop
inst✝ : DecidablePred p
s t : Multiset α
h : s ≤ t
⊢ countP p s ≤ countP p t

Next tactic:
simpa [countP_eq_card_filter] using card_le_of_le (filter_le_filter p h)
@[simp]
theorem countP_filter (q) [DecidablePred q] (s : Multiset α) :
    countP p (filter q s) = countP (fun a => p a ∧ q a) s := by 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
p : α → Prop
inst✝¹ : DecidablePred p
q : α → Prop
inst✝ : DecidablePred q
s : Multiset α
⊢ countP p (filter q s) = countP (fun a => p a ∧ q a) s

Next tactic:
simp [countP_eq_card_filter]
theorem countP_eq_countP_filter_add (s) (p q : α → Prop) [DecidablePred p] [DecidablePred q] :
    countP p s = (filter q s).countP p + (filter (fun a => ¬q a) s).countP p :=
  Quot.inductionOn s fun l => by
    

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
p✝ : α → Prop
inst✝² : DecidablePred p✝
s : Multiset α
p q : α → Prop
inst✝¹ : DecidablePred p
inst✝ : DecidablePred q
l : List α
⊢ countP p (Quot.mk Setoid.r l) =
    countP p (filter q (Quot.mk Setoid.r l)) + countP p (filter (fun a => ¬q a) (Quot.mk Setoid.r l))

Next tactic:
convert l.countP_eq_countP_filter_add (p ·) (q ·)
theorem countP_eq_countP_filter_add (s) (p q : α → Prop) [DecidablePred p] [DecidablePred q] :
    countP p s = (filter q s).countP p + (filter (fun a => ¬q a) s).countP p :=
  Quot.inductionOn s fun l => by
    convert l.countP_eq_countP_filter_add (p ·) (q ·)
    

Proof state:
case h.e'_3.h.e'_6
α : Type u_1
β : Type v
γ : Type u_2
p✝ : α → Prop
inst✝² : DecidablePred p✝
s : Multiset α
p q : α → Prop
inst✝¹ : DecidablePred p
inst✝ : DecidablePred q
l : List α
⊢ countP p (filter (fun a => ¬q a) (Quot.mk Setoid.r l)) =
    List.countP (fun x => decide (p x)) (List.filter (fun a => !decide (q a)) l)

Next tactic:
simp [countP_filter]
theorem countP_map (f : α → β) (s : Multiset α) (p : β → Prop) [DecidablePred p] :
    countP p (map f s) = card (s.filter fun a => p (f a)) := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
p✝ : α → Prop
inst✝¹ : DecidablePred p✝
f : α → β
s : Multiset α
p : β → Prop
inst✝ : DecidablePred p
⊢ countP p (map f s) = card (filter (fun a => p (f a)) s)

Next tactic:
refine' Multiset.induction_on s _ fun a t IH => _
theorem countP_map (f : α → β) (s : Multiset α) (p : β → Prop) [DecidablePred p] :
    countP p (map f s) = card (s.filter fun a => p (f a)) := by
  refine' Multiset.induction_on s _ fun a t IH => _
  · 

Proof state:
case refine'_1
α : Type u_1
β : Type v
γ : Type u_2
p✝ : α → Prop
inst✝¹ : DecidablePred p✝
f : α → β
s : Multiset α
p : β → Prop
inst✝ : DecidablePred p
⊢ countP p (map f 0) = card (filter (fun a => p (f a)) 0)

Next tactic:
rw [map_zero, countP_zero, filter_zero, card_zero]
theorem countP_map (f : α → β) (s : Multiset α) (p : β → Prop) [DecidablePred p] :
    countP p (map f s) = card (s.filter fun a => p (f a)) := by
  refine' Multiset.induction_on s _ fun a t IH => _
  · rw [map_zero, countP_zero, filter_zero, card_zero]
  · 

Proof state:
case refine'_2
α : Type u_1
β : Type v
γ : Type u_2
p✝ : α → Prop
inst✝¹ : DecidablePred p✝
f : α → β
s : Multiset α
p : β → Prop
inst✝ : DecidablePred p
a : α
t : Multiset α
IH : countP p (map f t) = card (filter (fun a => p (f a)) t)
⊢ countP p (map f (a ::ₘ t)) = card (filter (fun a => p (f a)) (a ::ₘ t))

Next tactic:
rw [map_cons, countP_cons, IH, filter_cons, card_add, apply_ite card, card_zero, card_singleton,
      add_comm]
lemma countP_attach (s : Multiset α) : s.attach.countP (fun a : {a // a ∈ s} ↦ p a) = s.countP p :=
  Quotient.inductionOn s fun l => by
    

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
p : α → Prop
inst✝ : DecidablePred p
s : Multiset α
l : List α
⊢ countP (fun a => p ↑a) (attach ⟦l⟧) = countP p ⟦l⟧

Next tactic:
simp only [quot_mk_to_coe, coe_countP]
lemma countP_attach (s : Multiset α) : s.attach.countP (fun a : {a // a ∈ s} ↦ p a) = s.countP p :=
  Quotient.inductionOn s fun l => by
    simp only [quot_mk_to_coe, coe_countP]
    -- porting note: was
    -- rw [quot_mk_to_coe, coe_attach, coe_countP]
    -- exact List.countP_attach _ _
    

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
p : α → Prop
inst✝ : DecidablePred p
s : Multiset α
l : List α
⊢ countP (fun a => p ↑a) (attach ↑l) = List.countP (fun b => decide (p b)) l

Next tactic:
rw [coe_attach]
lemma countP_attach (s : Multiset α) : s.attach.countP (fun a : {a // a ∈ s} ↦ p a) = s.countP p :=
  Quotient.inductionOn s fun l => by
    simp only [quot_mk_to_coe, coe_countP]
    -- porting note: was
    -- rw [quot_mk_to_coe, coe_attach, coe_countP]
    -- exact List.countP_attach _ _
    rw [coe_attach]
    

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
p : α → Prop
inst✝ : DecidablePred p
s : Multiset α
l : List α
⊢ countP (fun a => p ↑a) ↑(List.attach l) = List.countP (fun b => decide (p b)) l

Next tactic:
refine (coe_countP _ _).trans ?_
lemma countP_attach (s : Multiset α) : s.attach.countP (fun a : {a // a ∈ s} ↦ p a) = s.countP p :=
  Quotient.inductionOn s fun l => by
    simp only [quot_mk_to_coe, coe_countP]
    -- porting note: was
    -- rw [quot_mk_to_coe, coe_attach, coe_countP]
    -- exact List.countP_attach _ _
    rw [coe_attach]
    refine (coe_countP _ _).trans ?_
    

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
p : α → Prop
inst✝ : DecidablePred p
s : Multiset α
l : List α
⊢ List.countP (fun b => decide (p ↑b)) (List.attach l) = List.countP (fun b => decide (p b)) l

Next tactic:
convert List.countP_attach _ _
lemma countP_attach (s : Multiset α) : s.attach.countP (fun a : {a // a ∈ s} ↦ p a) = s.countP p :=
  Quotient.inductionOn s fun l => by
    simp only [quot_mk_to_coe, coe_countP]
    -- porting note: was
    -- rw [quot_mk_to_coe, coe_attach, coe_countP]
    -- exact List.countP_attach _ _
    rw [coe_attach]
    refine (coe_countP _ _).trans ?_
    convert List.countP_attach _ _
    

Proof state:
case h.e'_2
α : Type u_1
β : Type v
γ : Type u_2
p : α → Prop
inst✝ : DecidablePred p
s : Multiset α
l : List α
⊢ List.countP (fun b => decide (p ↑b)) (List.attach l) = List.countP (fun a => decide (p ↑a)) (List.attach l)

Next tactic:
rfl
theorem countP_pos {s} : 0 < countP p s ↔ ∃ a ∈ s, p a :=
  Quot.inductionOn s fun _l => by 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
p : α → Prop
inst✝ : DecidablePred p
s : Multiset α
_l : List α
⊢ 0 < countP p (Quot.mk Setoid.r _l) ↔ ∃ a ∈ Quot.mk Setoid.r _l, p a

Next tactic:
simpa using List.countP_pos (p ·)
theorem countP_eq_zero {s} : countP p s = 0 ↔ ∀ a ∈ s, ¬p a :=
  Quot.inductionOn s fun _l => by 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
p : α → Prop
inst✝ : DecidablePred p
s : Multiset α
_l : List α
⊢ countP p (Quot.mk Setoid.r _l) = 0 ↔ ∀ a ∈ Quot.mk Setoid.r _l, ¬p a

Next tactic:
simp [List.countP_eq_zero]
theorem countP_eq_card {s} : countP p s = card s ↔ ∀ a ∈ s, p a :=
  Quot.inductionOn s fun _l => by 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
p : α → Prop
inst✝ : DecidablePred p
s : Multiset α
_l : List α
⊢ countP p (Quot.mk Setoid.r _l) = card (Quot.mk Setoid.r _l) ↔ ∀ a ∈ Quot.mk Setoid.r _l, p a

Next tactic:
simp [List.countP_eq_length]
theorem countP_congr {s s' : Multiset α} (hs : s = s')
    {p p' : α → Prop} [DecidablePred p] [DecidablePred p']
    (hp : ∀ x ∈ s, p x = p' x) : s.countP p = s'.countP p' := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
p✝ : α → Prop
inst✝² : DecidablePred p✝
s s' : Multiset α
hs : s = s'
p p' : α → Prop
inst✝¹ : DecidablePred p
inst✝ : DecidablePred p'
hp : ∀ x ∈ s, p x = p' x
⊢ countP p s = countP p' s'

Next tactic:
revert hs hp
theorem countP_congr {s s' : Multiset α} (hs : s = s')
    {p p' : α → Prop} [DecidablePred p] [DecidablePred p']
    (hp : ∀ x ∈ s, p x = p' x) : s.countP p = s'.countP p' := by
  revert hs hp
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
p✝ : α → Prop
inst✝² : DecidablePred p✝
s s' : Multiset α
p p' : α → Prop
inst✝¹ : DecidablePred p
inst✝ : DecidablePred p'
⊢ s = s' → (∀ x ∈ s, p x = p' x) → countP p s = countP p' s'

Next tactic:
exact Quot.induction_on₂ s s'
    (fun l l' hs hp => by
      simp only [quot_mk_to_coe'', coe_eq_coe] at hs
      apply hs.countP_congr
      simpa using hp)
theorem countP_congr {s s' : Multiset α} (hs : s = s')
    {p p' : α → Prop} [DecidablePred p] [DecidablePred p']
    (hp : ∀ x ∈ s, p x = p' x) : s.countP p = s'.countP p' := by
  revert hs hp
  exact Quot.induction_on₂ s s'
    (fun l l' hs hp => by
      

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
p✝ : α → Prop
inst✝² : DecidablePred p✝
s s' : Multiset α
p p' : α → Prop
inst✝¹ : DecidablePred p
inst✝ : DecidablePred p'
l l' : List α
hs : Quot.mk Setoid.r l = Quot.mk Setoid.r l'
hp : ∀ x ∈ Quot.mk Setoid.r l, p x = p' x
⊢ countP p (Quot.mk Setoid.r l) = countP p' (Quot.mk Setoid.r l')

Next tactic:
simp only [quot_mk_to_coe'', coe_eq_coe] at hs
theorem countP_congr {s s' : Multiset α} (hs : s = s')
    {p p' : α → Prop} [DecidablePred p] [DecidablePred p']
    (hp : ∀ x ∈ s, p x = p' x) : s.countP p = s'.countP p' := by
  revert hs hp
  exact Quot.induction_on₂ s s'
    (fun l l' hs hp => by
      simp only [quot_mk_to_coe'', coe_eq_coe] at hs
      

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
p✝ : α → Prop
inst✝² : DecidablePred p✝
s s' : Multiset α
p p' : α → Prop
inst✝¹ : DecidablePred p
inst✝ : DecidablePred p'
l l' : List α
hp : ∀ x ∈ Quot.mk Setoid.r l, p x = p' x
hs : l ~ l'
⊢ countP p (Quot.mk Setoid.r l) = countP p' (Quot.mk Setoid.r l')

Next tactic:
apply hs.countP_congr
theorem countP_congr {s s' : Multiset α} (hs : s = s')
    {p p' : α → Prop} [DecidablePred p] [DecidablePred p']
    (hp : ∀ x ∈ s, p x = p' x) : s.countP p = s'.countP p' := by
  revert hs hp
  exact Quot.induction_on₂ s s'
    (fun l l' hs hp => by
      simp only [quot_mk_to_coe'', coe_eq_coe] at hs
      apply hs.countP_congr
      

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
p✝ : α → Prop
inst✝² : DecidablePred p✝
s s' : Multiset α
p p' : α → Prop
inst✝¹ : DecidablePred p
inst✝ : DecidablePred p'
l l' : List α
hp : ∀ x ∈ Quot.mk Setoid.r l, p x = p' x
hs : l ~ l'
⊢ ∀ x ∈ l, decide (p x) = decide (p' x)

Next tactic:
simpa using hp
@[simp]
theorem coe_count (a : α) (l : List α) : count a (ofList l) = l.count a := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
s : Multiset α
a : α
l : List α
⊢ count a ↑l = List.count a l

Next tactic:
simp_rw [count, List.count, coe_countP (a = ·) l, @eq_comm _ a]
@[simp]
theorem coe_count (a : α) (l : List α) : count a (ofList l) = l.count a := by
  simp_rw [count, List.count, coe_countP (a = ·) l, @eq_comm _ a]
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
s : Multiset α
a : α
l : List α
⊢ List.countP (fun b => decide (b = a)) l = List.countP (fun x => x == a) l

Next tactic:
rfl
theorem count_singleton (a b : α) : count a ({b} : Multiset α) = if a = b then 1 else 0 := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
s : Multiset α
a b : α
⊢ count a {b} = if a = b then 1 else 0

Next tactic:
simp only [count_cons, ← cons_zero, count_zero, zero_add]
@[simp]
theorem count_nsmul (a : α) (n s) : count a (n • s) = n * count a s := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
s✝ : Multiset α
a : α
n : ℕ
s : Multiset α
⊢ count a (n • s) = n * count a s

Next tactic:
induction n
@[simp]
theorem count_nsmul (a : α) (n s) : count a (n • s) = n * count a s := by
  induction n <;> 

Proof state:
case zero
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
s✝ : Multiset α
a : α
s : Multiset α
⊢ count a (zero • s) = zero * count a s

Next tactic:
simp [*, succ_nsmul', succ_mul, zero_nsmul]
@[simp]
theorem count_nsmul (a : α) (n s) : count a (n • s) = n * count a s := by
  induction n <;> 

Proof state:
case succ
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
s✝ : Multiset α
a : α
s : Multiset α
n✝ : ℕ
n_ih✝ : count a (n✝ • s) = n✝ * count a s
⊢ count a (succ n✝ • s) = succ n✝ * count a s

Next tactic:
simp [*, succ_nsmul', succ_mul, zero_nsmul]
@[simp]
lemma count_attach (a : {x // x ∈ s}) : s.attach.count a = s.count ↑a :=
  Eq.trans (countP_congr rfl fun _ _ => by 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
s : Multiset α
a x✝¹ : { x // x ∈ s }
x✝ : x✝¹ ∈ attach s
⊢ (a = x✝¹) = (↑a = ↑x✝¹)

Next tactic:
simp [Subtype.ext_iff]
theorem count_pos {a : α} {s : Multiset α} : 0 < count a s ↔ a ∈ s := by 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
s✝ : Multiset α
a : α
s : Multiset α
⊢ 0 < count a s ↔ a ∈ s

Next tactic:
simp [count, countP_pos]
theorem one_le_count_iff_mem {a : α} {s : Multiset α} : 1 ≤ count a s ↔ a ∈ s := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
s✝ : Multiset α
a : α
s : Multiset α
⊢ 1 ≤ count a s ↔ a ∈ s

Next tactic:
rw [succ_le_iff, count_pos]
theorem count_ne_zero {a : α} {s : Multiset α} : count a s ≠ 0 ↔ a ∈ s := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
s✝ : Multiset α
a : α
s : Multiset α
⊢ count a s ≠ 0 ↔ a ∈ s

Next tactic:
simp [Ne.def, count_eq_zero]
theorem count_eq_card {a : α} {s} : count a s = card s ↔ ∀ x ∈ s, a = x := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
s✝ : Multiset α
a : α
s : Multiset α
⊢ count a s = card s ↔ ∀ x ∈ s, a = x

Next tactic:
simp [countP_eq_card, count, @eq_comm _ a]
@[simp]
theorem count_replicate_self (a : α) (n : ℕ) : count a (replicate n a) = n := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
s : Multiset α
a : α
n : ℕ
⊢ count a (replicate n a) = n

Next tactic:
convert List.count_replicate_self a n
@[simp]
theorem count_replicate_self (a : α) (n : ℕ) : count a (replicate n a) = n := by
  convert List.count_replicate_self a n
  

Proof state:
case h.e'_2
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
s : Multiset α
a : α
n : ℕ
⊢ count a (replicate n a) = List.count a (List.replicate n a)

Next tactic:
rw [← coe_count, coe_replicate]
theorem count_replicate (a b : α) (n : ℕ) : count a (replicate n b) = if a = b then n else 0 := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
s : Multiset α
a b : α
n : ℕ
⊢ count a (replicate n b) = if a = b then n else 0

Next tactic:
convert List.count_replicate a b n
theorem count_replicate (a b : α) (n : ℕ) : count a (replicate n b) = if a = b then n else 0 := by
  convert List.count_replicate a b n
  

Proof state:
case h.e'_2
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
s : Multiset α
a b : α
n : ℕ
⊢ count a (replicate n b) = List.count a (List.replicate n b)

Next tactic:
rw [← coe_count, coe_replicate]
@[simp]
theorem count_erase_self (a : α) (s : Multiset α) : count a (erase s a) = count a s - 1 :=
  Quotient.inductionOn s <| fun l => by
    

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
s✝ : Multiset α
a : α
s : Multiset α
l : List α
⊢ count a (erase ⟦l⟧ a) = count a ⟦l⟧ - 1

Next tactic:
convert List.count_erase_self a l
@[simp]
theorem count_erase_self (a : α) (s : Multiset α) : count a (erase s a) = count a s - 1 :=
  Quotient.inductionOn s <| fun l => by
    convert List.count_erase_self a l <;> 

Proof state:
case h.e'_2
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
s✝ : Multiset α
a : α
s : Multiset α
l : List α
⊢ count a (erase ⟦l⟧ a) = List.count a (List.erase l a)

Next tactic:
rw [← coe_count]
@[simp]
theorem count_erase_self (a : α) (s : Multiset α) : count a (erase s a) = count a s - 1 :=
  Quotient.inductionOn s <| fun l => by
    convert List.count_erase_self a l <;> 

Proof state:
case h.e'_3.h.e'_5
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
s✝ : Multiset α
a : α
s : Multiset α
l : List α
⊢ count a ⟦l⟧ = List.count a l

Next tactic:
rw [← coe_count]
@[simp]
theorem count_erase_self (a : α) (s : Multiset α) : count a (erase s a) = count a s - 1 :=
  Quotient.inductionOn s <| fun l => by
    convert List.count_erase_self a l <;> rw [← coe_count] <;> 

Proof state:
case h.e'_2
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
s✝ : Multiset α
a : α
s : Multiset α
l : List α
⊢ count a (erase ⟦l⟧ a) = count a ↑(List.erase l a)

Next tactic:
simp
@[simp]
theorem count_erase_self (a : α) (s : Multiset α) : count a (erase s a) = count a s - 1 :=
  Quotient.inductionOn s <| fun l => by
    convert List.count_erase_self a l <;> rw [← coe_count] <;> 

Proof state:
case h.e'_3.h.e'_5
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
s✝ : Multiset α
a : α
s : Multiset α
l : List α
⊢ count a ⟦l⟧ = count a ↑l

Next tactic:
simp
@[simp]
theorem count_erase_of_ne {a b : α} (ab : a ≠ b) (s : Multiset α) :
    count a (erase s b) = count a s :=
  Quotient.inductionOn s <| fun l => by
    

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
s✝ : Multiset α
a b : α
ab : a ≠ b
s : Multiset α
l : List α
⊢ count a (erase ⟦l⟧ b) = count a ⟦l⟧

Next tactic:
convert List.count_erase_of_ne ab l
@[simp]
theorem count_erase_of_ne {a b : α} (ab : a ≠ b) (s : Multiset α) :
    count a (erase s b) = count a s :=
  Quotient.inductionOn s <| fun l => by
    convert List.count_erase_of_ne ab l <;> 

Proof state:
case h.e'_2
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
s✝ : Multiset α
a b : α
ab : a ≠ b
s : Multiset α
l : List α
⊢ count a (erase ⟦l⟧ b) = List.count a (List.erase l b)

Next tactic:
rw [← coe_count]