Section list_util.
Variables A B C : Type.
Hypothesis A_eq_dec : forall x y : A, {x = y} + {x <> y}.
Proof using.
intros l x H.
symmetry in H.
induction l;
now inversion H.
Qed.
Proof using.
induction xs; intros.
- intuition auto.
- simpl in *.
concludes.
break_or_hyp; break_if; subst; try congruence; intuition (auto with datatypes).
Qed.
Proof using.
induction xs; intros.
- auto.
- simpl in *. break_if; simpl in *; intuition auto.
Qed.
Proof using.
induction xs; intros; simpl; break_if; congruence.
Qed.
Proof using.
intros. induction xs; simpl in *; try break_if; intuition congruence.
Qed.
Proof using.
induction xs; intros.
- auto.
- simpl. rewrite IHxs. break_if; auto.
Qed.
Proof using.
induction xs; intros.
- auto.
- simpl. rewrite H by intuition (auto with datatypes).
rewrite IHxs by intuition (auto with datatypes). auto.
Qed.
Proof using.
induction xs; intros.
- constructor.
- simpl. invc_NoDup. constructor.
+ intro. do_in_map.
assert (x = a) by intuition (auto with datatypes).
congruence.
+ intuition (auto with datatypes).
Qed.
Proof using.
induction l; intros.
- auto.
- simpl. invc_NoDup. constructor.
+ intro. do_in_app. intuition eauto with datatypes.
+ intuition eauto with datatypes.
Qed.
Proof using.
induction xs; simpl; intros; destruct xs'.
- auto.
- subst. simpl in *. find_inversion.
invc H. exfalso. rewrite map_app in *. simpl in *.
repeat find_rewrite. intuition (auto with datatypes).
- subst. simpl in *. find_inversion.
invc H. exfalso. rewrite map_app in *. simpl in *.
repeat find_rewrite. intuition (auto with datatypes).
- subst. simpl in *. find_injection. intros. subst.
f_equal. eapply IHxs; eauto. solve_by_inversion.
Qed.
Proof using.
induction l; intros.
- auto.
- invc_NoDup. simpl. break_if; auto.
constructor; auto.
intro. apply filter_In in H. intuition auto.
Qed.
Proof using.
intros. induction l; simpl in *.
- constructor.
- invc_NoDup. concludes.
break_if; simpl in *; auto.
constructor; auto.
intro. do_in_map.
find_apply_lem_hyp filter_In. intuition auto.
match goal with | H : _ -> False |- False => apply H end.
apply in_map_iff. eauto.
Qed.
Proof using.
induction xs; intros.
- auto.
- simpl. now rewrite H, IHxs by intuition (auto with datatypes).
Qed.
Proof using.
induction xs; simpl; auto using f_equal2.
Qed.
Proof using.
induction xs; intros.
- auto.
- simpl.
break_if.
+ subst. repeat find_rewrite. eauto with datatypes.
+ simpl. rewrite H by auto with datatypes.
break_if; eauto using f_equal2 with datatypes.
Qed.
Proof using.
induction l; intros.
- intuition auto.
- right. simpl in *.
apply app_eq_nil in H.
intros; break_and; break_or_hyp; concludes; break_or_hyp; auto.
contradiction.
Qed.
Proof using.
intros l l' Hnd Hp.
induction Hp; auto; invc_NoDup; constructor;
eauto using Permutation_in, Permutation_sym;
simpl in *; intuition (auto with struct_util).
Qed.
Proof using.
intuition eauto using NoDup_Permutation_NoDup, Permutation_sym, Permutation_cons_append.
Qed.
Proof using.
induction xs; intros; simpl in *.
- intuition auto.
- invc_NoDup. intuition auto; subst; auto; exfalso.
+ repeat find_rewrite. auto using in_map.
+ repeat find_reverse_rewrite. auto using in_map.
Qed.
Proof using.
induction xs; intros.
- auto.
- simpl in *. intuition auto.
break_if; subst; simpl; intuition auto.
Qed.
Proof using.
induction xs; intros; simpl in *; intuition; invc_NoDup;
break_if; subst; intuition (simpl; try congruence).
now rewrite remove_length_not_in.
Qed.
Proof using.
induction xs; intros.
- destruct ys; simpl in *; congruence.
- invc_NoDup. concludes.
assert (In a ys) by eauto with datatypes.
find_apply_lem_hyp in_split.
break_exists_name l1.
break_exists_name l2.
subst.
specialize (IHxs (l1 ++ l2)).
conclude_using ltac:(eauto using NoDup_remove_1).
forward IHxs.
intros x' Hx'.
assert (In x' (l1 ++ a :: l2)) by eauto with datatypes.
do_in_app. simpl in *. intuition auto with datatypes. subst. congruence.
concludes.
forward IHxs.
rewrite app_length in *. simpl in *. lia.
concludes.
do_in_app. simpl in *. intuition auto with datatypes.
Qed.
Proof using.
induction xs; intros.
- auto with struct_util.
- invc_NoDup. simpl. break_if; eauto 6 using in_remove with struct_util.
Qed.
Proof using.
induction xs; intros.
- auto.
- invc_NoDup. simpl. break_if.
+ rewrite Nat.sub_0_r.
subst.
rewrite remove_length_not_in; auto.
+ simpl. concludes. lia.
Qed.
Proof using.
induction xs; intros.
- auto.
- simpl in *.
specialize (IHxs eq_dec).
break_if; subst; simpl; lia.
Qed.
Proof using.
induction xs; intros; simpl in *; [contradiction|]; break_or_hyp.
- subst.
break_if; try congruence.
pose proof remove_length_le x xs eq_dec.
lia.
- specialize (IHxs ltac:(eauto) ltac:(eauto)).
break_if; subst; simpl; lia.
Qed.
Proof using A_eq_dec.
induction xs; intros.
- simpl. lia.
- specialize (IHxs (remove A_eq_dec a ys)).
invc_NoDup.
concludes.
forward IHxs.
intros.
apply remove_preserve;
[congruence|intuition (auto with datatypes)].
concludes.
pose proof remove_length_lt a ys A_eq_dec.
assert (In a ys) by auto with datatypes.
concludes.
simpl. lia.
Qed.
Proof using.
intros.
destruct xs.
- solve_by_inversion.
- destruct xs; solve_by_inversion.
Qed.
Proof using.
intros. subst. auto with datatypes.
Qed.
Hint Resolve app_cons_in : struct_util.
Proof using.
intros. subst.
do_in_app; intuition auto with datatypes.
Qed.
Hint Resolve app_cons_in_rest : struct_util.
Proof using.
intros.
subst_max.
do_in_app.
break_or_hyp.
- auto with datatypes.
- find_apply_lem_hyp in_inv.
break_or_hyp; auto using in_or_app || congruence.
Qed.
Hint Resolve in_rest_app_cons : struct_util.
Proof using.
induction l; intros; simpl in *; auto.
repeat (break_if; subst; simpl in *; try congruence).
Qed.
Proof using.
intros. subst.
eapply filter_In; eauto.
Qed.
Proof using.
induction l1; intros; simpl in *; break_if; simpl in *; invc_NoDup.
- destruct l1'; simpl in *.
+ solve_by_inversion.
+ find_inversion. exfalso. eauto using In_filter_In with datatypes.
- exfalso. eauto using In_filter_In with datatypes.
- destruct l1'; simpl in *; break_and; find_inversion.
+ exfalso. eauto with datatypes.
+ find_apply_hyp_hyp. intuition auto using f_equal2.
- eauto.
Qed.

Lemma map_inverses :
forall (la : list A) (lb : list B)  (f : A -> B) g,
(forall a, g (f a) = a) ->
(forall b, f (g b) = b) ->
lb = map f la ->
la = map g lb.