Section RndListElem.
Variable A : Set.
Hypothesis eqd : EqDec A.
Local Open Scope list_scope.
Definition rndListElem(ls : list A) : Comp (option A) :=
match (length ls) with
| O => ret None
| S _ =>
i <-$ [0 .. (length ls));
ret (nth_option ls i)
end.
intuition.
unfold rndListElem.
case_eq (length ls); intuition; wftac.
Qed.
End RndListElem.
Local Open Scope list_scope.
induction ls; intuition; simpl in *.
discriminate.
destruct i.
inversion H; clear H; subst.
intuition.
right.
eapply IHls.
eauto.
Qed.
Fixpoint firstIndexOf(A : Set)(eqd : eq_dec A)(ls : list A)(a : A)(def : nat) :=
match ls with
| nil => def
| a' :: ls' =>
if (eqd a a') then O else (S (firstIndexOf eqd ls' a def))
end.
induction ls; intuition; simpl in *;
intuition.
subst.
destruct (eqd a0 a0); subst.
omega.
intuition.
destruct (eqd a0 a); subst.
omega.
eapply lt_n_S.
eauto.
Qed.
induction ls; intuition; simpl in *.
intuition.
intuition.
subst.
destruct (eqd a0 a0); subst; intuition.
destruct (eqd a0 a); subst; intuition.
Qed.
intuition.
unfold rndListElem.
case_eq (length ls); intuition.
exfalso.
destruct ls; simpl in *; intuition.
eapply getSupport_In_Seq.
eapply in_getSupport_RndNat.
rewrite <- H0.
eapply firstIndexOf_in_lt; eauto.
simpl.
left.
eapply nth_firstIndexOf; trivial.
unfold rndListElem in *.
repeat simp_in_support.
discriminate.
eapply nth_option_In; eauto.
Grab Existential Variables.
apply O.
unfold eq_dec.
eapply (EqDec_dec eqd).
Qed.
induction ls; intuition; simpl in *.
discriminate.
inversion H0; clear H0; subst.
destruct n.
inversion H; clear H; subst.
destruct (eqd a0 a0); subst; intuition.
destruct (eqd a0 a); subst; intuition.
exfalso.
eapply H3.
eapply nth_option_In.
eauto.
Qed.
induction ls; intuition; simpl in *.
omega.
destruct n.
econstructor; eauto.
destruct (IHls n).
omega.
econstructor; eauto.
Qed.
intuition.
unfold rndListElem in *.
case_eq (length ls); intuition.
destruct ls; simpl in *; trivial; discriminate.
rewrite H0 in H.
repeat simp_in_support.
apply RndNat_support_lt in H1.
edestruct (nth_option_some ls); eauto.
rewrite H0.
eauto.
congruence.
subst.
simpl.
intuition.
Qed.
intuition.
destruct a1.
destruct a2.
rewrite <- rndListElem_support in *.
unfold rndListElem.
case_eq (length ls); intuition.
destruct ls; simpl in *. intuition. omega.
eapply comp_spec_impl_eq.
eapply comp_spec_seq.
apply (Some a).
apply (Some a).
eapply eq_impl_comp_spec.
eapply well_formed_RndNat.
omega.
eapply well_formed_RndNat.
omega.
eapply RndNat_uniform.
3:{
intros.
simpl in H5.
eapply comp_spec_ret.
assert (a1 = (firstIndexOf (EqDec_dec _) ls a 0) <->
b = (firstIndexOf (EqDec_dec _) ls a0 0)).
eapply H5.
clear H5.
intuition; subst.
rewrite H5.
eapply nth_firstIndexOf; trivial.
symmetry.
eapply nth_firstIndexOf_if; intuition.
rewrite H7.
eapply nth_firstIndexOf; trivial.
symmetry.
eapply nth_firstIndexOf_if; intuition.
}
rewrite <- H2.
apply firstIndexOf_in_lt; trivial.
rewrite <- H2.
apply firstIndexOf_in_lt; trivial.
apply rndListElem_support in H0.
apply rndListElem_support_None in H1.
subst.
simpl in *.
intuition.
destruct a2.
apply rndListElem_support in H1.
apply rndListElem_support_None in H0.
subst.
simpl in *.
intuition.
intuition.
Qed.
induction ls; intuition; simpl in *.
discriminate.
destruct i.
inversion H0; clear H0; subst.
intuition.
eapply IHls; eauto.
Qed.

Theorem nth_firstIndexOf_None :
forall (A : Set)(eqd : eq_dec A)(ls : list A),
NoDup ls ->
forall (a a' : A) i,
In a ls ->
i <> firstIndexOf eqd ls a O ->
nth_option ls i = Some a' ->
a <> a'.