Fixpoint trunc (v : list A) : nat -> list A :=
  fun n : nat =>
  match v return (list A) with
  | nil => nil
  | b :: w =>
      match n return (list A) with
      | O => nil
      | S p => b :: trunc w p
      end
  end.Definition strip (v : list A) (n : nat) :=
  rev A (trunc (rev A v) (length v - n)).(* Selection d'une sous liste commencant a la position start, de
   longueur lengt *)
Definition sublist (v : list A) (start lengt : nat) :=
  trunc (strip v start) lengt.(* Selection de la liste contenant le i-eme element d'une liste *)
Definition elemlist (v : list A) (i : nat) := trunc (strip v i) 1.

(* Specifications: *)
Lemma length_trunc : forall (v : list A) (i : nat), (*****************) i <= length v -> length (trunc v i) = i.
Lemma trunc_inv : forall (v : list A) (i : nat) (b : A), (**************) b :: trunc v i = trunc (b :: v) (S i).
Lemma trunc_all : forall v : list A, trunc v (length v) = v.
Lemma trunc_max : forall (v : list A) (i : nat), (**************) length v <= i -> trunc v i = v.
Lemma trunc_O : forall v : list A, trunc v 0 = nil.
Lemma le_length_trunc : forall (v : list A) (i : nat), length (trunc v i) <= i.
Lemma trunc_app : forall (v1 v2 : list A) (i : nat), (**************) trunc (v1 ++ v2) i = trunc v1 i ++ trunc v2 (i - length v1).
Lemma app_v_trunc : forall (v1 v2 : list A) (i : nat), (****************) v1 ++ trunc v2 i = trunc (v1 ++ v2) (length v1 + i).
Lemma trunc_eq : forall (v1 v2 : list A) (i : nat), v1 = v2 -> trunc v1 i = trunc v2 i.
Lemma trunc_sym : forall (v : list A) (i j : nat), (**************) trunc (trunc v i) j = trunc (trunc v j) i.
Lemma trunc_trunc1 : forall (v : list A) (i : nat), (*****************) trunc (trunc v i) i = trunc v i.
Lemma trunc_trunc2 : forall (v : list A) (i j : nat), (*****************) i <= j -> trunc (trunc v i) j = trunc v i.
Lemma trunc_trunc3 : forall (v : list A) (i j : nat), (*****************) j <= i -> trunc (trunc v i) j = trunc v j.
Lemma trunc_plus_petit : forall (v1 v2 : list A) (i j : nat), (*********************) j <= i -> trunc v1 i = v2 -> trunc v1 j = trunc v2 j.
Lemma strip_nil : forall i : nat, strip nil i = nil.
Lemma strip_cons_S : forall (v : list A) (i : nat) (b : A), (*****************) strip (b :: v) (S i) = strip v i.
Lemma length_strip : forall (v : list A) (i : nat), (*****************) i <= length v -> length (strip v i) = length v - i.
Lemma le_length_strip : forall (v : list A) (i : nat), (********************) length (strip v i) <= length v - i.
Lemma strip_inv : forall (v : list A) (i : nat), (***************) rev A (trunc (rev A v) (length v - i)) = strip v i.
Lemma strip_all : forall v : list A, strip v (length v) = nil.
Lemma strip_max : forall (v : list A) (i : nat), (**************) length v <= i -> strip v i = nil.
Lemma strip_O : forall v : list A, strip v 0 = v.
Lemma strip_app : forall (v1 v2 : list A) (i : nat), (**************) strip (v1 ++ v2) i = strip v1 i ++ strip v2 (i - length v1).
Lemma strip_strip_S : forall (v : list A) (i j : nat), (******************) strip (strip v (S i)) j = strip (strip v i) (S j).
Lemma strip_sym : forall (v : list A) (i j : nat), (**************) strip (strip v i) j = strip (strip v j) i.
Lemma strip_eq : forall (v1 v2 : list A) (i : nat), v1 = v2 -> strip v1 i = strip v2 i.
Lemma strip_strip : forall (v : list A) (i j : nat), (****************) strip (strip v i) j = strip v (i + j).
Lemma app_trunc_strip : forall (v : list A) (i : nat), (********************) trunc v i ++ strip v i = v.
Lemma strip_trunc_i : forall (v : list A) (i : nat), strip (trunc v i) i = nil.
Lemma strip_trunc : forall (v : list A) (i j : nat), (****************) strip (trunc v i) j = trunc (strip v j) (i - j).
Lemma trunc_strip : forall (v : list A) (i j : nat), (****************) trunc (strip v i) j = strip (trunc v (i + j)) i.
Lemma elemlist_is_sublist : forall (v : list A) (i : nat), (************************) elemlist v i = sublist v i 1.
Lemma elemlist_cons_S : forall (v : list A) (i : nat) (b : A), (********************) elemlist (b :: v) (S i) = elemlist v i.
Lemma elemlist_cons_O : forall (v : list A) (b : A), (********************) elemlist (b :: v) 0 = b :: nil.
Lemma elemlist_inv : forall (l : list A) (i : nat), (*****************) trunc (strip l i) 1 = elemlist l i.
Lemma app_trunc_elemlist : forall (v : list A) (i : nat), (***********************) S i <= length v -> trunc v i ++ elemlist v i = trunc v (S i).
Lemma length_elemlist : forall (l : list A) (i : nat), (********************) i < length l -> length (elemlist l i) = 1.