Built with
doc-gen4 , running Lean4.
Bubbles (
) indicate interactive fragments: hover for details, tap to reveal contents.
Use
Ctrl+↑ Ctrl+↓ to navigate,
Ctrl+🖱️ to focus.
On Mac, use
Cmd instead of
Ctrl .
/-
Copyright (c) 2014 Parikshit Khanna. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Parikshit Khanna, Jeremy Avigad, Leonardo de Moura, Floris van Doorn, Mario Carneiro
! This file was ported from Lean 3 source module data.list.count
! leanprover-community/mathlib commit 47adfab39a11a072db552f47594bf8ed2cf8a722
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
import Mathlib.Data.List.BigOperators.Basic
/-!
# Counting in lists
This file proves basic properties of `List.countp` and `List.count`, which count the number of
elements of a list satisfying a predicate and equal to a given element respectively. Their
definitions can be found in `Std.Data.List.Basic`.
-/
open Nat
variable { l : List α }
namespace List
section Countp
variable ( p q : α → Bool )
@[ simp ]
theorem countp_nil : countp p [] = 0 := rfl : ∀ {α : Sort ?u.77} {a : α }, a = a rfl
#align list.countp_nil List.countp_nil
-- Porting note: added to aid in the following proof.
protected theorem countp_go_eq_add ( l : unknown metavariable '?_uniq.122'
l ) : countp.go p l n = n + countp.go p l 0 := by
induction' l with head tail ih generalizing n
· rfl
· unfold countp.go
rw [ ih (n := n + 1 ), ih (n := n ), ih (n := 1 ) ]
by_cases h : p head
· simp [ h , add_assoc ]
· simp [ h ]
@[ simp ]
theorem countp_cons_of_pos { a : α } ( l ) ( pa : p a ) : countp p ( a :: l ) = countp p l + 1 := by
have : countp.go p ( a :: l ) 0 = countp.go p l 1
· change ( bif _ then _ else _ ) = countp.go _ _ _
rw [ pa ]
rfl
unfold countp
rw [ this , add_comm , List.countp_go_eq_add ]
#align list.countp_cons_of_pos List.countp_cons_of_pos
@[ simp ]
theorem countp_cons_of_neg { a : α } ( l ) ( pa : ¬ p a ) : countp p ( a :: l ) = countp p l := by
change ( bif _ then _ else _ ) = countp.go _ _ _
rw [ Bool.of_not_eq_true pa ]
rfl
#align list.countp_cons_of_neg List.countp_cons_of_neg
theorem countp_cons ( a : α ) ( l ) : countp p ( a :: l ) = countp p l + if p a then 1 else 0 := by
by_cases h : p a <;> simp [ h ]
#align list.countp_cons List.countp_cons
theorem length_eq_countp_add_countp ( l ) : length l = countp p l + countp ( fun a => ¬ p a ) l := by
induction' l with x h ih
· rfl
by_cases h : p x
· rw [ countp_cons_of_pos _ _ h , countp_cons_of_neg _ _ _ , length , ih ]
· ac_rfl
· simp only [ h ]
· rw [ countp_cons_of_pos ( fun a => ¬ p a ) _ _ , countp_cons_of_neg _ _ h , length , ih ]
· ac_rfl
· simp only [ h ]
#align list.length_eq_countp_add_countp List.length_eq_countp_add_countp
theorem countp_eq_length_filter ( l ) : countp p l = length ( filter p l ) := by
induction' l with x l ih
· rfl
by_cases h : p x
· rw [ countp_cons_of_pos p l h , ih , filter_cons_of_pos l h , length ]
· rw [ countp_cons_of_neg p l h , ih , filter_cons_of_neg l h ]
#align list.countp_eq_length_filter List.countp_eq_length_filter
theorem countp_le_length : countp p l ≤ l . length := by
simpa only [ countp_eq_length_filter ] using length_filter_le _ _
#align list.countp_le_length List.countp_le_length
@[ simp ]
theorem countp_append ( l₁ l₂ ) : countp p ( l₁ ++ l₂ ) = countp p l₁ + countp p l₂ := by
simp only [ countp_eq_length_filter , filter_append , length_append ]
#align list.countp_append List.countp_append
theorem countp_join : ∀ l : List ( List α ), countp p l . join = ( l . map ( countp p )). sum
| [] => rfl : ∀ {α : Sort ?u.5111} {a : α }, a = a rfl
| a :: l => by rw [ join , countp_append , map_cons : ∀ {α : Type ?u.5545} {β : Type ?u.5546} (f : α → β ) (a : α ) (l : List α ), map f (a :: l ) = f a :: map f l map_cons, sum_cons , countp_join l ]
#align list.countp_join List.countp_join
theorem countp_pos : 0 < countp p l ↔ ∃ a ∈ l , p a := by
simp only [ countp_eq_length_filter , length_pos_iff_exists_mem , mem_filter , exists_prop : ∀ {b a : Prop }, (∃ _h , b ) ↔ a ∧ b exists_prop]
#align list.countp_pos List.countp_pos
@[ simp ]
theorem countp_eq_zero : countp p l = 0 ↔ ∀ a ∈ l , ¬ p a := by
rw [ ← not_iff_not : ∀ {a b : Prop }, (¬ a ↔ ¬ b ) ↔ (a ↔ b ) not_iff_not, ← Ne.def : ∀ {α : Sort ?u.6334} (a b : α ), (a ≠ b ) = ¬ a = b Ne.def, ← pos_iff_ne_zero , countp_pos ]
simp
#align list.countp_eq_zero List.countp_eq_zero
@[ simp ]
theorem countp_eq_length : countp p l = l . length ↔ ∀ a ∈ l , p a := by
rw [ countp_eq_length_filter , filter_length_eq_length ]
#align list.countp_eq_length List.countp_eq_length
theorem length_filter_lt_length_iff_exists ( l ) :
length ( filter p l ) < length l ↔ ∃ x ∈ l , ¬ p x := by
simpa [ length_eq_countp_add_countp p l , countp_eq_length_filter ] using
countp_pos ( fun x => ¬ p x ) (l := l )
#align list.length_filter_lt_length_iff_exists List.length_filter_lt_length_iff_exists
theorem Sublist.countp_le ( s : l₁ <+ l₂ ) : countp p l₁ ≤ countp p l₂ := by
simpa only [ countp_eq_length_filter ] using length_le_of_sublist ( s . filter p )
#align list.sublist.countp_le List.Sublist.countp_le
@[ simp ]
theorem countp_filter ( l : List α ) : countp p ( filter q l ) = countp ( fun a => p a ∧ q a ) l := by
simp only [ countp_eq_length_filter , filter_filter ]
#align list.countp_filter List.countp_filter
@[ simp ]
theorem countp_true : ( l . countp fun _ => true ) = l . length := by simp
#align list.countp_true List.countp_true
@[ simp ]
theorem countp_false : ( l . countp fun _ => false ) = 0 := by simp
#align list.countp_false List.countp_false
@[ simp ]
theorem countp_map ( p : β → Bool ) ( f : α → β ) :
∀ l , countp p ( map f l ) = countp ( p ∘ f ) l
| [] => rfl : ∀ {α : Sort ?u.21974} {a : α }, a = a rfl
| a :: l => by rw [ map_cons : ∀ {α : Type ?u.22125} {β : Type ?u.22126} (f : α → β ) (a : α ) (l : List α ), map f (a :: l ) = f a :: map f l map_cons, countp_cons , countp_cons , countp_map p f l ] ; rfl
#align list.countp_map List.countp_map
variable { p q }
theorem countp_mono_left ( h : ∀ x ∈ l , p x → q x ) : countp p l ≤ countp q l := by
induction' l with a l ihl
· rfl
rw [ forall_mem_cons : ∀ {α : Type ?u.22569} {p : α → Prop } {a : α } {l : List α }, (∀ (x : α ), x ∈ a :: l → p x ) ↔ p a ∧ ∀ (x : α ), x ∈ l → p x forall_mem_cons] at h
cases' h with ha hl
rw [ countp_cons , countp_cons ]
refine' _root_.add_le_add ( ihl hl ) _ cons.intro (if p a = true then 1 else 0 ) ≤ if q a = true then 1 else 0
split_ifs cons.intro.inl.inl cons.intro.inl.inr cons.intro.inr.inl cons.intro.inr.inr