l3lab/ntp-mathlib huggingface dataset:
theorem dedup_eq_cons (l : List α) (a : α) (l' : List α) :
    l.dedup = a :: l' ↔ a ∈ l ∧ a ∉ l' ∧ l.dedup.tail = l' := by
  refine' ⟨fun h => _, fun h => _⟩
  · refine' ⟨mem_dedup.1 (h.symm ▸ mem_cons_self _ _), fun ha => _, by rw [h, tail_cons]⟩
    have : count a l.dedup ≤ 1 := nodup_iff_count_le_one.1 (nodup_dedup l) a
    

Proof state:
case refine'_1
α : Type u
inst✝ : DecidableEq α
l : List α
a : α
l' : List α
h : dedup l = a :: l'
ha : a ∈ l'
this : count a (dedup l) ≤ 1
⊢ False

Next tactic:
rw [h, count_cons_self, add_le_iff_nonpos_left] at this
theorem dedup_eq_cons (l : List α) (a : α) (l' : List α) :
    l.dedup = a :: l' ↔ a ∈ l ∧ a ∉ l' ∧ l.dedup.tail = l' := by
  refine' ⟨fun h => _, fun h => _⟩
  · refine' ⟨mem_dedup.1 (h.symm ▸ mem_cons_self _ _), fun ha => _, by rw [h, tail_cons]⟩
    have : count a l.dedup ≤ 1 := nodup_iff_count_le_one.1 (nodup_dedup l) a
    rw [h, count_cons_self, add_le_iff_nonpos_left] at this
    

Proof state:
case refine'_1
α : Type u
inst✝ : DecidableEq α
l : List α
a : α
l' : List α
h : dedup l = a :: l'
ha : a ∈ l'
this : count a l' ≤ 0
⊢ False

Next tactic:
exact not_le_of_lt (count_pos_iff_mem.2 ha) this
theorem dedup_eq_cons (l : List α) (a : α) (l' : List α) :
    l.dedup = a :: l' ↔ a ∈ l ∧ a ∉ l' ∧ l.dedup.tail = l' := by
  refine' ⟨fun h => _, fun h => _⟩
  · refine' ⟨mem_dedup.1 (h.symm ▸ mem_cons_self _ _), fun ha => _, by rw [h, tail_cons]⟩
    have : count a l.dedup ≤ 1 := nodup_iff_count_le_one.1 (nodup_dedup l) a
    rw [h, count_cons_self, add_le_iff_nonpos_left] at this
    exact not_le_of_lt (count_pos_iff_mem.2 ha) this
  · 

Proof state:
case refine'_2
α : Type u
inst✝ : DecidableEq α
l : List α
a : α
l' : List α
h : a ∈ l ∧ a ∉ l' ∧ tail (dedup l) = l'
⊢ dedup l = a :: l'

Next tactic:
have := @List.cons_head!_tail α ⟨a⟩ _ (ne_nil_of_mem (mem_dedup.2 h.1))
theorem dedup_eq_cons (l : List α) (a : α) (l' : List α) :
    l.dedup = a :: l' ↔ a ∈ l ∧ a ∉ l' ∧ l.dedup.tail = l' := by
  refine' ⟨fun h => _, fun h => _⟩
  · refine' ⟨mem_dedup.1 (h.symm ▸ mem_cons_self _ _), fun ha => _, by rw [h, tail_cons]⟩
    have : count a l.dedup ≤ 1 := nodup_iff_count_le_one.1 (nodup_dedup l) a
    rw [h, count_cons_self, add_le_iff_nonpos_left] at this
    exact not_le_of_lt (count_pos_iff_mem.2 ha) this
  · have := @List.cons_head!_tail α ⟨a⟩ _ (ne_nil_of_mem (mem_dedup.2 h.1))
    

Proof state:
case refine'_2
α : Type u
inst✝ : DecidableEq α
l : List α
a : α
l' : List α
h : a ∈ l ∧ a ∉ l' ∧ tail (dedup l) = l'
this : head! (dedup l) :: tail (dedup l) = dedup l
⊢ dedup l = a :: l'

Next tactic:
have hal : a ∈ l.dedup := mem_dedup.2 h.1
theorem dedup_eq_cons (l : List α) (a : α) (l' : List α) :
    l.dedup = a :: l' ↔ a ∈ l ∧ a ∉ l' ∧ l.dedup.tail = l' := by
  refine' ⟨fun h => _, fun h => _⟩
  · refine' ⟨mem_dedup.1 (h.symm ▸ mem_cons_self _ _), fun ha => _, by rw [h, tail_cons]⟩
    have : count a l.dedup ≤ 1 := nodup_iff_count_le_one.1 (nodup_dedup l) a
    rw [h, count_cons_self, add_le_iff_nonpos_left] at this
    exact not_le_of_lt (count_pos_iff_mem.2 ha) this
  · have := @List.cons_head!_tail α ⟨a⟩ _ (ne_nil_of_mem (mem_dedup.2 h.1))
    have hal : a ∈ l.dedup := mem_dedup.2 h.1
    

Proof state:
case refine'_2
α : Type u
inst✝ : DecidableEq α
l : List α
a : α
l' : List α
h : a ∈ l ∧ a ∉ l' ∧ tail (dedup l) = l'
this : head! (dedup l) :: tail (dedup l) = dedup l
hal : a ∈ dedup l
⊢ dedup l = a :: l'

Next tactic:
rw [← this, mem_cons, or_iff_not_imp_right] at hal
theorem dedup_eq_cons (l : List α) (a : α) (l' : List α) :
    l.dedup = a :: l' ↔ a ∈ l ∧ a ∉ l' ∧ l.dedup.tail = l' := by
  refine' ⟨fun h => _, fun h => _⟩
  · refine' ⟨mem_dedup.1 (h.symm ▸ mem_cons_self _ _), fun ha => _, by rw [h, tail_cons]⟩
    have : count a l.dedup ≤ 1 := nodup_iff_count_le_one.1 (nodup_dedup l) a
    rw [h, count_cons_self, add_le_iff_nonpos_left] at this
    exact not_le_of_lt (count_pos_iff_mem.2 ha) this
  · have := @List.cons_head!_tail α ⟨a⟩ _ (ne_nil_of_mem (mem_dedup.2 h.1))
    have hal : a ∈ l.dedup := mem_dedup.2 h.1
    rw [← this, mem_cons, or_iff_not_imp_right] at hal
    

Proof state:
case refine'_2
α : Type u
inst✝ : DecidableEq α
l : List α
a : α
l' : List α
h : a ∈ l ∧ a ∉ l' ∧ tail (dedup l) = l'
this : head! (dedup l) :: tail (dedup l) = dedup l
hal : a ∉ tail (dedup l) → a = head! (dedup l)
⊢ dedup l = a :: l'

Next tactic:
exact this ▸ h.2.2.symm ▸ cons_eq_cons.2 ⟨(hal (h.2.2.symm ▸ h.2.1)).symm, rfl⟩
@[simp]
theorem dedup_eq_nil (l : List α) : l.dedup = [] ↔ l = [] := by
  

Proof state:
α : Type u
inst✝ : DecidableEq α
l : List α
⊢ dedup l = [] ↔ l = []

Next tactic:
induction' l with a l hl
@[simp]
theorem dedup_eq_nil (l : List α) : l.dedup = [] ↔ l = [] := by
  induction' l with a l hl
  · 

Proof state:
case nil
α : Type u
inst✝ : DecidableEq α
⊢ dedup [] = [] ↔ [] = []

Next tactic:
exact Iff.rfl
@[simp]
theorem dedup_eq_nil (l : List α) : l.dedup = [] ↔ l = [] := by
  induction' l with a l hl
  · exact Iff.rfl
  · 

Proof state:
case cons
α : Type u
inst✝ : DecidableEq α
a : α
l : List α
hl : dedup l = [] ↔ l = []
⊢ dedup (a :: l) = [] ↔ a :: l = []

Next tactic:
by_cases h : a ∈ l
@[simp]
theorem dedup_eq_nil (l : List α) : l.dedup = [] ↔ l = [] := by
  induction' l with a l hl
  · exact Iff.rfl
  · by_cases h : a ∈ l
    · 

Proof state:
case pos
α : Type u
inst✝ : DecidableEq α
a : α
l : List α
hl : dedup l = [] ↔ l = []
h : a ∈ l
⊢ dedup (a :: l) = [] ↔ a :: l = []

Next tactic:
simp only [List.dedup_cons_of_mem h, hl, List.ne_nil_of_mem h]
@[simp]
theorem dedup_eq_nil (l : List α) : l.dedup = [] ↔ l = [] := by
  induction' l with a l hl
  · exact Iff.rfl
  · by_cases h : a ∈ l
    · simp only [List.dedup_cons_of_mem h, hl, List.ne_nil_of_mem h]
    · 

Proof state:
case neg
α : Type u
inst✝ : DecidableEq α
a : α
l : List α
hl : dedup l = [] ↔ l = []
h : a ∉ l
⊢ dedup (a :: l) = [] ↔ a :: l = []

Next tactic:
simp only [List.dedup_cons_of_not_mem h, List.cons_ne_nil]
theorem dedup_append (l₁ l₂ : List α) : dedup (l₁ ++ l₂) = l₁ ∪ dedup l₂ := by
  

Proof state:
α : Type u
inst✝ : DecidableEq α
l₁ l₂ : List α
⊢ dedup (l₁ ++ l₂) = l₁ ∪ dedup l₂

Next tactic:
induction' l₁ with a l₁ IH
theorem dedup_append (l₁ l₂ : List α) : dedup (l₁ ++ l₂) = l₁ ∪ dedup l₂ := by
  induction' l₁ with a l₁ IH; · 

Proof state:
case nil
α : Type u
inst✝ : DecidableEq α
l₂ : List α
⊢ dedup ([] ++ l₂) = [] ∪ dedup l₂

Next tactic:
rfl
theorem dedup_append (l₁ l₂ : List α) : dedup (l₁ ++ l₂) = l₁ ∪ dedup l₂ := by
  induction' l₁ with a l₁ IH; · rfl
  

Proof state:
case cons
α : Type u
inst✝ : DecidableEq α
l₂ : List α
a : α
l₁ : List α
IH : dedup (l₁ ++ l₂) = l₁ ∪ dedup l₂
⊢ dedup (a :: l₁ ++ l₂) = a :: l₁ ∪ dedup l₂

Next tactic:
simp only [cons_union] at *
theorem dedup_append (l₁ l₂ : List α) : dedup (l₁ ++ l₂) = l₁ ∪ dedup l₂ := by
  induction' l₁ with a l₁ IH; · rfl
  simp only [cons_union] at *
  

Proof state:
case cons
α : Type u
inst✝ : DecidableEq α
l₂ : List α
a : α
l₁ : List α
IH : dedup (l₁ ++ l₂) = l₁ ∪ dedup l₂
⊢ dedup (a :: l₁ ++ l₂) = List.insert a (l₁ ∪ dedup l₂)

Next tactic:
rw [← IH, cons_append]
theorem dedup_append (l₁ l₂ : List α) : dedup (l₁ ++ l₂) = l₁ ∪ dedup l₂ := by
  induction' l₁ with a l₁ IH; · rfl
  simp only [cons_union] at *
  rw [← IH, cons_append]
  

Proof state:
case cons
α : Type u
inst✝ : DecidableEq α
l₂ : List α
a : α
l₁ : List α
IH : dedup (l₁ ++ l₂) = l₁ ∪ dedup l₂
⊢ dedup (a :: (l₁ ++ l₂)) = List.insert a (dedup (l₁ ++ l₂))

Next tactic:
by_cases h : a ∈ dedup (l₁ ++ l₂)
theorem dedup_append (l₁ l₂ : List α) : dedup (l₁ ++ l₂) = l₁ ∪ dedup l₂ := by
  induction' l₁ with a l₁ IH; · rfl
  simp only [cons_union] at *
  rw [← IH, cons_append]
  by_cases h : a ∈ dedup (l₁ ++ l₂)
  · 

Proof state:
case pos
α : Type u
inst✝ : DecidableEq α
l₂ : List α
a : α
l₁ : List α
IH : dedup (l₁ ++ l₂) = l₁ ∪ dedup l₂
h : a ∈ dedup (l₁ ++ l₂)
⊢ dedup (a :: (l₁ ++ l₂)) = List.insert a (dedup (l₁ ++ l₂))

Next tactic:
rw [dedup_cons_of_mem' h, insert_of_mem h]
theorem dedup_append (l₁ l₂ : List α) : dedup (l₁ ++ l₂) = l₁ ∪ dedup l₂ := by
  induction' l₁ with a l₁ IH; · rfl
  simp only [cons_union] at *
  rw [← IH, cons_append]
  by_cases h : a ∈ dedup (l₁ ++ l₂)
  · rw [dedup_cons_of_mem' h, insert_of_mem h]
  · 

Proof state:
case neg
α : Type u
inst✝ : DecidableEq α
l₂ : List α
a : α
l₁ : List α
IH : dedup (l₁ ++ l₂) = l₁ ∪ dedup l₂
h : a ∉ dedup (l₁ ++ l₂)
⊢ dedup (a :: (l₁ ++ l₂)) = List.insert a (dedup (l₁ ++ l₂))

Next tactic:
rw [dedup_cons_of_not_mem' h, insert_of_not_mem h]
theorem replicate_dedup {x : α} : ∀ {k}, k ≠ 0 → (replicate k x).dedup = [x]
  | 0, h => (h rfl).elim
  | 1, _ => rfl
  | n + 2, _ => by
    

Proof state:
α : Type u
inst✝ : DecidableEq α
x : α
n : ℕ
x✝ : n + 2 ≠ 0
⊢ dedup (replicate (n + 2) x) = [x]

Next tactic:
rw [replicate_succ, dedup_cons_of_mem (mem_replicate.2 ⟨n.succ_ne_zero, rfl⟩),
      replicate_dedup n.succ_ne_zero]
theorem count_dedup (l : List α) (a : α) : l.dedup.count a = if a ∈ l then 1 else 0 := by
  

Proof state:
α : Type u
inst✝ : DecidableEq α
l : List α
a : α
⊢ count a (dedup l) = if a ∈ l then 1 else 0

Next tactic:
simp_rw [count_eq_of_nodup <| nodup_dedup l, mem_dedup]
/-- Summing the count of `x` over a list filtered by some `p` is just `countP` applied to `p` -/
theorem sum_map_count_dedup_filter_eq_countP (p : α → Bool) (l : List α) :
    ((l.dedup.filter p).map fun x => l.count x).sum = l.countP p := by
  

Proof state:
α : Type u
inst✝ : DecidableEq α
p : α → Bool
l : List α
⊢ sum (map (fun x => count x l) (filter p (dedup l))) = countP p l

Next tactic:
induction' l with a as h
/-- Summing the count of `x` over a list filtered by some `p` is just `countP` applied to `p` -/
theorem sum_map_count_dedup_filter_eq_countP (p : α → Bool) (l : List α) :
    ((l.dedup.filter p).map fun x => l.count x).sum = l.countP p := by
  induction' l with a as h
  · 

Proof state:
case nil
α : Type u
inst✝ : DecidableEq α
p : α → Bool
⊢ sum (map (fun x => count x []) (filter p (dedup []))) = countP p []

Next tactic:
simp
/-- Summing the count of `x` over a list filtered by some `p` is just `countP` applied to `p` -/
theorem sum_map_count_dedup_filter_eq_countP (p : α → Bool) (l : List α) :
    ((l.dedup.filter p).map fun x => l.count x).sum = l.countP p := by
  induction' l with a as h
  · simp
  · 

Proof state:
case cons
α : Type u
inst✝ : DecidableEq α
p : α → Bool
a : α
as : List α
h : sum (map (fun x => count x as) (filter p (dedup as))) = countP p as
⊢ sum (map (fun x => count x (a :: as)) (filter p (dedup (a :: as)))) = countP p (a :: as)

Next tactic:
simp_rw [List.countP_cons, List.count_cons, List.sum_map_add]
/-- Summing the count of `x` over a list filtered by some `p` is just `countP` applied to `p` -/
theorem sum_map_count_dedup_filter_eq_countP (p : α → Bool) (l : List α) :
    ((l.dedup.filter p).map fun x => l.count x).sum = l.countP p := by
  induction' l with a as h
  · simp
  · simp_rw [List.countP_cons, List.count_cons, List.sum_map_add]
    

Proof state:
case cons
α : Type u
inst✝ : DecidableEq α
p : α → Bool
a : α
as : List α
h : sum (map (fun x => count x as) (filter p (dedup as))) = countP p as
⊢ sum (map (fun i => count i as) (filter p (dedup (a :: as)))) +
      sum (map (fun i => if i = a then 1 else 0) (filter p (dedup (a :: as)))) =
    countP p as + if p a = true then 1 else 0

Next tactic:
congr 1
/-- Summing the count of `x` over a list filtered by some `p` is just `countP` applied to `p` -/
theorem sum_map_count_dedup_filter_eq_countP (p : α → Bool) (l : List α) :
    ((l.dedup.filter p).map fun x => l.count x).sum = l.countP p := by
  induction' l with a as h
  · simp
  · simp_rw [List.countP_cons, List.count_cons, List.sum_map_add]
    congr 1
    · 

Proof state:
case cons.e_a
α : Type u
inst✝ : DecidableEq α
p : α → Bool
a : α
as : List α
h : sum (map (fun x => count x as) (filter p (dedup as))) = countP p as
⊢ sum (map (fun i => count i as) (filter p (dedup (a :: as)))) = countP p as

Next tactic:
refine' _root_.trans _ h
/-- Summing the count of `x` over a list filtered by some `p` is just `countP` applied to `p` -/
theorem sum_map_count_dedup_filter_eq_countP (p : α → Bool) (l : List α) :
    ((l.dedup.filter p).map fun x => l.count x).sum = l.countP p := by
  induction' l with a as h
  · simp
  · simp_rw [List.countP_cons, List.count_cons, List.sum_map_add]
    congr 1
    · refine' _root_.trans _ h
      

Proof state:
case cons.e_a
α : Type u
inst✝ : DecidableEq α
p : α → Bool
a : α
as : List α
h : sum (map (fun x => count x as) (filter p (dedup as))) = countP p as
⊢ sum (map (fun i => count i as) (filter p (dedup (a :: as)))) = sum (map (fun x => count x as) (filter p (dedup as)))

Next tactic:
by_cases ha : a ∈ as
/-- Summing the count of `x` over a list filtered by some `p` is just `countP` applied to `p` -/
theorem sum_map_count_dedup_filter_eq_countP (p : α → Bool) (l : List α) :
    ((l.dedup.filter p).map fun x => l.count x).sum = l.countP p := by
  induction' l with a as h
  · simp
  · simp_rw [List.countP_cons, List.count_cons, List.sum_map_add]
    congr 1
    · refine' _root_.trans _ h
      by_cases ha : a ∈ as
      · 

Proof state:
case pos
α : Type u
inst✝ : DecidableEq α
p : α → Bool
a : α
as : List α
h : sum (map (fun x => count x as) (filter p (dedup as))) = countP p as
ha : a ∈ as
⊢ sum (map (fun i => count i as) (filter p (dedup (a :: as)))) = sum (map (fun x => count x as) (filter p (dedup as)))

Next tactic:
simp [dedup_cons_of_mem ha]
/-- Summing the count of `x` over a list filtered by some `p` is just `countP` applied to `p` -/
theorem sum_map_count_dedup_filter_eq_countP (p : α → Bool) (l : List α) :
    ((l.dedup.filter p).map fun x => l.count x).sum = l.countP p := by
  induction' l with a as h
  · simp
  · simp_rw [List.countP_cons, List.count_cons, List.sum_map_add]
    congr 1
    · refine' _root_.trans _ h
      by_cases ha : a ∈ as
      · simp [dedup_cons_of_mem ha]
      · 

Proof state:
case neg
α : Type u
inst✝ : DecidableEq α
p : α → Bool
a : α
as : List α
h : sum (map (fun x => count x as) (filter p (dedup as))) = countP p as
ha : a ∉ as
⊢ sum (map (fun i => count i as) (filter p (dedup (a :: as)))) = sum (map (fun x => count x as) (filter p (dedup as)))

Next tactic:
simp only [dedup_cons_of_not_mem ha, List.filter]
/-- Summing the count of `x` over a list filtered by some `p` is just `countP` applied to `p` -/
theorem sum_map_count_dedup_filter_eq_countP (p : α → Bool) (l : List α) :
    ((l.dedup.filter p).map fun x => l.count x).sum = l.countP p := by
  induction' l with a as h
  · simp
  · simp_rw [List.countP_cons, List.count_cons, List.sum_map_add]
    congr 1
    · refine' _root_.trans _ h
      by_cases ha : a ∈ as
      · simp [dedup_cons_of_mem ha]
      · simp only [dedup_cons_of_not_mem ha, List.filter]
        

Proof state:
case neg
α : Type u
inst✝ : DecidableEq α
p : α → Bool
a : α
as : List α
h : sum (map (fun x => count x as) (filter p (dedup as))) = countP p as
ha : a ∉ as
⊢ sum
      (map (fun i => count i as)
        (match p a with
        | true => a :: filter p (dedup as)
        | false => filter p (dedup as))) =
    sum (map (fun i => count i as) (filter p (dedup as)))

Next tactic:
match p a with
        | true => simp only [List.map_cons, List.sum_cons, List.count_eq_zero.2 ha, zero_add]
        | false => simp only
/-- Summing the count of `x` over a list filtered by some `p` is just `countP` applied to `p` -/
theorem sum_map_count_dedup_filter_eq_countP (p : α → Bool) (l : List α) :
    ((l.dedup.filter p).map fun x => l.count x).sum = l.countP p := by
  induction' l with a as h
  · simp
  · simp_rw [List.countP_cons, List.count_cons, List.sum_map_add]
    congr 1
    · refine' _root_.trans _ h
      by_cases ha : a ∈ as
      · simp [dedup_cons_of_mem ha]
      · simp only [dedup_cons_of_not_mem ha, List.filter]
        match p a with
        | true => 

Proof state:
α : Type u
inst✝ : DecidableEq α
p : α → Bool
a : α
as : List α
h : sum (map (fun x => count x as) (filter p (dedup as))) = countP p as
ha : a ∉ as
⊢ sum
      (map (fun i => count i as)
        (match true with
        | true => a :: filter p (dedup as)
        | false => filter p (dedup as))) =
    sum (map (fun i => count i as) (filter p (dedup as)))

Next tactic:
simp only [List.map_cons, List.sum_cons, List.count_eq_zero.2 ha, zero_add]
/-- Summing the count of `x` over a list filtered by some `p` is just `countP` applied to `p` -/
theorem sum_map_count_dedup_filter_eq_countP (p : α → Bool) (l : List α) :
    ((l.dedup.filter p).map fun x => l.count x).sum = l.countP p := by
  induction' l with a as h
  · simp
  · simp_rw [List.countP_cons, List.count_cons, List.sum_map_add]
    congr 1
    · refine' _root_.trans _ h
      by_cases ha : a ∈ as
      · simp [dedup_cons_of_mem ha]
      · simp only [dedup_cons_of_not_mem ha, List.filter]
        match p a with
        | true => simp only [List.map_cons, List.sum_cons, List.count_eq_zero.2 ha, zero_add]
        | false => 

Proof state:
α : Type u
inst✝ : DecidableEq α
p : α → Bool
a : α
as : List α
h : sum (map (fun x => count x as) (filter p (dedup as))) = countP p as
ha : a ∉ as
⊢ sum
      (map (fun i => count i as)
        (match false with
        | true => a :: filter p (dedup as)
        | false => filter p (dedup as))) =
    sum (map (fun i => count i as) (filter p (dedup as)))

Next tactic:
simp only
/-- Summing the count of `x` over a list filtered by some `p` is just `countP` applied to `p` -/
theorem sum_map_count_dedup_filter_eq_countP (p : α → Bool) (l : List α) :
    ((l.dedup.filter p).map fun x => l.count x).sum = l.countP p := by
  induction' l with a as h
  · simp
  · simp_rw [List.countP_cons, List.count_cons, List.sum_map_add]
    congr 1
    · refine' _root_.trans _ h
      by_cases ha : a ∈ as
      · simp [dedup_cons_of_mem ha]
      · simp only [dedup_cons_of_not_mem ha, List.filter]
        match p a with
        | true => simp only [List.map_cons, List.sum_cons, List.count_eq_zero.2 ha, zero_add]
        | false => simp only
    · 

Proof state:
case cons.e_a
α : Type u
inst✝ : DecidableEq α
p : α → Bool
a : α
as : List α
h : sum (map (fun x => count x as) (filter p (dedup as))) = countP p as
⊢ sum (map (fun i => if i = a then 1 else 0) (filter p (dedup (a :: as)))) = if p a = true then 1 else 0

Next tactic:
by_cases hp : p a
/-- Summing the count of `x` over a list filtered by some `p` is just `countP` applied to `p` -/
theorem sum_map_count_dedup_filter_eq_countP (p : α → Bool) (l : List α) :
    ((l.dedup.filter p).map fun x => l.count x).sum = l.countP p := by
  induction' l with a as h
  · simp
  · simp_rw [List.countP_cons, List.count_cons, List.sum_map_add]
    congr 1
    · refine' _root_.trans _ h
      by_cases ha : a ∈ as
      · simp [dedup_cons_of_mem ha]
      · simp only [dedup_cons_of_not_mem ha, List.filter]
        match p a with
        | true => simp only [List.map_cons, List.sum_cons, List.count_eq_zero.2 ha, zero_add]
        | false => simp only
    · by_cases hp : p a
      · 

Proof state:
case pos
α : Type u
inst✝ : DecidableEq α
p : α → Bool
a : α
as : List α
h : sum (map (fun x => count x as) (filter p (dedup as))) = countP p as
hp : p a = true
⊢ sum (map (fun i => if i = a then 1 else 0) (filter p (dedup (a :: as)))) = if p a = true then 1 else 0

Next tactic:
refine' _root_.trans (sum_map_eq_nsmul_single a _ fun _ h _ => by simp [h]) _
/-- Summing the count of `x` over a list filtered by some `p` is just `countP` applied to `p` -/
theorem sum_map_count_dedup_filter_eq_countP (p : α → Bool) (l : List α) :
    ((l.dedup.filter p).map fun x => l.count x).sum = l.countP p := by
  induction' l with a as h
  · simp
  · simp_rw [List.countP_cons, List.count_cons, List.sum_map_add]
    congr 1
    · refine' _root_.trans _ h
      by_cases ha : a ∈ as
      · simp [dedup_cons_of_mem ha]
      · simp only [dedup_cons_of_not_mem ha, List.filter]
        match p a with
        | true => simp only [List.map_cons, List.sum_cons, List.count_eq_zero.2 ha, zero_add]
        | false => simp only
    · by_cases hp : p a
      · refine' _root_.trans (sum_map_eq_nsmul_single a _ fun _ h _ => by 

Proof state:
α : Type u
inst✝ : DecidableEq α
p : α → Bool
a : α
as : List α
h✝ : sum (map (fun x => count x as) (filter p (dedup as))) = countP p as
hp : p a = true
x✝¹ : α
h : x✝¹ ≠ a
x✝ : x✝¹ ∈ filter p (dedup (a :: as))
⊢ (if x✝¹ = a then 1 else 0) = 0

Next tactic:
simp [h]
/-- Summing the count of `x` over a list filtered by some `p` is just `countP` applied to `p` -/
theorem sum_map_count_dedup_filter_eq_countP (p : α → Bool) (l : List α) :
    ((l.dedup.filter p).map fun x => l.count x).sum = l.countP p := by
  induction' l with a as h
  · simp
  · simp_rw [List.countP_cons, List.count_cons, List.sum_map_add]
    congr 1
    · refine' _root_.trans _ h
      by_cases ha : a ∈ as
      · simp [dedup_cons_of_mem ha]
      · simp only [dedup_cons_of_not_mem ha, List.filter]
        match p a with
        | true => simp only [List.map_cons, List.sum_cons, List.count_eq_zero.2 ha, zero_add]
        | false => simp only
    · by_cases hp : p a
      · refine' _root_.trans (sum_map_eq_nsmul_single a _ fun _ h _ => by simp [h]) _
        

Proof state:
case pos
α : Type u
inst✝ : DecidableEq α
p : α → Bool
a : α
as : List α
h : sum (map (fun x => count x as) (filter p (dedup as))) = countP p as
hp : p a = true
⊢ (count a (filter p (dedup (a :: as))) • if a = a then 1 else 0) = if p a = true then 1 else 0

Next tactic:
simp [hp, count_dedup]
/-- Summing the count of `x` over a list filtered by some `p` is just `countP` applied to `p` -/
theorem sum_map_count_dedup_filter_eq_countP (p : α → Bool) (l : List α) :
    ((l.dedup.filter p).map fun x => l.count x).sum = l.countP p := by
  induction' l with a as h
  · simp
  · simp_rw [List.countP_cons, List.count_cons, List.sum_map_add]
    congr 1
    · refine' _root_.trans _ h
      by_cases ha : a ∈ as
      · simp [dedup_cons_of_mem ha]
      · simp only [dedup_cons_of_not_mem ha, List.filter]
        match p a with
        | true => simp only [List.map_cons, List.sum_cons, List.count_eq_zero.2 ha, zero_add]
        | false => simp only
    · by_cases hp : p a
      · refine' _root_.trans (sum_map_eq_nsmul_single a _ fun _ h _ => by simp [h]) _
        simp [hp, count_dedup]
      · 

Proof state:
case neg
α : Type u
inst✝ : DecidableEq α
p : α → Bool
a : α
as : List α
h : sum (map (fun x => count x as) (filter p (dedup as))) = countP p as
hp : ¬p a = true
⊢ sum (map (fun i => if i = a then 1 else 0) (filter p (dedup (a :: as)))) = if p a = true then 1 else 0

Next tactic:
refine' _root_.trans (List.sum_eq_zero fun n hn => _) (by simp [hp])
/-- Summing the count of `x` over a list filtered by some `p` is just `countP` applied to `p` -/
theorem sum_map_count_dedup_filter_eq_countP (p : α → Bool) (l : List α) :
    ((l.dedup.filter p).map fun x => l.count x).sum = l.countP p := by
  induction' l with a as h
  · simp
  · simp_rw [List.countP_cons, List.count_cons, List.sum_map_add]
    congr 1
    · refine' _root_.trans _ h
      by_cases ha : a ∈ as
      · simp [dedup_cons_of_mem ha]
      · simp only [dedup_cons_of_not_mem ha, List.filter]
        match p a with
        | true => simp only [List.map_cons, List.sum_cons, List.count_eq_zero.2 ha, zero_add]
        | false => simp only
    · by_cases hp : p a
      · refine' _root_.trans (sum_map_eq_nsmul_single a _ fun _ h _ => by simp [h]) _
        simp [hp, count_dedup]
      · refine' _root_.trans (List.sum_eq_zero fun n hn => _) (by 

Proof state:
α : Type u
inst✝ : DecidableEq α
p : α → Bool
a : α
as : List α
h : sum (map (fun x => count x as) (filter p (dedup as))) = countP p as
hp : ¬p a = true
⊢ 0 = if p a = true then 1 else 0

Next tactic:
simp [hp]