<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="es">
	<id>https://www.glc.us.es/~jalonso/SLC2018/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jorcatote</id>
	<title>Seminario de Lógica Computacional (2018) - Contribuciones del usuario [es]</title>
	<link rel="self" type="application/atom+xml" href="https://www.glc.us.es/~jalonso/SLC2018/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jorcatote"/>
	<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/SLC2018/index.php/Especial:Contribuciones/Jorcatote"/>
	<updated>2026-07-18T23:44:03Z</updated>
	<subtitle>Contribuciones del usuario</subtitle>
	<generator>MediaWiki 1.31.0</generator>
	<entry>
		<id>https://www.glc.us.es/~jalonso/SLC2018/index.php?title=Tema_3&amp;diff=64</id>
		<title>Tema 3</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/SLC2018/index.php?title=Tema_3&amp;diff=64"/>
		<updated>2018-03-21T22:05:32Z</updated>

		<summary type="html">&lt;p&gt;Jorcatote: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* Datos estructurados en Coq *)&lt;br /&gt;
&lt;br /&gt;
Require Export Induction.&lt;br /&gt;
&lt;br /&gt;
Module NatList. &lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § Pares de númenros &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. El tipo de los números naturales es natprod y su&lt;br /&gt;
   constructor es pair.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive natprod : Type :=&lt;br /&gt;
  pair : nat -&amp;gt; nat -&amp;gt; natprod.&lt;br /&gt;
&lt;br /&gt;
Check (pair 3 5).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      fst : natprod -&amp;gt; nat&lt;br /&gt;
   tal que (fst p) es la primera componente de p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition fst (p : natprod) : nat := &lt;br /&gt;
  match p with&lt;br /&gt;
  | pair x y =&amp;gt; x&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Evaluar la expresión &lt;br /&gt;
      fst (pair 3 5)&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Eval compute in (fst (pair 3 5)).&lt;br /&gt;
(* ===&amp;gt; 3 *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      snd : natprod -&amp;gt; nat&lt;br /&gt;
   tal que (snd p) es la segunda componente de p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition snd (p : natprod) : nat := &lt;br /&gt;
  match p with&lt;br /&gt;
  | pair x y =&amp;gt; y&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la notación (x,y) como una abreviaura de (pair x y).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;( x , y )&amp;quot; := (pair x y).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Evaluar la expresión &lt;br /&gt;
      fst (3,5)&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Eval compute in (fst (3,5)).&lt;br /&gt;
(* ===&amp;gt; 3 *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Redefinir la función fst usando la abreviatura de pares.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition fst&amp;#039; (p : natprod) : nat := &lt;br /&gt;
  match p with&lt;br /&gt;
  | (x,y) =&amp;gt; x&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Redefinir la función snd usando la abreviatura de pares.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition snd&amp;#039; (p : natprod) : nat := &lt;br /&gt;
  match p with&lt;br /&gt;
  | (x,y) =&amp;gt; y&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      swap_pair : natprod -&amp;gt; natprod&lt;br /&gt;
   tal que (swap_pair p) es el par obtenido intercambiando las&lt;br /&gt;
   componentes de p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition swap_pair (p : natprod) : natprod := &lt;br /&gt;
  match p with&lt;br /&gt;
  | (x,y) =&amp;gt; (y,x)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que para todos los naturales&lt;br /&gt;
      (n,m) = (fst (n,m), snd (n,m)).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem surjective_pairing&amp;#039; : forall (n m : nat),&lt;br /&gt;
  (n,m) = (fst (n,m), snd (n,m)).&lt;br /&gt;
Proof.&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que para todo par de naturales&lt;br /&gt;
      p = (fst p, snd p).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem surjective_pairing_stuck : forall (p : natprod),&lt;br /&gt;
  p = (fst p, snd p).&lt;br /&gt;
Proof.&lt;br /&gt;
  simpl. (* No reduce nada. *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
Theorem surjective_pairing : forall (p : natprod),&lt;br /&gt;
  p = (fst p, snd p).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros p.  destruct p as [n m].  simpl.  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1. Demostrar que para todo par de naturales p,&lt;br /&gt;
      (snd p, fst p) = swap_pair p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem snd_fst_is_swap : forall (p : natprod),&lt;br /&gt;
  (snd p, fst p) = swap_pair p.&lt;br /&gt;
Admitted.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2. Demostrar que para todo par de naturales p,&lt;br /&gt;
      fst (swap_pair p) = snd p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem fst_swap_is_snd : forall (p : natprod),&lt;br /&gt;
  fst (swap_pair p) = snd p.&lt;br /&gt;
Admitted.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § Listas de números &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. natlist es la lista de los números naturales y sus&lt;br /&gt;
   constructores son &lt;br /&gt;
   + nil (la lista vacía) y &lt;br /&gt;
   + cons (tal que (cons x ys) es la lista obtenida añadiéndole x a ys. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive natlist : Type :=&lt;br /&gt;
  | nil  : natlist&lt;br /&gt;
  | cons : nat -&amp;gt; natlist -&amp;gt; natlist.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la constante &lt;br /&gt;
      mylist : natlist&lt;br /&gt;
   que es la lista cuyos elementos son 1, 2 y 3.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition mylist := cons 1 (cons 2 (cons 3 nil)).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la notación (x :: ys) como una abreviatura de &lt;br /&gt;
   (cons x ys).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;x :: l&amp;quot; := (cons x l)&lt;br /&gt;
                     (at level 60, right associativity).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la notación de las listas finitas escribiendo sus&lt;br /&gt;
   elementos entre corchetes y separados por puntos y comas.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;[ ]&amp;quot; := nil.&lt;br /&gt;
Notation &amp;quot;[ x ; .. ; y ]&amp;quot; := (cons x .. (cons y nil) ..).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Distintas representaciones de mylist.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition mylist1 := 1 :: (2 :: (3 :: nil)).&lt;br /&gt;
Definition mylist2 := 1 :: 2 :: 3 :: nil.&lt;br /&gt;
Definition mylist3 := [1;2;3].&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ Repeat  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      repeat : nat -&amp;gt; nat -&amp;gt; natlist&lt;br /&gt;
   tal que (repeat n k) es la lista formada por k veces el número n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint repeat (n count : nat) : natlist :=&lt;br /&gt;
  match count with&lt;br /&gt;
  | O        =&amp;gt; nil&lt;br /&gt;
  | S count&amp;#039; =&amp;gt; n :: (repeat n count&amp;#039;)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ Length  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      length : natlist -&amp;gt; nat&lt;br /&gt;
   tal que (length xs) es el número de elementos de xs.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint length (l:natlist) : nat :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil    =&amp;gt; O&lt;br /&gt;
  | h :: t =&amp;gt; S (length t)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ Append  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      append : natlist -&amp;gt; natlist -&amp;gt; natlist&lt;br /&gt;
   tal que (append xs ys) es la concatenación de xs e ys.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
Fixpoint app (l1 l2 : natlist) : natlist :=&lt;br /&gt;
  match l1 with&lt;br /&gt;
  | nil    =&amp;gt; l2&lt;br /&gt;
  | h :: t =&amp;gt; h :: (app t l2)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la notación (xs ++ ys) como una abreviaura de &lt;br /&gt;
   (append xs ys).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;x ++ y&amp;quot; := (app x y)&lt;br /&gt;
                     (right associativity, at level 60).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que&lt;br /&gt;
      [1;2;3] ++ [4;5] = [1;2;3;4;5].&lt;br /&gt;
      nil     ++ [4;5] = [4;5].&lt;br /&gt;
      [1;2;3] ++ nil   = [1;2;3].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example test_app1: [1;2;3] ++ [4;5] = [1;2;3;4;5].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
Example test_app2: nil ++ [4;5] = [4;5].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
Example test_app3: [1;2;3] ++ nil = [1;2;3].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ Head y tail  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      hd : nat -&amp;gt; natlist -&amp;gt; natlist&lt;br /&gt;
   tal que (hd d xs) es el primer elemento de xs o d, si xs es la lista&lt;br /&gt;
   vacía. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition hd (default:nat) (l:natlist) : nat :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil    =&amp;gt; default&lt;br /&gt;
  | h :: t =&amp;gt; h&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      tl : natlist -&amp;gt; natlist&lt;br /&gt;
   tal que (tl xs) es el resto de xs.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition tl (l:natlist) : natlist :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil    =&amp;gt; nil&lt;br /&gt;
  | h :: t =&amp;gt; t&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que &lt;br /&gt;
       hd 0 [1;2;3] = 1.&lt;br /&gt;
       hd 0 []      = 0.&lt;br /&gt;
       tl [1;2;3]   = [2;3].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example test_hd1: hd 0 [1;2;3] = 1.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
Example test_hd2: hd 0 [] = 0.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
Example test_tl: tl [1;2;3] = [2;3].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3. Definir la función&lt;br /&gt;
      nonzeros : natlist -&amp;gt; natlist&lt;br /&gt;
   tal que (nonzeros xs) es la lista de los elementos de xs distintos de&lt;br /&gt;
   cero. Por ejemplo,&lt;br /&gt;
      nonzeros [0;1;0;2;3;0;0] = [1;2;3].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint nonzeros (l:natlist) : natlist :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil =&amp;gt; nil&lt;br /&gt;
  | a::bs =&amp;gt; match a with&lt;br /&gt;
            | 0 =&amp;gt; nonzeros bs &lt;br /&gt;
            | _ =&amp;gt;  a:: nonzeros bs end&lt;br /&gt;
 end.&lt;br /&gt;
Example test_nonzeros:&lt;br /&gt;
  nonzeros [0;1;0;2;3;0;0] = [1;2;3].&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4. Definir la función&lt;br /&gt;
      oddmembers : natlist -&amp;gt; natlist&lt;br /&gt;
   tal que (oddmembers xs) es la lista de los elementos impares de&lt;br /&gt;
   xs. Por ejemplo,&lt;br /&gt;
      oddmembers [0;1;0;2;3;0;0] = [1;3].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint oddmembers (l:natlist) : natlist :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil =&amp;gt; nil&lt;br /&gt;
  | t::xs =&amp;gt; if oddb t then t :: oddmembers xs else oddmembers xs&lt;br /&gt;
  end.&lt;br /&gt;
 &lt;br /&gt;
Example test_oddmembers:&lt;br /&gt;
  oddmembers [0;1;0;2;3;0;0] = [1;3].&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5. Definir la función&lt;br /&gt;
      countoddmembers : natlist -&amp;gt; nat&lt;br /&gt;
   tal que (countoddmembers xs) es el número de elementos impares de&lt;br /&gt;
   xs. Por ejemplo,&lt;br /&gt;
      countoddmembers [1;0;3;1;4;5] = 4.&lt;br /&gt;
      countoddmembers [0;2;4]       = 0.&lt;br /&gt;
      countoddmembers nil           = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition countoddmembers (l:natlist) : nat :=&lt;br /&gt;
 length (oddmembers l). &lt;br /&gt;
&lt;br /&gt;
Example test_countoddmembers1:&lt;br /&gt;
  countoddmembers [1;0;3;1;4;5] = 4.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_countoddmembers2:&lt;br /&gt;
  countoddmembers [0;2;4] = 0.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_countoddmembers3:&lt;br /&gt;
  countoddmembers nil = 0.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 6. Definir la función&lt;br /&gt;
      alternate : natlist -&amp;gt; natlist -&amp;gt; natlist&lt;br /&gt;
   tal que (alternate xs ys) es la lista obtenida intercalando los&lt;br /&gt;
   elementos de xs e ys. Por ejemplo,&lt;br /&gt;
      alternate [1;2;3] [4;5;6] = [1;4;2;5;3;6].&lt;br /&gt;
      alternate [1] [4;5;6]     = [1;4;5;6].&lt;br /&gt;
      alternate [1;2;3] [4]     = [1;4;2;3].&lt;br /&gt;
      alternate [] [20;30]      = [20;30].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint alternate (l1 l2 : natlist) : natlist :=&lt;br /&gt;
  match l1 with&lt;br /&gt;
  | nil =&amp;gt; l2&lt;br /&gt;
  | t::xs =&amp;gt; match l2 with&lt;br /&gt;
            | nil =&amp;gt; t::xs&lt;br /&gt;
            | p::ys =&amp;gt; t::p::alternate xs ys end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_alternate1:&lt;br /&gt;
  alternate [1;2;3] [4;5;6] = [1;4;2;5;3;6].&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_alternate2:&lt;br /&gt;
  alternate [1] [4;5;6] = [1;4;5;6].&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_alternate3:&lt;br /&gt;
  alternate [1;2;3] [4] = [1;4;2;3].&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_alternate4:&lt;br /&gt;
  alternate [] [20;30] = [20;30].&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(* ----------------------------------------------------------------- *)&lt;br /&gt;
(** *** Multiconjuntos como listas *)&lt;br /&gt;
&lt;br /&gt;
(** Un multiconjunto es como un conjunto donde los elementos pueden repetirse más de una vez. Podemos implementarlos como listas. *)&lt;br /&gt;
&lt;br /&gt;
Definition bag := natlist.&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 7. Definir la función count v s, que te cuenta las veces que aparece el elemento v en la lista s: &lt;br /&gt;
count 1 [1;2;3;1;4;1] = 3.&lt;br /&gt;
count 6 [1;2;3;1;4;1] = 0.&lt;br /&gt;
*)&lt;br /&gt;
&lt;br /&gt;
Fixpoint count (v:nat) (s:bag) : nat :=&lt;br /&gt;
  match s with&lt;br /&gt;
  | nil =&amp;gt; 0&lt;br /&gt;
  | t::xs =&amp;gt; if beq_nat t v then 1 + count v xs else count v xs&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_count1:              count 1 [1;2;3;1;4;1] = 3.&lt;br /&gt;
reflexivity. Qed.&lt;br /&gt;
Example test_count2:              count 6 [1;2;3;1;4;1] = 0.&lt;br /&gt;
reflexivity. Qed. &lt;br /&gt;
&lt;br /&gt;
(** La suma de multiconjuntos es parecida a la unión de conjuntos. Ejercicio 8. Definir la suma de multiconjuntos:&lt;br /&gt;
  count 1 (sum [1;2;3] [1;4;1]) = 3. *)&lt;br /&gt;
&lt;br /&gt;
Definition sum : bag -&amp;gt; bag -&amp;gt; bag := app.&lt;br /&gt;
&lt;br /&gt;
Example test_sum1:              count 1 (sum [1;2;3] [1;4;1]) = 3.&lt;br /&gt;
 reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
  (* Ejercicio 9. Definir la función add v s que añade el elemento v al multiconjunto s:&lt;br /&gt;
 count 1 (add 1 [1;4;1]) = 3.&lt;br /&gt;
 count 5 (add 1 [1;4;1]) = 0.&lt;br /&gt;
*)&lt;br /&gt;
&lt;br /&gt;
Definition add (v:nat) (s:bag) : bag :=&lt;br /&gt;
  v :: s .&lt;br /&gt;
&lt;br /&gt;
Example test_add1:                count 1 (add 1 [1;4;1]) = 3.&lt;br /&gt;
 reflexivity. Qed.&lt;br /&gt;
Example test_add2:                count 5 (add 1 [1;4;1]) = 0.&lt;br /&gt;
 reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
  (* Ejercicio 10. Definir la función member v s que se verfica si v es un elemento de la lista s: &lt;br /&gt;
member 1 [1;4;1] = true.&lt;br /&gt;
member 2 [1;4;1] = false.*)&lt;br /&gt;
&lt;br /&gt;
Definition member (v:nat) (s:bag) : bool := &lt;br /&gt;
 if beq_nat 0 (count v s) then false else true.&lt;br /&gt;
&lt;br /&gt;
Example test_member1:             member 1 [1;4;1] = true.&lt;br /&gt;
 reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_member2:             member 2 [1;4;1] = false.&lt;br /&gt;
reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Definition member2 (v:nat) (s:bag) : bool :=&lt;br /&gt;
  negb (beq_nat O (count v s)).&lt;br /&gt;
&lt;br /&gt;
(** [] *)&lt;br /&gt;
(** Definir las siguientes funciones:*)&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 11. Definir la función remove_one v s que borra una vez el elemento v de la lista s:&lt;br /&gt;
count 5 (remove_one 5 [2;1;5;4;1]) = 0.&lt;br /&gt;
count 4 (remove_one 5 [2;1;4;5;1;4]) = 2.&lt;br /&gt;
count 5 (remove_one 5 [2;1;5;4;5;1;4]) = 1.*)&lt;br /&gt;
&lt;br /&gt;
Fixpoint remove_one (v:nat) (s:bag) : bag :=&lt;br /&gt;
  match s with&lt;br /&gt;
  | nil =&amp;gt; nil&lt;br /&gt;
  | t :: xs =&amp;gt; if beq_nat t v then xs else t:: remove_one v xs&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_remove_one1:&lt;br /&gt;
  count 5 (remove_one 5 [2;1;5;4;1]) = 0.&lt;br /&gt;
 reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_remove_one2:&lt;br /&gt;
  count 5 (remove_one 5 [2;1;4;1]) = 0.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_remove_one3:&lt;br /&gt;
  count 4 (remove_one 5 [2;1;4;5;1;4]) = 2.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_remove_one4:&lt;br /&gt;
  count 5 (remove_one 5 [2;1;5;4;5;1;4]) = 1.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 12. Definir la función remove_all v s que borra todas las copias del elemento v en el multiconjunto s:&lt;br /&gt;
count 5 (remove_all 5 [2;1;5;4;1]) = 0.&lt;br /&gt;
count 5 (remove_all 5 [2;1;4;1]) = 0.&lt;br /&gt;
count 4 (remove_all 5 [2;1;4;5;1;4]) = 2.&lt;br /&gt;
count 5 (remove_all 5 [2;1;5;4;5;1;4;5;1;4]) = 0. *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint remove_all (v:nat) (s:bag) : bag :=&lt;br /&gt;
   match s with&lt;br /&gt;
  | nil =&amp;gt; nil&lt;br /&gt;
  | t :: xs =&amp;gt; if beq_nat t v then remove_all v xs else t:: remove_all v xs&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_remove_all1:  count 5 (remove_all 5 [2;1;5;4;1]) = 0.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
Example test_remove_all2:  count 5 (remove_all 5 [2;1;4;1]) = 0.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
Example test_remove_all3:  count 4 (remove_all 5 [2;1;4;5;1;4]) = 2.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
Example test_remove_all4:  count 5 (remove_all 5 [2;1;5;4;5;1;4;5;1;4]) = 0.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 13. Definir la función subset s1 s2 que se verifica si s1 es un submulticonjunto de s2 *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint subset (s1:bag) (s2:bag) : bool :=&lt;br /&gt;
  match s1 with&lt;br /&gt;
  | nil =&amp;gt; true&lt;br /&gt;
  | x::xs =&amp;gt; member x s2 &amp;amp;&amp;amp; subset xs (remove_one x s2)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_subset1:              subset [1;2] [2;1;4;1] = true.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
Example test_subset2:              subset [1;2;2] [2;1;4;1] = false.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 14 (avanzado). Escribir un teorema sobre multiconjuntos con las funciones count y add y probarlo.*)&lt;br /&gt;
&lt;br /&gt;
Theorem bag_theorem : forall s1 s2 : bag, forall n : nat,&lt;br /&gt;
  count n s1 + count n s2 = count n (app s1 s2).                 &lt;br /&gt;
Proof.&lt;br /&gt;
  intros s1 s2 n. induction s1 as [|s s&amp;#039;].&lt;br /&gt;
 - simpl. reflexivity.&lt;br /&gt;
 - simpl. destruct (beq_nat s n).&lt;br /&gt;
    + simpl. rewrite IHs&amp;#039;. reflexivity.&lt;br /&gt;
    + rewrite IHs&amp;#039;. reflexivity.&lt;br /&gt;
 Qed.&lt;br /&gt;
&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(* ################################################################# *)&lt;br /&gt;
(** * Listas *)&lt;br /&gt;
&lt;br /&gt;
(** El siguiente teorema se deduce directamente de la definición de app. *)&lt;br /&gt;
&lt;br /&gt;
Theorem nil_app : forall l:natlist,&lt;br /&gt;
  [] ++ l = l.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(** ... ya que esta es decreciente en la primera componenete. *)&lt;br /&gt;
&lt;br /&gt;
(** Sobre listas podemos usar las técnicas de demostración ya aprendidas sobre naturales: *)&lt;br /&gt;
&lt;br /&gt;
Theorem tl_length_pred : forall l:natlist,&lt;br /&gt;
  pred (length l) = length (tl l).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros l. destruct l as [| n l&amp;#039;].&lt;br /&gt;
  - (* l = nil *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  - (* l = cons n l&amp;#039; *)&lt;br /&gt;
    reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ================================================================= *)&lt;br /&gt;
(** ** Inducción en Listas *)&lt;br /&gt;
&lt;br /&gt;
(** La inducción sobre la longitud de las listas es análoga a la de los numeros naturales. *)&lt;br /&gt;
&lt;br /&gt;
Theorem app_assoc : forall l1 l2 l3 : natlist,&lt;br /&gt;
  (l1 ++ l2) ++ l3 = l1 ++ (l2 ++ l3).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros l1 l2 l3. induction l1 as [| n l1&amp;#039; IHl1&amp;#039;].&lt;br /&gt;
  - (* l1 = nil *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  - (* l1 = cons n l1&amp;#039; *)&lt;br /&gt;
    simpl. rewrite -&amp;gt; IHl1&amp;#039;. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* Comentar los nombres dados en la hipotesis de inducción. *)&lt;br /&gt;
&lt;br /&gt;
(* ----------------------------------------------------------------- *)&lt;br /&gt;
(** *** Reverse *)&lt;br /&gt;
&lt;br /&gt;
(** Definición de la función rev l que devuelve una lista formada por los elementos en orden l en orden contrario. *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint rev (l:natlist) : natlist :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil    =&amp;gt; nil&lt;br /&gt;
  | h :: t =&amp;gt; rev t ++ [h]&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_rev1:            rev [1;2;3] = [3;2;1].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
Example test_rev2:            rev nil = nil.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ----------------------------------------------------------------- *)&lt;br /&gt;
(** *** Propiedades de [rev] *)&lt;br /&gt;
&lt;br /&gt;
(** Definición de algunos teoremas más: *)&lt;br /&gt;
&lt;br /&gt;
Theorem rev_length_firsttry : forall l : natlist,&lt;br /&gt;
  length (rev l) = length l.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros l. induction l as [| n l&amp;#039; IHl&amp;#039;].&lt;br /&gt;
  - (* l = [] *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  - (* l = n :: l&amp;#039; *)&lt;br /&gt;
    (* Probamos simplificando *)&lt;br /&gt;
    simpl.&lt;br /&gt;
    rewrite &amp;lt;- IHl&amp;#039;.&lt;br /&gt;
    (* Nos encontramos sin más que hacer, así que buscamos un lema que nos ayude. *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
Theorem app_length : forall l1 l2 : natlist,&lt;br /&gt;
  length (l1 ++ l2) = (length l1) + (length l2).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros l1 l2. induction l1 as [| n l1&amp;#039; IHl1&amp;#039;].&lt;br /&gt;
  - (* l1 = nil *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  - (* l1 = cons *)&lt;br /&gt;
    simpl. rewrite -&amp;gt; IHl1&amp;#039;. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(** Ahora completamos la prueba original. *)&lt;br /&gt;
&lt;br /&gt;
Theorem rev_length : forall l : natlist,&lt;br /&gt;
  length (rev l) = length l.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros l. induction l as [| n l&amp;#039; IHl&amp;#039;].&lt;br /&gt;
  - (* l = nil *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  - (* l = cons *)&lt;br /&gt;
    simpl. rewrite -&amp;gt; app_length, plus_comm.&lt;br /&gt;
    simpl. rewrite -&amp;gt; IHl&amp;#039;. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ================================================================= *)&lt;br /&gt;
(** ** Lista de ejercicios, Parte 1 *)&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 15. Demostrar que la lista vacía es el elemento neutro a derechas de la suma de listas: *)&lt;br /&gt;
&lt;br /&gt;
Theorem app_nil_r : forall l : natlist,&lt;br /&gt;
  l ++ [] = l.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros l. induction l as [| x xs HI].&lt;br /&gt;
  - reflexivity.&lt;br /&gt;
  - simpl. rewrite HI. reflexivity.&lt;br /&gt;
    Qed.&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 16. Demostrar la propiedad distributiva del reverso de una lista respecto a la suma: *)&lt;br /&gt;
&lt;br /&gt;
Theorem rev_app_distr: forall l1 l2 : natlist,&lt;br /&gt;
  rev (l1 ++ l2) = rev l2 ++ rev l1.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros l1 l2. induction l1 as [|x xs HI].&lt;br /&gt;
  - simpl. rewrite app_nil_r. reflexivity.&lt;br /&gt;
  - simpl. rewrite HI, app_assoc. reflexivity.&lt;br /&gt;
  Qed.&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 17. Demostrar que el inverso de la función rev es ella misma (que es involutiva): *)&lt;br /&gt;
&lt;br /&gt;
Theorem rev_involutive : forall l : natlist,&lt;br /&gt;
  rev (rev l) = l.&lt;br /&gt;
Proof.&lt;br /&gt;
  induction l as [|x xs HI].&lt;br /&gt;
  - reflexivity.&lt;br /&gt;
  - simpl. rewrite rev_app_distr. rewrite HI. reflexivity.&lt;br /&gt;
  Qed.&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 18. Demostrar la asociatividad de la suma de 4 listas: *)&lt;br /&gt;
&lt;br /&gt;
Theorem app_assoc4 : forall l1 l2 l3 l4 : natlist,&lt;br /&gt;
  l1 ++ (l2 ++ (l3 ++ l4)) = ((l1 ++ l2) ++ l3) ++ l4.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros l1 l2 l3 l4. rewrite app_assoc. rewrite app_assoc. reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 19. Demostrar que al sumar dos listas no aparecen ni desaparecen ceros: *)&lt;br /&gt;
&lt;br /&gt;
Lemma nonzeros_app : forall l1 l2 : natlist,&lt;br /&gt;
  nonzeros (l1 ++ l2) = (nonzeros l1) ++ (nonzeros l2).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros l1 l2. induction l1 as [|x xs HI].&lt;br /&gt;
  - reflexivity.&lt;br /&gt;
  - simpl. destruct x.&lt;br /&gt;
    + rewrite HI. reflexivity.&lt;br /&gt;
    + simpl. rewrite HI. reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 20. Definir beq_natlist como la igualdad de listas:&lt;br /&gt;
beq_natlist nil nil = true.&lt;br /&gt;
beq_natlist [1;2;3] [1;2;3] = true.&lt;br /&gt;
beq_natlist [1;2;3] [1;2;4] = false. *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint beq_natlist (l1 l2 : natlist) : bool:=&lt;br /&gt;
  match l1, l2 with&lt;br /&gt;
  | nil, nil =&amp;gt; true&lt;br /&gt;
  | x::xs, y::ys =&amp;gt; beq_nat x y &amp;amp;&amp;amp; beq_natlist xs ys&lt;br /&gt;
  | _, _ =&amp;gt; false&lt;br /&gt;
 end.&lt;br /&gt;
&lt;br /&gt;
Example test_beq_natlist1 :&lt;br /&gt;
  (beq_natlist nil nil = true).&lt;br /&gt;
 reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_beq_natlist2 :&lt;br /&gt;
  beq_natlist [1;2;3] [1;2;3] = true.&lt;br /&gt;
 reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_beq_natlist3 :&lt;br /&gt;
  beq_natlist [1;2;3] [1;2;4] = false.&lt;br /&gt;
 reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 21. Demostrar que la igualdad de listas cumple la propiedad reflexiva *)&lt;br /&gt;
&lt;br /&gt;
Theorem beq_natlist_refl : forall l:natlist,&lt;br /&gt;
  true = beq_natlist l l.&lt;br /&gt;
Proof.&lt;br /&gt;
  induction l as [|n xs HI].&lt;br /&gt;
  - reflexivity.&lt;br /&gt;
  - simpl. rewrite &amp;lt;- HI. replace (beq_nat n n) with true.  reflexivity.&lt;br /&gt;
    + rewrite &amp;lt;- beq_nat_refl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(* ================================================================= *)&lt;br /&gt;
(** ** Lista de ejercicios, Parte 2 *)&lt;br /&gt;
&lt;br /&gt;
(** Teoremas sobre multiconjuntos: *)&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 22. Demuestra el siguiente teorema sobre que al incluir un elemento en un multiconjunto, ese elemento aparece al menos una vez en él. *)&lt;br /&gt;
&lt;br /&gt;
Theorem count_member_nonzero : forall (s : bag),&lt;br /&gt;
  leb 1 (count 1 (1 :: s)) = true.&lt;br /&gt;
Proof.&lt;br /&gt;
 intro s.  simpl. reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(** Lema sobre los numeros naturales que nos ayudará más adelante: *)&lt;br /&gt;
&lt;br /&gt;
Theorem ble_n_Sn : forall n,&lt;br /&gt;
  leb n (S n) = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n. induction n as [| n&amp;#039; IHn&amp;#039;].&lt;br /&gt;
  - (* 0 *)&lt;br /&gt;
    simpl.  reflexivity.&lt;br /&gt;
  - (* S n&amp;#039; *)&lt;br /&gt;
    simpl.  rewrite IHn&amp;#039;.  reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 23. Demostrar el teorema siguiente que afirma que al borrar elementos de un multiconjuntos esto desciende el numero de ese tipo que contiene. *)&lt;br /&gt;
&lt;br /&gt;
Theorem remove_decreases_count: forall (s : bag),&lt;br /&gt;
  leb (count 0 (remove_one 0 s)) (count 0 s) = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  induction s as [|x xs HI].&lt;br /&gt;
  - reflexivity.&lt;br /&gt;
  - simpl. destruct x.&lt;br /&gt;
    + rewrite ble_n_Sn. reflexivity.&lt;br /&gt;
    + simpl. rewrite HI. reflexivity.&lt;br /&gt;
  Qed.    &lt;br /&gt;
&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 24. Escribir un teorema con las funciones count y sum de los multiconjuntos *)&lt;br /&gt;
&lt;br /&gt;
Theorem bag_count_sum: forall n : nat, forall b1 b2 : bag,&lt;br /&gt;
      count n b1 + count n b2 = count n (sum b1 b2).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n b1 b2. induction b1 as [|b bs HI].&lt;br /&gt;
  - reflexivity.&lt;br /&gt;
  - simpl. destruct (beq_nat b n).&lt;br /&gt;
    + simpl. rewrite HI. reflexivity.&lt;br /&gt;
    + rewrite HI. reflexivity.&lt;br /&gt;
 Qed.&lt;br /&gt;
&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 25. Probar que la función rev es inyectiva *)&lt;br /&gt;
&lt;br /&gt;
    forall (l1 l2 : natlist), rev l1 = rev l2 -&amp;gt; l1 = l2.&lt;br /&gt;
&lt;br /&gt;
(There is a hard way and an easy way to do this.) *)&lt;br /&gt;
&lt;br /&gt;
(* FILL IN HERE *)&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(* ################################################################# *)&lt;br /&gt;
&lt;br /&gt;
(** Cuando construimos una función que devuelva el elemento n-ésimo de la lista, necesitamos un valor que devuelva por defecto cuando sea demasiado corta la lista. *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint nth_bad (l:natlist) (n:nat) : nat :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil =&amp;gt; 42  (* arbitrary! *)&lt;br /&gt;
  | a :: l&amp;#039; =&amp;gt; match beq_nat n O with&lt;br /&gt;
               | true =&amp;gt; a&lt;br /&gt;
               | false =&amp;gt; nth_bad l&amp;#039; (pred n)&lt;br /&gt;
               end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(** Una solución para evitarlo es la siguiente: *)&lt;br /&gt;
&lt;br /&gt;
Inductive natoption : Type :=&lt;br /&gt;
  | Some : nat -&amp;gt; natoption&lt;br /&gt;
  | None : natoption.&lt;br /&gt;
&lt;br /&gt;
Fixpoint nth_error (l:natlist) (n:nat) : natoption :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil =&amp;gt; None&lt;br /&gt;
  | a :: l&amp;#039; =&amp;gt; match beq_nat n O with&lt;br /&gt;
               | true =&amp;gt; Some a&lt;br /&gt;
               | false =&amp;gt; nth_error l&amp;#039; (pred n)&lt;br /&gt;
               end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_nth_error1 : nth_error [4;5;6;7] 0 = Some 4.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
Example test_nth_error2 : nth_error [4;5;6;7] 3 = Some 7.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
Example test_nth_error3 : nth_error [4;5;6;7] 9 = None.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(** Introduciendo condicionales nos queda: *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint nth_error&amp;#039; (l:natlist) (n:nat) : natoption :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil =&amp;gt; None&lt;br /&gt;
  | a :: l&amp;#039; =&amp;gt; if beq_nat n O then Some a&lt;br /&gt;
               else nth_error&amp;#039; l&amp;#039; (pred n)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(** Los condicionales funcionan sobre todo tipo inductivo con dos constructores en Coq, sin booleanos. *)&lt;br /&gt;
&lt;br /&gt;
(** Para extraer un valor de natoption: *)&lt;br /&gt;
&lt;br /&gt;
Definition option_elim (d : nat) (o : natoption) : nat :=&lt;br /&gt;
  match o with&lt;br /&gt;
  | Some n&amp;#039; =&amp;gt; n&amp;#039;&lt;br /&gt;
  | None =&amp;gt; d&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 26. Con la misma idea definir una versión sin valor predeterminado de hd (head). *)&lt;br /&gt;
&lt;br /&gt;
Definition hd_error (l : natlist) : natoption :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil =&amp;gt; None&lt;br /&gt;
  | x::xs =&amp;gt; Some x&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_hd_error1 : hd_error [] = None.&lt;br /&gt;
 reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_hd_error2 : hd_error [1] = Some 1.&lt;br /&gt;
 reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_hd_error3 : hd_error [5;6] = Some 5.&lt;br /&gt;
reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 27. Demostrar el teorema siguiente: *)&lt;br /&gt;
&lt;br /&gt;
Theorem option_elim_hd : forall (l:natlist) (default:nat),&lt;br /&gt;
    hd default l = option_elim default (hd_error l).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros l default. destruct l as [|x xs].&lt;br /&gt;
  - reflexivity.&lt;br /&gt;
  - simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
End NatList.&lt;br /&gt;
&lt;br /&gt;
(* ################################################################# *)&lt;br /&gt;
(** * Diccionarios *)&lt;br /&gt;
&lt;br /&gt;
(** Definimos el tipo id para usar como claves: *)&lt;br /&gt;
&lt;br /&gt;
Inductive id : Type :=&lt;br /&gt;
  | Id : nat -&amp;gt; id.&lt;br /&gt;
&lt;br /&gt;
(** Y su igualdad: *)&lt;br /&gt;
&lt;br /&gt;
Definition beq_id (x1 x2 : id) :=&lt;br /&gt;
  match x1, x2 with&lt;br /&gt;
  | Id n1, Id n2 =&amp;gt; beq_nat n1 n2&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 28. Demostrar que beq_id es reflexiva: *)&lt;br /&gt;
&lt;br /&gt;
Theorem beq_id_refl : forall x, true = beq_id x x.&lt;br /&gt;
Proof. intro x. destruct x. simpl. rewrite &amp;lt;- beq_nat_refl. reflexivity.&lt;br /&gt;
       Qed.&lt;br /&gt;
&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(** Definimos de la siguiente forma los diccionarios: *)&lt;br /&gt;
&lt;br /&gt;
Module PartialMap.&lt;br /&gt;
Export NatList.&lt;br /&gt;
  &lt;br /&gt;
Inductive partial_map : Type :=&lt;br /&gt;
  | empty  : partial_map&lt;br /&gt;
  | record : id -&amp;gt; nat -&amp;gt; partial_map -&amp;gt; partial_map.&lt;br /&gt;
&lt;br /&gt;
(** La siguiente función update d x value ingresa el nuevo valor value con la clave x en el diccionario d o si ya existe la clave le cambia el valor: *)&lt;br /&gt;
&lt;br /&gt;
Definition update (d : partial_map)&lt;br /&gt;
                  (x : id) (value : nat)&lt;br /&gt;
                  : partial_map :=&lt;br /&gt;
  record x value d.&lt;br /&gt;
&lt;br /&gt;
(** Y definimos también la función find: *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint find (x : id) (d : partial_map) : natoption :=&lt;br /&gt;
  match d with&lt;br /&gt;
  | empty         =&amp;gt; None&lt;br /&gt;
  | record y v d&amp;#039; =&amp;gt; if beq_id x y&lt;br /&gt;
                     then Some v&lt;br /&gt;
                     else find x d&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 29: update_eq *)&lt;br /&gt;
&lt;br /&gt;
Theorem update_eq :&lt;br /&gt;
  forall (d : partial_map) (x : id) (v: nat),&lt;br /&gt;
    find x (update d x v) = Some v.&lt;br /&gt;
Proof. intros d x v. destruct d as [|d&amp;#039; x&amp;#039; v&amp;#039;].&lt;br /&gt;
       - simpl. destruct x. simpl. rewrite &amp;lt;- beq_nat_refl. reflexivity.&lt;br /&gt;
       - simpl. destruct x. simpl. rewrite &amp;lt;- beq_nat_refl. reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(** [] *)&lt;br /&gt;
(** Ejercicio 30. update_neq  *)&lt;br /&gt;
&lt;br /&gt;
Theorem update_neq :&lt;br /&gt;
  forall (d : partial_map) (x y : id) (o: nat),&lt;br /&gt;
    beq_id x y = false -&amp;gt; find x (update d y o) = find x d.&lt;br /&gt;
Proof. intros d x y o p. simpl. rewrite p. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(** [] *)&lt;br /&gt;
End PartialMap.&lt;br /&gt;
&lt;br /&gt;
(** Otra definición inductiva: *)&lt;br /&gt;
&lt;br /&gt;
Inductive baz : Type :=&lt;br /&gt;
  | Baz1 : baz -&amp;gt; baz&lt;br /&gt;
  | Baz2 : baz -&amp;gt; bool -&amp;gt; baz.&lt;br /&gt;
&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(** $Date: 2017-10-10 09:30:37 -0400 (Tue, 10 Oct 2017) $ *)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jorcatote</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/SLC2018/index.php?title=Tema_3&amp;diff=62</id>
		<title>Tema 3</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/SLC2018/index.php?title=Tema_3&amp;diff=62"/>
		<updated>2018-03-21T19:42:22Z</updated>

		<summary type="html">&lt;p&gt;Jorcatote: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* Datos estructurados en Coq *)&lt;br /&gt;
&lt;br /&gt;
Require Export Induction.&lt;br /&gt;
&lt;br /&gt;
Module NatList. &lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § Pares de númenros &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. El tipo de los números naturales es natprod y su&lt;br /&gt;
   constructor es pair.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive natprod : Type :=&lt;br /&gt;
  pair : nat -&amp;gt; nat -&amp;gt; natprod.&lt;br /&gt;
&lt;br /&gt;
Check (pair 3 5).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      fst : natprod -&amp;gt; nat&lt;br /&gt;
   tal que (fst p) es la primera componente de p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition fst (p : natprod) : nat := &lt;br /&gt;
  match p with&lt;br /&gt;
  | pair x y =&amp;gt; x&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Evaluar la expresión &lt;br /&gt;
      fst (pair 3 5)&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Eval compute in (fst (pair 3 5)).&lt;br /&gt;
(* ===&amp;gt; 3 *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      snd : natprod -&amp;gt; nat&lt;br /&gt;
   tal que (snd p) es la segunda componente de p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition snd (p : natprod) : nat := &lt;br /&gt;
  match p with&lt;br /&gt;
  | pair x y =&amp;gt; y&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la notación (x,y) como una abreviaura de (pair x y).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;( x , y )&amp;quot; := (pair x y).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Evaluar la expresión &lt;br /&gt;
      fst (3,5)&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Eval compute in (fst (3,5)).&lt;br /&gt;
(* ===&amp;gt; 3 *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Redefinir la función fst usando la abreviatura de pares.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition fst&amp;#039; (p : natprod) : nat := &lt;br /&gt;
  match p with&lt;br /&gt;
  | (x,y) =&amp;gt; x&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Redefinir la función snd usando la abreviatura de pares.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition snd&amp;#039; (p : natprod) : nat := &lt;br /&gt;
  match p with&lt;br /&gt;
  | (x,y) =&amp;gt; y&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      swap_pair : natprod -&amp;gt; natprod&lt;br /&gt;
   tal que (swap_pair p) es el par obtenido intercambiando las&lt;br /&gt;
   componentes de p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition swap_pair (p : natprod) : natprod := &lt;br /&gt;
  match p with&lt;br /&gt;
  | (x,y) =&amp;gt; (y,x)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que para todos los naturales&lt;br /&gt;
      (n,m) = (fst (n,m), snd (n,m)).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem surjective_pairing&amp;#039; : forall (n m : nat),&lt;br /&gt;
  (n,m) = (fst (n,m), snd (n,m)).&lt;br /&gt;
Proof.&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que para todo par de naturales&lt;br /&gt;
      p = (fst p, snd p).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem surjective_pairing_stuck : forall (p : natprod),&lt;br /&gt;
  p = (fst p, snd p).&lt;br /&gt;
Proof.&lt;br /&gt;
  simpl. (* No reduce nada. *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
Theorem surjective_pairing : forall (p : natprod),&lt;br /&gt;
  p = (fst p, snd p).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros p.  destruct p as [n m].  simpl.  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1. Demostrar que para todo par de naturales p,&lt;br /&gt;
      (snd p, fst p) = swap_pair p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem snd_fst_is_swap : forall (p : natprod),&lt;br /&gt;
  (snd p, fst p) = swap_pair p.&lt;br /&gt;
Admitted.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2. Demostrar que para todo par de naturales p,&lt;br /&gt;
      fst (swap_pair p) = snd p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem fst_swap_is_snd : forall (p : natprod),&lt;br /&gt;
  fst (swap_pair p) = snd p.&lt;br /&gt;
Admitted.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § Listas de números &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. natlist es la lista de los números naturales y sus&lt;br /&gt;
   constructores son &lt;br /&gt;
   + nil (la lista vacía) y &lt;br /&gt;
   + cons (tal que (cons x ys) es la lista obtenida añadiéndole x a ys. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive natlist : Type :=&lt;br /&gt;
  | nil  : natlist&lt;br /&gt;
  | cons : nat -&amp;gt; natlist -&amp;gt; natlist.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la constante &lt;br /&gt;
      mylist : natlist&lt;br /&gt;
   que es la lista cuyos elementos son 1, 2 y 3.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition mylist := cons 1 (cons 2 (cons 3 nil)).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la notación (x :: ys) como una abreviatura de &lt;br /&gt;
   (cons x ys).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;x :: l&amp;quot; := (cons x l)&lt;br /&gt;
                     (at level 60, right associativity).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la notación de las listas finitas escribiendo sus&lt;br /&gt;
   elementos entre corchetes y separados por puntos y comas.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;[ ]&amp;quot; := nil.&lt;br /&gt;
Notation &amp;quot;[ x ; .. ; y ]&amp;quot; := (cons x .. (cons y nil) ..).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Distintas representaciones de mylist.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition mylist1 := 1 :: (2 :: (3 :: nil)).&lt;br /&gt;
Definition mylist2 := 1 :: 2 :: 3 :: nil.&lt;br /&gt;
Definition mylist3 := [1;2;3].&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ Repeat  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      repeat : nat -&amp;gt; nat -&amp;gt; natlist&lt;br /&gt;
   tal que (repeat n k) es la lista formada por k veces el número n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint repeat (n count : nat) : natlist :=&lt;br /&gt;
  match count with&lt;br /&gt;
  | O        =&amp;gt; nil&lt;br /&gt;
  | S count&amp;#039; =&amp;gt; n :: (repeat n count&amp;#039;)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ Length  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      length : natlist -&amp;gt; nat&lt;br /&gt;
   tal que (length xs) es el número de elementos de xs.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint length (l:natlist) : nat :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil    =&amp;gt; O&lt;br /&gt;
  | h :: t =&amp;gt; S (length t)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ Append  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      append : natlist -&amp;gt; natlist -&amp;gt; natlist&lt;br /&gt;
   tal que (append xs ys) es la concatenación de xs e ys.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
Fixpoint app (l1 l2 : natlist) : natlist :=&lt;br /&gt;
  match l1 with&lt;br /&gt;
  | nil    =&amp;gt; l2&lt;br /&gt;
  | h :: t =&amp;gt; h :: (app t l2)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la notación (xs ++ ys) como una abreviaura de &lt;br /&gt;
   (append xs ys).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;x ++ y&amp;quot; := (app x y)&lt;br /&gt;
                     (right associativity, at level 60).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que&lt;br /&gt;
      [1;2;3] ++ [4;5] = [1;2;3;4;5].&lt;br /&gt;
      nil     ++ [4;5] = [4;5].&lt;br /&gt;
      [1;2;3] ++ nil   = [1;2;3].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example test_app1: [1;2;3] ++ [4;5] = [1;2;3;4;5].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
Example test_app2: nil ++ [4;5] = [4;5].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
Example test_app3: [1;2;3] ++ nil = [1;2;3].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ Head y tail  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      hd : nat -&amp;gt; natlist -&amp;gt; natlist&lt;br /&gt;
   tal que (hd d xs) es el primer elemento de xs o d, si xs es la lista&lt;br /&gt;
   vacía. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition hd (default:nat) (l:natlist) : nat :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil    =&amp;gt; default&lt;br /&gt;
  | h :: t =&amp;gt; h&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      tl : natlist -&amp;gt; natlist&lt;br /&gt;
   tal que (tl xs) es el resto de xs.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition tl (l:natlist) : natlist :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil    =&amp;gt; nil&lt;br /&gt;
  | h :: t =&amp;gt; t&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que &lt;br /&gt;
       hd 0 [1;2;3] = 1.&lt;br /&gt;
       hd 0 []      = 0.&lt;br /&gt;
       tl [1;2;3]   = [2;3].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example test_hd1: hd 0 [1;2;3] = 1.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
Example test_hd2: hd 0 [] = 0.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
Example test_tl: tl [1;2;3] = [2;3].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3. Definir la función&lt;br /&gt;
      nonzeros : natlist -&amp;gt; natlist&lt;br /&gt;
   tal que (nonzeros xs) es la lista de los elementos de xs distintos de&lt;br /&gt;
   cero. Por ejemplo,&lt;br /&gt;
      nonzeros [0;1;0;2;3;0;0] = [1;2;3].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint nonzeros (l:natlist) : natlist :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil =&amp;gt; nil&lt;br /&gt;
  | a::bs =&amp;gt; match a with&lt;br /&gt;
            | 0 =&amp;gt; nonzeros bs &lt;br /&gt;
            | _ =&amp;gt;  a:: nonzeros bs end&lt;br /&gt;
 end.&lt;br /&gt;
Example test_nonzeros:&lt;br /&gt;
  nonzeros [0;1;0;2;3;0;0] = [1;2;3].&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4. Definir la función&lt;br /&gt;
      oddmembers : natlist -&amp;gt; natlist&lt;br /&gt;
   tal que (oddmembers xs) es la lista de los elementos impares de&lt;br /&gt;
   xs. Por ejemplo,&lt;br /&gt;
      oddmembers [0;1;0;2;3;0;0] = [1;3].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint oddmembers (l:natlist) : natlist :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil =&amp;gt; nil&lt;br /&gt;
  | t::xs =&amp;gt; if oddb t then t :: oddmembers xs else oddmembers xs&lt;br /&gt;
  end.&lt;br /&gt;
 &lt;br /&gt;
Example test_oddmembers:&lt;br /&gt;
  oddmembers [0;1;0;2;3;0;0] = [1;3].&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5. Definir la función&lt;br /&gt;
      countoddmembers : natlist -&amp;gt; nat&lt;br /&gt;
   tal que (countoddmembers xs) es el número de elementos impares de&lt;br /&gt;
   xs. Por ejemplo,&lt;br /&gt;
      countoddmembers [1;0;3;1;4;5] = 4.&lt;br /&gt;
      countoddmembers [0;2;4]       = 0.&lt;br /&gt;
      countoddmembers nil           = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition countoddmembers (l:natlist) : nat :=&lt;br /&gt;
 length (oddmembers l). &lt;br /&gt;
&lt;br /&gt;
Example test_countoddmembers1:&lt;br /&gt;
  countoddmembers [1;0;3;1;4;5] = 4.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_countoddmembers2:&lt;br /&gt;
  countoddmembers [0;2;4] = 0.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_countoddmembers3:&lt;br /&gt;
  countoddmembers nil = 0.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 6. Definir la función&lt;br /&gt;
      alternate : natlist -&amp;gt; natlist -&amp;gt; natlist&lt;br /&gt;
   tal que (alternate xs ys) es la lista obtenida intercalando los&lt;br /&gt;
   elementos de xs e ys. Por ejemplo,&lt;br /&gt;
      alternate [1;2;3] [4;5;6] = [1;4;2;5;3;6].&lt;br /&gt;
      alternate [1] [4;5;6]     = [1;4;5;6].&lt;br /&gt;
      alternate [1;2;3] [4]     = [1;4;2;3].&lt;br /&gt;
      alternate [] [20;30]      = [20;30].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint alternate (l1 l2 : natlist) : natlist :=&lt;br /&gt;
  match l1 with&lt;br /&gt;
  | nil =&amp;gt; l2&lt;br /&gt;
  | t::xs =&amp;gt; match l2 with&lt;br /&gt;
            | nil =&amp;gt; t::xs&lt;br /&gt;
            | p::ys =&amp;gt; t::p::alternate xs ys end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_alternate1:&lt;br /&gt;
  alternate [1;2;3] [4;5;6] = [1;4;2;5;3;6].&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_alternate2:&lt;br /&gt;
  alternate [1] [4;5;6] = [1;4;5;6].&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_alternate3:&lt;br /&gt;
  alternate [1;2;3] [4] = [1;4;2;3].&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_alternate4:&lt;br /&gt;
  alternate [] [20;30] = [20;30].&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(* ----------------------------------------------------------------- *)&lt;br /&gt;
(** *** Multiconjuntos como listas *)&lt;br /&gt;
&lt;br /&gt;
(** Un multiconjunto es como un conjunto donde los elementos pueden repetirse más de una vez. Podemos implementarlos como listas. *)&lt;br /&gt;
&lt;br /&gt;
Definition bag := natlist.&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 7. Definir la función count v s, que te cuenta las veces que aparece el elemento v en la lista s: &lt;br /&gt;
count 1 [1;2;3;1;4;1] = 3.&lt;br /&gt;
count 6 [1;2;3;1;4;1] = 0.&lt;br /&gt;
*)&lt;br /&gt;
&lt;br /&gt;
Fixpoint count (v:nat) (s:bag) : nat :=&lt;br /&gt;
  match s with&lt;br /&gt;
  | nil =&amp;gt; 0&lt;br /&gt;
  | t::xs =&amp;gt; if beq_nat t v then 1 + count v xs else count v xs&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_count1:              count 1 [1;2;3;1;4;1] = 3.&lt;br /&gt;
reflexivity. Qed.&lt;br /&gt;
Example test_count2:              count 6 [1;2;3;1;4;1] = 0.&lt;br /&gt;
reflexivity. Qed. &lt;br /&gt;
&lt;br /&gt;
(** La suma de multiconjuntos es parecida a la unión de conjuntos. Ejercicio 8. Definir la suma de multiconjuntos:&lt;br /&gt;
  count 1 (sum [1;2;3] [1;4;1]) = 3. *)&lt;br /&gt;
&lt;br /&gt;
Definition sum : bag -&amp;gt; bag -&amp;gt; bag := app.&lt;br /&gt;
&lt;br /&gt;
Example test_sum1:              count 1 (sum [1;2;3] [1;4;1]) = 3.&lt;br /&gt;
 reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
  (* Ejercicio 9. Definir la función add v s que añade el elemento v al multiconjunto s:&lt;br /&gt;
 count 1 (add 1 [1;4;1]) = 3.&lt;br /&gt;
 count 5 (add 1 [1;4;1]) = 0.&lt;br /&gt;
*)&lt;br /&gt;
&lt;br /&gt;
Definition add (v:nat) (s:bag) : bag :=&lt;br /&gt;
  v :: s .&lt;br /&gt;
&lt;br /&gt;
Example test_add1:                count 1 (add 1 [1;4;1]) = 3.&lt;br /&gt;
 reflexivity. Qed.&lt;br /&gt;
Example test_add2:                count 5 (add 1 [1;4;1]) = 0.&lt;br /&gt;
 reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
  (* Ejercicio 10. Definir la función member v s que se verfica si v es un elemento de la lista s: &lt;br /&gt;
member 1 [1;4;1] = true.&lt;br /&gt;
member 2 [1;4;1] = false.*)&lt;br /&gt;
&lt;br /&gt;
Definition member (v:nat) (s:bag) : bool := &lt;br /&gt;
 if beq_nat 0 (count v s) then false else true.&lt;br /&gt;
&lt;br /&gt;
Example test_member1:             member 1 [1;4;1] = true.&lt;br /&gt;
 reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_member2:             member 2 [1;4;1] = false.&lt;br /&gt;
reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(** [] *)&lt;br /&gt;
(** Definir las siguientes funciones:*)&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 11. Definir la función remove_one v s que borra una vez el elemento v de la lista s:&lt;br /&gt;
count 5 (remove_one 5 [2;1;5;4;1]) = 0.&lt;br /&gt;
count 4 (remove_one 5 [2;1;4;5;1;4]) = 2.&lt;br /&gt;
count 5 (remove_one 5 [2;1;5;4;5;1;4]) = 1.*)&lt;br /&gt;
&lt;br /&gt;
Fixpoint remove_one (v:nat) (s:bag) : bag :=&lt;br /&gt;
  match s with&lt;br /&gt;
  | nil =&amp;gt; nil&lt;br /&gt;
  | t :: xs =&amp;gt; if beq_nat t v then xs else t:: remove_one v xs&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_remove_one1:&lt;br /&gt;
  count 5 (remove_one 5 [2;1;5;4;1]) = 0.&lt;br /&gt;
 reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_remove_one2:&lt;br /&gt;
  count 5 (remove_one 5 [2;1;4;1]) = 0.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_remove_one3:&lt;br /&gt;
  count 4 (remove_one 5 [2;1;4;5;1;4]) = 2.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_remove_one4:&lt;br /&gt;
  count 5 (remove_one 5 [2;1;5;4;5;1;4]) = 1.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 12. Definir la función remove_all v s que borra todas las copias del elemento v en el multiconjunto s:&lt;br /&gt;
count 5 (remove_all 5 [2;1;5;4;1]) = 0.&lt;br /&gt;
count 5 (remove_all 5 [2;1;4;1]) = 0.&lt;br /&gt;
count 4 (remove_all 5 [2;1;4;5;1;4]) = 2.&lt;br /&gt;
count 5 (remove_all 5 [2;1;5;4;5;1;4;5;1;4]) = 0. *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint remove_all (v:nat) (s:bag) : bag :=&lt;br /&gt;
   match s with&lt;br /&gt;
  | nil =&amp;gt; nil&lt;br /&gt;
  | t :: xs =&amp;gt; if beq_nat t v then remove_all v xs else t:: remove_all v xs&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_remove_all1:  count 5 (remove_all 5 [2;1;5;4;1]) = 0.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
Example test_remove_all2:  count 5 (remove_all 5 [2;1;4;1]) = 0.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
Example test_remove_all3:  count 4 (remove_all 5 [2;1;4;5;1;4]) = 2.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
Example test_remove_all4:  count 5 (remove_all 5 [2;1;5;4;5;1;4;5;1;4]) = 0.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 13. Definir la función subset s1 s2 que se verifica si s1 es un submulticonjunto de s2 *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint subset (s1:bag) (s2:bag) : bool :=&lt;br /&gt;
  match s1 with&lt;br /&gt;
  | nil =&amp;gt; true&lt;br /&gt;
  | x::xs =&amp;gt; member x s2 &amp;amp;&amp;amp; subset xs (remove_one x s2)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_subset1:              subset [1;2] [2;1;4;1] = true.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
Example test_subset2:              subset [1;2;2] [2;1;4;1] = false.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 14 (avanzado). Escribir un teorema sobre multiconjuntos con las funciones count y add y probarlo.*)&lt;br /&gt;
&lt;br /&gt;
Theorem bag_theorem : forall s1 s2 : bag, forall n : nat,&lt;br /&gt;
  count n s1 + count n s2 = count n (app s1 s2).                 &lt;br /&gt;
Proof.&lt;br /&gt;
  intros s1 s2 n. induction s1 as [|s s&amp;#039;].&lt;br /&gt;
 - simpl. reflexivity.&lt;br /&gt;
 - simpl. destruct (beq_nat s n).&lt;br /&gt;
    + simpl. rewrite IHs&amp;#039;. reflexivity.&lt;br /&gt;
    + rewrite IHs&amp;#039;. reflexivity.&lt;br /&gt;
 Qed.&lt;br /&gt;
&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(* ################################################################# *)&lt;br /&gt;
(** * Listas *)&lt;br /&gt;
&lt;br /&gt;
(** El siguiente teorema se deduce directamente de la definición de app. *)&lt;br /&gt;
&lt;br /&gt;
Theorem nil_app : forall l:natlist,&lt;br /&gt;
  [] ++ l = l.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(** ... ya que esta es decreciente en la primera componenete. *)&lt;br /&gt;
&lt;br /&gt;
(** Sobre listas podemos usar las técnicas de demostración ya aprendidas sobre naturales: *)&lt;br /&gt;
&lt;br /&gt;
Theorem tl_length_pred : forall l:natlist,&lt;br /&gt;
  pred (length l) = length (tl l).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros l. destruct l as [| n l&amp;#039;].&lt;br /&gt;
  - (* l = nil *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  - (* l = cons n l&amp;#039; *)&lt;br /&gt;
    reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ================================================================= *)&lt;br /&gt;
(** ** Inducción en Listas *)&lt;br /&gt;
&lt;br /&gt;
(** La inducción sobre la longitud de las listas es análoga a la de los numeros naturales. *)&lt;br /&gt;
&lt;br /&gt;
Theorem app_assoc : forall l1 l2 l3 : natlist,&lt;br /&gt;
  (l1 ++ l2) ++ l3 = l1 ++ (l2 ++ l3).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros l1 l2 l3. induction l1 as [| n l1&amp;#039; IHl1&amp;#039;].&lt;br /&gt;
  - (* l1 = nil *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  - (* l1 = cons n l1&amp;#039; *)&lt;br /&gt;
    simpl. rewrite -&amp;gt; IHl1&amp;#039;. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* Comentar los nombres dados en la hipotesis de inducción. *)&lt;br /&gt;
&lt;br /&gt;
(* ----------------------------------------------------------------- *)&lt;br /&gt;
(** *** Reverse *)&lt;br /&gt;
&lt;br /&gt;
(** Definición de la función rev l que devuelve una lista formada por los elementos en orden l en orden contrario. *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint rev (l:natlist) : natlist :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil    =&amp;gt; nil&lt;br /&gt;
  | h :: t =&amp;gt; rev t ++ [h]&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_rev1:            rev [1;2;3] = [3;2;1].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
Example test_rev2:            rev nil = nil.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ----------------------------------------------------------------- *)&lt;br /&gt;
(** *** Propiedades de [rev] *)&lt;br /&gt;
&lt;br /&gt;
(** Definición de algunos teoremas más: *)&lt;br /&gt;
&lt;br /&gt;
Theorem rev_length_firsttry : forall l : natlist,&lt;br /&gt;
  length (rev l) = length l.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros l. induction l as [| n l&amp;#039; IHl&amp;#039;].&lt;br /&gt;
  - (* l = [] *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  - (* l = n :: l&amp;#039; *)&lt;br /&gt;
    (* Probamos simplificando *)&lt;br /&gt;
    simpl.&lt;br /&gt;
    rewrite &amp;lt;- IHl&amp;#039;.&lt;br /&gt;
    (* Nos encontramos sin más que hacer, así que buscamos un lema que nos ayude. *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
Theorem app_length : forall l1 l2 : natlist,&lt;br /&gt;
  length (l1 ++ l2) = (length l1) + (length l2).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros l1 l2. induction l1 as [| n l1&amp;#039; IHl1&amp;#039;].&lt;br /&gt;
  - (* l1 = nil *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  - (* l1 = cons *)&lt;br /&gt;
    simpl. rewrite -&amp;gt; IHl1&amp;#039;. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(** Ahora completamos la prueba original. *)&lt;br /&gt;
&lt;br /&gt;
Theorem rev_length : forall l : natlist,&lt;br /&gt;
  length (rev l) = length l.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros l. induction l as [| n l&amp;#039; IHl&amp;#039;].&lt;br /&gt;
  - (* l = nil *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  - (* l = cons *)&lt;br /&gt;
    simpl. rewrite -&amp;gt; app_length, plus_comm.&lt;br /&gt;
    simpl. rewrite -&amp;gt; IHl&amp;#039;. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ================================================================= *)&lt;br /&gt;
(** ** Lista de ejercicios, Parte 1 *)&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 15. Demostrar que la lista vacía es el elemento neutro a derechas de la suma de listas: *)&lt;br /&gt;
&lt;br /&gt;
Theorem app_nil_r : forall l : natlist,&lt;br /&gt;
  l ++ [] = l.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros l. induction l as [| x xs HI].&lt;br /&gt;
  - reflexivity.&lt;br /&gt;
  - simpl. rewrite HI. reflexivity.&lt;br /&gt;
    Qed.&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 16. Demostrar la propiedad distributiva del reverso de una lista respecto a la suma: *)&lt;br /&gt;
&lt;br /&gt;
Theorem rev_app_distr: forall l1 l2 : natlist,&lt;br /&gt;
  rev (l1 ++ l2) = rev l2 ++ rev l1.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros l1 l2. induction l1 as [|x xs HI].&lt;br /&gt;
  - simpl. rewrite app_nil_r. reflexivity.&lt;br /&gt;
  - simpl. rewrite HI, app_assoc. reflexivity.&lt;br /&gt;
  Qed.&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 17. Demostrar que el inverso de la función rev es ella misma (que es involutiva): *)&lt;br /&gt;
&lt;br /&gt;
Theorem rev_involutive : forall l : natlist,&lt;br /&gt;
  rev (rev l) = l.&lt;br /&gt;
Proof.&lt;br /&gt;
  induction l as [|x xs HI].&lt;br /&gt;
  - reflexivity.&lt;br /&gt;
  - simpl. rewrite rev_app_distr. rewrite HI. reflexivity.&lt;br /&gt;
  Qed.&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 18. Demostrar la asociatividad de la suma de 4 listas: *)&lt;br /&gt;
&lt;br /&gt;
Theorem app_assoc4 : forall l1 l2 l3 l4 : natlist,&lt;br /&gt;
  l1 ++ (l2 ++ (l3 ++ l4)) = ((l1 ++ l2) ++ l3) ++ l4.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros l1 l2 l3 l4. rewrite app_assoc. rewrite app_assoc. reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 19. Demostrar que al sumar dos listas no aparecen ni desaparecen ceros: *)&lt;br /&gt;
&lt;br /&gt;
Lemma nonzeros_app : forall l1 l2 : natlist,&lt;br /&gt;
  nonzeros (l1 ++ l2) = (nonzeros l1) ++ (nonzeros l2).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros l1 l2. induction l1 as [|x xs HI].&lt;br /&gt;
  - reflexivity.&lt;br /&gt;
  - simpl. destruct x.&lt;br /&gt;
    + rewrite HI. reflexivity.&lt;br /&gt;
    + simpl. rewrite HI. reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 20. Definir beq_natlist como la igualdad de listas:&lt;br /&gt;
beq_natlist nil nil = true.&lt;br /&gt;
beq_natlist [1;2;3] [1;2;3] = true.&lt;br /&gt;
beq_natlist [1;2;3] [1;2;4] = false. *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint beq_natlist (l1 l2 : natlist) : bool:=&lt;br /&gt;
  match l1, l2 with&lt;br /&gt;
  | nil, nil =&amp;gt; true&lt;br /&gt;
  | x::xs, y::ys =&amp;gt; beq_nat x y &amp;amp;&amp;amp; beq_natlist xs ys&lt;br /&gt;
  | _, _ =&amp;gt; false&lt;br /&gt;
 end.&lt;br /&gt;
&lt;br /&gt;
Example test_beq_natlist1 :&lt;br /&gt;
  (beq_natlist nil nil = true).&lt;br /&gt;
 reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_beq_natlist2 :&lt;br /&gt;
  beq_natlist [1;2;3] [1;2;3] = true.&lt;br /&gt;
 reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_beq_natlist3 :&lt;br /&gt;
  beq_natlist [1;2;3] [1;2;4] = false.&lt;br /&gt;
 reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 21. Demostrar que la igualdad de listas cumple la propiedad reflexiva *)&lt;br /&gt;
&lt;br /&gt;
Theorem beq_natlist_refl : forall l:natlist,&lt;br /&gt;
  true = beq_natlist l l.&lt;br /&gt;
Proof.&lt;br /&gt;
  induction l as [|n xs HI].&lt;br /&gt;
  - reflexivity.&lt;br /&gt;
  - simpl. rewrite &amp;lt;- HI. replace (beq_nat n n) with true.  reflexivity.&lt;br /&gt;
    + rewrite &amp;lt;- beq_nat_refl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(* ================================================================= *)&lt;br /&gt;
(** ** Lista de ejercicios, Parte 2 *)&lt;br /&gt;
&lt;br /&gt;
(** Teoremas sobre multiconjuntos: *)&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 22. Demuestra el siguiente teorema sobre que al incluir un elemento en un multiconjunto, ese elemento aparece al menos una vez en él. *)&lt;br /&gt;
&lt;br /&gt;
Theorem count_member_nonzero : forall (s : bag),&lt;br /&gt;
  leb 1 (count 1 (1 :: s)) = true.&lt;br /&gt;
Proof.&lt;br /&gt;
 intro s.  simpl. reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(** Lema sobre los numeros naturales que nos ayudará más adelante: *)&lt;br /&gt;
&lt;br /&gt;
Theorem ble_n_Sn : forall n,&lt;br /&gt;
  leb n (S n) = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n. induction n as [| n&amp;#039; IHn&amp;#039;].&lt;br /&gt;
  - (* 0 *)&lt;br /&gt;
    simpl.  reflexivity.&lt;br /&gt;
  - (* S n&amp;#039; *)&lt;br /&gt;
    simpl.  rewrite IHn&amp;#039;.  reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 23. Demostrar el teorema siguiente que afirma que al borrar elementos de un multiconjuntos esto desciende el numero de ese tipo que contiene. *)&lt;br /&gt;
&lt;br /&gt;
Theorem remove_decreases_count: forall (s : bag),&lt;br /&gt;
  leb (count 0 (remove_one 0 s)) (count 0 s) = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  induction s as [|x xs HI].&lt;br /&gt;
  - reflexivity.&lt;br /&gt;
  - simpl. destruct x.&lt;br /&gt;
    + rewrite ble_n_Sn. reflexivity.&lt;br /&gt;
    + simpl. rewrite HI. reflexivity.&lt;br /&gt;
  Qed.    &lt;br /&gt;
&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 3 stars, optional (bag_count_sum)  *)&lt;br /&gt;
(** Write down an interesting theorem [bag_count_sum] about bags&lt;br /&gt;
    involving the functions [count] and [sum], and prove it using&lt;br /&gt;
    Coq.  (You may find that the difficulty of the proof depends on&lt;br /&gt;
    how you defined [count]!) *)&lt;br /&gt;
(* FILL IN HERE *)&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 4 stars, advanced (rev_injective)  *)&lt;br /&gt;
(** Prove that the [rev] function is injective -- that is,&lt;br /&gt;
&lt;br /&gt;
    forall (l1 l2 : natlist), rev l1 = rev l2 -&amp;gt; l1 = l2.&lt;br /&gt;
&lt;br /&gt;
(There is a hard way and an easy way to do this.) *)&lt;br /&gt;
&lt;br /&gt;
(* FILL IN HERE *)&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(* ################################################################# *)&lt;br /&gt;
(** * Options *)&lt;br /&gt;
&lt;br /&gt;
(** Suppose we want to write a function that returns the [n]th&lt;br /&gt;
    element of some list.  If we give it type [nat -&amp;gt; natlist -&amp;gt; nat],&lt;br /&gt;
    then we&amp;#039;ll have to choose some number to return when the list is&lt;br /&gt;
    too short... *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint nth_bad (l:natlist) (n:nat) : nat :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil =&amp;gt; 42  (* arbitrary! *)&lt;br /&gt;
  | a :: l&amp;#039; =&amp;gt; match beq_nat n O with&lt;br /&gt;
               | true =&amp;gt; a&lt;br /&gt;
               | false =&amp;gt; nth_bad l&amp;#039; (pred n)&lt;br /&gt;
               end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(** This solution is not so good: If [nth_bad] returns [42], we&lt;br /&gt;
    can&amp;#039;t tell whether that value actually appears on the input&lt;br /&gt;
    without further processing. A better alternative is to change the&lt;br /&gt;
    return type of [nth_bad] to include an error value as a possible&lt;br /&gt;
    outcome. We call this type [natoption]. *)&lt;br /&gt;
&lt;br /&gt;
Inductive natoption : Type :=&lt;br /&gt;
  | Some : nat -&amp;gt; natoption&lt;br /&gt;
  | None : natoption.&lt;br /&gt;
&lt;br /&gt;
(** We can then change the above definition of [nth_bad] to&lt;br /&gt;
    return [None] when the list is too short and [Some a] when the&lt;br /&gt;
    list has enough members and [a] appears at position [n]. We call&lt;br /&gt;
    this new function [nth_error] to indicate that it may result in an&lt;br /&gt;
    error. *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint nth_error (l:natlist) (n:nat) : natoption :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil =&amp;gt; None&lt;br /&gt;
  | a :: l&amp;#039; =&amp;gt; match beq_nat n O with&lt;br /&gt;
               | true =&amp;gt; Some a&lt;br /&gt;
               | false =&amp;gt; nth_error l&amp;#039; (pred n)&lt;br /&gt;
               end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_nth_error1 : nth_error [4;5;6;7] 0 = Some 4.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
Example test_nth_error2 : nth_error [4;5;6;7] 3 = Some 7.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
Example test_nth_error3 : nth_error [4;5;6;7] 9 = None.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(** (In the HTML version, the boilerplate proofs of these&lt;br /&gt;
    examples are elided.  Click on a box if you want to see one.)&lt;br /&gt;
&lt;br /&gt;
    This example is also an opportunity to introduce one more small&lt;br /&gt;
    feature of Coq&amp;#039;s programming language: conditional&lt;br /&gt;
    expressions... *)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fixpoint nth_error&amp;#039; (l:natlist) (n:nat) : natoption :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil =&amp;gt; None&lt;br /&gt;
  | a :: l&amp;#039; =&amp;gt; if beq_nat n O then Some a&lt;br /&gt;
               else nth_error&amp;#039; l&amp;#039; (pred n)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(** Coq&amp;#039;s conditionals are exactly like those found in any other&lt;br /&gt;
    language, with one small generalization.  Since the boolean type&lt;br /&gt;
    is not built in, Coq actually supports conditional expressions over&lt;br /&gt;
    _any_ inductively defined type with exactly two constructors.  The&lt;br /&gt;
    guard is considered true if it evaluates to the first constructor&lt;br /&gt;
    in the [Inductive] definition and false if it evaluates to the&lt;br /&gt;
    second. *)&lt;br /&gt;
&lt;br /&gt;
(** The function below pulls the [nat] out of a [natoption], returning&lt;br /&gt;
    a supplied default in the [None] case. *)&lt;br /&gt;
&lt;br /&gt;
Definition option_elim (d : nat) (o : natoption) : nat :=&lt;br /&gt;
  match o with&lt;br /&gt;
  | Some n&amp;#039; =&amp;gt; n&amp;#039;&lt;br /&gt;
  | None =&amp;gt; d&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 2 stars (hd_error)  *)&lt;br /&gt;
(** Using the same idea, fix the [hd] function from earlier so we don&amp;#039;t&lt;br /&gt;
    have to pass a default element for the [nil] case.  *)&lt;br /&gt;
&lt;br /&gt;
Definition hd_error (l : natlist) : natoption&lt;br /&gt;
  (* REPLACE THIS LINE WITH &amp;quot;:= _your_definition_ .&amp;quot; *). Admitted.&lt;br /&gt;
&lt;br /&gt;
Example test_hd_error1 : hd_error [] = None.&lt;br /&gt;
 (* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
Example test_hd_error2 : hd_error [1] = Some 1.&lt;br /&gt;
 (* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
Example test_hd_error3 : hd_error [5;6] = Some 5.&lt;br /&gt;
 (* FILL IN HERE *) Admitted.&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 1 star, optional (option_elim_hd)  *)&lt;br /&gt;
(** This exercise relates your new [hd_error] to the old [hd]. *)&lt;br /&gt;
&lt;br /&gt;
Theorem option_elim_hd : forall (l:natlist) (default:nat),&lt;br /&gt;
  hd default l = option_elim default (hd_error l).&lt;br /&gt;
Proof.&lt;br /&gt;
  (* FILL IN HERE *) Admitted.&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
End NatList.&lt;br /&gt;
&lt;br /&gt;
(* ################################################################# *)&lt;br /&gt;
(** * Partial Maps *)&lt;br /&gt;
&lt;br /&gt;
(** As a final illustration of how data structures can be defined in&lt;br /&gt;
    Coq, here is a simple _partial map_ data type, analogous to the&lt;br /&gt;
    map or dictionary data structures found in most programming&lt;br /&gt;
    languages. *)&lt;br /&gt;
&lt;br /&gt;
(** First, we define a new inductive datatype [id] to serve as the&lt;br /&gt;
    &amp;quot;keys&amp;quot; of our partial maps. *)&lt;br /&gt;
&lt;br /&gt;
Inductive id : Type :=&lt;br /&gt;
  | Id : nat -&amp;gt; id.&lt;br /&gt;
&lt;br /&gt;
(** Internally, an [id] is just a number.  Introducing a separate type&lt;br /&gt;
    by wrapping each nat with the tag [Id] makes definitions more&lt;br /&gt;
    readable and gives us the flexibility to change representations&lt;br /&gt;
    later if we wish. *)&lt;br /&gt;
&lt;br /&gt;
(** We&amp;#039;ll also need an equality test for [id]s: *)&lt;br /&gt;
&lt;br /&gt;
Definition beq_id (x1 x2 : id) :=&lt;br /&gt;
  match x1, x2 with&lt;br /&gt;
  | Id n1, Id n2 =&amp;gt; beq_nat n1 n2&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 1 star (beq_id_refl)  *)&lt;br /&gt;
Theorem beq_id_refl : forall x, true = beq_id x x.&lt;br /&gt;
Proof.&lt;br /&gt;
  (* FILL IN HERE *) Admitted.&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(** Now we define the type of partial maps: *)&lt;br /&gt;
&lt;br /&gt;
Module PartialMap.&lt;br /&gt;
Export NatList.&lt;br /&gt;
  &lt;br /&gt;
Inductive partial_map : Type :=&lt;br /&gt;
  | empty  : partial_map&lt;br /&gt;
  | record : id -&amp;gt; nat -&amp;gt; partial_map -&amp;gt; partial_map.&lt;br /&gt;
&lt;br /&gt;
(** This declaration can be read: &amp;quot;There are two ways to construct a&lt;br /&gt;
    [partial_map]: either using the constructor [empty] to represent an&lt;br /&gt;
    empty partial map, or by applying the constructor [record] to&lt;br /&gt;
    a key, a value, and an existing [partial_map] to construct a&lt;br /&gt;
    [partial_map] with an additional key-to-value mapping.&amp;quot; *)&lt;br /&gt;
&lt;br /&gt;
(** The [update] function overrides the entry for a given key in a&lt;br /&gt;
    partial map (or adds a new entry if the given key is not already&lt;br /&gt;
    present). *)&lt;br /&gt;
&lt;br /&gt;
Definition update (d : partial_map)&lt;br /&gt;
                  (x : id) (value : nat)&lt;br /&gt;
                  : partial_map :=&lt;br /&gt;
  record x value d.&lt;br /&gt;
&lt;br /&gt;
(** Last, the [find] function searches a [partial_map] for a given&lt;br /&gt;
    key.  It returns [None] if the key was not found and [Some val] if&lt;br /&gt;
    the key was associated with [val]. If the same key is mapped to&lt;br /&gt;
    multiple values, [find] will return the first one it&lt;br /&gt;
    encounters. *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint find (x : id) (d : partial_map) : natoption :=&lt;br /&gt;
  match d with&lt;br /&gt;
  | empty         =&amp;gt; None&lt;br /&gt;
  | record y v d&amp;#039; =&amp;gt; if beq_id x y&lt;br /&gt;
                     then Some v&lt;br /&gt;
                     else find x d&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 1 star (update_eq)  *)&lt;br /&gt;
Theorem update_eq :&lt;br /&gt;
  forall (d : partial_map) (x : id) (v: nat),&lt;br /&gt;
    find x (update d x v) = Some v.&lt;br /&gt;
Proof.&lt;br /&gt;
 (* FILL IN HERE *) Admitted.&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 1 star (update_neq)  *)&lt;br /&gt;
Theorem update_neq :&lt;br /&gt;
  forall (d : partial_map) (x y : id) (o: nat),&lt;br /&gt;
    beq_id x y = false -&amp;gt; find x (update d y o) = find x d.&lt;br /&gt;
Proof.&lt;br /&gt;
 (* FILL IN HERE *) Admitted.&lt;br /&gt;
(** [] *)&lt;br /&gt;
End PartialMap.&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 2 stars (baz_num_elts)  *)&lt;br /&gt;
(** Consider the following inductive definition: *)&lt;br /&gt;
&lt;br /&gt;
Inductive baz : Type :=&lt;br /&gt;
  | Baz1 : baz -&amp;gt; baz&lt;br /&gt;
  | Baz2 : baz -&amp;gt; bool -&amp;gt; baz.&lt;br /&gt;
&lt;br /&gt;
(** How _many_ elements does the type [baz] have?  (Answer in English&lt;br /&gt;
    or the natural language of your choice.)&lt;br /&gt;
&lt;br /&gt;
(* FILL IN HERE *)&lt;br /&gt;
*)&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(** $Date: 2017-10-10 09:30:37 -0400 (Tue, 10 Oct 2017) $ *)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jorcatote</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/SLC2018/index.php?title=Tema_3&amp;diff=61</id>
		<title>Tema 3</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/SLC2018/index.php?title=Tema_3&amp;diff=61"/>
		<updated>2018-03-21T19:31:34Z</updated>

		<summary type="html">&lt;p&gt;Jorcatote: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* Datos estructurados en Coq *)&lt;br /&gt;
&lt;br /&gt;
Require Export Induction.&lt;br /&gt;
&lt;br /&gt;
Module NatList. &lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § Pares de númenros &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. El tipo de los números naturales es natprod y su&lt;br /&gt;
   constructor es pair.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive natprod : Type :=&lt;br /&gt;
  pair : nat -&amp;gt; nat -&amp;gt; natprod.&lt;br /&gt;
&lt;br /&gt;
Check (pair 3 5).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      fst : natprod -&amp;gt; nat&lt;br /&gt;
   tal que (fst p) es la primera componente de p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition fst (p : natprod) : nat := &lt;br /&gt;
  match p with&lt;br /&gt;
  | pair x y =&amp;gt; x&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Evaluar la expresión &lt;br /&gt;
      fst (pair 3 5)&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Eval compute in (fst (pair 3 5)).&lt;br /&gt;
(* ===&amp;gt; 3 *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      snd : natprod -&amp;gt; nat&lt;br /&gt;
   tal que (snd p) es la segunda componente de p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition snd (p : natprod) : nat := &lt;br /&gt;
  match p with&lt;br /&gt;
  | pair x y =&amp;gt; y&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la notación (x,y) como una abreviaura de (pair x y).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;( x , y )&amp;quot; := (pair x y).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Evaluar la expresión &lt;br /&gt;
      fst (3,5)&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Eval compute in (fst (3,5)).&lt;br /&gt;
(* ===&amp;gt; 3 *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Redefinir la función fst usando la abreviatura de pares.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition fst&amp;#039; (p : natprod) : nat := &lt;br /&gt;
  match p with&lt;br /&gt;
  | (x,y) =&amp;gt; x&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Redefinir la función snd usando la abreviatura de pares.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition snd&amp;#039; (p : natprod) : nat := &lt;br /&gt;
  match p with&lt;br /&gt;
  | (x,y) =&amp;gt; y&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      swap_pair : natprod -&amp;gt; natprod&lt;br /&gt;
   tal que (swap_pair p) es el par obtenido intercambiando las&lt;br /&gt;
   componentes de p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition swap_pair (p : natprod) : natprod := &lt;br /&gt;
  match p with&lt;br /&gt;
  | (x,y) =&amp;gt; (y,x)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que para todos los naturales&lt;br /&gt;
      (n,m) = (fst (n,m), snd (n,m)).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem surjective_pairing&amp;#039; : forall (n m : nat),&lt;br /&gt;
  (n,m) = (fst (n,m), snd (n,m)).&lt;br /&gt;
Proof.&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que para todo par de naturales&lt;br /&gt;
      p = (fst p, snd p).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem surjective_pairing_stuck : forall (p : natprod),&lt;br /&gt;
  p = (fst p, snd p).&lt;br /&gt;
Proof.&lt;br /&gt;
  simpl. (* No reduce nada. *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
Theorem surjective_pairing : forall (p : natprod),&lt;br /&gt;
  p = (fst p, snd p).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros p.  destruct p as [n m].  simpl.  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1. Demostrar que para todo par de naturales p,&lt;br /&gt;
      (snd p, fst p) = swap_pair p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem snd_fst_is_swap : forall (p : natprod),&lt;br /&gt;
  (snd p, fst p) = swap_pair p.&lt;br /&gt;
Admitted.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2. Demostrar que para todo par de naturales p,&lt;br /&gt;
      fst (swap_pair p) = snd p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem fst_swap_is_snd : forall (p : natprod),&lt;br /&gt;
  fst (swap_pair p) = snd p.&lt;br /&gt;
Admitted.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § Listas de números &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. natlist es la lista de los números naturales y sus&lt;br /&gt;
   constructores son &lt;br /&gt;
   + nil (la lista vacía) y &lt;br /&gt;
   + cons (tal que (cons x ys) es la lista obtenida añadiéndole x a ys. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive natlist : Type :=&lt;br /&gt;
  | nil  : natlist&lt;br /&gt;
  | cons : nat -&amp;gt; natlist -&amp;gt; natlist.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la constante &lt;br /&gt;
      mylist : natlist&lt;br /&gt;
   que es la lista cuyos elementos son 1, 2 y 3.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition mylist := cons 1 (cons 2 (cons 3 nil)).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la notación (x :: ys) como una abreviatura de &lt;br /&gt;
   (cons x ys).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;x :: l&amp;quot; := (cons x l)&lt;br /&gt;
                     (at level 60, right associativity).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la notación de las listas finitas escribiendo sus&lt;br /&gt;
   elementos entre corchetes y separados por puntos y comas.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;[ ]&amp;quot; := nil.&lt;br /&gt;
Notation &amp;quot;[ x ; .. ; y ]&amp;quot; := (cons x .. (cons y nil) ..).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Distintas representaciones de mylist.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition mylist1 := 1 :: (2 :: (3 :: nil)).&lt;br /&gt;
Definition mylist2 := 1 :: 2 :: 3 :: nil.&lt;br /&gt;
Definition mylist3 := [1;2;3].&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ Repeat  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      repeat : nat -&amp;gt; nat -&amp;gt; natlist&lt;br /&gt;
   tal que (repeat n k) es la lista formada por k veces el número n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint repeat (n count : nat) : natlist :=&lt;br /&gt;
  match count with&lt;br /&gt;
  | O        =&amp;gt; nil&lt;br /&gt;
  | S count&amp;#039; =&amp;gt; n :: (repeat n count&amp;#039;)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ Length  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      length : natlist -&amp;gt; nat&lt;br /&gt;
   tal que (length xs) es el número de elementos de xs.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint length (l:natlist) : nat :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil    =&amp;gt; O&lt;br /&gt;
  | h :: t =&amp;gt; S (length t)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ Append  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      append : natlist -&amp;gt; natlist -&amp;gt; natlist&lt;br /&gt;
   tal que (append xs ys) es la concatenación de xs e ys.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
Fixpoint app (l1 l2 : natlist) : natlist :=&lt;br /&gt;
  match l1 with&lt;br /&gt;
  | nil    =&amp;gt; l2&lt;br /&gt;
  | h :: t =&amp;gt; h :: (app t l2)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la notación (xs ++ ys) como una abreviaura de &lt;br /&gt;
   (append xs ys).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;x ++ y&amp;quot; := (app x y)&lt;br /&gt;
                     (right associativity, at level 60).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que&lt;br /&gt;
      [1;2;3] ++ [4;5] = [1;2;3;4;5].&lt;br /&gt;
      nil     ++ [4;5] = [4;5].&lt;br /&gt;
      [1;2;3] ++ nil   = [1;2;3].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example test_app1: [1;2;3] ++ [4;5] = [1;2;3;4;5].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
Example test_app2: nil ++ [4;5] = [4;5].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
Example test_app3: [1;2;3] ++ nil = [1;2;3].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ Head y tail  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      hd : nat -&amp;gt; natlist -&amp;gt; natlist&lt;br /&gt;
   tal que (hd d xs) es el primer elemento de xs o d, si xs es la lista&lt;br /&gt;
   vacía. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition hd (default:nat) (l:natlist) : nat :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil    =&amp;gt; default&lt;br /&gt;
  | h :: t =&amp;gt; h&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      tl : natlist -&amp;gt; natlist&lt;br /&gt;
   tal que (tl xs) es el resto de xs.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition tl (l:natlist) : natlist :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil    =&amp;gt; nil&lt;br /&gt;
  | h :: t =&amp;gt; t&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que &lt;br /&gt;
       hd 0 [1;2;3] = 1.&lt;br /&gt;
       hd 0 []      = 0.&lt;br /&gt;
       tl [1;2;3]   = [2;3].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example test_hd1: hd 0 [1;2;3] = 1.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
Example test_hd2: hd 0 [] = 0.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
Example test_tl: tl [1;2;3] = [2;3].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3. Definir la función&lt;br /&gt;
      nonzeros : natlist -&amp;gt; natlist&lt;br /&gt;
   tal que (nonzeros xs) es la lista de los elementos de xs distintos de&lt;br /&gt;
   cero. Por ejemplo,&lt;br /&gt;
      nonzeros [0;1;0;2;3;0;0] = [1;2;3].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint nonzeros (l:natlist) : natlist :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil =&amp;gt; nil&lt;br /&gt;
  | a::bs =&amp;gt; match a with&lt;br /&gt;
            | 0 =&amp;gt; nonzeros bs &lt;br /&gt;
            | _ =&amp;gt;  a:: nonzeros bs end&lt;br /&gt;
 end.&lt;br /&gt;
Example test_nonzeros:&lt;br /&gt;
  nonzeros [0;1;0;2;3;0;0] = [1;2;3].&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4. Definir la función&lt;br /&gt;
      oddmembers : natlist -&amp;gt; natlist&lt;br /&gt;
   tal que (oddmembers xs) es la lista de los elementos impares de&lt;br /&gt;
   xs. Por ejemplo,&lt;br /&gt;
      oddmembers [0;1;0;2;3;0;0] = [1;3].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint oddmembers (l:natlist) : natlist :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil =&amp;gt; nil&lt;br /&gt;
  | t::xs =&amp;gt; if oddb t then t :: oddmembers xs else oddmembers xs&lt;br /&gt;
  end.&lt;br /&gt;
 &lt;br /&gt;
Example test_oddmembers:&lt;br /&gt;
  oddmembers [0;1;0;2;3;0;0] = [1;3].&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5. Definir la función&lt;br /&gt;
      countoddmembers : natlist -&amp;gt; nat&lt;br /&gt;
   tal que (countoddmembers xs) es el número de elementos impares de&lt;br /&gt;
   xs. Por ejemplo,&lt;br /&gt;
      countoddmembers [1;0;3;1;4;5] = 4.&lt;br /&gt;
      countoddmembers [0;2;4]       = 0.&lt;br /&gt;
      countoddmembers nil           = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition countoddmembers (l:natlist) : nat :=&lt;br /&gt;
 length (oddmembers l). &lt;br /&gt;
&lt;br /&gt;
Example test_countoddmembers1:&lt;br /&gt;
  countoddmembers [1;0;3;1;4;5] = 4.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_countoddmembers2:&lt;br /&gt;
  countoddmembers [0;2;4] = 0.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_countoddmembers3:&lt;br /&gt;
  countoddmembers nil = 0.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 6. Definir la función&lt;br /&gt;
      alternate : natlist -&amp;gt; natlist -&amp;gt; natlist&lt;br /&gt;
   tal que (alternate xs ys) es la lista obtenida intercalando los&lt;br /&gt;
   elementos de xs e ys. Por ejemplo,&lt;br /&gt;
      alternate [1;2;3] [4;5;6] = [1;4;2;5;3;6].&lt;br /&gt;
      alternate [1] [4;5;6]     = [1;4;5;6].&lt;br /&gt;
      alternate [1;2;3] [4]     = [1;4;2;3].&lt;br /&gt;
      alternate [] [20;30]      = [20;30].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint alternate (l1 l2 : natlist) : natlist :=&lt;br /&gt;
  match l1 with&lt;br /&gt;
  | nil =&amp;gt; l2&lt;br /&gt;
  | t::xs =&amp;gt; match l2 with&lt;br /&gt;
            | nil =&amp;gt; t::xs&lt;br /&gt;
            | p::ys =&amp;gt; t::p::alternate xs ys end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_alternate1:&lt;br /&gt;
  alternate [1;2;3] [4;5;6] = [1;4;2;5;3;6].&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_alternate2:&lt;br /&gt;
  alternate [1] [4;5;6] = [1;4;5;6].&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_alternate3:&lt;br /&gt;
  alternate [1;2;3] [4] = [1;4;2;3].&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_alternate4:&lt;br /&gt;
  alternate [] [20;30] = [20;30].&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(* ----------------------------------------------------------------- *)&lt;br /&gt;
(** *** Multiconjuntos como listas *)&lt;br /&gt;
&lt;br /&gt;
(** Un multiconjunto es como un conjunto donde los elementos pueden repetirse más de una vez. Podemos implementarlos como listas. *)&lt;br /&gt;
&lt;br /&gt;
Definition bag := natlist.&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 7. Definir la función count v s, que te cuenta las veces que aparece el elemento v en la lista s: &lt;br /&gt;
count 1 [1;2;3;1;4;1] = 3.&lt;br /&gt;
count 6 [1;2;3;1;4;1] = 0.&lt;br /&gt;
*)&lt;br /&gt;
&lt;br /&gt;
Fixpoint count (v:nat) (s:bag) : nat :=&lt;br /&gt;
  match s with&lt;br /&gt;
  | nil =&amp;gt; 0&lt;br /&gt;
  | t::xs =&amp;gt; if beq_nat t v then 1 + count v xs else count v xs&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_count1:              count 1 [1;2;3;1;4;1] = 3.&lt;br /&gt;
reflexivity. Qed.&lt;br /&gt;
Example test_count2:              count 6 [1;2;3;1;4;1] = 0.&lt;br /&gt;
reflexivity. Qed. &lt;br /&gt;
&lt;br /&gt;
(** La suma de multiconjuntos es parecida a la unión de conjuntos. Ejercicio 8. Definir la suma de multiconjuntos:&lt;br /&gt;
  count 1 (sum [1;2;3] [1;4;1]) = 3. *)&lt;br /&gt;
&lt;br /&gt;
Definition sum : bag -&amp;gt; bag -&amp;gt; bag := app.&lt;br /&gt;
&lt;br /&gt;
Example test_sum1:              count 1 (sum [1;2;3] [1;4;1]) = 3.&lt;br /&gt;
 reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
  (* Ejercicio 9. Definir la función add v s que añade el elemento v al multiconjunto s:&lt;br /&gt;
 count 1 (add 1 [1;4;1]) = 3.&lt;br /&gt;
 count 5 (add 1 [1;4;1]) = 0.&lt;br /&gt;
*)&lt;br /&gt;
&lt;br /&gt;
Definition add (v:nat) (s:bag) : bag :=&lt;br /&gt;
  v :: s .&lt;br /&gt;
&lt;br /&gt;
Example test_add1:                count 1 (add 1 [1;4;1]) = 3.&lt;br /&gt;
 reflexivity. Qed.&lt;br /&gt;
Example test_add2:                count 5 (add 1 [1;4;1]) = 0.&lt;br /&gt;
 reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
  (* Ejercicio 10. Definir la función member v s que se verfica si v es un elemento de la lista s: &lt;br /&gt;
member 1 [1;4;1] = true.&lt;br /&gt;
member 2 [1;4;1] = false.*)&lt;br /&gt;
&lt;br /&gt;
Definition member (v:nat) (s:bag) : bool := &lt;br /&gt;
 if beq_nat 0 (count v s) then false else true.&lt;br /&gt;
&lt;br /&gt;
Example test_member1:             member 1 [1;4;1] = true.&lt;br /&gt;
 reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_member2:             member 2 [1;4;1] = false.&lt;br /&gt;
reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(** [] *)&lt;br /&gt;
(** Definir las siguientes funciones:*)&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 11. Definir la función remove_one v s que borra una vez el elemento v de la lista s:&lt;br /&gt;
count 5 (remove_one 5 [2;1;5;4;1]) = 0.&lt;br /&gt;
count 4 (remove_one 5 [2;1;4;5;1;4]) = 2.&lt;br /&gt;
count 5 (remove_one 5 [2;1;5;4;5;1;4]) = 1.*)&lt;br /&gt;
&lt;br /&gt;
Fixpoint remove_one (v:nat) (s:bag) : bag :=&lt;br /&gt;
  match s with&lt;br /&gt;
  | nil =&amp;gt; nil&lt;br /&gt;
  | t :: xs =&amp;gt; if beq_nat t v then xs else t:: remove_one v xs&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_remove_one1:&lt;br /&gt;
  count 5 (remove_one 5 [2;1;5;4;1]) = 0.&lt;br /&gt;
 reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_remove_one2:&lt;br /&gt;
  count 5 (remove_one 5 [2;1;4;1]) = 0.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_remove_one3:&lt;br /&gt;
  count 4 (remove_one 5 [2;1;4;5;1;4]) = 2.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_remove_one4:&lt;br /&gt;
  count 5 (remove_one 5 [2;1;5;4;5;1;4]) = 1.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 12. Definir la función remove_all v s que borra todas las copias del elemento v en el multiconjunto s:&lt;br /&gt;
count 5 (remove_all 5 [2;1;5;4;1]) = 0.&lt;br /&gt;
count 5 (remove_all 5 [2;1;4;1]) = 0.&lt;br /&gt;
count 4 (remove_all 5 [2;1;4;5;1;4]) = 2.&lt;br /&gt;
count 5 (remove_all 5 [2;1;5;4;5;1;4;5;1;4]) = 0. *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint remove_all (v:nat) (s:bag) : bag :=&lt;br /&gt;
   match s with&lt;br /&gt;
  | nil =&amp;gt; nil&lt;br /&gt;
  | t :: xs =&amp;gt; if beq_nat t v then remove_all v xs else t:: remove_all v xs&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_remove_all1:  count 5 (remove_all 5 [2;1;5;4;1]) = 0.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
Example test_remove_all2:  count 5 (remove_all 5 [2;1;4;1]) = 0.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
Example test_remove_all3:  count 4 (remove_all 5 [2;1;4;5;1;4]) = 2.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
Example test_remove_all4:  count 5 (remove_all 5 [2;1;5;4;5;1;4;5;1;4]) = 0.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 13. Definir la función subset s1 s2 que se verifica si s1 es un submulticonjunto de s2 *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint subset (s1:bag) (s2:bag) : bool :=&lt;br /&gt;
  match s1 with&lt;br /&gt;
  | nil =&amp;gt; true&lt;br /&gt;
  | x::xs =&amp;gt; member x s2 &amp;amp;&amp;amp; subset xs (remove_one x s2)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_subset1:              subset [1;2] [2;1;4;1] = true.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
Example test_subset2:              subset [1;2;2] [2;1;4;1] = false.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 14 (avanzado). Escribir un teorema sobre multiconjuntos con las funciones count y add y probarlo.*)&lt;br /&gt;
&lt;br /&gt;
Theorem bag_theorem : forall s1 s2 : bag, forall n : nat,&lt;br /&gt;
  count n s1 + count n s2 = count n (app s1 s2).                 &lt;br /&gt;
Proof.&lt;br /&gt;
  intros s1 s2 n. induction s1 as [|s s&amp;#039;].&lt;br /&gt;
 - simpl. reflexivity.&lt;br /&gt;
 - simpl. destruct (beq_nat s n).&lt;br /&gt;
    + simpl. rewrite IHs&amp;#039;. reflexivity.&lt;br /&gt;
    + rewrite IHs&amp;#039;. reflexivity.&lt;br /&gt;
 Qed.&lt;br /&gt;
&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(* ################################################################# *)&lt;br /&gt;
(** * Listas *)&lt;br /&gt;
&lt;br /&gt;
(** El siguiente teorema se deduce directamente de la definición de app. *)&lt;br /&gt;
&lt;br /&gt;
Theorem nil_app : forall l:natlist,&lt;br /&gt;
  [] ++ l = l.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(** ... ya que esta es decreciente en la primera componenete. *)&lt;br /&gt;
&lt;br /&gt;
(** Sobre listas podemos usar las técnicas de demostración ya aprendidas sobre naturales: *)&lt;br /&gt;
&lt;br /&gt;
Theorem tl_length_pred : forall l:natlist,&lt;br /&gt;
  pred (length l) = length (tl l).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros l. destruct l as [| n l&amp;#039;].&lt;br /&gt;
  - (* l = nil *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  - (* l = cons n l&amp;#039; *)&lt;br /&gt;
    reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ================================================================= *)&lt;br /&gt;
(** ** Inducción en Listas *)&lt;br /&gt;
&lt;br /&gt;
(** La inducción sobre la longitud de las listas es análoga a la de los numeros naturales. *)&lt;br /&gt;
&lt;br /&gt;
Theorem app_assoc : forall l1 l2 l3 : natlist,&lt;br /&gt;
  (l1 ++ l2) ++ l3 = l1 ++ (l2 ++ l3).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros l1 l2 l3. induction l1 as [| n l1&amp;#039; IHl1&amp;#039;].&lt;br /&gt;
  - (* l1 = nil *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  - (* l1 = cons n l1&amp;#039; *)&lt;br /&gt;
    simpl. rewrite -&amp;gt; IHl1&amp;#039;. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* Comentar los nombres dados en la hipotesis de inducción. *)&lt;br /&gt;
&lt;br /&gt;
(* ----------------------------------------------------------------- *)&lt;br /&gt;
(** *** Reverse *)&lt;br /&gt;
&lt;br /&gt;
(** Definición de la función rev l que devuelve una lista formada por los elementos en orden l en orden contrario. *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint rev (l:natlist) : natlist :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil    =&amp;gt; nil&lt;br /&gt;
  | h :: t =&amp;gt; rev t ++ [h]&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_rev1:            rev [1;2;3] = [3;2;1].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
Example test_rev2:            rev nil = nil.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ----------------------------------------------------------------- *)&lt;br /&gt;
(** *** Propiedades de [rev] *)&lt;br /&gt;
&lt;br /&gt;
(** Definición de algunos teoremas más: *)&lt;br /&gt;
&lt;br /&gt;
Theorem rev_length_firsttry : forall l : natlist,&lt;br /&gt;
  length (rev l) = length l.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros l. induction l as [| n l&amp;#039; IHl&amp;#039;].&lt;br /&gt;
  - (* l = [] *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  - (* l = n :: l&amp;#039; *)&lt;br /&gt;
    (* Probamos simplificando *)&lt;br /&gt;
    simpl.&lt;br /&gt;
    rewrite &amp;lt;- IHl&amp;#039;.&lt;br /&gt;
    (* Nos encontramos sin más que hacer, así que buscamos un lema que nos ayude. *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
Theorem app_length : forall l1 l2 : natlist,&lt;br /&gt;
  length (l1 ++ l2) = (length l1) + (length l2).&lt;br /&gt;
Proof.&lt;br /&gt;
  (* WORKED IN CLASS *)&lt;br /&gt;
  intros l1 l2. induction l1 as [| n l1&amp;#039; IHl1&amp;#039;].&lt;br /&gt;
  - (* l1 = nil *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  - (* l1 = cons *)&lt;br /&gt;
    simpl. rewrite -&amp;gt; IHl1&amp;#039;. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(** Ahora completamos la prueba original. *)&lt;br /&gt;
&lt;br /&gt;
Theorem rev_length : forall l : natlist,&lt;br /&gt;
  length (rev l) = length l.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros l. induction l as [| n l&amp;#039; IHl&amp;#039;].&lt;br /&gt;
  - (* l = nil *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  - (* l = cons *)&lt;br /&gt;
    simpl. rewrite -&amp;gt; app_length, plus_comm.&lt;br /&gt;
    simpl. rewrite -&amp;gt; IHl&amp;#039;. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ================================================================= *)&lt;br /&gt;
(** ** Lista de ejercicios, Parte 1 *)&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 15. Demostrar que la lista vacía es el elemento neutro a derechas de la suma de listas: *)&lt;br /&gt;
&lt;br /&gt;
Theorem app_nil_r : forall l : natlist,&lt;br /&gt;
  l ++ [] = l.&lt;br /&gt;
Proof.&lt;br /&gt;
  (* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 16. Demostrar la propiedad distributiva del reverso de una lista respecto a la suma: *)&lt;br /&gt;
&lt;br /&gt;
Theorem rev_app_distr: forall l1 l2 : natlist,&lt;br /&gt;
  rev (l1 ++ l2) = rev l2 ++ rev l1.&lt;br /&gt;
Proof.&lt;br /&gt;
(* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 17. Demostrar que el inverso de la función rev es ella misma (que es involutiva): *)&lt;br /&gt;
&lt;br /&gt;
Theorem rev_involutive : forall l : natlist,&lt;br /&gt;
  rev (rev l) = l.&lt;br /&gt;
Proof.&lt;br /&gt;
  (* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 18. Demostrar la asociatividad de la suma de 4 listas: *)&lt;br /&gt;
&lt;br /&gt;
Theorem app_assoc4 : forall l1 l2 l3 l4 : natlist,&lt;br /&gt;
  l1 ++ (l2 ++ (l3 ++ l4)) = ((l1 ++ l2) ++ l3) ++ l4.&lt;br /&gt;
Proof.&lt;br /&gt;
  (* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 19. Demostrar que al sumar dos listas no aparecen ni desaparecen ceros: *)&lt;br /&gt;
&lt;br /&gt;
Lemma nonzeros_app : forall l1 l2 : natlist,&lt;br /&gt;
  nonzeros (l1 ++ l2) = (nonzeros l1) ++ (nonzeros l2).&lt;br /&gt;
Proof.&lt;br /&gt;
  (* FILL IN HERE *) Admitted.&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 20. Definir beq_natlist como la igualdad de listas:&lt;br /&gt;
beq_natlist nil nil = true.&lt;br /&gt;
beq_natlist [1;2;3] [1;2;3] = true.&lt;br /&gt;
beq_natlist [1;2;3] [1;2;4] = false. *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint beq_natlist (l1 l2 : natlist) : bool&lt;br /&gt;
  (* REPLACE THIS LINE WITH &amp;quot;:= _your_definition_ .&amp;quot; *). Admitted.&lt;br /&gt;
&lt;br /&gt;
Example test_beq_natlist1 :&lt;br /&gt;
  (beq_natlist nil nil = true).&lt;br /&gt;
 (* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
Example test_beq_natlist2 :&lt;br /&gt;
  beq_natlist [1;2;3] [1;2;3] = true.&lt;br /&gt;
(* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
Example test_beq_natlist3 :&lt;br /&gt;
  beq_natlist [1;2;3] [1;2;4] = false.&lt;br /&gt;
 (* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 21. Demostrar que la igualdad de listas cumple la propiedad reflexiva *)&lt;br /&gt;
&lt;br /&gt;
Theorem beq_natlist_refl : forall l:natlist,&lt;br /&gt;
  true = beq_natlist l l.&lt;br /&gt;
Proof.&lt;br /&gt;
  (* FILL IN HERE *) Admitted.&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(* ================================================================= *)&lt;br /&gt;
(** ** List Exercises, Part 2 *)&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 3 stars, advanced (bag_proofs)  *)&lt;br /&gt;
(** Here are a couple of little theorems to prove about your&lt;br /&gt;
    definitions about bags above. *)&lt;br /&gt;
&lt;br /&gt;
Theorem count_member_nonzero : forall (s : bag),&lt;br /&gt;
  leb 1 (count 1 (1 :: s)) = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  (* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
(** The following lemma about [leb] might help you in the next proof. *)&lt;br /&gt;
&lt;br /&gt;
Theorem ble_n_Sn : forall n,&lt;br /&gt;
  leb n (S n) = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n. induction n as [| n&amp;#039; IHn&amp;#039;].&lt;br /&gt;
  - (* 0 *)&lt;br /&gt;
    simpl.  reflexivity.&lt;br /&gt;
  - (* S n&amp;#039; *)&lt;br /&gt;
    simpl.  rewrite IHn&amp;#039;.  reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem remove_decreases_count: forall (s : bag),&lt;br /&gt;
  leb (count 0 (remove_one 0 s)) (count 0 s) = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  (* FILL IN HERE *) Admitted.&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 3 stars, optional (bag_count_sum)  *)&lt;br /&gt;
(** Write down an interesting theorem [bag_count_sum] about bags&lt;br /&gt;
    involving the functions [count] and [sum], and prove it using&lt;br /&gt;
    Coq.  (You may find that the difficulty of the proof depends on&lt;br /&gt;
    how you defined [count]!) *)&lt;br /&gt;
(* FILL IN HERE *)&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 4 stars, advanced (rev_injective)  *)&lt;br /&gt;
(** Prove that the [rev] function is injective -- that is,&lt;br /&gt;
&lt;br /&gt;
    forall (l1 l2 : natlist), rev l1 = rev l2 -&amp;gt; l1 = l2.&lt;br /&gt;
&lt;br /&gt;
(There is a hard way and an easy way to do this.) *)&lt;br /&gt;
&lt;br /&gt;
(* FILL IN HERE *)&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(* ################################################################# *)&lt;br /&gt;
(** * Options *)&lt;br /&gt;
&lt;br /&gt;
(** Suppose we want to write a function that returns the [n]th&lt;br /&gt;
    element of some list.  If we give it type [nat -&amp;gt; natlist -&amp;gt; nat],&lt;br /&gt;
    then we&amp;#039;ll have to choose some number to return when the list is&lt;br /&gt;
    too short... *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint nth_bad (l:natlist) (n:nat) : nat :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil =&amp;gt; 42  (* arbitrary! *)&lt;br /&gt;
  | a :: l&amp;#039; =&amp;gt; match beq_nat n O with&lt;br /&gt;
               | true =&amp;gt; a&lt;br /&gt;
               | false =&amp;gt; nth_bad l&amp;#039; (pred n)&lt;br /&gt;
               end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(** This solution is not so good: If [nth_bad] returns [42], we&lt;br /&gt;
    can&amp;#039;t tell whether that value actually appears on the input&lt;br /&gt;
    without further processing. A better alternative is to change the&lt;br /&gt;
    return type of [nth_bad] to include an error value as a possible&lt;br /&gt;
    outcome. We call this type [natoption]. *)&lt;br /&gt;
&lt;br /&gt;
Inductive natoption : Type :=&lt;br /&gt;
  | Some : nat -&amp;gt; natoption&lt;br /&gt;
  | None : natoption.&lt;br /&gt;
&lt;br /&gt;
(** We can then change the above definition of [nth_bad] to&lt;br /&gt;
    return [None] when the list is too short and [Some a] when the&lt;br /&gt;
    list has enough members and [a] appears at position [n]. We call&lt;br /&gt;
    this new function [nth_error] to indicate that it may result in an&lt;br /&gt;
    error. *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint nth_error (l:natlist) (n:nat) : natoption :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil =&amp;gt; None&lt;br /&gt;
  | a :: l&amp;#039; =&amp;gt; match beq_nat n O with&lt;br /&gt;
               | true =&amp;gt; Some a&lt;br /&gt;
               | false =&amp;gt; nth_error l&amp;#039; (pred n)&lt;br /&gt;
               end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_nth_error1 : nth_error [4;5;6;7] 0 = Some 4.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
Example test_nth_error2 : nth_error [4;5;6;7] 3 = Some 7.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
Example test_nth_error3 : nth_error [4;5;6;7] 9 = None.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(** (In the HTML version, the boilerplate proofs of these&lt;br /&gt;
    examples are elided.  Click on a box if you want to see one.)&lt;br /&gt;
&lt;br /&gt;
    This example is also an opportunity to introduce one more small&lt;br /&gt;
    feature of Coq&amp;#039;s programming language: conditional&lt;br /&gt;
    expressions... *)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fixpoint nth_error&amp;#039; (l:natlist) (n:nat) : natoption :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil =&amp;gt; None&lt;br /&gt;
  | a :: l&amp;#039; =&amp;gt; if beq_nat n O then Some a&lt;br /&gt;
               else nth_error&amp;#039; l&amp;#039; (pred n)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(** Coq&amp;#039;s conditionals are exactly like those found in any other&lt;br /&gt;
    language, with one small generalization.  Since the boolean type&lt;br /&gt;
    is not built in, Coq actually supports conditional expressions over&lt;br /&gt;
    _any_ inductively defined type with exactly two constructors.  The&lt;br /&gt;
    guard is considered true if it evaluates to the first constructor&lt;br /&gt;
    in the [Inductive] definition and false if it evaluates to the&lt;br /&gt;
    second. *)&lt;br /&gt;
&lt;br /&gt;
(** The function below pulls the [nat] out of a [natoption], returning&lt;br /&gt;
    a supplied default in the [None] case. *)&lt;br /&gt;
&lt;br /&gt;
Definition option_elim (d : nat) (o : natoption) : nat :=&lt;br /&gt;
  match o with&lt;br /&gt;
  | Some n&amp;#039; =&amp;gt; n&amp;#039;&lt;br /&gt;
  | None =&amp;gt; d&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 2 stars (hd_error)  *)&lt;br /&gt;
(** Using the same idea, fix the [hd] function from earlier so we don&amp;#039;t&lt;br /&gt;
    have to pass a default element for the [nil] case.  *)&lt;br /&gt;
&lt;br /&gt;
Definition hd_error (l : natlist) : natoption&lt;br /&gt;
  (* REPLACE THIS LINE WITH &amp;quot;:= _your_definition_ .&amp;quot; *). Admitted.&lt;br /&gt;
&lt;br /&gt;
Example test_hd_error1 : hd_error [] = None.&lt;br /&gt;
 (* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
Example test_hd_error2 : hd_error [1] = Some 1.&lt;br /&gt;
 (* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
Example test_hd_error3 : hd_error [5;6] = Some 5.&lt;br /&gt;
 (* FILL IN HERE *) Admitted.&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 1 star, optional (option_elim_hd)  *)&lt;br /&gt;
(** This exercise relates your new [hd_error] to the old [hd]. *)&lt;br /&gt;
&lt;br /&gt;
Theorem option_elim_hd : forall (l:natlist) (default:nat),&lt;br /&gt;
  hd default l = option_elim default (hd_error l).&lt;br /&gt;
Proof.&lt;br /&gt;
  (* FILL IN HERE *) Admitted.&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
End NatList.&lt;br /&gt;
&lt;br /&gt;
(* ################################################################# *)&lt;br /&gt;
(** * Partial Maps *)&lt;br /&gt;
&lt;br /&gt;
(** As a final illustration of how data structures can be defined in&lt;br /&gt;
    Coq, here is a simple _partial map_ data type, analogous to the&lt;br /&gt;
    map or dictionary data structures found in most programming&lt;br /&gt;
    languages. *)&lt;br /&gt;
&lt;br /&gt;
(** First, we define a new inductive datatype [id] to serve as the&lt;br /&gt;
    &amp;quot;keys&amp;quot; of our partial maps. *)&lt;br /&gt;
&lt;br /&gt;
Inductive id : Type :=&lt;br /&gt;
  | Id : nat -&amp;gt; id.&lt;br /&gt;
&lt;br /&gt;
(** Internally, an [id] is just a number.  Introducing a separate type&lt;br /&gt;
    by wrapping each nat with the tag [Id] makes definitions more&lt;br /&gt;
    readable and gives us the flexibility to change representations&lt;br /&gt;
    later if we wish. *)&lt;br /&gt;
&lt;br /&gt;
(** We&amp;#039;ll also need an equality test for [id]s: *)&lt;br /&gt;
&lt;br /&gt;
Definition beq_id (x1 x2 : id) :=&lt;br /&gt;
  match x1, x2 with&lt;br /&gt;
  | Id n1, Id n2 =&amp;gt; beq_nat n1 n2&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 1 star (beq_id_refl)  *)&lt;br /&gt;
Theorem beq_id_refl : forall x, true = beq_id x x.&lt;br /&gt;
Proof.&lt;br /&gt;
  (* FILL IN HERE *) Admitted.&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(** Now we define the type of partial maps: *)&lt;br /&gt;
&lt;br /&gt;
Module PartialMap.&lt;br /&gt;
Export NatList.&lt;br /&gt;
  &lt;br /&gt;
Inductive partial_map : Type :=&lt;br /&gt;
  | empty  : partial_map&lt;br /&gt;
  | record : id -&amp;gt; nat -&amp;gt; partial_map -&amp;gt; partial_map.&lt;br /&gt;
&lt;br /&gt;
(** This declaration can be read: &amp;quot;There are two ways to construct a&lt;br /&gt;
    [partial_map]: either using the constructor [empty] to represent an&lt;br /&gt;
    empty partial map, or by applying the constructor [record] to&lt;br /&gt;
    a key, a value, and an existing [partial_map] to construct a&lt;br /&gt;
    [partial_map] with an additional key-to-value mapping.&amp;quot; *)&lt;br /&gt;
&lt;br /&gt;
(** The [update] function overrides the entry for a given key in a&lt;br /&gt;
    partial map (or adds a new entry if the given key is not already&lt;br /&gt;
    present). *)&lt;br /&gt;
&lt;br /&gt;
Definition update (d : partial_map)&lt;br /&gt;
                  (x : id) (value : nat)&lt;br /&gt;
                  : partial_map :=&lt;br /&gt;
  record x value d.&lt;br /&gt;
&lt;br /&gt;
(** Last, the [find] function searches a [partial_map] for a given&lt;br /&gt;
    key.  It returns [None] if the key was not found and [Some val] if&lt;br /&gt;
    the key was associated with [val]. If the same key is mapped to&lt;br /&gt;
    multiple values, [find] will return the first one it&lt;br /&gt;
    encounters. *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint find (x : id) (d : partial_map) : natoption :=&lt;br /&gt;
  match d with&lt;br /&gt;
  | empty         =&amp;gt; None&lt;br /&gt;
  | record y v d&amp;#039; =&amp;gt; if beq_id x y&lt;br /&gt;
                     then Some v&lt;br /&gt;
                     else find x d&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 1 star (update_eq)  *)&lt;br /&gt;
Theorem update_eq :&lt;br /&gt;
  forall (d : partial_map) (x : id) (v: nat),&lt;br /&gt;
    find x (update d x v) = Some v.&lt;br /&gt;
Proof.&lt;br /&gt;
 (* FILL IN HERE *) Admitted.&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 1 star (update_neq)  *)&lt;br /&gt;
Theorem update_neq :&lt;br /&gt;
  forall (d : partial_map) (x y : id) (o: nat),&lt;br /&gt;
    beq_id x y = false -&amp;gt; find x (update d y o) = find x d.&lt;br /&gt;
Proof.&lt;br /&gt;
 (* FILL IN HERE *) Admitted.&lt;br /&gt;
(** [] *)&lt;br /&gt;
End PartialMap.&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 2 stars (baz_num_elts)  *)&lt;br /&gt;
(** Consider the following inductive definition: *)&lt;br /&gt;
&lt;br /&gt;
Inductive baz : Type :=&lt;br /&gt;
  | Baz1 : baz -&amp;gt; baz&lt;br /&gt;
  | Baz2 : baz -&amp;gt; bool -&amp;gt; baz.&lt;br /&gt;
&lt;br /&gt;
(** How _many_ elements does the type [baz] have?  (Answer in English&lt;br /&gt;
    or the natural language of your choice.)&lt;br /&gt;
&lt;br /&gt;
(* FILL IN HERE *)&lt;br /&gt;
*)&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(** $Date: 2017-10-10 09:30:37 -0400 (Tue, 10 Oct 2017) $ *)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jorcatote</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/SLC2018/index.php?title=Tema_3&amp;diff=60</id>
		<title>Tema 3</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/SLC2018/index.php?title=Tema_3&amp;diff=60"/>
		<updated>2018-03-21T18:59:05Z</updated>

		<summary type="html">&lt;p&gt;Jorcatote: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* Datos estructurados en Coq *)&lt;br /&gt;
&lt;br /&gt;
Require Export Induction.&lt;br /&gt;
&lt;br /&gt;
Module NatList. &lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § Pares de númenros &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. El tipo de los números naturales es natprod y su&lt;br /&gt;
   constructor es pair.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive natprod : Type :=&lt;br /&gt;
  pair : nat -&amp;gt; nat -&amp;gt; natprod.&lt;br /&gt;
&lt;br /&gt;
Check (pair 3 5).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      fst : natprod -&amp;gt; nat&lt;br /&gt;
   tal que (fst p) es la primera componente de p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition fst (p : natprod) : nat := &lt;br /&gt;
  match p with&lt;br /&gt;
  | pair x y =&amp;gt; x&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Evaluar la expresión &lt;br /&gt;
      fst (pair 3 5)&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Eval compute in (fst (pair 3 5)).&lt;br /&gt;
(* ===&amp;gt; 3 *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      snd : natprod -&amp;gt; nat&lt;br /&gt;
   tal que (snd p) es la segunda componente de p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition snd (p : natprod) : nat := &lt;br /&gt;
  match p with&lt;br /&gt;
  | pair x y =&amp;gt; y&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la notación (x,y) como una abreviaura de (pair x y).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;( x , y )&amp;quot; := (pair x y).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Evaluar la expresión &lt;br /&gt;
      fst (3,5)&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Eval compute in (fst (3,5)).&lt;br /&gt;
(* ===&amp;gt; 3 *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Redefinir la función fst usando la abreviatura de pares.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition fst&amp;#039; (p : natprod) : nat := &lt;br /&gt;
  match p with&lt;br /&gt;
  | (x,y) =&amp;gt; x&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Redefinir la función snd usando la abreviatura de pares.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition snd&amp;#039; (p : natprod) : nat := &lt;br /&gt;
  match p with&lt;br /&gt;
  | (x,y) =&amp;gt; y&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      swap_pair : natprod -&amp;gt; natprod&lt;br /&gt;
   tal que (swap_pair p) es el par obtenido intercambiando las&lt;br /&gt;
   componentes de p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition swap_pair (p : natprod) : natprod := &lt;br /&gt;
  match p with&lt;br /&gt;
  | (x,y) =&amp;gt; (y,x)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que para todos los naturales&lt;br /&gt;
      (n,m) = (fst (n,m), snd (n,m)).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem surjective_pairing&amp;#039; : forall (n m : nat),&lt;br /&gt;
  (n,m) = (fst (n,m), snd (n,m)).&lt;br /&gt;
Proof.&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que para todo par de naturales&lt;br /&gt;
      p = (fst p, snd p).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem surjective_pairing_stuck : forall (p : natprod),&lt;br /&gt;
  p = (fst p, snd p).&lt;br /&gt;
Proof.&lt;br /&gt;
  simpl. (* No reduce nada. *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
Theorem surjective_pairing : forall (p : natprod),&lt;br /&gt;
  p = (fst p, snd p).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros p.  destruct p as [n m].  simpl.  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1. Demostrar que para todo par de naturales p,&lt;br /&gt;
      (snd p, fst p) = swap_pair p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem snd_fst_is_swap : forall (p : natprod),&lt;br /&gt;
  (snd p, fst p) = swap_pair p.&lt;br /&gt;
Admitted.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2. Demostrar que para todo par de naturales p,&lt;br /&gt;
      fst (swap_pair p) = snd p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem fst_swap_is_snd : forall (p : natprod),&lt;br /&gt;
  fst (swap_pair p) = snd p.&lt;br /&gt;
Admitted.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § Listas de números &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. natlist es la lista de los números naturales y sus&lt;br /&gt;
   constructores son &lt;br /&gt;
   + nil (la lista vacía) y &lt;br /&gt;
   + cons (tal que (cons x ys) es la lista obtenida añadiéndole x a ys. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive natlist : Type :=&lt;br /&gt;
  | nil  : natlist&lt;br /&gt;
  | cons : nat -&amp;gt; natlist -&amp;gt; natlist.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la constante &lt;br /&gt;
      mylist : natlist&lt;br /&gt;
   que es la lista cuyos elementos son 1, 2 y 3.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition mylist := cons 1 (cons 2 (cons 3 nil)).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la notación (x :: ys) como una abreviatura de &lt;br /&gt;
   (cons x ys).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;x :: l&amp;quot; := (cons x l)&lt;br /&gt;
                     (at level 60, right associativity).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la notación de las listas finitas escribiendo sus&lt;br /&gt;
   elementos entre corchetes y separados por puntos y comas.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;[ ]&amp;quot; := nil.&lt;br /&gt;
Notation &amp;quot;[ x ; .. ; y ]&amp;quot; := (cons x .. (cons y nil) ..).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Distintas representaciones de mylist.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition mylist1 := 1 :: (2 :: (3 :: nil)).&lt;br /&gt;
Definition mylist2 := 1 :: 2 :: 3 :: nil.&lt;br /&gt;
Definition mylist3 := [1;2;3].&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ Repeat  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      repeat : nat -&amp;gt; nat -&amp;gt; natlist&lt;br /&gt;
   tal que (repeat n k) es la lista formada por k veces el número n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint repeat (n count : nat) : natlist :=&lt;br /&gt;
  match count with&lt;br /&gt;
  | O        =&amp;gt; nil&lt;br /&gt;
  | S count&amp;#039; =&amp;gt; n :: (repeat n count&amp;#039;)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ Length  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      length : natlist -&amp;gt; nat&lt;br /&gt;
   tal que (length xs) es el número de elementos de xs.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint length (l:natlist) : nat :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil    =&amp;gt; O&lt;br /&gt;
  | h :: t =&amp;gt; S (length t)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ Append  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      append : natlist -&amp;gt; natlist -&amp;gt; natlist&lt;br /&gt;
   tal que (append xs ys) es la concatenación de xs e ys.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
Fixpoint app (l1 l2 : natlist) : natlist :=&lt;br /&gt;
  match l1 with&lt;br /&gt;
  | nil    =&amp;gt; l2&lt;br /&gt;
  | h :: t =&amp;gt; h :: (app t l2)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la notación (xs ++ ys) como una abreviaura de &lt;br /&gt;
   (append xs ys).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;x ++ y&amp;quot; := (app x y)&lt;br /&gt;
                     (right associativity, at level 60).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que&lt;br /&gt;
      [1;2;3] ++ [4;5] = [1;2;3;4;5].&lt;br /&gt;
      nil     ++ [4;5] = [4;5].&lt;br /&gt;
      [1;2;3] ++ nil   = [1;2;3].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example test_app1: [1;2;3] ++ [4;5] = [1;2;3;4;5].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
Example test_app2: nil ++ [4;5] = [4;5].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
Example test_app3: [1;2;3] ++ nil = [1;2;3].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ Head y tail  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      hd : nat -&amp;gt; natlist -&amp;gt; natlist&lt;br /&gt;
   tal que (hd d xs) es el primer elemento de xs o d, si xs es la lista&lt;br /&gt;
   vacía. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition hd (default:nat) (l:natlist) : nat :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil    =&amp;gt; default&lt;br /&gt;
  | h :: t =&amp;gt; h&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      tl : natlist -&amp;gt; natlist&lt;br /&gt;
   tal que (tl xs) es el resto de xs.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition tl (l:natlist) : natlist :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil    =&amp;gt; nil&lt;br /&gt;
  | h :: t =&amp;gt; t&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que &lt;br /&gt;
       hd 0 [1;2;3] = 1.&lt;br /&gt;
       hd 0 []      = 0.&lt;br /&gt;
       tl [1;2;3]   = [2;3].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example test_hd1: hd 0 [1;2;3] = 1.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
Example test_hd2: hd 0 [] = 0.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
Example test_tl: tl [1;2;3] = [2;3].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3. Definir la función&lt;br /&gt;
      nonzeros : natlist -&amp;gt; natlist&lt;br /&gt;
   tal que (nonzeros xs) es la lista de los elementos de xs distintos de&lt;br /&gt;
   cero. Por ejemplo,&lt;br /&gt;
      nonzeros [0;1;0;2;3;0;0] = [1;2;3].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint nonzeros (l:natlist) : natlist :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil =&amp;gt; nil&lt;br /&gt;
  | a::bs =&amp;gt; match a with&lt;br /&gt;
            | 0 =&amp;gt; nonzeros bs &lt;br /&gt;
            | _ =&amp;gt;  a:: nonzeros bs end&lt;br /&gt;
 end.&lt;br /&gt;
Example test_nonzeros:&lt;br /&gt;
  nonzeros [0;1;0;2;3;0;0] = [1;2;3].&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4. Definir la función&lt;br /&gt;
      oddmembers : natlist -&amp;gt; natlist&lt;br /&gt;
   tal que (oddmembers xs) es la lista de los elementos impares de&lt;br /&gt;
   xs. Por ejemplo,&lt;br /&gt;
      oddmembers [0;1;0;2;3;0;0] = [1;3].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint oddmembers (l:natlist) : natlist :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil =&amp;gt; nil&lt;br /&gt;
  | t::xs =&amp;gt; if oddb t then t :: oddmembers xs else oddmembers xs&lt;br /&gt;
  end.&lt;br /&gt;
 &lt;br /&gt;
Example test_oddmembers:&lt;br /&gt;
  oddmembers [0;1;0;2;3;0;0] = [1;3].&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5. Definir la función&lt;br /&gt;
      countoddmembers : natlist -&amp;gt; nat&lt;br /&gt;
   tal que (countoddmembers xs) es el número de elementos impares de&lt;br /&gt;
   xs. Por ejemplo,&lt;br /&gt;
      countoddmembers [1;0;3;1;4;5] = 4.&lt;br /&gt;
      countoddmembers [0;2;4]       = 0.&lt;br /&gt;
      countoddmembers nil           = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition countoddmembers (l:natlist) : nat :=&lt;br /&gt;
 length (oddmembers l). &lt;br /&gt;
&lt;br /&gt;
Example test_countoddmembers1:&lt;br /&gt;
  countoddmembers [1;0;3;1;4;5] = 4.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_countoddmembers2:&lt;br /&gt;
  countoddmembers [0;2;4] = 0.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_countoddmembers3:&lt;br /&gt;
  countoddmembers nil = 0.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 6. Definir la función&lt;br /&gt;
      alternate : natlist -&amp;gt; natlist -&amp;gt; natlist&lt;br /&gt;
   tal que (alternate xs ys) es la lista obtenida intercalando los&lt;br /&gt;
   elementos de xs e ys. Por ejemplo,&lt;br /&gt;
      alternate [1;2;3] [4;5;6] = [1;4;2;5;3;6].&lt;br /&gt;
      alternate [1] [4;5;6]     = [1;4;5;6].&lt;br /&gt;
      alternate [1;2;3] [4]     = [1;4;2;3].&lt;br /&gt;
      alternate [] [20;30]      = [20;30].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint alternate (l1 l2 : natlist) : natlist :=&lt;br /&gt;
  match l1 with&lt;br /&gt;
  | nil =&amp;gt; l2&lt;br /&gt;
  | t::xs =&amp;gt; match l2 with&lt;br /&gt;
            | nil =&amp;gt; t::xs&lt;br /&gt;
            | p::ys =&amp;gt; t::p::alternate xs ys end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_alternate1:&lt;br /&gt;
  alternate [1;2;3] [4;5;6] = [1;4;2;5;3;6].&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_alternate2:&lt;br /&gt;
  alternate [1] [4;5;6] = [1;4;5;6].&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_alternate3:&lt;br /&gt;
  alternate [1;2;3] [4] = [1;4;2;3].&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_alternate4:&lt;br /&gt;
  alternate [] [20;30] = [20;30].&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(* ----------------------------------------------------------------- *)&lt;br /&gt;
(** *** Multiconjuntos como listas *)&lt;br /&gt;
&lt;br /&gt;
(** Un multiconjunto es como un conjunto donde los elementos pueden repetirse más de una vez. Podemos implementarlos como listas. *)&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 7. Definir la función count v s, que te cuenta las veces que aparece el elemento v en la lista s: &lt;br /&gt;
count 1 [1;2;3;1;4;1] = 3.&lt;br /&gt;
count 6 [1;2;3;1;4;1] = 0.&lt;br /&gt;
*)&lt;br /&gt;
&lt;br /&gt;
Fixpoint count (v:nat) (s:bag) : nat :=&lt;br /&gt;
  match s with&lt;br /&gt;
  | nil =&amp;gt; 0&lt;br /&gt;
  | t::xs =&amp;gt; if beq_nat t v then 1 + count v xs else count v xs&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_count1:              count 1 [1;2;3;1;4;1] = 3.&lt;br /&gt;
reflexivity. Qed.&lt;br /&gt;
Example test_count2:              count 6 [1;2;3;1;4;1] = 0.&lt;br /&gt;
reflexivity. Qed. &lt;br /&gt;
&lt;br /&gt;
(** La suma de multiconjuntos es parecida a la unión de conjuntos. Ejercicio 8. Definir la suma de multiconjuntos:&lt;br /&gt;
  count 1 (sum [1;2;3] [1;4;1]) = 3. *)&lt;br /&gt;
&lt;br /&gt;
Definition sum : bag -&amp;gt; bag -&amp;gt; bag := app.&lt;br /&gt;
&lt;br /&gt;
Example test_sum1:              count 1 (sum [1;2;3] [1;4;1]) = 3.&lt;br /&gt;
 reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
  (* Ejercicio 9. Definir la función add v s que añade el elemento v al multiconjunto s:&lt;br /&gt;
 count 1 (add 1 [1;4;1]) = 3.&lt;br /&gt;
 count 5 (add 1 [1;4;1]) = 0.&lt;br /&gt;
*). &lt;br /&gt;
&lt;br /&gt;
Definition add (v:nat) (s:bag) : bag :=&lt;br /&gt;
  v :: s .&lt;br /&gt;
&lt;br /&gt;
Example test_add1:                count 1 (add 1 [1;4;1]) = 3.&lt;br /&gt;
 reflexivity. Qed.&lt;br /&gt;
Example test_add2:                count 5 (add 1 [1;4;1]) = 0.&lt;br /&gt;
 reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
  (* Ejercicio 10. Definir la función member v s que se verfica si v es un elemento de la lista s: &lt;br /&gt;
member 1 [1;4;1] = true.&lt;br /&gt;
member 2 [1;4;1] = false.*)&lt;br /&gt;
&lt;br /&gt;
Definition member (v:nat) (s:bag) : bool := &lt;br /&gt;
 if beq_nat 0 (count v s) then false else true.&lt;br /&gt;
&lt;br /&gt;
Example test_member1:             member 1 [1;4;1] = true.&lt;br /&gt;
 reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_member2:             member 2 [1;4;1] = false.&lt;br /&gt;
reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(** [] *)&lt;br /&gt;
(** Definir las siguientes funciones:)&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 11. Definir la función remove_one v s que borra una vez el elemento v de la lista s:&lt;br /&gt;
count 5 (remove_one 5 [2;1;5;4;1]) = 0.&lt;br /&gt;
count 4 (remove_one 5 [2;1;4;5;1;4]) = 2.&lt;br /&gt;
 count 5 (remove_one 5 [2;1;5;4;5;1;4]) = 1.*)&lt;br /&gt;
&lt;br /&gt;
Fixpoint remove_one (v:nat) (s:bag) : bag :=&lt;br /&gt;
  match s with&lt;br /&gt;
  | nil =&amp;gt; nil&lt;br /&gt;
  | t :: xs =&amp;gt; if beq_nat t v then xs else t:: remove_one v xs&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_remove_one1:&lt;br /&gt;
  count 5 (remove_one 5 [2;1;5;4;1]) = 0.&lt;br /&gt;
 reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_remove_one2:&lt;br /&gt;
  count 5 (remove_one 5 [2;1;4;1]) = 0.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_remove_one3:&lt;br /&gt;
  count 4 (remove_one 5 [2;1;4;5;1;4]) = 2.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_remove_one4:&lt;br /&gt;
  count 5 (remove_one 5 [2;1;5;4;5;1;4]) = 1.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 12. Definir la función remove_all v s que borra todas las copias del elemento v en el multiconjunto s:&lt;br /&gt;
count 5 (remove_all 5 [2;1;5;4;1]) = 0.&lt;br /&gt;
count 5 (remove_all 5 [2;1;4;1]) = 0.&lt;br /&gt;
count 4 (remove_all 5 [2;1;4;5;1;4]) = 2.&lt;br /&gt;
count 5 (remove_all 5 [2;1;5;4;5;1;4;5;1;4]) = 0. *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint remove_all (v:nat) (s:bag) : bag :=&lt;br /&gt;
   match s with&lt;br /&gt;
  | nil =&amp;gt; nil&lt;br /&gt;
  | t :: xs =&amp;gt; if beq_nat t v then remove_all v xs else t:: remove_all v xs&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_remove_all1:  count 5 (remove_all 5 [2;1;5;4;1]) = 0.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
Example test_remove_all2:  count 5 (remove_all 5 [2;1;4;1]) = 0.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
Example test_remove_all3:  count 4 (remove_all 5 [2;1;4;5;1;4]) = 2.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
Example test_remove_all4:  count 5 (remove_all 5 [2;1;5;4;5;1;4;5;1;4]) = 0.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 13. Definir la función subset s1 s2 que se verifica si s1 es un submulticonjunto de s2 *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint subset (s1:bag) (s2:bag) : bool :=&lt;br /&gt;
  match s1 with&lt;br /&gt;
  | nil =&amp;gt; true&lt;br /&gt;
  | x::xs =&amp;gt; member x s2 &amp;amp;&amp;amp; subset xs (remove_one x s2)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_subset1:              subset [1;2] [2;1;4;1] = true.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
Example test_subset2:              subset [1;2;2] [2;1;4;1] = false.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(** Ejercicio 14 (avanzado). Escribir un teorema sobre multiconjuntos con las funciones count y add y probarlo.*)&lt;br /&gt;
&lt;br /&gt;
Theorem bag_theorem : forall s1 s2 : bag, forall n : nat,&lt;br /&gt;
  count n s1 + count n s2 = count n (app s1 s2).                 &lt;br /&gt;
Proof.&lt;br /&gt;
  intros s1 s2 n. induction s1 as [|s s&amp;#039;].&lt;br /&gt;
 - simpl. reflexivity.&lt;br /&gt;
 - simpl. destruct (beq_nat s n).&lt;br /&gt;
    + simpl. rewrite IHs&amp;#039;. reflexivity.&lt;br /&gt;
    + rewrite IHs&amp;#039;. reflexivity.&lt;br /&gt;
 Qed.&lt;br /&gt;
&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(* ################################################################# *)&lt;br /&gt;
(** * Listas *)&lt;br /&gt;
&lt;br /&gt;
(** El siguiente teorema se deduce directamente de la definición de app. *)&lt;br /&gt;
&lt;br /&gt;
Theorem nil_app : forall l:natlist,&lt;br /&gt;
  [] ++ l = l.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(** ... because the [[]] is substituted into the&lt;br /&gt;
    &amp;quot;scrutinee&amp;quot; (the expression whose value is being &amp;quot;scrutinized&amp;quot; by&lt;br /&gt;
    the match) in the definition of [app], allowing the match itself&lt;br /&gt;
    to be simplified. *)&lt;br /&gt;
&lt;br /&gt;
(** Also, as with numbers, it is sometimes helpful to perform case&lt;br /&gt;
    analysis on the possible shapes (empty or non-empty) of an unknown&lt;br /&gt;
    list. *)&lt;br /&gt;
&lt;br /&gt;
Theorem tl_length_pred : forall l:natlist,&lt;br /&gt;
  pred (length l) = length (tl l).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros l. destruct l as [| n l&amp;#039;].&lt;br /&gt;
  - (* l = nil *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  - (* l = cons n l&amp;#039; *)&lt;br /&gt;
    reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(** Here, the [nil] case works because we&amp;#039;ve chosen to define&lt;br /&gt;
    [tl nil = nil]. Notice that the [as] annotation on the [destruct]&lt;br /&gt;
    tactic here introduces two names, [n] and [l&amp;#039;], corresponding to&lt;br /&gt;
    the fact that the [cons] constructor for lists takes two&lt;br /&gt;
    arguments (the head and tail of the list it is constructing). *)&lt;br /&gt;
&lt;br /&gt;
(** Usually, though, interesting theorems about lists require&lt;br /&gt;
    induction for their proofs. *)&lt;br /&gt;
&lt;br /&gt;
(* ----------------------------------------------------------------- *)&lt;br /&gt;
(** *** Micro-Sermon *)&lt;br /&gt;
&lt;br /&gt;
(** Simply reading example proof scripts will not get you very far!&lt;br /&gt;
    It is important to work through the details of each one, using Coq&lt;br /&gt;
    and thinking about what each step achieves.  Otherwise it is more&lt;br /&gt;
    or less guaranteed that the exercises will make no sense when you&lt;br /&gt;
    get to them.  &amp;#039;Nuff said. *)&lt;br /&gt;
&lt;br /&gt;
(* ================================================================= *)&lt;br /&gt;
(** ** Induction on Lists *)&lt;br /&gt;
&lt;br /&gt;
(** Proofs by induction over datatypes like [natlist] are a&lt;br /&gt;
    little less familiar than standard natural number induction, but&lt;br /&gt;
    the idea is equally simple.  Each [Inductive] declaration defines&lt;br /&gt;
    a set of data values that can be built up using the declared&lt;br /&gt;
    constructors: a boolean can be either [true] or [false]; a number&lt;br /&gt;
    can be either [O] or [S] applied to another number; a list can be&lt;br /&gt;
    either [nil] or [cons] applied to a number and a list.&lt;br /&gt;
&lt;br /&gt;
    Moreover, applications of the declared constructors to one another&lt;br /&gt;
    are the _only_ possible shapes that elements of an inductively&lt;br /&gt;
    defined set can have, and this fact directly gives rise to a way&lt;br /&gt;
    of reasoning about inductively defined sets: a number is either&lt;br /&gt;
    [O] or else it is [S] applied to some _smaller_ number; a list is&lt;br /&gt;
    either [nil] or else it is [cons] applied to some number and some&lt;br /&gt;
    _smaller_ list; etc. So, if we have in mind some proposition [P]&lt;br /&gt;
    that mentions a list [l] and we want to argue that [P] holds for&lt;br /&gt;
    _all_ lists, we can reason as follows:&lt;br /&gt;
&lt;br /&gt;
      - First, show that [P] is true of [l] when [l] is [nil].&lt;br /&gt;
&lt;br /&gt;
      - Then show that [P] is true of [l] when [l] is [cons n l&amp;#039;] for&lt;br /&gt;
        some number [n] and some smaller list [l&amp;#039;], assuming that [P]&lt;br /&gt;
        is true for [l&amp;#039;].&lt;br /&gt;
&lt;br /&gt;
    Since larger lists can only be built up from smaller ones,&lt;br /&gt;
    eventually reaching [nil], these two arguments together establish&lt;br /&gt;
    the truth of [P] for all lists [l].  Here&amp;#039;s a concrete example: *)&lt;br /&gt;
&lt;br /&gt;
Theorem app_assoc : forall l1 l2 l3 : natlist,&lt;br /&gt;
  (l1 ++ l2) ++ l3 = l1 ++ (l2 ++ l3).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros l1 l2 l3. induction l1 as [| n l1&amp;#039; IHl1&amp;#039;].&lt;br /&gt;
  - (* l1 = nil *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  - (* l1 = cons n l1&amp;#039; *)&lt;br /&gt;
    simpl. rewrite -&amp;gt; IHl1&amp;#039;. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(** Notice that, as when doing induction on natural numbers, the&lt;br /&gt;
    [as...] clause provided to the [induction] tactic gives a name to&lt;br /&gt;
    the induction hypothesis corresponding to the smaller list [l1&amp;#039;]&lt;br /&gt;
    in the [cons] case. Once again, this Coq proof is not especially&lt;br /&gt;
    illuminating as a static written document -- it is easy to see&lt;br /&gt;
    what&amp;#039;s going on if you are reading the proof in an interactive Coq&lt;br /&gt;
    session and you can see the current goal and context at each&lt;br /&gt;
    point, but this state is not visible in the written-down parts of&lt;br /&gt;
    the Coq proof.  So a natural-language proof -- one written for&lt;br /&gt;
    human readers -- will need to include more explicit signposts; in&lt;br /&gt;
    particular, it will help the reader stay oriented if we remind&lt;br /&gt;
    them exactly what the induction hypothesis is in the second&lt;br /&gt;
    case. *)&lt;br /&gt;
&lt;br /&gt;
(** For comparison, here is an informal proof of the same theorem. *)&lt;br /&gt;
&lt;br /&gt;
(** _Theorem_: For all lists [l1], [l2], and [l3],&lt;br /&gt;
   [(l1 ++ l2) ++ l3 = l1 ++ (l2 ++ l3)].&lt;br /&gt;
&lt;br /&gt;
   _Proof_: By induction on [l1].&lt;br /&gt;
&lt;br /&gt;
   - First, suppose [l1 = []].  We must show&lt;br /&gt;
&lt;br /&gt;
       ([] ++ l2) ++ l3 = [] ++ (l2 ++ l3),&lt;br /&gt;
&lt;br /&gt;
     which follows directly from the definition of [++].&lt;br /&gt;
&lt;br /&gt;
   - Next, suppose [l1 = n::l1&amp;#039;], with&lt;br /&gt;
&lt;br /&gt;
       (l1&amp;#039; ++ l2) ++ l3 = l1&amp;#039; ++ (l2 ++ l3)&lt;br /&gt;
&lt;br /&gt;
     (the induction hypothesis). We must show&lt;br /&gt;
&lt;br /&gt;
       ((n :: l1&amp;#039;) ++ l2) ++ l3 = (n :: l1&amp;#039;) ++ (l2 ++ l3).&lt;br /&gt;
&lt;br /&gt;
     By the definition of [++], this follows from&lt;br /&gt;
&lt;br /&gt;
       n :: ((l1&amp;#039; ++ l2) ++ l3) = n :: (l1&amp;#039; ++ (l2 ++ l3)),&lt;br /&gt;
&lt;br /&gt;
     which is immediate from the induction hypothesis.  [] *)&lt;br /&gt;
&lt;br /&gt;
(* ----------------------------------------------------------------- *)&lt;br /&gt;
(** *** Reversing a List *)&lt;br /&gt;
&lt;br /&gt;
(** For a slightly more involved example of inductive proof over&lt;br /&gt;
    lists, suppose we use [app] to define a list-reversing function&lt;br /&gt;
    [rev]: *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint rev (l:natlist) : natlist :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil    =&amp;gt; nil&lt;br /&gt;
  | h :: t =&amp;gt; rev t ++ [h]&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_rev1:            rev [1;2;3] = [3;2;1].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
Example test_rev2:            rev nil = nil.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ----------------------------------------------------------------- *)&lt;br /&gt;
(** *** Properties of [rev] *)&lt;br /&gt;
&lt;br /&gt;
(** Now let&amp;#039;s prove some theorems about our newly defined [rev].&lt;br /&gt;
    For something a bit more challenging than what we&amp;#039;ve seen, let&amp;#039;s&lt;br /&gt;
    prove that reversing a list does not change its length.  Our first&lt;br /&gt;
    attempt gets stuck in the successor case... *)&lt;br /&gt;
&lt;br /&gt;
Theorem rev_length_firsttry : forall l : natlist,&lt;br /&gt;
  length (rev l) = length l.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros l. induction l as [| n l&amp;#039; IHl&amp;#039;].&lt;br /&gt;
  - (* l = [] *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  - (* l = n :: l&amp;#039; *)&lt;br /&gt;
    (* This is the tricky case.  Let&amp;#039;s begin as usual&lt;br /&gt;
       by simplifying. *)&lt;br /&gt;
    simpl.&lt;br /&gt;
    (* Now we seem to be stuck: the goal is an equality&lt;br /&gt;
       involving [++], but we don&amp;#039;t have any useful equations&lt;br /&gt;
       in either the immediate context or in the global&lt;br /&gt;
       environment!  We can make a little progress by using&lt;br /&gt;
       the IH to rewrite the goal... *)&lt;br /&gt;
    rewrite &amp;lt;- IHl&amp;#039;.&lt;br /&gt;
    (* ... but now we can&amp;#039;t go any further. *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(** So let&amp;#039;s take the equation relating [++] and [length] that&lt;br /&gt;
    would have enabled us to make progress and prove it as a separate&lt;br /&gt;
    lemma. *)&lt;br /&gt;
&lt;br /&gt;
Theorem app_length : forall l1 l2 : natlist,&lt;br /&gt;
  length (l1 ++ l2) = (length l1) + (length l2).&lt;br /&gt;
Proof.&lt;br /&gt;
  (* WORKED IN CLASS *)&lt;br /&gt;
  intros l1 l2. induction l1 as [| n l1&amp;#039; IHl1&amp;#039;].&lt;br /&gt;
  - (* l1 = nil *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  - (* l1 = cons *)&lt;br /&gt;
    simpl. rewrite -&amp;gt; IHl1&amp;#039;. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(** Note that, to make the lemma as general as possible, we&lt;br /&gt;
    quantify over _all_ [natlist]s, not just those that result from an&lt;br /&gt;
    application of [rev].  This should seem natural, because the truth&lt;br /&gt;
    of the goal clearly doesn&amp;#039;t depend on the list having been&lt;br /&gt;
    reversed.  Moreover, it is easier to prove the more general&lt;br /&gt;
    property. *)&lt;br /&gt;
&lt;br /&gt;
(** Now we can complete the original proof. *)&lt;br /&gt;
&lt;br /&gt;
Theorem rev_length : forall l : natlist,&lt;br /&gt;
  length (rev l) = length l.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros l. induction l as [| n l&amp;#039; IHl&amp;#039;].&lt;br /&gt;
  - (* l = nil *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  - (* l = cons *)&lt;br /&gt;
    simpl. rewrite -&amp;gt; app_length, plus_comm.&lt;br /&gt;
    simpl. rewrite -&amp;gt; IHl&amp;#039;. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(** For comparison, here are informal proofs of these two theorems:&lt;br /&gt;
&lt;br /&gt;
    _Theorem_: For all lists [l1] and [l2],&lt;br /&gt;
       [length (l1 ++ l2) = length l1 + length l2].&lt;br /&gt;
&lt;br /&gt;
    _Proof_: By induction on [l1].&lt;br /&gt;
&lt;br /&gt;
    - First, suppose [l1 = []].  We must show&lt;br /&gt;
&lt;br /&gt;
        length ([] ++ l2) = length [] + length l2,&lt;br /&gt;
&lt;br /&gt;
      which follows directly from the definitions of&lt;br /&gt;
      [length] and [++].&lt;br /&gt;
&lt;br /&gt;
    - Next, suppose [l1 = n::l1&amp;#039;], with&lt;br /&gt;
&lt;br /&gt;
        length (l1&amp;#039; ++ l2) = length l1&amp;#039; + length l2.&lt;br /&gt;
&lt;br /&gt;
      We must show&lt;br /&gt;
&lt;br /&gt;
        length ((n::l1&amp;#039;) ++ l2) = length (n::l1&amp;#039;) + length l2).&lt;br /&gt;
&lt;br /&gt;
      This follows directly from the definitions of [length] and [++]&lt;br /&gt;
      together with the induction hypothesis. [] *)&lt;br /&gt;
&lt;br /&gt;
(** _Theorem_: For all lists [l], [length (rev l) = length l].&lt;br /&gt;
&lt;br /&gt;
    _Proof_: By induction on [l].&lt;br /&gt;
&lt;br /&gt;
      - First, suppose [l = []].  We must show&lt;br /&gt;
&lt;br /&gt;
          length (rev []) = length [],&lt;br /&gt;
&lt;br /&gt;
        which follows directly from the definitions of [length]&lt;br /&gt;
        and [rev].&lt;br /&gt;
&lt;br /&gt;
      - Next, suppose [l = n::l&amp;#039;], with&lt;br /&gt;
&lt;br /&gt;
          length (rev l&amp;#039;) = length l&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
        We must show&lt;br /&gt;
&lt;br /&gt;
          length (rev (n :: l&amp;#039;)) = length (n :: l&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
        By the definition of [rev], this follows from&lt;br /&gt;
&lt;br /&gt;
          length ((rev l&amp;#039;) ++ [n]) = S (length l&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
        which, by the previous lemma, is the same as&lt;br /&gt;
&lt;br /&gt;
          length (rev l&amp;#039;) + length [n] = S (length l&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
        This follows directly from the induction hypothesis and the&lt;br /&gt;
        definition of [length]. [] *)&lt;br /&gt;
&lt;br /&gt;
(** The style of these proofs is rather longwinded and pedantic.&lt;br /&gt;
    After the first few, we might find it easier to follow proofs that&lt;br /&gt;
    give fewer details (which can easily work out in our own minds or&lt;br /&gt;
    on scratch paper if necessary) and just highlight the non-obvious&lt;br /&gt;
    steps.  In this more compressed style, the above proof might look&lt;br /&gt;
    like this: *)&lt;br /&gt;
&lt;br /&gt;
(** _Theorem_:&lt;br /&gt;
     For all lists [l], [length (rev l) = length l].&lt;br /&gt;
&lt;br /&gt;
    _Proof_: First, observe that [length (l ++ [n]) = S (length l)]&lt;br /&gt;
     for any [l] (this follows by a straightforward induction on [l]).&lt;br /&gt;
     The main property again follows by induction on [l], using the&lt;br /&gt;
     observation together with the induction hypothesis in the case&lt;br /&gt;
     where [l = n&amp;#039;::l&amp;#039;]. [] *)&lt;br /&gt;
&lt;br /&gt;
(** Which style is preferable in a given situation depends on&lt;br /&gt;
    the sophistication of the expected audience and how similar the&lt;br /&gt;
    proof at hand is to ones that the audience will already be&lt;br /&gt;
    familiar with.  The more pedantic style is a good default for our&lt;br /&gt;
    present purposes. *)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(* ================================================================= *)&lt;br /&gt;
(** ** [Search] *)&lt;br /&gt;
&lt;br /&gt;
(** We&amp;#039;ve seen that proofs can make use of other theorems we&amp;#039;ve&lt;br /&gt;
    already proved, e.g., using [rewrite].  But in order to refer to a&lt;br /&gt;
    theorem, we need to know its name!  Indeed, it is often hard even&lt;br /&gt;
    to remember what theorems have been proven, much less what they&lt;br /&gt;
    are called.&lt;br /&gt;
&lt;br /&gt;
    Coq&amp;#039;s [Search] command is quite helpful with this.  Typing&lt;br /&gt;
    [Search foo] will cause Coq to display a list of all theorems&lt;br /&gt;
    involving [foo].  For example, try uncommenting the following line&lt;br /&gt;
    to see a list of theorems that we have proved about [rev]: *)&lt;br /&gt;
&lt;br /&gt;
(*  Search rev. *)&lt;br /&gt;
&lt;br /&gt;
(** Keep [Search] in mind as you do the following exercises and&lt;br /&gt;
    throughout the rest of the book; it can save you a lot of time!&lt;br /&gt;
&lt;br /&gt;
    If you are using ProofGeneral, you can run [Search] with [C-c&lt;br /&gt;
    C-a C-a]. Pasting its response into your buffer can be&lt;br /&gt;
    accomplished with [C-c C-;]. *)&lt;br /&gt;
&lt;br /&gt;
(* ================================================================= *)&lt;br /&gt;
(** ** List Exercises, Part 1 *)&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 3 stars (list_exercises)  *)&lt;br /&gt;
(** More practice with lists: *)&lt;br /&gt;
&lt;br /&gt;
Theorem app_nil_r : forall l : natlist,&lt;br /&gt;
  l ++ [] = l.&lt;br /&gt;
Proof.&lt;br /&gt;
  (* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
Theorem rev_app_distr: forall l1 l2 : natlist,&lt;br /&gt;
  rev (l1 ++ l2) = rev l2 ++ rev l1.&lt;br /&gt;
Proof.&lt;br /&gt;
  (* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
Theorem rev_involutive : forall l : natlist,&lt;br /&gt;
  rev (rev l) = l.&lt;br /&gt;
Proof.&lt;br /&gt;
  (* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
(** There is a short solution to the next one.  If you find yourself&lt;br /&gt;
    getting tangled up, step back and try to look for a simpler&lt;br /&gt;
    way. *)&lt;br /&gt;
&lt;br /&gt;
Theorem app_assoc4 : forall l1 l2 l3 l4 : natlist,&lt;br /&gt;
  l1 ++ (l2 ++ (l3 ++ l4)) = ((l1 ++ l2) ++ l3) ++ l4.&lt;br /&gt;
Proof.&lt;br /&gt;
  (* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
(** An exercise about your implementation of [nonzeros]: *)&lt;br /&gt;
&lt;br /&gt;
Lemma nonzeros_app : forall l1 l2 : natlist,&lt;br /&gt;
  nonzeros (l1 ++ l2) = (nonzeros l1) ++ (nonzeros l2).&lt;br /&gt;
Proof.&lt;br /&gt;
  (* FILL IN HERE *) Admitted.&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 2 stars (beq_natlist)  *)&lt;br /&gt;
(** Fill in the definition of [beq_natlist], which compares&lt;br /&gt;
    lists of numbers for equality.  Prove that [beq_natlist l l]&lt;br /&gt;
    yields [true] for every list [l]. *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint beq_natlist (l1 l2 : natlist) : bool&lt;br /&gt;
  (* REPLACE THIS LINE WITH &amp;quot;:= _your_definition_ .&amp;quot; *). Admitted.&lt;br /&gt;
&lt;br /&gt;
Example test_beq_natlist1 :&lt;br /&gt;
  (beq_natlist nil nil = true).&lt;br /&gt;
 (* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
Example test_beq_natlist2 :&lt;br /&gt;
  beq_natlist [1;2;3] [1;2;3] = true.&lt;br /&gt;
(* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
Example test_beq_natlist3 :&lt;br /&gt;
  beq_natlist [1;2;3] [1;2;4] = false.&lt;br /&gt;
 (* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
Theorem beq_natlist_refl : forall l:natlist,&lt;br /&gt;
  true = beq_natlist l l.&lt;br /&gt;
Proof.&lt;br /&gt;
  (* FILL IN HERE *) Admitted.&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(* ================================================================= *)&lt;br /&gt;
(** ** List Exercises, Part 2 *)&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 3 stars, advanced (bag_proofs)  *)&lt;br /&gt;
(** Here are a couple of little theorems to prove about your&lt;br /&gt;
    definitions about bags above. *)&lt;br /&gt;
&lt;br /&gt;
Theorem count_member_nonzero : forall (s : bag),&lt;br /&gt;
  leb 1 (count 1 (1 :: s)) = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  (* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
(** The following lemma about [leb] might help you in the next proof. *)&lt;br /&gt;
&lt;br /&gt;
Theorem ble_n_Sn : forall n,&lt;br /&gt;
  leb n (S n) = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n. induction n as [| n&amp;#039; IHn&amp;#039;].&lt;br /&gt;
  - (* 0 *)&lt;br /&gt;
    simpl.  reflexivity.&lt;br /&gt;
  - (* S n&amp;#039; *)&lt;br /&gt;
    simpl.  rewrite IHn&amp;#039;.  reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem remove_decreases_count: forall (s : bag),&lt;br /&gt;
  leb (count 0 (remove_one 0 s)) (count 0 s) = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  (* FILL IN HERE *) Admitted.&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 3 stars, optional (bag_count_sum)  *)&lt;br /&gt;
(** Write down an interesting theorem [bag_count_sum] about bags&lt;br /&gt;
    involving the functions [count] and [sum], and prove it using&lt;br /&gt;
    Coq.  (You may find that the difficulty of the proof depends on&lt;br /&gt;
    how you defined [count]!) *)&lt;br /&gt;
(* FILL IN HERE *)&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 4 stars, advanced (rev_injective)  *)&lt;br /&gt;
(** Prove that the [rev] function is injective -- that is,&lt;br /&gt;
&lt;br /&gt;
    forall (l1 l2 : natlist), rev l1 = rev l2 -&amp;gt; l1 = l2.&lt;br /&gt;
&lt;br /&gt;
(There is a hard way and an easy way to do this.) *)&lt;br /&gt;
&lt;br /&gt;
(* FILL IN HERE *)&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(* ################################################################# *)&lt;br /&gt;
(** * Options *)&lt;br /&gt;
&lt;br /&gt;
(** Suppose we want to write a function that returns the [n]th&lt;br /&gt;
    element of some list.  If we give it type [nat -&amp;gt; natlist -&amp;gt; nat],&lt;br /&gt;
    then we&amp;#039;ll have to choose some number to return when the list is&lt;br /&gt;
    too short... *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint nth_bad (l:natlist) (n:nat) : nat :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil =&amp;gt; 42  (* arbitrary! *)&lt;br /&gt;
  | a :: l&amp;#039; =&amp;gt; match beq_nat n O with&lt;br /&gt;
               | true =&amp;gt; a&lt;br /&gt;
               | false =&amp;gt; nth_bad l&amp;#039; (pred n)&lt;br /&gt;
               end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(** This solution is not so good: If [nth_bad] returns [42], we&lt;br /&gt;
    can&amp;#039;t tell whether that value actually appears on the input&lt;br /&gt;
    without further processing. A better alternative is to change the&lt;br /&gt;
    return type of [nth_bad] to include an error value as a possible&lt;br /&gt;
    outcome. We call this type [natoption]. *)&lt;br /&gt;
&lt;br /&gt;
Inductive natoption : Type :=&lt;br /&gt;
  | Some : nat -&amp;gt; natoption&lt;br /&gt;
  | None : natoption.&lt;br /&gt;
&lt;br /&gt;
(** We can then change the above definition of [nth_bad] to&lt;br /&gt;
    return [None] when the list is too short and [Some a] when the&lt;br /&gt;
    list has enough members and [a] appears at position [n]. We call&lt;br /&gt;
    this new function [nth_error] to indicate that it may result in an&lt;br /&gt;
    error. *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint nth_error (l:natlist) (n:nat) : natoption :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil =&amp;gt; None&lt;br /&gt;
  | a :: l&amp;#039; =&amp;gt; match beq_nat n O with&lt;br /&gt;
               | true =&amp;gt; Some a&lt;br /&gt;
               | false =&amp;gt; nth_error l&amp;#039; (pred n)&lt;br /&gt;
               end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_nth_error1 : nth_error [4;5;6;7] 0 = Some 4.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
Example test_nth_error2 : nth_error [4;5;6;7] 3 = Some 7.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
Example test_nth_error3 : nth_error [4;5;6;7] 9 = None.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(** (In the HTML version, the boilerplate proofs of these&lt;br /&gt;
    examples are elided.  Click on a box if you want to see one.)&lt;br /&gt;
&lt;br /&gt;
    This example is also an opportunity to introduce one more small&lt;br /&gt;
    feature of Coq&amp;#039;s programming language: conditional&lt;br /&gt;
    expressions... *)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fixpoint nth_error&amp;#039; (l:natlist) (n:nat) : natoption :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil =&amp;gt; None&lt;br /&gt;
  | a :: l&amp;#039; =&amp;gt; if beq_nat n O then Some a&lt;br /&gt;
               else nth_error&amp;#039; l&amp;#039; (pred n)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(** Coq&amp;#039;s conditionals are exactly like those found in any other&lt;br /&gt;
    language, with one small generalization.  Since the boolean type&lt;br /&gt;
    is not built in, Coq actually supports conditional expressions over&lt;br /&gt;
    _any_ inductively defined type with exactly two constructors.  The&lt;br /&gt;
    guard is considered true if it evaluates to the first constructor&lt;br /&gt;
    in the [Inductive] definition and false if it evaluates to the&lt;br /&gt;
    second. *)&lt;br /&gt;
&lt;br /&gt;
(** The function below pulls the [nat] out of a [natoption], returning&lt;br /&gt;
    a supplied default in the [None] case. *)&lt;br /&gt;
&lt;br /&gt;
Definition option_elim (d : nat) (o : natoption) : nat :=&lt;br /&gt;
  match o with&lt;br /&gt;
  | Some n&amp;#039; =&amp;gt; n&amp;#039;&lt;br /&gt;
  | None =&amp;gt; d&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 2 stars (hd_error)  *)&lt;br /&gt;
(** Using the same idea, fix the [hd] function from earlier so we don&amp;#039;t&lt;br /&gt;
    have to pass a default element for the [nil] case.  *)&lt;br /&gt;
&lt;br /&gt;
Definition hd_error (l : natlist) : natoption&lt;br /&gt;
  (* REPLACE THIS LINE WITH &amp;quot;:= _your_definition_ .&amp;quot; *). Admitted.&lt;br /&gt;
&lt;br /&gt;
Example test_hd_error1 : hd_error [] = None.&lt;br /&gt;
 (* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
Example test_hd_error2 : hd_error [1] = Some 1.&lt;br /&gt;
 (* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
Example test_hd_error3 : hd_error [5;6] = Some 5.&lt;br /&gt;
 (* FILL IN HERE *) Admitted.&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 1 star, optional (option_elim_hd)  *)&lt;br /&gt;
(** This exercise relates your new [hd_error] to the old [hd]. *)&lt;br /&gt;
&lt;br /&gt;
Theorem option_elim_hd : forall (l:natlist) (default:nat),&lt;br /&gt;
  hd default l = option_elim default (hd_error l).&lt;br /&gt;
Proof.&lt;br /&gt;
  (* FILL IN HERE *) Admitted.&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
End NatList.&lt;br /&gt;
&lt;br /&gt;
(* ################################################################# *)&lt;br /&gt;
(** * Partial Maps *)&lt;br /&gt;
&lt;br /&gt;
(** As a final illustration of how data structures can be defined in&lt;br /&gt;
    Coq, here is a simple _partial map_ data type, analogous to the&lt;br /&gt;
    map or dictionary data structures found in most programming&lt;br /&gt;
    languages. *)&lt;br /&gt;
&lt;br /&gt;
(** First, we define a new inductive datatype [id] to serve as the&lt;br /&gt;
    &amp;quot;keys&amp;quot; of our partial maps. *)&lt;br /&gt;
&lt;br /&gt;
Inductive id : Type :=&lt;br /&gt;
  | Id : nat -&amp;gt; id.&lt;br /&gt;
&lt;br /&gt;
(** Internally, an [id] is just a number.  Introducing a separate type&lt;br /&gt;
    by wrapping each nat with the tag [Id] makes definitions more&lt;br /&gt;
    readable and gives us the flexibility to change representations&lt;br /&gt;
    later if we wish. *)&lt;br /&gt;
&lt;br /&gt;
(** We&amp;#039;ll also need an equality test for [id]s: *)&lt;br /&gt;
&lt;br /&gt;
Definition beq_id (x1 x2 : id) :=&lt;br /&gt;
  match x1, x2 with&lt;br /&gt;
  | Id n1, Id n2 =&amp;gt; beq_nat n1 n2&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 1 star (beq_id_refl)  *)&lt;br /&gt;
Theorem beq_id_refl : forall x, true = beq_id x x.&lt;br /&gt;
Proof.&lt;br /&gt;
  (* FILL IN HERE *) Admitted.&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(** Now we define the type of partial maps: *)&lt;br /&gt;
&lt;br /&gt;
Module PartialMap.&lt;br /&gt;
Export NatList.&lt;br /&gt;
  &lt;br /&gt;
Inductive partial_map : Type :=&lt;br /&gt;
  | empty  : partial_map&lt;br /&gt;
  | record : id -&amp;gt; nat -&amp;gt; partial_map -&amp;gt; partial_map.&lt;br /&gt;
&lt;br /&gt;
(** This declaration can be read: &amp;quot;There are two ways to construct a&lt;br /&gt;
    [partial_map]: either using the constructor [empty] to represent an&lt;br /&gt;
    empty partial map, or by applying the constructor [record] to&lt;br /&gt;
    a key, a value, and an existing [partial_map] to construct a&lt;br /&gt;
    [partial_map] with an additional key-to-value mapping.&amp;quot; *)&lt;br /&gt;
&lt;br /&gt;
(** The [update] function overrides the entry for a given key in a&lt;br /&gt;
    partial map (or adds a new entry if the given key is not already&lt;br /&gt;
    present). *)&lt;br /&gt;
&lt;br /&gt;
Definition update (d : partial_map)&lt;br /&gt;
                  (x : id) (value : nat)&lt;br /&gt;
                  : partial_map :=&lt;br /&gt;
  record x value d.&lt;br /&gt;
&lt;br /&gt;
(** Last, the [find] function searches a [partial_map] for a given&lt;br /&gt;
    key.  It returns [None] if the key was not found and [Some val] if&lt;br /&gt;
    the key was associated with [val]. If the same key is mapped to&lt;br /&gt;
    multiple values, [find] will return the first one it&lt;br /&gt;
    encounters. *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint find (x : id) (d : partial_map) : natoption :=&lt;br /&gt;
  match d with&lt;br /&gt;
  | empty         =&amp;gt; None&lt;br /&gt;
  | record y v d&amp;#039; =&amp;gt; if beq_id x y&lt;br /&gt;
                     then Some v&lt;br /&gt;
                     else find x d&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 1 star (update_eq)  *)&lt;br /&gt;
Theorem update_eq :&lt;br /&gt;
  forall (d : partial_map) (x : id) (v: nat),&lt;br /&gt;
    find x (update d x v) = Some v.&lt;br /&gt;
Proof.&lt;br /&gt;
 (* FILL IN HERE *) Admitted.&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 1 star (update_neq)  *)&lt;br /&gt;
Theorem update_neq :&lt;br /&gt;
  forall (d : partial_map) (x y : id) (o: nat),&lt;br /&gt;
    beq_id x y = false -&amp;gt; find x (update d y o) = find x d.&lt;br /&gt;
Proof.&lt;br /&gt;
 (* FILL IN HERE *) Admitted.&lt;br /&gt;
(** [] *)&lt;br /&gt;
End PartialMap.&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 2 stars (baz_num_elts)  *)&lt;br /&gt;
(** Consider the following inductive definition: *)&lt;br /&gt;
&lt;br /&gt;
Inductive baz : Type :=&lt;br /&gt;
  | Baz1 : baz -&amp;gt; baz&lt;br /&gt;
  | Baz2 : baz -&amp;gt; bool -&amp;gt; baz.&lt;br /&gt;
&lt;br /&gt;
(** How _many_ elements does the type [baz] have?  (Answer in English&lt;br /&gt;
    or the natural language of your choice.)&lt;br /&gt;
&lt;br /&gt;
(* FILL IN HERE *)&lt;br /&gt;
*)&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(** $Date: 2017-10-10 09:30:37 -0400 (Tue, 10 Oct 2017) $ *)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jorcatote</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/SLC2018/index.php?title=Tema_3&amp;diff=59</id>
		<title>Tema 3</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/SLC2018/index.php?title=Tema_3&amp;diff=59"/>
		<updated>2018-03-21T17:59:48Z</updated>

		<summary type="html">&lt;p&gt;Jorcatote: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* Datos estructurados en Coq *)&lt;br /&gt;
&lt;br /&gt;
Require Export Induction.&lt;br /&gt;
&lt;br /&gt;
Module NatList. &lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § Pares de númenros &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. El tipo de los números naturales es natprod y su&lt;br /&gt;
   constructor es pair.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive natprod : Type :=&lt;br /&gt;
  pair : nat -&amp;gt; nat -&amp;gt; natprod.&lt;br /&gt;
&lt;br /&gt;
Check (pair 3 5).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      fst : natprod -&amp;gt; nat&lt;br /&gt;
   tal que (fst p) es la primera componente de p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition fst (p : natprod) : nat := &lt;br /&gt;
  match p with&lt;br /&gt;
  | pair x y =&amp;gt; x&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Evaluar la expresión &lt;br /&gt;
      fst (pair 3 5)&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Eval compute in (fst (pair 3 5)).&lt;br /&gt;
(* ===&amp;gt; 3 *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      snd : natprod -&amp;gt; nat&lt;br /&gt;
   tal que (snd p) es la segunda componente de p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition snd (p : natprod) : nat := &lt;br /&gt;
  match p with&lt;br /&gt;
  | pair x y =&amp;gt; y&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la notación (x,y) como una abreviaura de (pair x y).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;( x , y )&amp;quot; := (pair x y).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Evaluar la expresión &lt;br /&gt;
      fst (3,5)&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Eval compute in (fst (3,5)).&lt;br /&gt;
(* ===&amp;gt; 3 *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Redefinir la función fst usando la abreviatura de pares.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition fst&amp;#039; (p : natprod) : nat := &lt;br /&gt;
  match p with&lt;br /&gt;
  | (x,y) =&amp;gt; x&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Redefinir la función snd usando la abreviatura de pares.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition snd&amp;#039; (p : natprod) : nat := &lt;br /&gt;
  match p with&lt;br /&gt;
  | (x,y) =&amp;gt; y&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      swap_pair : natprod -&amp;gt; natprod&lt;br /&gt;
   tal que (swap_pair p) es el par obtenido intercambiando las&lt;br /&gt;
   componentes de p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition swap_pair (p : natprod) : natprod := &lt;br /&gt;
  match p with&lt;br /&gt;
  | (x,y) =&amp;gt; (y,x)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que para todos los naturales&lt;br /&gt;
      (n,m) = (fst (n,m), snd (n,m)).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem surjective_pairing&amp;#039; : forall (n m : nat),&lt;br /&gt;
  (n,m) = (fst (n,m), snd (n,m)).&lt;br /&gt;
Proof.&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que para todo par de naturales&lt;br /&gt;
      p = (fst p, snd p).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem surjective_pairing_stuck : forall (p : natprod),&lt;br /&gt;
  p = (fst p, snd p).&lt;br /&gt;
Proof.&lt;br /&gt;
  simpl. (* No reduce nada. *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
Theorem surjective_pairing : forall (p : natprod),&lt;br /&gt;
  p = (fst p, snd p).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros p.  destruct p as [n m].  simpl.  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1. Demostrar que para todo par de naturales p,&lt;br /&gt;
      (snd p, fst p) = swap_pair p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem snd_fst_is_swap : forall (p : natprod),&lt;br /&gt;
  (snd p, fst p) = swap_pair p.&lt;br /&gt;
Admitted.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2. Demostrar que para todo par de naturales p,&lt;br /&gt;
      fst (swap_pair p) = snd p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem fst_swap_is_snd : forall (p : natprod),&lt;br /&gt;
  fst (swap_pair p) = snd p.&lt;br /&gt;
Admitted.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § Listas de números &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. natlist es la lista de los números naturales y sus&lt;br /&gt;
   constructores son &lt;br /&gt;
   + nil (la lista vacía) y &lt;br /&gt;
   + cons (tal que (cons x ys) es la lista obtenida añadiéndole x a ys. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive natlist : Type :=&lt;br /&gt;
  | nil  : natlist&lt;br /&gt;
  | cons : nat -&amp;gt; natlist -&amp;gt; natlist.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la constante &lt;br /&gt;
      mylist : natlist&lt;br /&gt;
   que es la lista cuyos elementos son 1, 2 y 3.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition mylist := cons 1 (cons 2 (cons 3 nil)).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la notación (x :: ys) como una abreviatura de &lt;br /&gt;
   (cons x ys).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;x :: l&amp;quot; := (cons x l)&lt;br /&gt;
                     (at level 60, right associativity).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la notación de las listas finitas escribiendo sus&lt;br /&gt;
   elementos entre corchetes y separados por puntos y comas.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;[ ]&amp;quot; := nil.&lt;br /&gt;
Notation &amp;quot;[ x ; .. ; y ]&amp;quot; := (cons x .. (cons y nil) ..).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Distintas representaciones de mylist.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition mylist1 := 1 :: (2 :: (3 :: nil)).&lt;br /&gt;
Definition mylist2 := 1 :: 2 :: 3 :: nil.&lt;br /&gt;
Definition mylist3 := [1;2;3].&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ Repeat  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      repeat : nat -&amp;gt; nat -&amp;gt; natlist&lt;br /&gt;
   tal que (repeat n k) es la lista formada por k veces el número n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint repeat (n count : nat) : natlist :=&lt;br /&gt;
  match count with&lt;br /&gt;
  | O        =&amp;gt; nil&lt;br /&gt;
  | S count&amp;#039; =&amp;gt; n :: (repeat n count&amp;#039;)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ Length  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      length : natlist -&amp;gt; nat&lt;br /&gt;
   tal que (length xs) es el número de elementos de xs.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint length (l:natlist) : nat :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil    =&amp;gt; O&lt;br /&gt;
  | h :: t =&amp;gt; S (length t)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ Append  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      append : natlist -&amp;gt; natlist -&amp;gt; natlist&lt;br /&gt;
   tal que (append xs ys) es la concatenación de xs e ys.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
Fixpoint app (l1 l2 : natlist) : natlist :=&lt;br /&gt;
  match l1 with&lt;br /&gt;
  | nil    =&amp;gt; l2&lt;br /&gt;
  | h :: t =&amp;gt; h :: (app t l2)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la notación (xs ++ ys) como una abreviaura de &lt;br /&gt;
   (append xs ys).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;x ++ y&amp;quot; := (app x y)&lt;br /&gt;
                     (right associativity, at level 60).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que&lt;br /&gt;
      [1;2;3] ++ [4;5] = [1;2;3;4;5].&lt;br /&gt;
      nil     ++ [4;5] = [4;5].&lt;br /&gt;
      [1;2;3] ++ nil   = [1;2;3].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example test_app1: [1;2;3] ++ [4;5] = [1;2;3;4;5].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
Example test_app2: nil ++ [4;5] = [4;5].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
Example test_app3: [1;2;3] ++ nil = [1;2;3].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ Head y tail  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      hd : nat -&amp;gt; natlist -&amp;gt; natlist&lt;br /&gt;
   tal que (hd d xs) es el primer elemento de xs o d, si xs es la lista&lt;br /&gt;
   vacía. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition hd (default:nat) (l:natlist) : nat :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil    =&amp;gt; default&lt;br /&gt;
  | h :: t =&amp;gt; h&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      tl : natlist -&amp;gt; natlist&lt;br /&gt;
   tal que (tl xs) es el resto de xs.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition tl (l:natlist) : natlist :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil    =&amp;gt; nil&lt;br /&gt;
  | h :: t =&amp;gt; t&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que &lt;br /&gt;
       hd 0 [1;2;3] = 1.&lt;br /&gt;
       hd 0 []      = 0.&lt;br /&gt;
       tl [1;2;3]   = [2;3].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example test_hd1: hd 0 [1;2;3] = 1.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
Example test_hd2: hd 0 [] = 0.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
Example test_tl: tl [1;2;3] = [2;3].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3. Definir la función&lt;br /&gt;
      nonzeros : natlist -&amp;gt; natlist&lt;br /&gt;
   tal que (nonzeros xs) es la lista de los elementos de xs distintos de&lt;br /&gt;
   cero. Por ejemplo,&lt;br /&gt;
      nonzeros [0;1;0;2;3;0;0] = [1;2;3].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint nonzeros (l:natlist) : natlist :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil =&amp;gt; nil&lt;br /&gt;
  | a::bs =&amp;gt; match a with&lt;br /&gt;
            | 0 =&amp;gt; nonzeros bs &lt;br /&gt;
            | _ =&amp;gt;  a:: nonzeros bs end&lt;br /&gt;
 end.&lt;br /&gt;
Example test_nonzeros:&lt;br /&gt;
  nonzeros [0;1;0;2;3;0;0] = [1;2;3].&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4. Definir la función&lt;br /&gt;
      oddmembers : natlist -&amp;gt; natlist&lt;br /&gt;
   tal que (oddmembers xs) es la lista de los elementos impares de&lt;br /&gt;
   xs. Por ejemplo,&lt;br /&gt;
      oddmembers [0;1;0;2;3;0;0] = [1;3].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint oddmembers (l:natlist) : natlist :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil =&amp;gt; nil&lt;br /&gt;
  | t::xs =&amp;gt; if oddb t then t :: oddmembers xs else oddmembers xs&lt;br /&gt;
  end.&lt;br /&gt;
 &lt;br /&gt;
Example test_oddmembers:&lt;br /&gt;
  oddmembers [0;1;0;2;3;0;0] = [1;3].&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5. Definir la función&lt;br /&gt;
      countoddmembers : natlist -&amp;gt; nat&lt;br /&gt;
   tal que (countoddmembers xs) es el número de elementos impares de&lt;br /&gt;
   xs. Por ejemplo,&lt;br /&gt;
      countoddmembers [1;0;3;1;4;5] = 4.&lt;br /&gt;
      countoddmembers [0;2;4]       = 0.&lt;br /&gt;
      countoddmembers nil           = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition countoddmembers (l:natlist) : nat :=&lt;br /&gt;
 length (oddmembers l). &lt;br /&gt;
&lt;br /&gt;
Example test_countoddmembers1:&lt;br /&gt;
  countoddmembers [1;0;3;1;4;5] = 4.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_countoddmembers2:&lt;br /&gt;
  countoddmembers [0;2;4] = 0.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_countoddmembers3:&lt;br /&gt;
  countoddmembers nil = 0.&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 6. Definir la función&lt;br /&gt;
      alternate : natlist -&amp;gt; natlist -&amp;gt; natlist&lt;br /&gt;
   tal que (alternate xs ys) es la lista obtenida intercalando los&lt;br /&gt;
   elementos de xs e ys. Por ejemplo,&lt;br /&gt;
      alternate [1;2;3] [4;5;6] = [1;4;2;5;3;6].&lt;br /&gt;
      alternate [1] [4;5;6]     = [1;4;5;6].&lt;br /&gt;
      alternate [1;2;3] [4]     = [1;4;2;3].&lt;br /&gt;
      alternate [] [20;30]      = [20;30].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint alternate (l1 l2 : natlist) : natlist :=&lt;br /&gt;
  match l1 with&lt;br /&gt;
  | nil =&amp;gt; l2&lt;br /&gt;
  | t::xs =&amp;gt; match l2 with&lt;br /&gt;
            | nil =&amp;gt; t::xs&lt;br /&gt;
            | p::ys =&amp;gt; t::p::alternate xs ys end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_alternate1:&lt;br /&gt;
  alternate [1;2;3] [4;5;6] = [1;4;2;5;3;6].&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_alternate2:&lt;br /&gt;
  alternate [1] [4;5;6] = [1;4;5;6].&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_alternate3:&lt;br /&gt;
  alternate [1;2;3] [4] = [1;4;2;3].&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_alternate4:&lt;br /&gt;
  alternate [] [20;30] = [20;30].&lt;br /&gt;
  reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(* ----------------------------------------------------------------- *)&lt;br /&gt;
(** *** Bags via Lists *)&lt;br /&gt;
&lt;br /&gt;
(** A [bag] (or [multiset]) is like a set, except that each element&lt;br /&gt;
    can appear multiple times rather than just once.  One possible&lt;br /&gt;
    implementation is to represent a bag of numbers as a list. *)&lt;br /&gt;
&lt;br /&gt;
Definition bag := natlist.&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 3 stars, recommended (bag_functions)  *)&lt;br /&gt;
(** Complete the following definitions for the functions&lt;br /&gt;
    [count], [sum], [add], and [member] for bags. *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint count (v:nat) (s:bag) : nat&lt;br /&gt;
  (* REPLACE THIS LINE WITH &amp;quot;:= _your_definition_ .&amp;quot; *). Admitted.&lt;br /&gt;
&lt;br /&gt;
(** All these proofs can be done just by [reflexivity]. *)&lt;br /&gt;
&lt;br /&gt;
Example test_count1:              count 1 [1;2;3;1;4;1] = 3.&lt;br /&gt;
 (* FILL IN HERE *) Admitted.&lt;br /&gt;
Example test_count2:              count 6 [1;2;3;1;4;1] = 0.&lt;br /&gt;
 (* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
(** Multiset [sum] is similar to set [union]: [sum a b] contains all&lt;br /&gt;
    the elements of [a] and of [b].  (Mathematicians usually define&lt;br /&gt;
    [union] on multisets a little bit differently -- using max instead&lt;br /&gt;
    of sum -- which is why we don&amp;#039;t use that name for this operation.)&lt;br /&gt;
    For [sum] we&amp;#039;re giving you a header that does not give explicit&lt;br /&gt;
    names to the arguments.  Moreover, it uses the keyword&lt;br /&gt;
    [Definition] instead of [Fixpoint], so even if you had names for&lt;br /&gt;
    the arguments, you wouldn&amp;#039;t be able to process them recursively.&lt;br /&gt;
    The point of stating the question this way is to encourage you to&lt;br /&gt;
    think about whether [sum] can be implemented in another way --&lt;br /&gt;
    perhaps by using functions that have already been defined.  *)&lt;br /&gt;
&lt;br /&gt;
Definition sum : bag -&amp;gt; bag -&amp;gt; bag&lt;br /&gt;
  (* REPLACE THIS LINE WITH &amp;quot;:= _your_definition_ .&amp;quot; *). Admitted.&lt;br /&gt;
&lt;br /&gt;
Example test_sum1:              count 1 (sum [1;2;3] [1;4;1]) = 3.&lt;br /&gt;
 (* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
Definition add (v:nat) (s:bag) : bag&lt;br /&gt;
  (* REPLACE THIS LINE WITH &amp;quot;:= _your_definition_ .&amp;quot; *). Admitted.&lt;br /&gt;
&lt;br /&gt;
Example test_add1:                count 1 (add 1 [1;4;1]) = 3.&lt;br /&gt;
 (* FILL IN HERE *) Admitted.&lt;br /&gt;
Example test_add2:                count 5 (add 1 [1;4;1]) = 0.&lt;br /&gt;
 (* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
Definition member (v:nat) (s:bag) : bool&lt;br /&gt;
  (* REPLACE THIS LINE WITH &amp;quot;:= _your_definition_ .&amp;quot; *). Admitted.&lt;br /&gt;
&lt;br /&gt;
Example test_member1:             member 1 [1;4;1] = true.&lt;br /&gt;
 (* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
Example test_member2:             member 2 [1;4;1] = false.&lt;br /&gt;
 (* FILL IN HERE *) Admitted.&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 3 stars, optional (bag_more_functions)  *)&lt;br /&gt;
(** Here are some more bag functions for you to practice with. *)&lt;br /&gt;
&lt;br /&gt;
(** When remove_one is applied to a bag without the number to remove,&lt;br /&gt;
   it should return the same bag unchanged. *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint remove_one (v:nat) (s:bag) : bag&lt;br /&gt;
  (* REPLACE THIS LINE WITH &amp;quot;:= _your_definition_ .&amp;quot; *). Admitted.&lt;br /&gt;
&lt;br /&gt;
Example test_remove_one1:&lt;br /&gt;
  count 5 (remove_one 5 [2;1;5;4;1]) = 0.&lt;br /&gt;
  (* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
Example test_remove_one2:&lt;br /&gt;
  count 5 (remove_one 5 [2;1;4;1]) = 0.&lt;br /&gt;
  (* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
Example test_remove_one3:&lt;br /&gt;
  count 4 (remove_one 5 [2;1;4;5;1;4]) = 2.&lt;br /&gt;
  (* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
Example test_remove_one4:&lt;br /&gt;
  count 5 (remove_one 5 [2;1;5;4;5;1;4]) = 1.&lt;br /&gt;
  (* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
Fixpoint remove_all (v:nat) (s:bag) : bag&lt;br /&gt;
  (* REPLACE THIS LINE WITH &amp;quot;:= _your_definition_ .&amp;quot; *). Admitted.&lt;br /&gt;
&lt;br /&gt;
Example test_remove_all1:  count 5 (remove_all 5 [2;1;5;4;1]) = 0.&lt;br /&gt;
 (* FILL IN HERE *) Admitted.&lt;br /&gt;
Example test_remove_all2:  count 5 (remove_all 5 [2;1;4;1]) = 0.&lt;br /&gt;
 (* FILL IN HERE *) Admitted.&lt;br /&gt;
Example test_remove_all3:  count 4 (remove_all 5 [2;1;4;5;1;4]) = 2.&lt;br /&gt;
 (* FILL IN HERE *) Admitted.&lt;br /&gt;
Example test_remove_all4:  count 5 (remove_all 5 [2;1;5;4;5;1;4;5;1;4]) = 0.&lt;br /&gt;
 (* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
Fixpoint subset (s1:bag) (s2:bag) : bool&lt;br /&gt;
  (* REPLACE THIS LINE WITH &amp;quot;:= _your_definition_ .&amp;quot; *). Admitted.&lt;br /&gt;
&lt;br /&gt;
Example test_subset1:              subset [1;2] [2;1;4;1] = true.&lt;br /&gt;
 (* FILL IN HERE *) Admitted.&lt;br /&gt;
Example test_subset2:              subset [1;2;2] [2;1;4;1] = false.&lt;br /&gt;
 (* FILL IN HERE *) Admitted.&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 3 stars, recommended (bag_theorem)  *)&lt;br /&gt;
(** Write down an interesting theorem [bag_theorem] about bags&lt;br /&gt;
    involving the functions [count] and [add], and prove it.  Note&lt;br /&gt;
    that, since this problem is somewhat open-ended, it&amp;#039;s possible&lt;br /&gt;
    that you may come up with a theorem which is true, but whose proof&lt;br /&gt;
    requires techniques you haven&amp;#039;t learned yet.  Feel free to ask for&lt;br /&gt;
    help if you get stuck! *)&lt;br /&gt;
&lt;br /&gt;
(*&lt;br /&gt;
Theorem bag_theorem : ...&lt;br /&gt;
Proof.&lt;br /&gt;
  ...&lt;br /&gt;
Qed.&lt;br /&gt;
*)&lt;br /&gt;
&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(* ################################################################# *)&lt;br /&gt;
(** * Reasoning About Lists *)&lt;br /&gt;
&lt;br /&gt;
(** As with numbers, simple facts about list-processing&lt;br /&gt;
    functions can sometimes be proved entirely by simplification.  For&lt;br /&gt;
    example, the simplification performed by [reflexivity] is enough&lt;br /&gt;
    for this theorem... *)&lt;br /&gt;
&lt;br /&gt;
Theorem nil_app : forall l:natlist,&lt;br /&gt;
  [] ++ l = l.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(** ... because the [[]] is substituted into the&lt;br /&gt;
    &amp;quot;scrutinee&amp;quot; (the expression whose value is being &amp;quot;scrutinized&amp;quot; by&lt;br /&gt;
    the match) in the definition of [app], allowing the match itself&lt;br /&gt;
    to be simplified. *)&lt;br /&gt;
&lt;br /&gt;
(** Also, as with numbers, it is sometimes helpful to perform case&lt;br /&gt;
    analysis on the possible shapes (empty or non-empty) of an unknown&lt;br /&gt;
    list. *)&lt;br /&gt;
&lt;br /&gt;
Theorem tl_length_pred : forall l:natlist,&lt;br /&gt;
  pred (length l) = length (tl l).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros l. destruct l as [| n l&amp;#039;].&lt;br /&gt;
  - (* l = nil *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  - (* l = cons n l&amp;#039; *)&lt;br /&gt;
    reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(** Here, the [nil] case works because we&amp;#039;ve chosen to define&lt;br /&gt;
    [tl nil = nil]. Notice that the [as] annotation on the [destruct]&lt;br /&gt;
    tactic here introduces two names, [n] and [l&amp;#039;], corresponding to&lt;br /&gt;
    the fact that the [cons] constructor for lists takes two&lt;br /&gt;
    arguments (the head and tail of the list it is constructing). *)&lt;br /&gt;
&lt;br /&gt;
(** Usually, though, interesting theorems about lists require&lt;br /&gt;
    induction for their proofs. *)&lt;br /&gt;
&lt;br /&gt;
(* ----------------------------------------------------------------- *)&lt;br /&gt;
(** *** Micro-Sermon *)&lt;br /&gt;
&lt;br /&gt;
(** Simply reading example proof scripts will not get you very far!&lt;br /&gt;
    It is important to work through the details of each one, using Coq&lt;br /&gt;
    and thinking about what each step achieves.  Otherwise it is more&lt;br /&gt;
    or less guaranteed that the exercises will make no sense when you&lt;br /&gt;
    get to them.  &amp;#039;Nuff said. *)&lt;br /&gt;
&lt;br /&gt;
(* ================================================================= *)&lt;br /&gt;
(** ** Induction on Lists *)&lt;br /&gt;
&lt;br /&gt;
(** Proofs by induction over datatypes like [natlist] are a&lt;br /&gt;
    little less familiar than standard natural number induction, but&lt;br /&gt;
    the idea is equally simple.  Each [Inductive] declaration defines&lt;br /&gt;
    a set of data values that can be built up using the declared&lt;br /&gt;
    constructors: a boolean can be either [true] or [false]; a number&lt;br /&gt;
    can be either [O] or [S] applied to another number; a list can be&lt;br /&gt;
    either [nil] or [cons] applied to a number and a list.&lt;br /&gt;
&lt;br /&gt;
    Moreover, applications of the declared constructors to one another&lt;br /&gt;
    are the _only_ possible shapes that elements of an inductively&lt;br /&gt;
    defined set can have, and this fact directly gives rise to a way&lt;br /&gt;
    of reasoning about inductively defined sets: a number is either&lt;br /&gt;
    [O] or else it is [S] applied to some _smaller_ number; a list is&lt;br /&gt;
    either [nil] or else it is [cons] applied to some number and some&lt;br /&gt;
    _smaller_ list; etc. So, if we have in mind some proposition [P]&lt;br /&gt;
    that mentions a list [l] and we want to argue that [P] holds for&lt;br /&gt;
    _all_ lists, we can reason as follows:&lt;br /&gt;
&lt;br /&gt;
      - First, show that [P] is true of [l] when [l] is [nil].&lt;br /&gt;
&lt;br /&gt;
      - Then show that [P] is true of [l] when [l] is [cons n l&amp;#039;] for&lt;br /&gt;
        some number [n] and some smaller list [l&amp;#039;], assuming that [P]&lt;br /&gt;
        is true for [l&amp;#039;].&lt;br /&gt;
&lt;br /&gt;
    Since larger lists can only be built up from smaller ones,&lt;br /&gt;
    eventually reaching [nil], these two arguments together establish&lt;br /&gt;
    the truth of [P] for all lists [l].  Here&amp;#039;s a concrete example: *)&lt;br /&gt;
&lt;br /&gt;
Theorem app_assoc : forall l1 l2 l3 : natlist,&lt;br /&gt;
  (l1 ++ l2) ++ l3 = l1 ++ (l2 ++ l3).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros l1 l2 l3. induction l1 as [| n l1&amp;#039; IHl1&amp;#039;].&lt;br /&gt;
  - (* l1 = nil *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  - (* l1 = cons n l1&amp;#039; *)&lt;br /&gt;
    simpl. rewrite -&amp;gt; IHl1&amp;#039;. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(** Notice that, as when doing induction on natural numbers, the&lt;br /&gt;
    [as...] clause provided to the [induction] tactic gives a name to&lt;br /&gt;
    the induction hypothesis corresponding to the smaller list [l1&amp;#039;]&lt;br /&gt;
    in the [cons] case. Once again, this Coq proof is not especially&lt;br /&gt;
    illuminating as a static written document -- it is easy to see&lt;br /&gt;
    what&amp;#039;s going on if you are reading the proof in an interactive Coq&lt;br /&gt;
    session and you can see the current goal and context at each&lt;br /&gt;
    point, but this state is not visible in the written-down parts of&lt;br /&gt;
    the Coq proof.  So a natural-language proof -- one written for&lt;br /&gt;
    human readers -- will need to include more explicit signposts; in&lt;br /&gt;
    particular, it will help the reader stay oriented if we remind&lt;br /&gt;
    them exactly what the induction hypothesis is in the second&lt;br /&gt;
    case. *)&lt;br /&gt;
&lt;br /&gt;
(** For comparison, here is an informal proof of the same theorem. *)&lt;br /&gt;
&lt;br /&gt;
(** _Theorem_: For all lists [l1], [l2], and [l3],&lt;br /&gt;
   [(l1 ++ l2) ++ l3 = l1 ++ (l2 ++ l3)].&lt;br /&gt;
&lt;br /&gt;
   _Proof_: By induction on [l1].&lt;br /&gt;
&lt;br /&gt;
   - First, suppose [l1 = []].  We must show&lt;br /&gt;
&lt;br /&gt;
       ([] ++ l2) ++ l3 = [] ++ (l2 ++ l3),&lt;br /&gt;
&lt;br /&gt;
     which follows directly from the definition of [++].&lt;br /&gt;
&lt;br /&gt;
   - Next, suppose [l1 = n::l1&amp;#039;], with&lt;br /&gt;
&lt;br /&gt;
       (l1&amp;#039; ++ l2) ++ l3 = l1&amp;#039; ++ (l2 ++ l3)&lt;br /&gt;
&lt;br /&gt;
     (the induction hypothesis). We must show&lt;br /&gt;
&lt;br /&gt;
       ((n :: l1&amp;#039;) ++ l2) ++ l3 = (n :: l1&amp;#039;) ++ (l2 ++ l3).&lt;br /&gt;
&lt;br /&gt;
     By the definition of [++], this follows from&lt;br /&gt;
&lt;br /&gt;
       n :: ((l1&amp;#039; ++ l2) ++ l3) = n :: (l1&amp;#039; ++ (l2 ++ l3)),&lt;br /&gt;
&lt;br /&gt;
     which is immediate from the induction hypothesis.  [] *)&lt;br /&gt;
&lt;br /&gt;
(* ----------------------------------------------------------------- *)&lt;br /&gt;
(** *** Reversing a List *)&lt;br /&gt;
&lt;br /&gt;
(** For a slightly more involved example of inductive proof over&lt;br /&gt;
    lists, suppose we use [app] to define a list-reversing function&lt;br /&gt;
    [rev]: *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint rev (l:natlist) : natlist :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil    =&amp;gt; nil&lt;br /&gt;
  | h :: t =&amp;gt; rev t ++ [h]&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_rev1:            rev [1;2;3] = [3;2;1].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
Example test_rev2:            rev nil = nil.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ----------------------------------------------------------------- *)&lt;br /&gt;
(** *** Properties of [rev] *)&lt;br /&gt;
&lt;br /&gt;
(** Now let&amp;#039;s prove some theorems about our newly defined [rev].&lt;br /&gt;
    For something a bit more challenging than what we&amp;#039;ve seen, let&amp;#039;s&lt;br /&gt;
    prove that reversing a list does not change its length.  Our first&lt;br /&gt;
    attempt gets stuck in the successor case... *)&lt;br /&gt;
&lt;br /&gt;
Theorem rev_length_firsttry : forall l : natlist,&lt;br /&gt;
  length (rev l) = length l.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros l. induction l as [| n l&amp;#039; IHl&amp;#039;].&lt;br /&gt;
  - (* l = [] *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  - (* l = n :: l&amp;#039; *)&lt;br /&gt;
    (* This is the tricky case.  Let&amp;#039;s begin as usual&lt;br /&gt;
       by simplifying. *)&lt;br /&gt;
    simpl.&lt;br /&gt;
    (* Now we seem to be stuck: the goal is an equality&lt;br /&gt;
       involving [++], but we don&amp;#039;t have any useful equations&lt;br /&gt;
       in either the immediate context or in the global&lt;br /&gt;
       environment!  We can make a little progress by using&lt;br /&gt;
       the IH to rewrite the goal... *)&lt;br /&gt;
    rewrite &amp;lt;- IHl&amp;#039;.&lt;br /&gt;
    (* ... but now we can&amp;#039;t go any further. *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(** So let&amp;#039;s take the equation relating [++] and [length] that&lt;br /&gt;
    would have enabled us to make progress and prove it as a separate&lt;br /&gt;
    lemma. *)&lt;br /&gt;
&lt;br /&gt;
Theorem app_length : forall l1 l2 : natlist,&lt;br /&gt;
  length (l1 ++ l2) = (length l1) + (length l2).&lt;br /&gt;
Proof.&lt;br /&gt;
  (* WORKED IN CLASS *)&lt;br /&gt;
  intros l1 l2. induction l1 as [| n l1&amp;#039; IHl1&amp;#039;].&lt;br /&gt;
  - (* l1 = nil *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  - (* l1 = cons *)&lt;br /&gt;
    simpl. rewrite -&amp;gt; IHl1&amp;#039;. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(** Note that, to make the lemma as general as possible, we&lt;br /&gt;
    quantify over _all_ [natlist]s, not just those that result from an&lt;br /&gt;
    application of [rev].  This should seem natural, because the truth&lt;br /&gt;
    of the goal clearly doesn&amp;#039;t depend on the list having been&lt;br /&gt;
    reversed.  Moreover, it is easier to prove the more general&lt;br /&gt;
    property. *)&lt;br /&gt;
&lt;br /&gt;
(** Now we can complete the original proof. *)&lt;br /&gt;
&lt;br /&gt;
Theorem rev_length : forall l : natlist,&lt;br /&gt;
  length (rev l) = length l.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros l. induction l as [| n l&amp;#039; IHl&amp;#039;].&lt;br /&gt;
  - (* l = nil *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  - (* l = cons *)&lt;br /&gt;
    simpl. rewrite -&amp;gt; app_length, plus_comm.&lt;br /&gt;
    simpl. rewrite -&amp;gt; IHl&amp;#039;. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(** For comparison, here are informal proofs of these two theorems:&lt;br /&gt;
&lt;br /&gt;
    _Theorem_: For all lists [l1] and [l2],&lt;br /&gt;
       [length (l1 ++ l2) = length l1 + length l2].&lt;br /&gt;
&lt;br /&gt;
    _Proof_: By induction on [l1].&lt;br /&gt;
&lt;br /&gt;
    - First, suppose [l1 = []].  We must show&lt;br /&gt;
&lt;br /&gt;
        length ([] ++ l2) = length [] + length l2,&lt;br /&gt;
&lt;br /&gt;
      which follows directly from the definitions of&lt;br /&gt;
      [length] and [++].&lt;br /&gt;
&lt;br /&gt;
    - Next, suppose [l1 = n::l1&amp;#039;], with&lt;br /&gt;
&lt;br /&gt;
        length (l1&amp;#039; ++ l2) = length l1&amp;#039; + length l2.&lt;br /&gt;
&lt;br /&gt;
      We must show&lt;br /&gt;
&lt;br /&gt;
        length ((n::l1&amp;#039;) ++ l2) = length (n::l1&amp;#039;) + length l2).&lt;br /&gt;
&lt;br /&gt;
      This follows directly from the definitions of [length] and [++]&lt;br /&gt;
      together with the induction hypothesis. [] *)&lt;br /&gt;
&lt;br /&gt;
(** _Theorem_: For all lists [l], [length (rev l) = length l].&lt;br /&gt;
&lt;br /&gt;
    _Proof_: By induction on [l].&lt;br /&gt;
&lt;br /&gt;
      - First, suppose [l = []].  We must show&lt;br /&gt;
&lt;br /&gt;
          length (rev []) = length [],&lt;br /&gt;
&lt;br /&gt;
        which follows directly from the definitions of [length]&lt;br /&gt;
        and [rev].&lt;br /&gt;
&lt;br /&gt;
      - Next, suppose [l = n::l&amp;#039;], with&lt;br /&gt;
&lt;br /&gt;
          length (rev l&amp;#039;) = length l&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
        We must show&lt;br /&gt;
&lt;br /&gt;
          length (rev (n :: l&amp;#039;)) = length (n :: l&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
        By the definition of [rev], this follows from&lt;br /&gt;
&lt;br /&gt;
          length ((rev l&amp;#039;) ++ [n]) = S (length l&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
        which, by the previous lemma, is the same as&lt;br /&gt;
&lt;br /&gt;
          length (rev l&amp;#039;) + length [n] = S (length l&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
        This follows directly from the induction hypothesis and the&lt;br /&gt;
        definition of [length]. [] *)&lt;br /&gt;
&lt;br /&gt;
(** The style of these proofs is rather longwinded and pedantic.&lt;br /&gt;
    After the first few, we might find it easier to follow proofs that&lt;br /&gt;
    give fewer details (which can easily work out in our own minds or&lt;br /&gt;
    on scratch paper if necessary) and just highlight the non-obvious&lt;br /&gt;
    steps.  In this more compressed style, the above proof might look&lt;br /&gt;
    like this: *)&lt;br /&gt;
&lt;br /&gt;
(** _Theorem_:&lt;br /&gt;
     For all lists [l], [length (rev l) = length l].&lt;br /&gt;
&lt;br /&gt;
    _Proof_: First, observe that [length (l ++ [n]) = S (length l)]&lt;br /&gt;
     for any [l] (this follows by a straightforward induction on [l]).&lt;br /&gt;
     The main property again follows by induction on [l], using the&lt;br /&gt;
     observation together with the induction hypothesis in the case&lt;br /&gt;
     where [l = n&amp;#039;::l&amp;#039;]. [] *)&lt;br /&gt;
&lt;br /&gt;
(** Which style is preferable in a given situation depends on&lt;br /&gt;
    the sophistication of the expected audience and how similar the&lt;br /&gt;
    proof at hand is to ones that the audience will already be&lt;br /&gt;
    familiar with.  The more pedantic style is a good default for our&lt;br /&gt;
    present purposes. *)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(* ================================================================= *)&lt;br /&gt;
(** ** [Search] *)&lt;br /&gt;
&lt;br /&gt;
(** We&amp;#039;ve seen that proofs can make use of other theorems we&amp;#039;ve&lt;br /&gt;
    already proved, e.g., using [rewrite].  But in order to refer to a&lt;br /&gt;
    theorem, we need to know its name!  Indeed, it is often hard even&lt;br /&gt;
    to remember what theorems have been proven, much less what they&lt;br /&gt;
    are called.&lt;br /&gt;
&lt;br /&gt;
    Coq&amp;#039;s [Search] command is quite helpful with this.  Typing&lt;br /&gt;
    [Search foo] will cause Coq to display a list of all theorems&lt;br /&gt;
    involving [foo].  For example, try uncommenting the following line&lt;br /&gt;
    to see a list of theorems that we have proved about [rev]: *)&lt;br /&gt;
&lt;br /&gt;
(*  Search rev. *)&lt;br /&gt;
&lt;br /&gt;
(** Keep [Search] in mind as you do the following exercises and&lt;br /&gt;
    throughout the rest of the book; it can save you a lot of time!&lt;br /&gt;
&lt;br /&gt;
    If you are using ProofGeneral, you can run [Search] with [C-c&lt;br /&gt;
    C-a C-a]. Pasting its response into your buffer can be&lt;br /&gt;
    accomplished with [C-c C-;]. *)&lt;br /&gt;
&lt;br /&gt;
(* ================================================================= *)&lt;br /&gt;
(** ** List Exercises, Part 1 *)&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 3 stars (list_exercises)  *)&lt;br /&gt;
(** More practice with lists: *)&lt;br /&gt;
&lt;br /&gt;
Theorem app_nil_r : forall l : natlist,&lt;br /&gt;
  l ++ [] = l.&lt;br /&gt;
Proof.&lt;br /&gt;
  (* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
Theorem rev_app_distr: forall l1 l2 : natlist,&lt;br /&gt;
  rev (l1 ++ l2) = rev l2 ++ rev l1.&lt;br /&gt;
Proof.&lt;br /&gt;
  (* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
Theorem rev_involutive : forall l : natlist,&lt;br /&gt;
  rev (rev l) = l.&lt;br /&gt;
Proof.&lt;br /&gt;
  (* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
(** There is a short solution to the next one.  If you find yourself&lt;br /&gt;
    getting tangled up, step back and try to look for a simpler&lt;br /&gt;
    way. *)&lt;br /&gt;
&lt;br /&gt;
Theorem app_assoc4 : forall l1 l2 l3 l4 : natlist,&lt;br /&gt;
  l1 ++ (l2 ++ (l3 ++ l4)) = ((l1 ++ l2) ++ l3) ++ l4.&lt;br /&gt;
Proof.&lt;br /&gt;
  (* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
(** An exercise about your implementation of [nonzeros]: *)&lt;br /&gt;
&lt;br /&gt;
Lemma nonzeros_app : forall l1 l2 : natlist,&lt;br /&gt;
  nonzeros (l1 ++ l2) = (nonzeros l1) ++ (nonzeros l2).&lt;br /&gt;
Proof.&lt;br /&gt;
  (* FILL IN HERE *) Admitted.&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 2 stars (beq_natlist)  *)&lt;br /&gt;
(** Fill in the definition of [beq_natlist], which compares&lt;br /&gt;
    lists of numbers for equality.  Prove that [beq_natlist l l]&lt;br /&gt;
    yields [true] for every list [l]. *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint beq_natlist (l1 l2 : natlist) : bool&lt;br /&gt;
  (* REPLACE THIS LINE WITH &amp;quot;:= _your_definition_ .&amp;quot; *). Admitted.&lt;br /&gt;
&lt;br /&gt;
Example test_beq_natlist1 :&lt;br /&gt;
  (beq_natlist nil nil = true).&lt;br /&gt;
 (* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
Example test_beq_natlist2 :&lt;br /&gt;
  beq_natlist [1;2;3] [1;2;3] = true.&lt;br /&gt;
(* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
Example test_beq_natlist3 :&lt;br /&gt;
  beq_natlist [1;2;3] [1;2;4] = false.&lt;br /&gt;
 (* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
Theorem beq_natlist_refl : forall l:natlist,&lt;br /&gt;
  true = beq_natlist l l.&lt;br /&gt;
Proof.&lt;br /&gt;
  (* FILL IN HERE *) Admitted.&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(* ================================================================= *)&lt;br /&gt;
(** ** List Exercises, Part 2 *)&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 3 stars, advanced (bag_proofs)  *)&lt;br /&gt;
(** Here are a couple of little theorems to prove about your&lt;br /&gt;
    definitions about bags above. *)&lt;br /&gt;
&lt;br /&gt;
Theorem count_member_nonzero : forall (s : bag),&lt;br /&gt;
  leb 1 (count 1 (1 :: s)) = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  (* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
(** The following lemma about [leb] might help you in the next proof. *)&lt;br /&gt;
&lt;br /&gt;
Theorem ble_n_Sn : forall n,&lt;br /&gt;
  leb n (S n) = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n. induction n as [| n&amp;#039; IHn&amp;#039;].&lt;br /&gt;
  - (* 0 *)&lt;br /&gt;
    simpl.  reflexivity.&lt;br /&gt;
  - (* S n&amp;#039; *)&lt;br /&gt;
    simpl.  rewrite IHn&amp;#039;.  reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem remove_decreases_count: forall (s : bag),&lt;br /&gt;
  leb (count 0 (remove_one 0 s)) (count 0 s) = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  (* FILL IN HERE *) Admitted.&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 3 stars, optional (bag_count_sum)  *)&lt;br /&gt;
(** Write down an interesting theorem [bag_count_sum] about bags&lt;br /&gt;
    involving the functions [count] and [sum], and prove it using&lt;br /&gt;
    Coq.  (You may find that the difficulty of the proof depends on&lt;br /&gt;
    how you defined [count]!) *)&lt;br /&gt;
(* FILL IN HERE *)&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 4 stars, advanced (rev_injective)  *)&lt;br /&gt;
(** Prove that the [rev] function is injective -- that is,&lt;br /&gt;
&lt;br /&gt;
    forall (l1 l2 : natlist), rev l1 = rev l2 -&amp;gt; l1 = l2.&lt;br /&gt;
&lt;br /&gt;
(There is a hard way and an easy way to do this.) *)&lt;br /&gt;
&lt;br /&gt;
(* FILL IN HERE *)&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(* ################################################################# *)&lt;br /&gt;
(** * Options *)&lt;br /&gt;
&lt;br /&gt;
(** Suppose we want to write a function that returns the [n]th&lt;br /&gt;
    element of some list.  If we give it type [nat -&amp;gt; natlist -&amp;gt; nat],&lt;br /&gt;
    then we&amp;#039;ll have to choose some number to return when the list is&lt;br /&gt;
    too short... *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint nth_bad (l:natlist) (n:nat) : nat :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil =&amp;gt; 42  (* arbitrary! *)&lt;br /&gt;
  | a :: l&amp;#039; =&amp;gt; match beq_nat n O with&lt;br /&gt;
               | true =&amp;gt; a&lt;br /&gt;
               | false =&amp;gt; nth_bad l&amp;#039; (pred n)&lt;br /&gt;
               end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(** This solution is not so good: If [nth_bad] returns [42], we&lt;br /&gt;
    can&amp;#039;t tell whether that value actually appears on the input&lt;br /&gt;
    without further processing. A better alternative is to change the&lt;br /&gt;
    return type of [nth_bad] to include an error value as a possible&lt;br /&gt;
    outcome. We call this type [natoption]. *)&lt;br /&gt;
&lt;br /&gt;
Inductive natoption : Type :=&lt;br /&gt;
  | Some : nat -&amp;gt; natoption&lt;br /&gt;
  | None : natoption.&lt;br /&gt;
&lt;br /&gt;
(** We can then change the above definition of [nth_bad] to&lt;br /&gt;
    return [None] when the list is too short and [Some a] when the&lt;br /&gt;
    list has enough members and [a] appears at position [n]. We call&lt;br /&gt;
    this new function [nth_error] to indicate that it may result in an&lt;br /&gt;
    error. *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint nth_error (l:natlist) (n:nat) : natoption :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil =&amp;gt; None&lt;br /&gt;
  | a :: l&amp;#039; =&amp;gt; match beq_nat n O with&lt;br /&gt;
               | true =&amp;gt; Some a&lt;br /&gt;
               | false =&amp;gt; nth_error l&amp;#039; (pred n)&lt;br /&gt;
               end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_nth_error1 : nth_error [4;5;6;7] 0 = Some 4.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
Example test_nth_error2 : nth_error [4;5;6;7] 3 = Some 7.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
Example test_nth_error3 : nth_error [4;5;6;7] 9 = None.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(** (In the HTML version, the boilerplate proofs of these&lt;br /&gt;
    examples are elided.  Click on a box if you want to see one.)&lt;br /&gt;
&lt;br /&gt;
    This example is also an opportunity to introduce one more small&lt;br /&gt;
    feature of Coq&amp;#039;s programming language: conditional&lt;br /&gt;
    expressions... *)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fixpoint nth_error&amp;#039; (l:natlist) (n:nat) : natoption :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil =&amp;gt; None&lt;br /&gt;
  | a :: l&amp;#039; =&amp;gt; if beq_nat n O then Some a&lt;br /&gt;
               else nth_error&amp;#039; l&amp;#039; (pred n)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(** Coq&amp;#039;s conditionals are exactly like those found in any other&lt;br /&gt;
    language, with one small generalization.  Since the boolean type&lt;br /&gt;
    is not built in, Coq actually supports conditional expressions over&lt;br /&gt;
    _any_ inductively defined type with exactly two constructors.  The&lt;br /&gt;
    guard is considered true if it evaluates to the first constructor&lt;br /&gt;
    in the [Inductive] definition and false if it evaluates to the&lt;br /&gt;
    second. *)&lt;br /&gt;
&lt;br /&gt;
(** The function below pulls the [nat] out of a [natoption], returning&lt;br /&gt;
    a supplied default in the [None] case. *)&lt;br /&gt;
&lt;br /&gt;
Definition option_elim (d : nat) (o : natoption) : nat :=&lt;br /&gt;
  match o with&lt;br /&gt;
  | Some n&amp;#039; =&amp;gt; n&amp;#039;&lt;br /&gt;
  | None =&amp;gt; d&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 2 stars (hd_error)  *)&lt;br /&gt;
(** Using the same idea, fix the [hd] function from earlier so we don&amp;#039;t&lt;br /&gt;
    have to pass a default element for the [nil] case.  *)&lt;br /&gt;
&lt;br /&gt;
Definition hd_error (l : natlist) : natoption&lt;br /&gt;
  (* REPLACE THIS LINE WITH &amp;quot;:= _your_definition_ .&amp;quot; *). Admitted.&lt;br /&gt;
&lt;br /&gt;
Example test_hd_error1 : hd_error [] = None.&lt;br /&gt;
 (* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
Example test_hd_error2 : hd_error [1] = Some 1.&lt;br /&gt;
 (* FILL IN HERE *) Admitted.&lt;br /&gt;
&lt;br /&gt;
Example test_hd_error3 : hd_error [5;6] = Some 5.&lt;br /&gt;
 (* FILL IN HERE *) Admitted.&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 1 star, optional (option_elim_hd)  *)&lt;br /&gt;
(** This exercise relates your new [hd_error] to the old [hd]. *)&lt;br /&gt;
&lt;br /&gt;
Theorem option_elim_hd : forall (l:natlist) (default:nat),&lt;br /&gt;
  hd default l = option_elim default (hd_error l).&lt;br /&gt;
Proof.&lt;br /&gt;
  (* FILL IN HERE *) Admitted.&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
End NatList.&lt;br /&gt;
&lt;br /&gt;
(* ################################################################# *)&lt;br /&gt;
(** * Partial Maps *)&lt;br /&gt;
&lt;br /&gt;
(** As a final illustration of how data structures can be defined in&lt;br /&gt;
    Coq, here is a simple _partial map_ data type, analogous to the&lt;br /&gt;
    map or dictionary data structures found in most programming&lt;br /&gt;
    languages. *)&lt;br /&gt;
&lt;br /&gt;
(** First, we define a new inductive datatype [id] to serve as the&lt;br /&gt;
    &amp;quot;keys&amp;quot; of our partial maps. *)&lt;br /&gt;
&lt;br /&gt;
Inductive id : Type :=&lt;br /&gt;
  | Id : nat -&amp;gt; id.&lt;br /&gt;
&lt;br /&gt;
(** Internally, an [id] is just a number.  Introducing a separate type&lt;br /&gt;
    by wrapping each nat with the tag [Id] makes definitions more&lt;br /&gt;
    readable and gives us the flexibility to change representations&lt;br /&gt;
    later if we wish. *)&lt;br /&gt;
&lt;br /&gt;
(** We&amp;#039;ll also need an equality test for [id]s: *)&lt;br /&gt;
&lt;br /&gt;
Definition beq_id (x1 x2 : id) :=&lt;br /&gt;
  match x1, x2 with&lt;br /&gt;
  | Id n1, Id n2 =&amp;gt; beq_nat n1 n2&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 1 star (beq_id_refl)  *)&lt;br /&gt;
Theorem beq_id_refl : forall x, true = beq_id x x.&lt;br /&gt;
Proof.&lt;br /&gt;
  (* FILL IN HERE *) Admitted.&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(** Now we define the type of partial maps: *)&lt;br /&gt;
&lt;br /&gt;
Module PartialMap.&lt;br /&gt;
Export NatList.&lt;br /&gt;
  &lt;br /&gt;
Inductive partial_map : Type :=&lt;br /&gt;
  | empty  : partial_map&lt;br /&gt;
  | record : id -&amp;gt; nat -&amp;gt; partial_map -&amp;gt; partial_map.&lt;br /&gt;
&lt;br /&gt;
(** This declaration can be read: &amp;quot;There are two ways to construct a&lt;br /&gt;
    [partial_map]: either using the constructor [empty] to represent an&lt;br /&gt;
    empty partial map, or by applying the constructor [record] to&lt;br /&gt;
    a key, a value, and an existing [partial_map] to construct a&lt;br /&gt;
    [partial_map] with an additional key-to-value mapping.&amp;quot; *)&lt;br /&gt;
&lt;br /&gt;
(** The [update] function overrides the entry for a given key in a&lt;br /&gt;
    partial map (or adds a new entry if the given key is not already&lt;br /&gt;
    present). *)&lt;br /&gt;
&lt;br /&gt;
Definition update (d : partial_map)&lt;br /&gt;
                  (x : id) (value : nat)&lt;br /&gt;
                  : partial_map :=&lt;br /&gt;
  record x value d.&lt;br /&gt;
&lt;br /&gt;
(** Last, the [find] function searches a [partial_map] for a given&lt;br /&gt;
    key.  It returns [None] if the key was not found and [Some val] if&lt;br /&gt;
    the key was associated with [val]. If the same key is mapped to&lt;br /&gt;
    multiple values, [find] will return the first one it&lt;br /&gt;
    encounters. *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint find (x : id) (d : partial_map) : natoption :=&lt;br /&gt;
  match d with&lt;br /&gt;
  | empty         =&amp;gt; None&lt;br /&gt;
  | record y v d&amp;#039; =&amp;gt; if beq_id x y&lt;br /&gt;
                     then Some v&lt;br /&gt;
                     else find x d&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 1 star (update_eq)  *)&lt;br /&gt;
Theorem update_eq :&lt;br /&gt;
  forall (d : partial_map) (x : id) (v: nat),&lt;br /&gt;
    find x (update d x v) = Some v.&lt;br /&gt;
Proof.&lt;br /&gt;
 (* FILL IN HERE *) Admitted.&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 1 star (update_neq)  *)&lt;br /&gt;
Theorem update_neq :&lt;br /&gt;
  forall (d : partial_map) (x y : id) (o: nat),&lt;br /&gt;
    beq_id x y = false -&amp;gt; find x (update d y o) = find x d.&lt;br /&gt;
Proof.&lt;br /&gt;
 (* FILL IN HERE *) Admitted.&lt;br /&gt;
(** [] *)&lt;br /&gt;
End PartialMap.&lt;br /&gt;
&lt;br /&gt;
(** **** Exercise: 2 stars (baz_num_elts)  *)&lt;br /&gt;
(** Consider the following inductive definition: *)&lt;br /&gt;
&lt;br /&gt;
Inductive baz : Type :=&lt;br /&gt;
  | Baz1 : baz -&amp;gt; baz&lt;br /&gt;
  | Baz2 : baz -&amp;gt; bool -&amp;gt; baz.&lt;br /&gt;
&lt;br /&gt;
(** How _many_ elements does the type [baz] have?  (Answer in English&lt;br /&gt;
    or the natural language of your choice.)&lt;br /&gt;
&lt;br /&gt;
(* FILL IN HERE *)&lt;br /&gt;
*)&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(** $Date: 2017-10-10 09:30:37 -0400 (Tue, 10 Oct 2017) $ *)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jorcatote</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/SLC2018/index.php?title=Relaci%C3%B3n_1&amp;diff=45</id>
		<title>Relación 1</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/SLC2018/index.php?title=Relaci%C3%B3n_1&amp;diff=45"/>
		<updated>2018-02-28T16:03:19Z</updated>

		<summary type="html">&lt;p&gt;Jorcatote: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* Relación 1: Programación funcional en Coq *)&lt;br /&gt;
&lt;br /&gt;
Definition admit {T: Type} : T.  Admitted.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1. Definir la función &lt;br /&gt;
      nandb :: bool -&amp;gt; bool -&amp;gt; bool &lt;br /&gt;
   tal que (nanb x y) se verifica si x e y no son verdaderos.&lt;br /&gt;
&lt;br /&gt;
   Demostrar las siguientes propiedades de nand&lt;br /&gt;
      (nandb true  false) = true.&lt;br /&gt;
      (nandb false false) = true.&lt;br /&gt;
      (nandb false true)  = true.&lt;br /&gt;
      (nandb true  true)  = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* alerodrod5 *)&lt;br /&gt;
Definition nandb (b1:bool) (b2:bool) : bool :=&lt;br /&gt;
  match b1 with &lt;br /&gt;
  | true  =&amp;gt; negb b2&lt;br /&gt;
  | false =&amp;gt; true&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example prop_nandb1: (nandb true false) = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed. &lt;br /&gt;
Example prop_nandb2: (nandb false false) = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed. &lt;br /&gt;
Example prop_nandb3: (nandb false true) = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed. &lt;br /&gt;
Example prop_nandb4: (nandb true true) = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed. &lt;br /&gt;
&lt;br /&gt;
(* angruicam1 *)&lt;br /&gt;
Definition nandb1 (b1:bool) (b2:bool) : bool :=&lt;br /&gt;
  match b1 with&lt;br /&gt;
  | true =&amp;gt; negb b2&lt;br /&gt;
  | _    =&amp;gt; true&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_nandb11: (nandb1 true false) = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
Example test_nandb12: (nandb1 false false) = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
Example test_nandb13: (nandb1 false true) = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
Example test_nandb14: (nandb1 true true) = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* angruicam1 *)&lt;br /&gt;
Definition nandb2 (b1:bool) (b2:bool) : bool :=&lt;br /&gt;
  match b1, b2 with&lt;br /&gt;
  | true, true =&amp;gt; false&lt;br /&gt;
  | _, _       =&amp;gt; true&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_nandb21: (nandb2 true false) = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
Example test_nandb22: (nandb2 false false) = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
Example test_nandb23: (nandb2 false true) = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
Example test_nandb24: (nandb2 true true) = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* angruicam1 *)&lt;br /&gt;
Definition nandb3 (b1:bool) (b2:bool) : bool :=&lt;br /&gt;
  if b1 then negb b2 else true.&lt;br /&gt;
&lt;br /&gt;
Example test_nandb31: (nandb3 true false) = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
Example test_nandb32: (nandb3 false false) = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
Example test_nandb33: (nandb3 false true) = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
Example test_nandb34: (nandb3 true true) = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* angruicam1 *)&lt;br /&gt;
Definition nandb4 (b1:bool) (b2:bool) : bool :=&lt;br /&gt;
  negb (b1 &amp;amp;&amp;amp; b2).&lt;br /&gt;
&lt;br /&gt;
Example test_nandb41: (nandb4 true false) = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
Example test_nandb42: (nandb4 false false) = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
Example test_nandb43: (nandb4 false true) = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
Example test_nandb44: (nandb4 true true) = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.1. Definir la función&lt;br /&gt;
      andb3 :: bool -&amp;gt; bool -&amp;gt; bool -&amp;gt; bool&lt;br /&gt;
   tal que (andb3 x y z) se verifica si x, y y z son verdaderos.&lt;br /&gt;
&lt;br /&gt;
   Demostrar las siguientes propiedades de andb3&lt;br /&gt;
      (andb3 true  true  true)  = true.&lt;br /&gt;
      (andb3 false true  true)  = false.&lt;br /&gt;
      (andb3 true  false true)  = false.&lt;br /&gt;
      (andb3 true  true  false) = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* alerodrod5 *)&lt;br /&gt;
Definition andb3 (b1:bool) (b2:bool) (b3:bool) : bool :=&lt;br /&gt;
  match b1 with&lt;br /&gt;
   | true  =&amp;gt; andb b2 b3&lt;br /&gt;
   | false =&amp;gt; false&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example prop_andb31: (andb3 true true true) = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed. &lt;br /&gt;
Example prop_andb32: (andb3 false true true) = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed. &lt;br /&gt;
Example prop_andb33: (andb3 true false true) = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed. &lt;br /&gt;
Example prop_andb34: (andb3 true true false) = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed. &lt;br /&gt;
&lt;br /&gt;
(* angruicam1 *)&lt;br /&gt;
Notation &amp;quot;x &amp;amp;&amp;amp; y&amp;quot; := (andb x y).&lt;br /&gt;
&lt;br /&gt;
Definition andb32 (b1:bool) (b2:bool) (b3:bool) : bool :=&lt;br /&gt;
  b1 &amp;amp;&amp;amp; b2 &amp;amp;&amp;amp; b3.&lt;br /&gt;
&lt;br /&gt;
Example test_andb321: (andb32 true true true) = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
Example test_andb322: (andb32 false true true) = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
Example test_andb323: (andb32 true false true) = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
Example test_andb324: (andb32 true true false) = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3. Definir la función&lt;br /&gt;
      factorial :: nat -&amp;gt; nat1&lt;br /&gt;
   tal que (factorial n) es el factorial de n. &lt;br /&gt;
&lt;br /&gt;
      (factorial 3) = 6.&lt;br /&gt;
      (factorial 5) = (mult 10 12).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* alerodrod5, angruicam1 *)&lt;br /&gt;
Fixpoint factorial (n:nat) : nat := &lt;br /&gt;
  match n with&lt;br /&gt;
  | O    =&amp;gt; 1&lt;br /&gt;
  | S n&amp;#039; =&amp;gt;  S n&amp;#039; * factorial n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example prop_factorial1: (factorial 3) = 6.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
Example prop_factorial2: (factorial 5) = (mult 10 12).&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4. Definir la función&lt;br /&gt;
      blt_nat :: nat -&amp;gt; nat -&amp;gt; bool&lt;br /&gt;
   tal que (blt n m) se verifica si n es menor que m.&lt;br /&gt;
&lt;br /&gt;
   Demostrar las siguientes propiedades&lt;br /&gt;
      (blt_nat 2 2) = false.&lt;br /&gt;
      (blt_nat 2 4) = true.&lt;br /&gt;
      (blt_nat 4 2) = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* Nota: Se puede usar las funciones beq_nat y leb del texto del tema 1 *)&lt;br /&gt;
Fixpoint beq_nat (n m : nat) : bool :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | O =&amp;gt; match m with&lt;br /&gt;
         | O =&amp;gt; true&lt;br /&gt;
         | S m&amp;#039; =&amp;gt; false&lt;br /&gt;
         end&lt;br /&gt;
  | S n&amp;#039; =&amp;gt; match m with&lt;br /&gt;
            | O =&amp;gt; false&lt;br /&gt;
            | S m&amp;#039; =&amp;gt; beq_nat n&amp;#039; m&amp;#039;&lt;br /&gt;
            end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Fixpoint leb (n m : nat) : bool :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | O =&amp;gt; true&lt;br /&gt;
  | S n&amp;#039; =&amp;gt;&lt;br /&gt;
      match m with&lt;br /&gt;
      | O =&amp;gt; false&lt;br /&gt;
      | S m&amp;#039; =&amp;gt; leb n&amp;#039; m&amp;#039;&lt;br /&gt;
      end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* alerodrod5 *)&lt;br /&gt;
Definition blt_nat (n m : nat) : bool :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | O =&amp;gt; true&lt;br /&gt;
  | S n&amp;#039; =&amp;gt;&lt;br /&gt;
      match m with&lt;br /&gt;
      | O    =&amp;gt; false&lt;br /&gt;
      | S m&amp;#039; =&amp;gt; leb (S n&amp;#039;)  m&amp;#039;&lt;br /&gt;
      end&lt;br /&gt;
  end.                                   &lt;br /&gt;
&lt;br /&gt;
Example prop_blt_nat1: (blt_nat 2 2) = false.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
Example prop_blt_nat2: (blt_nat 2 4) = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
Example prop_blt_nat3: (blt_nat 4 2) = false.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* angruicam1 *)&lt;br /&gt;
Definition blt_nat2 (n m : nat) : bool :=&lt;br /&gt;
  negb (beq_nat (m-n) 0).&lt;br /&gt;
&lt;br /&gt;
Example test_blt_nat21: (blt_nat2 2 2) = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
Example test_blt_nat22: (blt_nat2 2 4) = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
Example test_blt_nat23: (blt_nat2 4 2) = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5. Demostrar que&lt;br /&gt;
      forall n m o : nat,&lt;br /&gt;
         n = m -&amp;gt; m = o -&amp;gt; n + m = m + o.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* alerodrod5 *)&lt;br /&gt;
Theorem plus_id_exercise: forall n m o : nat,&lt;br /&gt;
  n = m -&amp;gt; m = o -&amp;gt; n + m = m + o.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.&lt;br /&gt;
  intros o Ho.&lt;br /&gt;
  rewrite -&amp;gt; Ho.&lt;br /&gt;
  intros H.&lt;br /&gt;
  rewrite -&amp;gt; H.&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* angruicam1 *)&lt;br /&gt;
Theorem plus_id_exercise2 : forall n m o : nat,&lt;br /&gt;
  n = m -&amp;gt; m = o -&amp;gt; n + m = m + o.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m o H1 H2.&lt;br /&gt;
  rewrite -&amp;gt; H1.&lt;br /&gt;
  rewrite -&amp;gt; H2.&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 6. Demostrar que&lt;br /&gt;
      forall n m : nat,&lt;br /&gt;
        m = S n -&amp;gt;&lt;br /&gt;
        m * (1 + n) = m * m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* Nota: Se puede usar el lema plus_1_l del texto del tema 1 *)&lt;br /&gt;
Theorem plus_1_l : forall n:nat, 1 + n = S n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* alerodrod5 *)&lt;br /&gt;
Theorem mult_S_1 : forall n m : nat,&lt;br /&gt;
  m = S n -&amp;gt;&lt;br /&gt;
  m * (1 + n) = m * m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.&lt;br /&gt;
  intros H.&lt;br /&gt;
  rewrite -&amp;gt; H.&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed. &lt;br /&gt;
&lt;br /&gt;
(* angruicam1 *)&lt;br /&gt;
Theorem mult_S_12 : forall n m : nat,&lt;br /&gt;
  m = S n -&amp;gt;&lt;br /&gt;
  m * (1 + n) = m * m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H.&lt;br /&gt;
  rewrite H.&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 7. Demostrar que&lt;br /&gt;
      forall b c : bool,&lt;br /&gt;
        andb b c = true -&amp;gt; c = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* alerodrod5 *)&lt;br /&gt;
Theorem andb_true_elim2 : forall b c : bool,&lt;br /&gt;
  andb b c = true -&amp;gt; c = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c. destruct b.&lt;br /&gt;
  - intros H. rewrite &amp;lt;-H. reflexivity.&lt;br /&gt;
  - intros H. rewrite &amp;lt;-H. destruct false.&lt;br /&gt;
    + reflexivity.&lt;br /&gt;
    + destruct c. rewrite &amp;lt;-H. reflexivity. reflexivity. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* angruicam1 *)&lt;br /&gt;
Theorem andb_true_elim22 : forall b c : bool,&lt;br /&gt;
  andb b c = true -&amp;gt; c = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [] [] [].&lt;br /&gt;
  - reflexivity.&lt;br /&gt;
  - reflexivity.&lt;br /&gt;
  - reflexivity.&lt;br /&gt;
  - reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* jorcatote *)&lt;br /&gt;
Theorem andb_true_elim23 : forall b c : bool,&lt;br /&gt;
  andb b c = true -&amp;gt; c = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c. destruct c.&lt;br /&gt;
    - reflexivity.   &lt;br /&gt;
    - destruct b.&lt;br /&gt;
      + simpl. intros h. rewrite h. reflexivity.&lt;br /&gt;
      + simpl. intros h. rewrite h. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 8. Dmostrar que&lt;br /&gt;
      forall n : nat,&lt;br /&gt;
        beq_nat 0 (n + 1) = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* alerodrod5 *)&lt;br /&gt;
Theorem zero_nbeq_plus_1: forall n : nat,&lt;br /&gt;
  beq_nat 0 (n + 1) = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n. destruct n.&lt;br /&gt;
  - reflexivity.&lt;br /&gt;
  - reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* angruicam1 *)&lt;br /&gt;
Theorem zero_nbeq_plus_12 : forall n : nat,&lt;br /&gt;
  beq_nat 0 (n + 1) = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [| n&amp;#039;].&lt;br /&gt;
  - reflexivity.&lt;br /&gt;
  - reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 9. Demostrar que&lt;br /&gt;
      forall (f : bool -&amp;gt; bool),&lt;br /&gt;
        (forall (x : bool), f x = x) -&amp;gt; &lt;br /&gt;
        forall (b : bool), f (f b) = b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* angruicam1, alerodrod5 *)&lt;br /&gt;
Theorem identity_fn_applied_twice :&lt;br /&gt;
  forall (f : bool -&amp;gt; bool),&lt;br /&gt;
  (forall (x : bool), f x = x) -&amp;gt;&lt;br /&gt;
  forall (b : bool), f (f b) = b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros f x b.&lt;br /&gt;
  rewrite x.&lt;br /&gt;
  rewrite x.&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 10. Demostrar que&lt;br /&gt;
      forall (b c : bool),&lt;br /&gt;
        (andb b c = orb b c) -&amp;gt; b = c.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* angruicam1 *) (* alerodrod5 *)&lt;br /&gt;
Theorem andb_eq_orb :&lt;br /&gt;
  forall (b c : bool),&lt;br /&gt;
  (andb b c = orb b c) -&amp;gt;&lt;br /&gt;
  b = c.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [] c.&lt;br /&gt;
  - simpl. intros H. rewrite H. reflexivity.&lt;br /&gt;
  - simpl. intros H. rewrite H. reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 11. En este ejercicio se considera la siguiente&lt;br /&gt;
   representación de los números naturales&lt;br /&gt;
      Inductive nat2 : Type :=&lt;br /&gt;
        | C  : nat2&lt;br /&gt;
        | D  : nat2 -&amp;gt; nat2&lt;br /&gt;
        | SD : nat2 -&amp;gt; nat2.&lt;br /&gt;
   donde C representa el cero, D el doble y SD el siguiente del doble.&lt;br /&gt;
&lt;br /&gt;
   Definir la función&lt;br /&gt;
      nat2Anat :: nat2 -&amp;gt; nat&lt;br /&gt;
   tal que (nat2Anat x) es el número natural representado por x. &lt;br /&gt;
&lt;br /&gt;
   Demostrar que &lt;br /&gt;
      nat2Anat (SD (SD C))     = 3&lt;br /&gt;
      nat2Anat (D (SD (SD C))) = 6.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* angruicam1, alerodrod5 *)&lt;br /&gt;
Inductive nat2 : Type :=&lt;br /&gt;
  | C  : nat2&lt;br /&gt;
  | D  : nat2 -&amp;gt; nat2&lt;br /&gt;
  | SD : nat2 -&amp;gt; nat2.&lt;br /&gt;
 &lt;br /&gt;
Fixpoint nat2Anat (x:nat2) : nat :=&lt;br /&gt;
  match x with&lt;br /&gt;
  | C =&amp;gt; O&lt;br /&gt;
  | D n =&amp;gt; 2*nat2Anat n&lt;br /&gt;
  | SD n =&amp;gt; (2*nat2Anat n)+1&lt;br /&gt;
  end.&lt;br /&gt;
 &lt;br /&gt;
Example prop_nat2Anat1: (nat2Anat (SD (SD C))) = 3.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
Example prop_nat2Anat2: (nat2Anat (D (SD (SD C)))) = 6.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jorcatote</name></author>
		
	</entry>
</feed>