Section count.
Context {X: Type} (p: X -> bool).
Fixpoint count (l: list X): nat :=
match l with
| nil => 0
| h :: t => if p h then S (count t) else count t
end.
Proof with auto.
induction l...
simpl.
destruct (p a)...
intros.
rewrite IHl...
Qed.
Proof with auto. induction l... simpl. intros. rewrite H... Qed.
Proof with auto with arith.
induction l...
simpl.
destruct (p a)...
Qed.
Proof with auto with arith.
induction x...
simpl.
destruct (f a).
simpl.
destruct (p a)...
destruct (p a)...
Qed.
Hint Resolve count_le.
Proof with auto with arith.
induction l; simpl; intros.
elimtype False...
inversion_clear H.
subst.
rewrite H0...
destruct (p a)...
Qed.
End count.
Hint Resolve @count_le.
Proof with auto.
induction l...
simpl.
intros.
inversion_clear H.
apply NoDup_cons...
Qed.
Proof with auto. intros. induction l... simpl. destruct (p a)... simpl... Qed.
Hint Resolve filter_preserves_incl.
Proof with eauto.
induction l; intros; inversion_clear H. subst...
destruct IHl...
Qed.
Instance Permutation_NoDup {X}: Proper (Permutation ==> iff) (@NoDup X).
Proof with firstorder auto.
pose proof NoDup_cons.
intros ? ? E.
induction E; [firstorder | | | firstorder].
split; intro A; inversion_clear A; apply NoDup_cons...
rewrite <- E...
rewrite E...
split; intro A; inversion_clear A; inversion_clear H1...
Qed.
Hint Resolve incl_tran.
Instance filter_perm X: Proper (pointwise_relation _ eq ==> Permutation ==> Permutation) (@filter X).
Proof with auto.
repeat intro.
induction H0; rewrite H in *; simpl...
destruct (y x0)...
destruct (y y0); destruct (y x0)...
eauto.
Qed.
Proof with auto.
induction l...
simpl.
unfold compose.
destruct (p a); simpl...
apply Permutation_cons_app...
Qed.
Proof with auto.
induction l.
split...
intros.
inversion H0.
destruct IHl.
split; simpl; intros.
rewrite H1...
destruct H2.
subst.
destruct (p x)...
discriminate.
apply H0...
destruct (p a)...
discriminate.
Qed.
Proof with auto.
do 3 intro.
destruct (In_map_inv H0).
destruct H1.
subst...
Qed.
Proof with auto.
unfold compose.
induction l...
intros.
simpl.
rewrite IHl.
destruct (p a); simpl...
Qed.
Proof with auto.
induction l...
simpl.
cset (H a).
destruct (q a)...
simpl.
rewrite H0...
Qed.
Proof with auto. induction l... simpl. rewrite IHl... Qed.
Hint Resolve Permutation_map.
Proof with auto.
induction l...
intros.
simpl.
apply in_or_app.
inversion_clear H0.
subst...
right...
Qed.
Proof with auto.
induction l.
intros.
elimtype False...
simpl.
intros.
destruct (in_app_or _ _ _ H).
exists a.
split...
destruct (IHl H0).
destruct H1.
exists x0...
Qed.
Definition eq_count X (d: forall (x y: X), { x = y } + { x <> y }) (x: X): list X -> nat :=
count (fun y => unsum_bool (d x y)).
Proof with auto.
induction l...
simpl.
intros.
destruct (d x a).
elimtype False.
apply H.
left...
simpl.
apply IHl.
intro.
apply H.
right...
Qed.
Proof with auto.
induction l...
simpl.
intros.
inversion_clear H...
destruct (d x a); simpl...
subst.
rewrite eq_count_0...
Qed.
Proof with auto. (* todo: prove in terms of the vec equivalent *)
induction a in b |- *; intros.
destruct b.
apply perm_nil.
discriminate.
assert (In a b).
apply H1.
left...
destruct (In_inv_perm a b H2).
apply perm_trans with (a :: x)...
apply perm_skip.
apply IHa.
cset (Permutation_length H3).
rewrite <- H in H4.
inversion_clear H4...
inversion_clear H0...
cut (incl a0 (a :: x)).
intros.
intro.
intros.
cset (H4 a1 H5).
inversion_clear H6...
subst.
inversion_clear H0.
elimtype False...
apply incl_tran with b...
intro.
intros.
apply H1.
right...
apply Permutation_incl.
apply Permutation_sym...
Qed.
Proof with auto.
induction l; simpl...
intros.
inversion_clear H0.
apply NoDup_cons...
intro.
destruct (In_map_inv H0).
destruct H3.
apply (H x a)...
intro.
subst...
Qed. (* todo: replace NoDup_map *)

Lemma NoDup_map A B (f: A -> B) l:
(forall x y, In x l -> In y l -> f x = f y -> x = y) -> NoDup l -> NoDup (map f l).