(* 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 Lesser 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                                                     *)
(***********************************************************************)
(*    Proof of Huffman algorithm: Frequency.v                          *)
(*                                                                     *)
(*    Frequency list from a message and some properties                *)
(*                                                                     *)
(*    Definitions: frequency_list, number_of_occurrences               *)
(*                                                                     *)
(*                                    Laurent.Thery@inria.fr (2003)    *)
(***********************************************************************)
Section Frequency.
Variable A : Type.
Variable eqA_dec : forall a b : A, {a = b} + {a <> b}.
(* Create a list of a given length with a given element  *)
Fixpoint id_list (a : A) (n : nat) {struct n} : list A :=
match n with
| O => nil
| S n1 => a :: id_list a n1
end.
(* An element in a frequency list *)
Fixpoint add_frequency_list (a : A) (l : list (A * nat)) {struct l} :
list (A * nat) :=
match l with
| nil => (a, 1) :: nil
| (b, n) :: l1 =>
match eqA_dec a b with
| left _ => (a, S n) :: l1
| right _ => (b, n) :: add_frequency_list a l1
end
end.

(* Adding an element gives the same list upto permutation if the frequency list is developed *)
Theorem add_frequency_list_perm :
forall (a : A) l,
permutation (a :: flat_map (fun p => id_list (fst p) (snd p)) l)
(flat_map (fun p => id_list (fst p) (snd p)) (add_frequency_list a l)).