(* This program is free software; you can redistribute it and/or      *)
(* modify it under the terms of the GNU Lesser General Public License *)
(* as published by the Free Software Foundation; either version 2.1   *)
(* of the License, or (at your option) any later version.             *)
(*                                                                    *)
(* This program is distributed in the hope that it will be useful,    *)
(* but WITHOUT ANY WARRANTY; without even the implied warranty of     *)
(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the      *)
(* GNU General Public License for more details.                       *)
(*                                                                    *)
(* You should have received a copy of the GNU Lesser General Public   *)
(* License along with this program; if not, write to the Free         *)
(* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *)
(* 02110-1301 USA                                                     *)
Set Asymmetric Patterns.
(* Contribution to the Coq Library   V6.3 (July 1999)                    *)
(****************************************************************************)
(*                 The Calculus of Inductive Constructions                  *)
(*                                                                          *)
(*                                Projet Coq                                *)
(*                                                                          *)
(*                     INRIA                        ENS-CNRS                *)
(*              Rocquencourt                        Lyon                    *)
(*                                                                          *)
(*                                Coq V5.10                                 *)
(*                              Nov 25th 1994                               *)
(*                                                                          *)
(****************************************************************************)
(*                                Sorting.v                                 *)
(****************************************************************************)
(* These sorting examples have first been compiled by P. Manoury using the  *)
(* ProPre tool to build recursive functions by cases                        *)
(* == Quelques fonctions utiles == *)
(* Inductive Set bool := true : bool | false : bool. *)
Definition si (X : Set) (b : bool) (x y : X) :=
match b with
| true => x
| _ => y
end.
(* Inductive Set nat : O:nat | S:nat->nat. *)
Fixpoint egal_nat (n : nat) : nat -> bool :=
fun m : nat =>
match n, m with
| O, O => true
| S n, S m => egal_nat n m
| _, _ => false
end.
Fixpoint inf_egal (n : nat) : nat -> bool :=
fun m : nat =>
match n, m with
| O, m => true
| S n, O => false
| S n, S m => inf_egal n m
end.
Inductive list (X : Set) : Set :=
| Nil : list X
| Cons : X -> list X -> list X.
Definition cdr (X : Set) (l : list X) :=
match l with
| Nil => Nil X
| Cons _ xs => xs
end.
Fixpoint length (X : Set) (l : list X) {struct l} : nat :=
match l with
| Nil => 0
| Cons _ xs => S (length X xs)
end.
(* append x y = yx *)
Fixpoint append (X : Set) (ys xs : list X) {struct xs} :
list X :=
match xs with
| Nil => ys
| Cons x xs' => Cons X x (append X ys xs')
end.
(* == Proprietes d'un tri == *)
Fixpoint sorted (l : list nat) : Prop :=
match l with
| Cons n (Cons m x as l) => inf_egal n m = true /\ sorted l
| _ => True
end.
Fixpoint nocc (n : nat) (l : list nat) {struct l} : nat :=
match l with
| Nil => 0
| Cons m x => si nat (egal_nat n m) (S (nocc n x)) (nocc n x)
end.
(* == Un lemme utile == *)
(* -- Sur les booleens *)
(* -- Sur le predicat "sorted" *)
(* == Tri par insertion *)
Fixpoint ins (n : nat) (l : list nat) {struct l} :
list nat :=
match l with
| Nil => Cons nat n (Nil nat)
| Cons m x =>
si (list nat) (inf_egal n m) (Cons nat n (Cons nat m x))
(Cons nat m (ins n x))
end.
Fixpoint tri_ins (l : list nat) : list nat :=
match l with
| Nil => Nil nat
| Cons n x => ins n (tri_ins x)
end.
(* -- Preuve de correction *)
(* -- 1 : Le resultat de "tri_ins" est une liste sorted *)
(* -- 2 : Le resultat de "tri_ins" est une permutation de son entree *)
(*   ie : meme nombre d'occurrences de chaque element                *)
(* == Tri bubble *)
Fixpoint bubble_aux (x : list nat) : nat -> list nat :=
fun n : nat =>
match x with
| Nil => Cons nat n (Nil nat)
| Cons n0 l =>
si (list nat) (inf_egal n n0) (Cons nat n (bubble_aux l n0))
(Cons nat n0 (bubble_aux l n))
end.
Definition bubble (x : list nat) : list nat :=
match x with
| Nil => Nil nat
| Cons n l => bubble_aux l n
end.
Fixpoint bubble_sort0 (n : nat) : list nat -> list nat :=
fun x : list nat =>
match n with
| O => x
| S n0 => bubble_sort0 n0 (bubble x)
end.
Definition bubble_sort (x : list nat) : list nat :=
bubble_sort0 (length nat x) x.
(* == Tri fusion *)
Fixpoint fusion (x : list nat) : list nat -> list nat :=
fun y : list nat =>
match x with
| Nil => y
| Cons n l0 =>
(fix fusion_r (y : list nat) : list nat :=
match y with
| Nil => x
| Cons n0 l2 =>
si (list nat) (inf_egal n n0)
(Cons nat n (fusion l0 (Cons nat n0 l2)))
(Cons nat n0 (fusion_r l2))
end) y
end.

Lemma fusion_eq2 :
forall (n : nat) (ns : list nat),
fusion (Cons nat n ns) (Nil nat) = Cons nat n ns.