<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>

<channel>
	<title>Apuntes</title>
	<atom:link href="http://www.metonymie.com/apuntes/feed" rel="self" type="application/rss+xml" />
	<link>http://www.metonymie.com/apuntes</link>
	<description>I blinded her with science!</description>
	<pubDate>Thu, 10 Sep 2009 01:02:14 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
	<language>en</language>
			<item>
		<title>Recuento: Permutaciones y Selecciones ( Formulas básicas)</title>
		<link>http://www.metonymie.com/apuntes/2009/08/26/recuento-permutaciones-y-selecciones-formulas-basica.html</link>
		<comments>http://www.metonymie.com/apuntes/2009/08/26/recuento-permutaciones-y-selecciones-formulas-basica.html#comments</comments>
		<pubDate>Wed, 26 Aug 2009 21:09:00 +0000</pubDate>
		<dc:creator>admin</dc:creator>
		
		<category><![CDATA[Apuntes]]></category>

		<category><![CDATA[Combinatoria]]></category>

		<category><![CDATA[números combinatorios]]></category>

		<category><![CDATA[Permutaciones]]></category>

		<category><![CDATA[selecciones]]></category>

		<guid isPermaLink="false">http://www.metonymie.com/apuntes/?p=47</guid>
		<description><![CDATA[Machete de Formulas básicas de recuento. Permutaciones y Combinaciones.]]></description>
			<content:encoded><![CDATA[<h2 >Principios B&aacute;sicos</h2>


<h3 >Principio de Multiplicaci&oacute;n (Regla del producto)</h3>

<p >Sean A<sub>1</sub>,A<sub>2</sub>,&#8230;, A<sub>n</sub> conjuntos finitos, entonces |A<sub>1</sub> x A<sub>2</sub> x &#8230; x A<sub>n</sub>| = |A<sub>1</sub>| . |A<sub>2</sub>|&nbsp;&nbsp;&#8230;.&nbsp;&nbsp;. |A<sub>n</sub>|</p>

<p >Ej: <br />Tomemos 2 conjuntos:<br />A = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } ; | A | = 10<br />B = { a, b, c, d, e, f } ; | B | = 5</p>

<p >Supongamos que quiero saber todos las posibles conjuntos formados por 1 elemento de A y otro de B, por ej: { 3, b }, { a, 2 }.</p>

<p >O visto desde lenguajes formales cual es la cantidad de posibles cadenas formadas por primero un elemento de A y después un elemento de B, Ej: &#8220;3b&#8221;, &#8220;2a&#8221;, &#8220;9c&#8221;, &#8220;3c&quot;.</p>

<p >Existen 10 elementos en A y 5 en B por lo que la soluci&oacute;n es: | A | x | B |&nbsp;&nbsp;= 50</p>



<h3 >Principio de Adici&oacute;n (Regla de la Suma)</h3>

<p >Sean A<sub>1</sub>,A<sub>2</sub>,&#8230;, A<sub>n</sub> conjuntos finitos y disjuntos, entonces |A<sub>1</sub> &#8746; A<sub>2</sub> &#8746; &#8230; &#8746; A<sub>n</sub>| = |A<sub>1</sub>| + |A<sub>2</sub>| +&nbsp;&nbsp;&#8230;.&nbsp;&nbsp;+ |A<sub>n</sub>|</p>

<p >Ej:</p>

<p >Supongamos que tengo que elegir un elemento de A o de B (del ejemplo anterior). Como |A| = 10 y |B| = 5 y A &#8745; B = &#8709; entonces |A &#8746; B| = 15, o sea que existen 15 posibles elementos que puedo elegir.</p>



<h3 >Principio de Exclusi&oacute;n y Exclusi&oacute;n</h3>

<p >Si A<sub>1</sub>, A<sub>2</sub> son conjuntos finitos pero no disjuntos. Entonces |A &#8746; B| = |A| + |B| - |A &#8745; B|<br />Esto se generaliza para la uni&oacute;n de varios conjuntos. </p>



<h2 >Permutaciones</h2>


<h3 >Permutaciones</h3>

<p >Supongamos que quiero calcular la cardinalidad del conjunto G formado por las cadenas de 3 caracteres formadas por elementos de C= {n, m, p} tales que no se repita nunca ningún elemento: { &#8220;nmp&#8221;, &#8220;npm&#8221;, &#8220;mnp&#8221;, &#8220;mpn&#8221;, &#8220;pmn&#8221;, &#8220;pnm&#8221; }. <br />Por el principio de multiplicaci&oacute;n, Existen 3 posibilidades para el primero, luego como no se repiten 2 para el segundo y 1 para el tercero. <br />| G | = 3! = 6</p>

<p ><b>La forma de poner n objetos en ord&eacute;n es: P(n, n) = n!</b></p>



<h3 >R-Permutaciones </h3>

<p >Supongamos ahora que quiero saber la cardinalidad del conjunto H formado por todas las cadenas de 3 car&aacute;cteres formadas por elementos de A= { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } sin que se repita nunca ning&uacute;n elemento. Hay 10 posibilidades para el primer espacio, 9 para el segundo y 8 para el tercero, por lo que:</p>

<p >| H | = <math xmlns='http://www.w3.org/1998/Math/MathML'
    
    
    display='inline'>

 <mfrac>
  <mrow>
   <mn>10</mn>
   <mo>!</mo>
  </mrow>
  <mrow>
   <mn>7</mn>

   <mo>!</mo>
  </mrow>
 </mfrac>
</math></p>

<p ><b>El n&uacute;mero de permutaciones de r objetos de n en ord&eacute;n pero sin repetici&oacute;n es: P(n, r) = </b><b><math xmlns='http://www.w3.org/1998/Math/MathML'
    
    
    display='inline'>
 <mfrac>
  <mrow>

   <mi>n</mi>
   <mo>!</mo>
  </mrow>
  <mrow>
   <mo>(</mo>
   <mrow>
    <mi>n</mi>

    <mo>-</mo>
    <mrow>
     <mi>r</mi>
     <mo>!</mo>
    </mrow>
   </mrow>
   <mo>)</mo>

  </mrow>
 </mfrac>
</math></b></p>



<h3 >Permutaciones con repetici&oacute;n</h3>

<p >Supongamos que quiero saber la cardinalidad del conjunto formado por todas las cadenas de 3 caracteres formadas por elementos de A = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } en las que se puedan repetir los elementos. Por la regla del producto existen 10 posibilidades para el primer carácter, 10 para el segundo y 10 para el tercero, por lo que el resultado es 10<sup>3</sup>.</p>

<p ><b>El n&uacute;mero de permutaciones de r objetos de n en ord&eacute;n con repetici&oacute;n es: n</b><sup>r</sup></p>




<h2 >Selecciones</h2>


<h3 >r-combinaciones</h3>

<p >Una <b>r-combinaci&oacute;n</b> de elementos de un conjunto es una selecci&oacute;n sin ordenar de r elementos del conjunto, es decir, de subconjuntos de r elementos.</p>

<p ><b>El n&uacute;mero de r-combinaciones de n elementos, donde n es un entero no negativo y r es un entero tal que 0 &lt;= r &lt;= n es: C(n, r) = </b><b><math xmlns='http://www.w3.org/1998/Math/MathML'
    
    
    display='inline'>
 <mrow>
  <mrow>

   <mo>(</mo>
   <mfrac linethickness='0'>
    <mi>n</mi>
    <mi>r</mi>
   </mfrac>
   <mo>)</mo>
  </mrow>

  <mo>=</mo>
 </mrow>
</math></b><b><math xmlns='http://www.w3.org/1998/Math/MathML'
    
    
    display='inline'>
 <mfrac>
  <mrow>
   <mi>n</mi>
   <mo>!</mo>
  </mrow>

  <mrow>
   <mrow>
    <mi>r</mi>
    <mo>!</mo>
   </mrow>
   <mo> . </mo>
   <mrow>
    <mrow>

     <mo>(</mo>
     <mrow>
      <mi>n</mi>
      <mo>-</mo>
      <mi>r</mi>
     </mrow>
     <mo>)</mo>

    </mrow>
    <mo>!</mo>
   </mrow>
  </mrow>
 </mfrac>
</math></b><br />Ej:</p>

<p >Supongamos que quiero calcular la cardinalidad del conjunto J formado por todos los posibles subconjuntos de 2 elementos que contienen elementos de D = {w, x, y, z},&nbsp;&nbsp;C(4,2) = 6, ya que J = { {w, x}, {w,y} , {w,z}, {x, y}, {x, z}, {y, z}}. </p>



<h3 >Relaci&oacute;n entre r-permutaciones y r-combinaciones</h3>

<p >Las r-permutaciones de un conjunto de cardinalidad n se pueden obtener formando las C(n,r) r-combinaciones del conjunto ( o sea todas los posibles subconjuntos de tama&ntilde;o r formados por los n elementos del conjunto ) y luego ordenando estos elementos de todas las formas posibles, como cada subconjunto tiene tama&ntilde;o r esto puede hacerse de P(r, r) formas de lo que sigue que:</p>

<p >P(n, r) = C(n, r) . P(r, r)</p>



<h3 >Selecciones con repetici&oacute;n</h3>

<p ><b>En un conjunto con n elementos hay C(n + r - 1, r) combinaciones con repetici&oacute;n.</b></p>

<p >Ej:</p>

<p >Supongamos que en un grupo de monedas hay 3 tipos distintos de 1, 5 y 10 centavos y hay por lo menos 5 de cada una de ellas. Cuantos posibles combinaciones de 5 monedas es posible extraer de este grupo?&nbsp;&nbsp;Es importante recalcar que las monedas de cada valor son indistinguibles entre si&nbsp;&nbsp;y no importa el orden en que se seleccionan las monedas, por lo que hay 5 combinaciones con repetici&oacute;n de 3 elementos. <br />Supongamos que cuando elejimos las monedas las metemos en una caja con 3 compartimentos, 1 para cada&nbsp;&nbsp;tipo de moneda, entre cada compartimento hay una barra que las separa, de esta manera algunas de las posibles combinaciones podrian representarse como:<br />** | * | ** <br />* | | ****<br />|*****|<br />***|*|*<br />&#8230;. etc.<br />Se ve que el numero de seleccionar 5 monedas de entre 3 tipos distintos corresponde al numero de formas de colocar 2 barras y 5 asteriscos. Por lo que el n&uacute;mero de formas de seleccionar las monedas es equivalente al n&uacute;mero de formas de seleccionar 5 asteriscos de entre 7 posiciones posibles, que se puede hacer de C(7, 5) maneras.</p>




<h2 >Equivalencias de N&uacute;meros Combinatorios</h2>

<p class="Equation"><math xmlns='http://www.w3.org/1998/Math/MathML'
    
    
    display='block'>
 <mrow>
  <mrow>
   <mo>(</mo>
   <mfrac linethickness='0'>

    <mn>0</mn>
    <mn>0</mn>
   </mfrac>
   <mo>)</mo>
  </mrow>
  <mo>=</mo>
  <mrow>

   <mfrac>
    <mrow>
     <mn>0</mn>
     <mo>!</mo>
    </mrow>
    <mrow>
     <mrow>
      <mn>0</mn>

      <mo>!</mo>
     </mrow>
     <mo> . </mo>
     <mrow>
      <mn>0</mn>
      <mo>!</mo>
     </mrow>

    </mrow>
   </mfrac>
   <mo>=</mo>
   <mn>1</mn>
  </mrow>
 </mrow>
</math></p>

<p class="Equation"><math xmlns='http://www.w3.org/1998/Math/MathML'
    
    
    display='block'>

 <mrow>
  <mrow>
   <mo>(</mo>
   <mfrac linethickness='0'>
    <mi>n</mi>
    <mn>0</mn>
   </mfrac>

   <mo>)</mo>
  </mrow>
  <mo>=</mo>
  <mrow>
   <mfrac>
    <mrow>
     <mi>n</mi>

     <mo>!</mo>
    </mrow>
    <mrow>
     <mrow>
      <mn>0</mn>
      <mo>!</mo>
     </mrow>

     <mo> . </mo>
     <mrow>
      <mi>n</mi>
      <mo>!</mo>
     </mrow>
    </mrow>
   </mfrac>
   <mo>=</mo>

   <mn>1</mn>
  </mrow>
 </mrow>
</math></p>

<p class="Equation"><math xmlns='http://www.w3.org/1998/Math/MathML'
    
    
    display='block'>
 <mrow>
  <mrow>
   <mo>(</mo>

   <mfrac linethickness='0'>
    <mi>n</mi>
    <mn>1</mn>
   </mfrac>
   <mo>)</mo>
  </mrow>
  <mo>=</mo>

  <mrow>
   <mfrac>
    <mrow>
     <mi>n</mi>
     <mo>!</mo>
    </mrow>
    <mrow>
     <mrow>

      <mn>1</mn>
      <mo>!</mo>
     </mrow>
     <mo> . </mo>
     <mrow>
      <mi>n</mi>
      <mo>!</mo>

     </mrow>
    </mrow>
   </mfrac>
   <mo>=</mo>
   <mn>1</mn>
  </mrow>
 </mrow>
</math></p>

<p class="Equation"><math xmlns='http://www.w3.org/1998/Math/MathML'
    
    
    display='block'>
 <mrow>
  <mrow>
   <mo>(</mo>
   <mfrac linethickness='0'>
    <mi>n</mi>
    <mi>n</mi>

   </mfrac>
   <mo>)</mo>
  </mrow>
  <mo>=</mo>
  <mrow>
   <mfrac>
    <mrow>
     <mi>n</mi>

     <mo>!</mo>
    </mrow>
    <mrow>
     <mrow>
      <mn>0</mn>
      <mo>!</mo>
     </mrow>

     <mo> . </mo>
     <mrow>
      <mi>n</mi>
      <mo>!</mo>
     </mrow>
    </mrow>
   </mfrac>
   <mo>=</mo>

   <mn>1</mn>
  </mrow>
 </mrow>
</math></p>




<h3 >N&uacute;meros combinatorios complentarios</h3>

<p class="Equation"><math xmlns='http://www.w3.org/1998/Math/MathML'
    
    
    display='block'>

 <mrow>
  <mrow>
   <mrow>
    <mo>(</mo>
    <mfrac linethickness='0'>
     <mi>n</mi>
     <mi>k</mi>

    </mfrac>
    <mo>)</mo>
   </mrow>
   <mo>=</mo>
   <mrow>
    <mfrac>
     <mrow>
      <mi>n</mi>

      <mo>!</mo>
     </mrow>
     <mrow>
      <mrow>
       <mi>k</mi>
       <mo>!</mo>
      </mrow>

      <mo> . </mo>
      <mrow>
       <mrow>
        <mo>(</mo>
        <mrow>
         <mi>n</mi>
         <mo>-</mo>

         <mi>k</mi>
        </mrow>
        <mo>)</mo>
       </mrow>
       <mo>!</mo>
      </mrow>
     </mrow>

    </mfrac>
    <mo>=</mo>
    <mtext>  </mtext>
    <mrow>
     <mfrac>
      <mrow>
       <mi>n</mi>

       <mo>!</mo>
      </mrow>
      <mrow>
       <mrow>
        <mrow>
         <mo>(</mo>
         <mrow>
          <mi>n</mi>

          <mo>-</mo>
          <mi>k</mi>
         </mrow>
         <mo>)</mo>
        </mrow>
        <mo>!</mo>
       </mrow>

       <mo> . </mo>
       <mrow>
        <mi>k</mi>
        <mo>!</mo>
       </mrow>
      </mrow>
     </mfrac>
     <mo>=</mo>

     <mrow>
      <mo>(</mo>
      <mfrac linethickness='0'>
       <mi>n</mi>
       <mrow>
        <mi>n</mi>
        <mo>-</mo>

        <mi>k</mi>
       </mrow>
      </mfrac>
      <mo>)</mo>
     </mrow>
    </mrow>
   </mrow>
  </mrow>

  <mspace linebreak='indentingnewline'/>
  <mspace linebreak='indentingnewline'/>
  <mspace linebreak='indentingnewline'/>
 </mrow>
</math></p>




<h2 >Permutaciones con Objetos Indistinguibles y Distribuciones de Objetos en Cajas</h2>

<p >Ej 4.5.8 de <a href="#matematica-discreta-rosen">MD</a><br />&iquest;Cuantas permutaciones se pueden realizar con las letras de la palabra &#8220;PAPAYA&uml;? . No se puede usar la formula general de Permutaciones porque la letra &#8220;A&#8221; se repite 3 veces y la letra &#8220;P&#8221; se repite 2. Por lo que debe pensarse as&iacute;: se pueden seleccionar las posiciones de las 3 letras &#8220;A&#8221; de C(6, 3) formas distintas, las &#8220;P&#8221; se pueden colocar en C(3,2) formas distinras quedando C(1, 1) para la &#8220;Y&#8221;. Por la regla del Producto queda:<br />C(6,3) . C(3, 2) . C(1,1) =&nbsp;&nbsp;<math xmlns='http://www.w3.org/1998/Math/MathML'
    
    
    display='inline'>

 <mfrac>
  <mrow>
   <mn>6</mn>
   <mo>!</mo>
  </mrow>
  <mrow>
   <mrow>
    <mn>3</mn>

    <mo>!</mo>
   </mrow>
   <mo> . </mo>
   <mrow>
    <mn>3</mn>
    <mo>!</mo>
   </mrow>

  </mrow>
 </mfrac>
</math>. <math xmlns='http://www.w3.org/1998/Math/MathML'
    
    
    display='inline'>
 <mfrac>
  <mrow>
   <mn>3</mn>
   <mo>!</mo>
  </mrow>

  <mrow>
   <mrow>
    <mn>2</mn>
    <mo>!</mo>
   </mrow>
   <mo> . </mo>
   <mrow>
    <mn>1</mn>

    <mo>!</mo>
   </mrow>
  </mrow>
 </mfrac>
</math>. 1 = <math xmlns='http://www.w3.org/1998/Math/MathML'
    
    
    display='inline'>
 <mfrac>
  <mrow>
   <mn>6</mn>

   <mo>!</mo>
  </mrow>
  <mrow>
   <mrow>
    <mn>3</mn>
    <mo>!</mo>
   </mrow>

   <mo> . </mo>
   <mrow>
    <mn>2</mn>
    <mo>!</mo>
   </mrow>
  </mrow>
 </mfrac>
</math>&nbsp;&nbsp;= 60</p>

<p ><b>El n&uacute;mero de permutaciones diferentes de n objetos; donde hay n<sub>1</sub>objetos indistinguibles de tipo 1, n<sub>2</sub>
objetos indistinguibles de tipo 2, &#8230;, n<sub>k</sub>
objetos indistinguibles de tipo k; es:<br /></b><b><math xmlns='http://www.w3.org/1998/Math/MathML'
    
    
    display='inline'>
 <mfrac>
  <mrow>
   <mi>n</mi>
   <mo>!</mo>
  </mrow>
  <mrow>

   <mrow>
    <mrow>
     <mrow>
      <msub>
       <mi>n</mi>
       <mn>1</mn>
      </msub>
      <mo>!</mo>

     </mrow>
     <mo> . </mo>
     <mrow>
      <msub>
       <mi>n</mi>
       <mn>2</mn>
      </msub>
      <mo>!</mo>

     </mrow>
    </mrow>
    <mo>&#8230;</mo>
   </mrow>
   <mo>.</mo>
   <mrow>
    <msub>
     <mi>n</mi>

     <mi>k</mi>
    </msub>
    <mo>!</mo>
   </mrow>
  </mrow>
 </mfrac>
</math></b></p>

<p >Ej 4.5.9 de <a href="#matematica-discreta-rosen">MD</a><br />&iquest;De cu&aacute;ntas formas se pueden distribuir a cuatro jugadores manos de 5 cartas usando una baraja de 5 cartas? . Observese que al primero se le pueden distribuir C(52, 5), al segundo C(47, 5), al terceso C(42, 5) y al cuarto C(37, 5) (Quedando 32 cartas en el maso como una 5ta clase posible). Por la regla del producto queda:<br />C(52, 5) . C(47, 5) . C(42, 5) . C(37, 5) = <math xmlns='http://www.w3.org/1998/Math/MathML'
    
    
    display='inline'>

 <mfrac>
  <mrow>
   <mn>52</mn>
   <mo>!</mo>
  </mrow>
  <mrow>
   <mrow>
    <mn>47</mn>

    <mo>!</mo>
   </mrow>
   <mo> . </mo>
   <mrow>
    <mn>5</mn>
    <mo>!</mo>
   </mrow>

  </mrow>
 </mfrac>
</math>. <math xmlns='http://www.w3.org/1998/Math/MathML'
    
    
    display='inline'>
 <mfrac>
  <mrow>
   <mn>47</mn>
   <mo>!</mo>
  </mrow>

  <mrow>
   <mrow>
    <mn>42</mn>
    <mo>!</mo>
   </mrow>
   <mo> . </mo>
   <mrow>
    <mn>5</mn>

    <mo>!</mo>
   </mrow>
  </mrow>
 </mfrac>
</math><math xmlns='http://www.w3.org/1998/Math/MathML'
    
    
    display='inline'>
 <mfrac>
  <mrow>
   <mn>42</mn>

   <mo>!</mo>
  </mrow>
  <mrow>
   <mrow>
    <mn>47</mn>
    <mo>!</mo>
   </mrow>

   <mo> . </mo>
   <mrow>
    <mn>5</mn>
    <mo>!</mo>
   </mrow>
  </mrow>
 </mfrac>
</math>. <math xmlns='http://www.w3.org/1998/Math/MathML'
    
    
    display='inline'>

 <mfrac>
  <mrow>
   <mn>37</mn>
   <mo>!</mo>
  </mrow>
  <mrow>
   <mrow>
    <mn>32</mn>

    <mo>!</mo>
   </mrow>
   <mo> . </mo>
   <mrow>
    <mn>5</mn>
    <mo>!</mo>
   </mrow>

  </mrow>
 </mfrac>
</math>=&nbsp;&nbsp;<math xmlns='http://www.w3.org/1998/Math/MathML'
    
    
    display='inline'>
 <mfrac>
  <mrow>
   <mn>52</mn>
   <mo>!</mo>
  </mrow>

  <mrow>
   <mrow>
    <mn>5</mn>
    <mo>!</mo>
   </mrow>
   <mo> . </mo>
   <mrow>
    <mn>5</mn>

    <mo>!</mo>
   </mrow>
   <mo> . </mo>
   <mrow>
    <mn>5</mn>
    <mo>!</mo>
   </mrow>

   <mo> . </mo>
   <mrow>
    <mn>5</mn>
    <mo>!</mo>
   </mrow>
   <mo> . </mo>
   <mrow>
    <mn>32</mn>

    <mo>!</mo>
   </mrow>
  </mrow>
 </mfrac>
</math></p>

<p ><b>El n&uacute;mero de formas de distribuir n objetos distinguibles en k cajas distinguibles de forma que en la caja i-&eacute;sima haya n</b><sub>i</sub> <b>objetos, i = 1,2, &#8230;, k; es:<br /></b><b><math xmlns='http://www.w3.org/1998/Math/MathML'
    
    
    display='inline'>

 <mfrac>
  <mrow>
   <mi>n</mi>
   <mo>!</mo>
  </mrow>
  <mrow>
   <mrow>
    <mrow>

     <mrow>
      <msub>
       <mi>n</mi>
       <mn>1</mn>
      </msub>
      <mo>!</mo>
     </mrow>

     <mo> . </mo>
     <mrow>
      <msub>
       <mi>n</mi>
       <mn>2</mn>
      </msub>
      <mo>!</mo>

     </mrow>
    </mrow>
    <mo>&#8230;</mo>
   </mrow>
   <mo>.</mo>
   <mrow>
    <msub>
     <mi>n</mi>

     <mi>k</mi>
    </msub>
    <mo>!</mo>
   </mrow>
  </mrow>
 </mfrac>
</math></b></p>

<h3>Referencias</h3>
<p><a class="amazon" id="matematica-discreta-rosen" href="http://www.amazon.com/Discrete-Mathematics-Applications-Kenneth-Rosen/dp/0073229725/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1251323778&#038;sr=8-1">Matemática Discreta y sus aplicaciones</a>; Rosen, Kenneth H.; 5ª edición, Mc Graw Hill, 2004</p>
<p><a class="amazon" href="http://www.amazon.com/Algebra-I-Armando-Rojo/dp/9872144885/">Algebra I</a>; Rojo, Armando; 21ª ed, Magister Eos; 2006</p>
]]></content:encoded>
			<wfw:commentRss>http://www.metonymie.com/apuntes/2009/08/26/recuento-permutaciones-y-selecciones-formulas-basica.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>Usando linked lists para trabajar con polinomios</title>
		<link>http://www.metonymie.com/apuntes/2009/08/13/usando-linked-lists-para-trabajar-con-polinomios.html</link>
		<comments>http://www.metonymie.com/apuntes/2009/08/13/usando-linked-lists-para-trabajar-con-polinomios.html#comments</comments>
		<pubDate>Thu, 13 Aug 2009 17:32:15 +0000</pubDate>
		<dc:creator>admin</dc:creator>
		
		<category><![CDATA[Estructuras de datos]]></category>

		<category><![CDATA[c]]></category>

		<category><![CDATA[computación simbolica]]></category>

		<category><![CDATA[Linked List]]></category>

		<category><![CDATA[polinomios]]></category>

		<guid isPermaLink="false">http://www.metonymie.com/apuntes/?p=46</guid>
		<description><![CDATA[Un ejemplo de cómputos simbólicos usando una linked list para manipular polinomios.]]></description>
			<content:encoded><![CDATA[<p>Uno de las cosas fascinantes del <a class="wiki" href="http://en.wikipedia.org/wiki/Mathematica">Mathematica</a> y ( ahora del <a href="http://www.wolframalpha.com/">wolfram alpha</a> ) es como resuelve y además simplifica expresiones matemáticas (por ejemplo: derivando funciones y dando cada uno de los pasos). Se usa de esta manera la computadora no para hacer cálculos numéricos ( que arrojen como resultado un número ) sino para computación simbólica ( cálculos que arrojan como resultado una expresión matemática ). </p>

<p>La pregunta es como una maquina que guarda resultados en memoria en forma de expresiones binarias ( esencialmente números, aunque pueden representar otra cosa ) para hacer esto. La respuesta es que la representación de formulas matemáticas puede ser realizada a través de diferentes estructuras de datos y es manipulando estas estructuras que se pueden realizar estos cómputos.</p>

<p>Como un ejemplo básico de esto acá va un ejemplo sacado de <a class="amazon" href="http://www.amazon.com/Data-Structures-Electrical-Computer-Engineering/dp/1584503386/">C &amp; Data Structures</a> sobre como se pueden hacer operaciones sobre polinomios.</p>

<h2>Una estructura de datos para guardar un polinomio y las funciones para llenarlo y mostrarlo.</h2>

<pre><code>

# include &lt;stdio.h>

# include &lt;stdlib.h>

struct pnode

   {

      int exp;

      int coeff;

      struct pnode *link;

   };

struct pnode *insert(struct pnode *p, int e,int c) {

   struct pnode *temp;

   temp = p;

   if(p==NULL) {

      p=(struct pnode *)malloc(sizeof(struct pnode));

      if(p==NULL) {

         printf("Error de alocación de memoria\n");

         exit(0);

      }

      p-> exp = e;

      p->coeff = c;

      p-> link = NULL;

   } else {

        //Si tienen el mismo exponente se suman los coeficientes en vez de agregar un nodo.

       if(p->exp == e) {

            p->coeff = p->coeff + c;

       } else {

            p->link = insert(p->link, e, c);

       }

   }

   return (p);

}



void printpoly ( struct pnode *p ) {

      printf("The polynomial is\n");

      while (p!= NULL) {

        if(p->exp != 1) {

            printf("%dx^%d\t", p->coeff, p-> exp);

        } else {

            printf("%dx\t", p->coeff);

        }

        p = p-> link;

      }

      printf("\n");

}

</code></pre>

<p><strong>Nota:</strong> en la función de insertar si un nuevo termino tiene el mismo exponente que uno anterior se lo suma en vez de agregarlo. Esto es una de las modificaciones al código del libro.</p>

<h2>Ordenando el polinomio</h2>

<pre><code>

/* a function to sort a list */

struct pnode *sortpoly(struct pnode *p)

{

   struct pnode *temp1,*temp2,*max,*prev,*q;

   q = NULL;

   while(p != NULL) {

      prev = NULL;

      max = temp1 = p;

      temp2 = p -> link;

      while ( temp2 != NULL ) {

         if(max -> exp &lt; temp2 -> exp) {

            max = temp2;

            prev = temp1;

         }

         temp1 = temp2;

         temp2 = temp2-> link;

      }

      if(prev == NULL) {

            p = max -> link;

       }  else {

            prev -> link = max -> link;

       }

       max -> link = NULL;

        if( q == NULL) {

            q = max;

        } else {

            temp1 = q;

            while( temp1 -> link != NULL) {

                temp1 = temp1 -> link;

            }

            temp1 -> link = max;

        }

    }

    return (q);

}

</code></pre>

<h2>Una Función para sumar 2 polinomios</h2>

<pre><code>

/* A function to add two polynomials */

   struct pnode *polyadd(struct pnode *p, struct pnode *q)

   {

      struct pnode *r = NULL;

      int e;

      int c;

      while((p!=NULL) &#038;&#038; (q != NULL)) {

            //p mayor exponente que q

            if(p->exp > q->exp) {

                r = insert(r,p->exp,p->coeff);

                p = p->link;



            //q mayor exponenete que p

            } else if(p->exp &lt; q->exp) {

                r = insert(r,q->exp,q->coeff);

                q = q->link;



            //mismo exponente

            } else {

                c = p->coeff + q->coeff;

                e = q->exp;

                r = insert( r, e,c);

                p = p->link;

                q = q->link;

            }

      }

   //Lo que quede de ambos polinomios

    while(p != NULL) {

        r = insert( r, p->exp,p->coeff);

        p = p->link;

    }

    while(q!=NULL) {

        r = insert( r, q->exp,q->coeff);

        q = q->link;

    }

   return(r);

}

</code></pre>

<h2>Una función para multiplicar polinomios.</h2>

<p>Teniendo una función insertar que sume los términos del mismo exponente y una función de suma es muy fácil agregar una función que multiplique polinomios.</p>

<pre><code>

struct pnode *polymult(struct pnode *p, struct pnode *q) {

    struct pnode *r, *r2, *temp;

    r = NULL;

    temp = q;

    while(p != NULL) {

        temp = q;

        while(temp != NULL) {

            r = insert(r, (temp->exp + p->exp), (temp->coeff * p->coeff));

            temp = temp->link;

        }

        p = p->link;

    }

    return r;

}

</code></pre>

<h2>Probando el programa</h2>

<pre><code>

int main()

   {

         int e;

         int n,i, c;

         struct pnode *poly1 = NULL ;

         struct pnode *poly2=NULL;

         struct pnode *result;

         printf("Enter the terms in the polynomial1 \n");

         scanf("%d",&#038;n);

         i=1;

         while ( n-- > 0 )

         {

      printf( "Enter the exponent and coefficient of the term number %d\n",n);

               scanf("%d %d",&#038;e,&#038;c);

               poly1 = insert ( poly1,e,c);

         }

        printf("Enter the terms in the polynomial2 \n");

         scanf("%d",&#038;n);

         i=1;

         while ( n-- > 0 )

         {

      printf( "Enter the exponent and coefficient of the term number %d\n",n);

               scanf("%d %d",&#038;e,&#038;c);

               poly2 = insert ( poly2,e,c);

         }

         poly1 = sortpoly(poly1);

         poly2 = sortpoly(poly2);

         printf("The polynomial 1 is\n");

         printpoly ( poly1 );

         printf("The polynomial 2 is\n");

         printpoly ( poly2 );

         result = polyadd(poly1,poly2);

         printf("The result of addition is\n");

         printpoly ( result );

         result = polymult(poly1, poly2);

         printf("The result of multiplication is\n");

         printpoly ( result );

         return 0;

   }

</code></pre>

<h2>Resultados</h2>

<pre><code>
Enter the terms in the polynomial1 
5
Enter the exponent and coefficient of the term number 4
5 5
Enter the exponent and coefficient of the term number 3
4 4
Enter the exponent and coefficient of the term number 2
3 3
Enter the exponent and coefficient of the term number 1
2 2
Enter the exponent and coefficient of the term number 0
1 1
Enter the terms in the polynomial2 
2
Enter the exponent and coefficient of the term number 1
2 2
Enter the exponent and coefficient of the term number 0
1 1
sdfsdfThe polynomial 1 is
The polynomial is
5x^5	4x^4	3x^3	2x^2	1x	
The polynomial 2 is
The polynomial is
2x^2	1x	
The result of addition is
The polynomial is
5x^5	4x^4	3x^3	4x^2	2x	
The result of multiplication is
The polynomial is
10x^7	13x^6	10x^5	7x^4	4x^3	1x^2	

</code></pre>
<p>Pensando en todo esto es interesante en como en MathML se usan estructuras arboreas ( <a class="wiki" href="http://www.wikipedia.org/wiki/MathML">MathML</a> esta basado en XML ) para representar expresiones matematicas y las implicaciones que puede tener a futuro para la automatización de determinado tipo de calculos.</p>

<h4>Referencias</h4>

<p><a class="amazon" href="http://www.amazon.com/Data-Structures-Electrical-Computer-Engineering/dp/1584503386/">C &amp; Data Structures</a>, Deshpande, Kakde; Charles River Media, 2004</p>]]></content:encoded>
			<wfw:commentRss>http://www.metonymie.com/apuntes/2009/08/13/usando-linked-lists-para-trabajar-con-polinomios.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>foldr, foldl, scanl, scanr</title>
		<link>http://www.metonymie.com/apuntes/2009/08/13/foldr-foldl-scanl-scanr.html</link>
		<comments>http://www.metonymie.com/apuntes/2009/08/13/foldr-foldl-scanl-scanr.html#comments</comments>
		<pubDate>Thu, 13 Aug 2009 17:26:50 +0000</pubDate>
		<dc:creator>admin</dc:creator>
		
		<category><![CDATA[Haskell]]></category>

		<category><![CDATA[Programación Funcional]]></category>

		<category><![CDATA[Estructuras de datos]]></category>

		<category><![CDATA[foldr]]></category>

		<category><![CDATA[Recursividad]]></category>

		<guid isPermaLink="false">http://www.metonymie.com/apuntes/?p=45</guid>
		<description><![CDATA[Foldr y Foldl
foldr y foldl son funciones de plegado sobre la estructura recursiva de las listas.
Cumpliendose que: 

foldr f z (x1 : (x2 : (&#8230; : (xn : []))))
= x1 &#8216;f&#8217; (x2 &#8216;f&#8217; (&#8230; &#8216;f&#8217; (xn &#8216;f&#8217; z))))


foldl f z (x1 : (x2 : (&#8230; : (xn : []))))
= ((((z &#8216;f&#8217; x1) &#8216;f&#8217; x2) &#8230; [...]]]></description>
			<content:encoded><![CDATA[<h3>Foldr y Foldl</h3>
<p>foldr y foldl son funciones de plegado sobre la <a href="http://www.metonymie.com/apuntes/2009/08/10/definicion-de-estructura-de-datos-recursiva.html">estructura recursiva</a> de las listas.</p>
<p>Cumpliendose que: </p>
<p>
foldr f z (x1 : (x2 : (&#8230; : (xn : []))))
<br/>= x1 &#8216;f&#8217; (x2 &#8216;f&#8217; (&#8230; &#8216;f&#8217; (xn &#8216;f&#8217; z))))
</p>
<p>
foldl f z (x1 : (x2 : (&#8230; : (xn : []))))
<br/>= ((((z &#8216;f&#8217; x1) &#8216;f&#8217; x2) &#8230; &#8216;f&#8217; xn-1) &#8216;f&#8217; xn)
</p>
<p>En ambas se toma una función y se la aplica sucesivamente a cada miembre de una lista, hasta recibir un resultado final.</p>
<p>Ejemplos. Definición de una función <code class="inline">and</code> que devuelve True si todos los elementos de una lista de Bool son verdaderos y definición de una función <code class="inline">or</code> que devuelve True si alguno es verdadero.</p>
<pre><code>
and3 :: [Bool] -> Bool
and3 = foldr (&#038;&#038;) True

or3 :: [Bool] -> Bool
or3 = foldr (||) False
</code></pre>
<p>scanl y scanl, devuelven los pasos intermedios de una operación de foldl y foldr respectivamente. Los siguientes ejemplos demuestran que si una operación no es asociativa (como la resta en los naturales) foldr y foldl devuelven resultados distintos.</p> 

<pre><code>
*Main> scanl (+) 0 [1..5]
[0,1,3,6,10,15]
*Main> scanr (+) 0 [1..5]
[15,14,12,9,5,0]

*Main> scanr (-) 0 [1..5]
[3,-2,4,-1,5,0]
*Main> scanl (-) 0 [1..5]
[0,-1,-3,-6,-10,-15]
</code></pre>
<p>El segundo argumento es el caso final o primero a aplicarse.</p>
<pre><code>
*Main> scanl (*) 10 [1..5]
[10,10,20,60,240,1200]
*Main> scanr (*) 10 [1..5]
[1200,1200,600,200,50,10]
</code></pre>
<h3>Referencias</h3>
<p><a class="biblio" href="http://www.lcc.uma.es/~blas/pfHaskell/">Razonando con Haskell</a>;Blas C. Ruiz,  Francisco Gutiérrez, Pablo Guerrero y  José E. Gallardo;Thomson Editores Spain;2004</p>]]></content:encoded>
			<wfw:commentRss>http://www.metonymie.com/apuntes/2009/08/13/foldr-foldl-scanl-scanr.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>Analizando los punteros de una linked list</title>
		<link>http://www.metonymie.com/apuntes/2009/08/10/analizando-los-punteros-de-una-linked-list.html</link>
		<comments>http://www.metonymie.com/apuntes/2009/08/10/analizando-los-punteros-de-una-linked-list.html#comments</comments>
		<pubDate>Mon, 10 Aug 2009 20:27:50 +0000</pubDate>
		<dc:creator>admin</dc:creator>
		
		<category><![CDATA[Estructuras de datos]]></category>

		<category><![CDATA[c]]></category>

		<category><![CDATA[Linked List]]></category>

		<category><![CDATA[punteros]]></category>

		<guid isPermaLink="false">http://www.metonymie.com/apuntes/?p=44</guid>
		<description><![CDATA[Un post sobre el manejo de los espacios de memoria en una linked list.]]></description>
			<content:encoded><![CDATA[<p>Uno de los temas que es difícil de entender en C es el tema de los punteros y como se relacionan con las estructuras de datos. Lo difícil ( o por lo menos fue difícil para mi que venia de lenguajes dinámicos ) es entender que los punteros guardan direcciones a memoria y a que a partir de esto se puede hacer el entrelazamiento de diferentes estructuras apuntadas. Voy a usar los ejemplo de <a class="wiki" href="http://en.wikipedia.org/wiki/Linked_list">linked list</a> de <a class="amazon" href="http://www.amazon.com/Data-Structures-Electrical-Computer-Engineering/dp/1584503386/">C &amp; Data Structures</a> para mostrar como se da esto.</p>
<p>Primero creamos la estructura y una función para insertar elementos en la misma: </p>
<code><pre>
struct node {

   int data;

   struct node *link;

};



/*Insert en versión recursiva */

struct node *insert(struct node *p, int n) {

   if(p==NULL) {

      p=(struct node *)malloc(sizeof(struct node));

      if(p==NULL) {

        printf("Allocation Error\n");

         exit(0);

      }

      p-> data = n;

      p-> link = NULL;

   } else {

       p->link = insert(p->link,n);

    }

      return(p);

}

</pre></code>
<p><strong>Nota: </strong>Se hace la búsqueda del ultimo nodo para insertar en forma recursiva.</p>
<p>Luego hago una función para mostrar la lista:</p>
<code><pre>
void printnode( struct node *p) {

    printf("Memory Space: %p\t Value: %d \t Link: %p\t\n",p, p-> data, p-> link);

}



void printlist ( struct node *p ) {

      printf("The data values in the list are\n");

      while (p!= NULL) {

         printnode(p);

         p = p-> link;

      }

}

</pre></code>
<p>La función <code class="inline">printnode</code>, muestra primero la dirección de memoria de la estructura, después su valor y finalmente la dirección de memoria a la que apunta, de esta manera podemos ver como se enlazan los nodos dentro de la lista.</p>
<h3>Agregando y borrando nodos.</h3>
<code><pre>
   /* a function which inserts a newly created node after the specified

node */

    //node_no empieza en 0 como en los arrays

   struct node * newinsert ( struct node *p, int node_no, int value ) {

      struct node *temp, * temp1;

      int i;

      temp = p;



      for(i=0; i&lt;node_no &#038;&#038; temp->link != NULL; i++) {

            temp = temp->link;

      }

        if(i != node_no ) {

            printf("Se pide insertar en un nodo mayor a la cantidad existente, se agrega tras el ultimo nodo existente.\n");

        }

        temp1 = ( struct node * )malloc ( sizeof ( struct node ));

        if ( temp1 == NULL ) {

            printf( " Cannot allocate \n");

            exit (0);

        }

        temp1->data = value;

        temp1->link = temp->link;

        printf("The newly created node to be inserted is:\n");

        printnode(temp1);

        temp->link = temp1;

        return(p);

   }



   struct node * erasenode( struct node *p, int node_no) {

        struct node *temp, *prev;

        int i;

        temp = p;

        if(node_no == 0) {

            temp = p->link;

            free(p);

            p = temp;

        } else {

            i = 0;

            while(i&lt;node_no &#038;&#038; temp->link != NULL) {

                prev = temp;

                temp = temp->link;

                i++;

            }

            if(i != (node_no)) {

                printf("Se pide borrar un nodo que no existe.\n");

                exit(0);

            }

            prev->link = temp->link;

            free(temp);

        }

        return(p);

   }

</pre></code>
<p>Corriéndolo en el main:</p>

<code><pre>
int main()

{

      int n;

      int x;

      struct node *start = NULL ;

      printf("Enter the nodes to be created \n");

      scanf("%d",&#038;n);

      while ( n-- > 0 )

      {

              printf( "Enter the data values to be placed in a node\n");

         scanf("%d",&#038;x);

         start = insert ( start,x);

      }

      printf("The created list is\n");

      printlist ( start );

      start = newinsert(start, 2, 7);

      printlist (start);

      start = erasenode(start, 2);

      printlist ( start );

      return 0;

}

</pre></code>
<p>Resultado en pantalla:</p>
<code><pre>
Enter the nodes to be created 
5
Enter the data values to be placed in a node
5
Enter the data values to be placed in a node
4
Enter the data values to be placed in a node
3
Enter the data values to be placed in a node
2
Enter the data values to be placed in a node
1
The created list is
The data values in the list are
Memory Space: 0x81a5008	 Value: 5 	 Link: 0x81a5018	
Memory Space: 0x81a5018	 Value: 4 	 Link: 0x81a5028	
Memory Space: 0x81a5028	 Value: 3 	 Link: 0x81a5038	
Memory Space: 0x81a5038	 Value: 2 	 Link: 0x81a5048	
Memory Space: 0x81a5048	 Value: 1 	 Link: (nil)	
The newly created node to be inserted is:
Memory Space: 0x81a5058	 Value: 7 	 Link: 0x81a5038	
The data values in the list are
Memory Space: 0x81a5008	 Value: 5 	 Link: 0x81a5018	
Memory Space: 0x81a5018	 Value: 4 	 Link: 0x81a5028	
Memory Space: 0x81a5028	 Value: 3 	 Link: 0x81a5058	
Memory Space: 0x81a5058	 Value: 7 	 Link: 0x81a5038	
Memory Space: 0x81a5038	 Value: 2 	 Link: 0x81a5048	
Memory Space: 0x81a5048	 Value: 1 	 Link: (nil)	
The data values in the list are
Memory Space: 0x81a5008	 Value: 5 	 Link: 0x81a5018	
Memory Space: 0x81a5018	 Value: 4 	 Link: 0x81a5058	
Memory Space: 0x81a5058	 Value: 7 	 Link: 0x81a5038	
Memory Space: 0x81a5038	 Value: 2 	 Link: 0x81a5048	
Memory Space: 0x81a5048	 Value: 1 	 Link: (nil)	
</pre></code>
<p>Se ve aca como en la primera corrida los nodos estan ubicados uno tras otro en la memoria, pero al agregar un nuevo nodo se salta en el tercer nodo ( en este caso, <code class="inline">Memory Space: 0x81a5028	 Value: 3 	 Link: 0x81a5058</code> ) se salta al agregado ( <code class="inline">Memory Space: 0x81a5058	 Value: 7 	 Link: 0x81a5038</code> ) y del agregado al que antes existia contiguamente ( <code class="inline">Memory Space: 0x81a5038	 Value: 2 	 Link: 0x81a5048</code> ). Algo similar ocurre cuando se borra un nodo.</p>
<h3>Revirtiendo y ordenando la lista.</h3>
<code><pre>
/* a function to sort reverse list */

struct node *reverse(struct node *p) {

   struct node *prev, *curr;

   prev = NULL;

   curr = p;

   while (curr != NULL) {

      p = p-> link;

      curr-> link = prev;

      prev = curr;

      curr = p;

   }

   return(prev);

}



/* a function to sort a list */

struct node *sortlist(struct node *p)

{

   struct node *temp1,*temp2,*min,*prev,*q;

   q = NULL;

   while(p != NULL) {

      //Encontrar el menor de la lista p

      prev = NULL;

      min = temp1 = p;

      temp2 = p -> link;

      while ( temp2 != NULL ) {

              if(min -> data > temp2 -> data) {

                     min = temp2;

                     prev = temp1;

            }

         temp1 = temp2;

         temp2 = temp2-> link;

      }



      //Cambiar el link en la lista p del previo al menor al siguiente del menor

      if(prev == NULL) {

             p = min -> link;

      } else {

             prev -> link = min -> link;

      }



      //Agregar el menor a q

      min -> link = NULL;

      if( q == NULL){

            q = min; /* moves the node with lowest data value in the list pointed to by p to the list pointed to by q as a first node*/

       } else {

            temp1 = q;

            /* traverses the list pointed to by q to get pointer to its last node */

            while( temp1 -> link != NULL) {

                         temp1 = temp1 -> link;

            }

            temp1 -> link = min; /* moves the node with lowest data value in the list pointed to by p to the list pointed to by q at the end of list pointed by q*/

      }

   }

   return (q);

}

</pre></code>
<p>Vemos la impresión en pantalla de como quedan ordenados los nodos:</p>
<code><pre>
The sorted list is
The data values in the list are
Memory Space: 0x8c03048	 Value: 1 	 Link: 0x8c03038	
Memory Space: 0x8c03038	 Value: 2 	 Link: 0x8c03018	
Memory Space: 0x8c03018	 Value: 4 	 Link: 0x8c03008	
Memory Space: 0x8c03008	 Value: 5 	 Link: 0x8c03058	
Memory Space: 0x8c03058	 Value: 7 	 Link: (nil)	
The reversed list is
The data values in the list are
Memory Space: 0x8c03058	 Value: 7 	 Link: 0x8c03008	
Memory Space: 0x8c03008	 Value: 5 	 Link: 0x8c03018	
Memory Space: 0x8c03018	 Value: 4 	 Link: 0x8c03038	
Memory Space: 0x8c03038	 Value: 2 	 Link: 0x8c03048	
Memory Space: 0x8c03048	 Value: 1 	 Link: (nil)	
</pre></code>

<h4>Referencias</h4>
<p><a class="amazon" href="http://www.amazon.com/Data-Structures-Electrical-Computer-Engineering/dp/1584503386/">C &amp; Data Structures</a>, Deshpande, Kakde; Charles River Media, 2004</p>]]></content:encoded>
			<wfw:commentRss>http://www.metonymie.com/apuntes/2009/08/10/analizando-los-punteros-de-una-linked-list.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>Funciones (Definiciones Básicas)</title>
		<link>http://www.metonymie.com/apuntes/2009/08/10/funciones-definiciones-basicas.html</link>
		<comments>http://www.metonymie.com/apuntes/2009/08/10/funciones-definiciones-basicas.html#comments</comments>
		<pubDate>Mon, 10 Aug 2009 16:45:48 +0000</pubDate>
		<dc:creator>admin</dc:creator>
		
		<category><![CDATA[Apuntes]]></category>

		<category><![CDATA[Teoría de Conjuntos]]></category>

		<category><![CDATA[Funciones]]></category>

		<guid isPermaLink="false">http://www.metonymie.com/apuntes/?p=43</guid>
		<description><![CDATA[Apunte con definiciones Básicas de Funciones]]></description>
			<content:encoded><![CDATA[<h4 >Definici&oacute;n de Funci&oacute;n.</h4>



<p >Sea F una relaci&oacute;n de A en B. F es una funci&oacute;n si se cumple que:</p>



<p >F: A -&gt; B &lt;=&gt; &#8704;a &#8712; A( &#8707;b &#8712; B ( (a, b) &#8712; F &#8743; ( (a, c) &#8712; F =&gt; b = c)))</p>



<p >Coloquialmente para todo elemento de A existe un elemento de B tal que <b>(a, b) &#8712; F</b> y este elemento es unico. </p>



<p >Considerando esto se suele expresar el valor de <b><i>f</i></b><b>&nbsp;&nbsp;</b>en <b>a </b>es <b>b </b>o en simbolos:</p>



<p ><i>f</i>(a) = b</p>







<h4 >Composici&oacute;n de Funciones</h4>



<p >Sean <i>f</i>: A -&gt; B y <i>g</i>: B -&gt; C, entonces (<i>g</i> o <i>f</i>) (a) : A -&gt; C es equivalente a <b><i>g</i></b><b> ( </b><b><i>f</i></b><b> (a) ) .</b></p>







<h4 >Funciones inyectivas (uno a uno)</h4>



<p ><i>f </i> es inyectiva si se cumple que:</p>



<p >&#8704;a<sub>1</sub> &#8712; A ( &not;&#8707; a<sub>2</sub> &#8712; A ( f(a<sub>1</sub>) = f(a<sub>2</sub>) )&nbsp;&nbsp;</p>







<h4 >Funciones suryectivas</h4>



<p ><i>f </i>: A -&gt; B es suryectiva si se cumple que:</p>



<p >&#8704;b &#8712; B( &#8707; a &#8712; A( f(a) = b) )</p>







<h4 >Funci&oacute;n inversa</h4>



<p >Si f: A -&gt; B es inyectiva y suryectiva se cumple que:</p>



<ul><li>f<sup>-1</sup>: B -&gt; A tambi&eacute;n es funci&oacute;n.</li>
<li>(f o f<sup>-1</sup>) = I<sub>A</sub></li>
<li>(f<sup>-1</sup> o f) = I<sub>B</sub></li></ul>



<p >Donde I<sub>C</sub> es la funci&oacute;n identidad de C, I: C -&gt; C tal que &#8704; c &#8712; C ( I(c) = c) ).</p>





<h3>Referencias</h3>
<p><a class="amazon" href="http://www.amazon.com/How-Prove-Structured-Daniel-Velleman/dp/0521675995/">How to Prove It: A Structured Approach</a>; Velleman, Daniel; Cambridge University Press; 2006</p>

]]></content:encoded>
			<wfw:commentRss>http://www.metonymie.com/apuntes/2009/08/10/funciones-definiciones-basicas.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>Definición de estructura de datos recursiva</title>
		<link>http://www.metonymie.com/apuntes/2009/08/10/definicion-de-estructura-de-datos-recursiva.html</link>
		<comments>http://www.metonymie.com/apuntes/2009/08/10/definicion-de-estructura-de-datos-recursiva.html#comments</comments>
		<pubDate>Mon, 10 Aug 2009 16:19:44 +0000</pubDate>
		<dc:creator>admin</dc:creator>
		
		<category><![CDATA[Estructuras de datos]]></category>

		<category><![CDATA[Recursividad]]></category>

		<guid isPermaLink="false">http://www.metonymie.com/apuntes/?p=42</guid>
		<description><![CDATA[A recursive data structure is a data structure that has the same form regardless of the size of the data.

Como ejemplo: linked list, arbol binario, etc.
 P S Deshpande, O G Kakde: C &#38; Data Structures ]]></description>
			<content:encoded><![CDATA[<blockquote>A recursive data structure is a data structure that has the same form regardless of the size of the data.</blockquote>

<p>Como ejemplo: linked list, arbol binario, etc.</p>
 <p>P S Deshpande, O G Kakde: <a class="amazon" href="http://www.amazon.com/Data-Structures-Electrical-Computer-Engineering/dp/1584503386/">C &amp; Data Structures</a></p> ]]></content:encoded>
			<wfw:commentRss>http://www.metonymie.com/apuntes/2009/08/10/definicion-de-estructura-de-datos-recursiva.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>Iterando por una matriz cuadrada recursivamente</title>
		<link>http://www.metonymie.com/apuntes/2009/06/05/iterando-por-una-matriz-cuadrada-recursivamente.html</link>
		<comments>http://www.metonymie.com/apuntes/2009/06/05/iterando-por-una-matriz-cuadrada-recursivamente.html#comments</comments>
		<pubDate>Sat, 06 Jun 2009 00:41:24 +0000</pubDate>
		<dc:creator>admin</dc:creator>
		
		<category><![CDATA[Algoritmia]]></category>

		<category><![CDATA[Estructuras de datos]]></category>

		<category><![CDATA[Java]]></category>

		<category><![CDATA[Lógica]]></category>

		<category><![CDATA[Algebra Lineal]]></category>

		<category><![CDATA[Matrices]]></category>

		<category><![CDATA[Recursividad]]></category>

		<guid isPermaLink="false">http://www.metonymie.com/apuntes/?p=41</guid>
		<description><![CDATA[Otro ejemplo de como razonar sobre corrección de programas.]]></description>
			<content:encoded><![CDATA[<p>En otro ejercicio de la facultad se me pedía sumar todos los valores individuales de una matriz cuadrada a través de un algoritmo recursivo. Mi resolución en Java fue la siguiente:</p>
<pre><code>
	public static int sumaMatriz(int arr2[][], int m, int n) {
		if( (m == n) &#038;&#038; (m == 0) ) return arr2[m][n];
		if(m == n) return arr2[m][n] + sumaMatriz(arr2, m-1, n) + sumaMatriz(arr2, m-1, n-1) + sumaMatriz(arr2, m, n-1); //Caso a
		if(m > n) {
			if(n > 0) {
				return arr2[m][n] + sumaMatriz(arr2, m, n-1); //Caso b
			} else {	
				return arr2[m][n];
			}
		} else { //n > m
			if(m > 0) {
				return arr2[m][n] + sumaMatriz(arr2, m-1, n); //Caso c
			} else {
				return arr2[m][n];
			}
		}
	}
</code></pre>
<p>Me interesa este ejercicio para pensar de otra forma sobre corrección de programas. La pregunta es si el algoritmo es correcto y después de pensarlo un poco llegue a la conclusión de que lo era. Por lo pronto para hacer una demostración formal debería usar inducción estructural pero este post trata más bien sobre trabajo previo a una demostración, lo que en <a href="http://www.amazon.com/How-Prove-Structured-Daniel-Velleman/dp/0521675995/" class="amazon">How to Prove it</a> llaman scratchwork. O sea el razonamiento a través del cual se llega a una demostración.</p>
<p>Primero que nada hagamos un poco de debugging con un caso simple de una matriz de 3&#215;3. Para esto agregamos lo siguiente al código anterior:</p>
<pre><code>
	public static int sumaMatriz(int arr2[][], int m, int n) {
		if( (m == n) &#038;&#038; (m == 0) ) return arr2[m][n];
		<strong>System.out.println(n + &#8221; &#8221; + m);</strong>
		if(m == n) return arr2[m][n] + sumaMatriz(arr2, m-1, n) + sumaMatriz(arr2, m-1, n-1) + sumaMatriz(arr2, m, n-1); //Caso a
		if(m > n) {
&#8230;.
&#8230;.
</code></pre>
<p>Y testeamos la función llamándola con:</p>
<pre><code>
public class TP4 {

	public static void main (String[] args) {
		int[][] arr2;
		arr2 = new int[3][3];
		arr2[0][0] = 1;
		arr2[0][1] = 2;
		arr2[0][2] = 2;
		arr2[1][0] = 4;
		arr2[1][1] = 2;
		arr2[1][2] = 3;
		arr2[2][0] = 4;
		arr2[2][1] = 7;
		arr2[2][2] = 8;
		System.out.println(&#8221;Ej9:&#8221;);
		System.out.println( TP4.sumaMatriz(arr2,2 ,2));
	}
}
</code></pre>
<p>Lo que muestra por consola es:</p>
<pre><code>
Ej9:

2 2
2 1
2 0
1 1
1 0
0 0
0 1
1 2
0 2

33
</code></pre>
<p>Podemos ver que todos los elementos de la matriz fueron accedidos y que el resultado es el correcto. Ahora imaginémonos el árbol de las llamadas de función.</p>
<p><img src="http://www.metonymie.com/projects/2009/square-matrix-recursive/3x3.jpeg"/> </p>
<p>Vemos que los elementos de la diagonal principal hacen 3 llamados más, al próximo elemento de la diagonal principal, y a los dos elementos con m o n decrementados en uno. Mientras que los elementos que no están en la diagonal principal hacen un solo llamado.</p>
<h3>Razonamiento (Informal) sobre la corrección del Algoritmo</h3>
<p>Consideremos una matriz cuadrada de grado m, tal que m sea mayor que 5 (esto es por claridad para hacer este ejercicio) y concentrémonos en los últimos 5&#215;5 casilleros del limite inferior derecho, que es donde comienza el algoritmo.</p>
<p><img src="http://www.metonymie.com/projects/2009/square-matrix-recursive/1.gif"/> </p>
<p>Primer paso toma el elemento en m x m:</p>
<p><img src="http://www.metonymie.com/projects/2009/square-matrix-recursive/2.gif"/> </p>
<p>A partir de esto se realiza la llamada recursiva: </p>
<pre><code>
if(m == n) return arr2[m][n] + sumaMatriz(arr2, m-1, n) + sumaMatriz(arr2, m-1, n-1) + sumaMatriz(arr2, m, n-1); //Caso a
</code></pre>
<p><img src="http://www.metonymie.com/projects/2009/square-matrix-recursive/3.gif"/> </p>
<p>De la que se desprenden los siguientes 3 pasos.</p>
<p>El caso b:</p>
<pre><code>
return arr2[m][n] + sumaMatriz(arr2, m, n-1); //Caso b
</code></pre>
<p><img src="http://www.metonymie.com/projects/2009/square-matrix-recursive/4.gif"/> </p>
<p>De nuevo el caso a:</p>
<pre><code>
if(m == n) return arr2[m][n] + sumaMatriz(arr2, m-1, n) + sumaMatriz(arr2, m-1, n-1) + sumaMatriz(arr2, m, n-1); //Caso a
</code></pre>
<p><img src="http://www.metonymie.com/projects/2009/square-matrix-recursive/5.gif"/> </p>
<p>Y finalmente el caso c:</p>
<pre><code>
				return arr2[m][n] + sumaMatriz(arr2, m-1, n); //Caso c
</code></pre>
<p><img src="http://www.metonymie.com/projects/2009/square-matrix-recursive/6.gif"/> </p>
<p>Hemos llegado a llenar una matriz de 3&#215;3, pero esto no nos demuestra nada, ahora lo interesante es saber que pasa cuando continua el algoritmo en los pasos siguientes y aquí es donde esta el truco.</p>
<p>Lo interesante es que las 3 posibles llamadas recursivas garantizan la siguiente:</p>
<ul>
<li><p>Por el caso a, desde una llamada de la función desde un casillero en la diagonal principal, no se llamara a la función en ningún casillero que este en la misma linea o columna de los elemento de donde han sido llamados por un casillero en la diagonal principal anterior.También por el caso a, la iteración a través de elementos de la diagonal principal eventualmente cubrirá todos los elementos de la diagonal principal de la matriz.</p>
<p><img src="http://www.metonymie.com/projects/2009/square-matrix-recursive/9.gif"/> </p>
</li> 
<li><p>Por el caso b, desde una llamada de la función desde un casillero en una columna que no sea en la diagonal principal, siempre continuara por esa misma columna hasta completarla.</p>
<p><img src="http://www.metonymie.com/projects/2009/square-matrix-recursive/7.gif"/> </p>
</li>
<li><p>Por el caso c, desde una llamada de la función desde un casillero en la fila que no sea en la diagonal principal, siempre continuara por esa misma fila hasta completarla.</p>
<p><img src="http://www.metonymie.com/projects/2009/square-matrix-recursive/8.gif"/> </p>
</li>
</ul>
<p>A partir de esto podemos inferir que el algoritmo pasa por todos los elementos de cualquier matriz cuadrada.</p>
<h3>Importante</h3>
<p>Quiero recalcar que esto es un razonamiento, a partir del cual por inducción estructural podría construirse una demostración, pero en términos de lógica formal no es una demostración. Igual, no deja de ser un razonamiento valido, lo cierto es que en la <strong>programación como practica</strong> es importante poder pensar si lo que se esta haciendo es correcto y si los programas que uno hace cumplen con las necesidades que uno tiene, pero también es cierto que sería completamente Overkill el tener que hacer una demostración formal de cada programa que uno hace. Lo importante es tener herramientas para poder razonar y pensar sobre como se programa.</p>

]]></content:encoded>
			<wfw:commentRss>http://www.metonymie.com/apuntes/2009/06/05/iterando-por-una-matriz-cuadrada-recursivamente.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>Implementación del Algoritmo de Euclides</title>
		<link>http://www.metonymie.com/apuntes/2009/06/04/implementacion-del-algoritmo-de-euclides.html</link>
		<comments>http://www.metonymie.com/apuntes/2009/06/04/implementacion-del-algoritmo-de-euclides.html#comments</comments>
		<pubDate>Thu, 04 Jun 2009 23:36:25 +0000</pubDate>
		<dc:creator>admin</dc:creator>
		
		<category><![CDATA[Algoritmia]]></category>

		<category><![CDATA[Haskell]]></category>

		<category><![CDATA[Java]]></category>

		<category><![CDATA[Algoritmo de Euclides]]></category>

		<category><![CDATA[Epistemologia]]></category>

		<category><![CDATA[Euclides]]></category>

		<category><![CDATA[Historia de las Matematicas]]></category>

		<category><![CDATA[Thomas Kuhn]]></category>

		<guid isPermaLink="false">http://www.metonymie.com/apuntes/?p=40</guid>
		<description><![CDATA[Al Algoritmo de Euclides implementado en Haskell y en Java]]></description>
			<content:encoded><![CDATA[<p>En un ejercicio de la facultad me pidieron hacer un función recursiva que encuentre el Maximo común divisor entre dos números por medio de restas. Ahora, esto que parece un simple ejercicio en realidad se engancha con un montón de temas interesantes de la historia de la matemática. Bueno, lo primero que se me ocurrió fue factorizar los dos números y después buscar los factores comunes, obviamente esta idea no es lo que se dice fácil ( quizás hasta imposible ) de hacer recursivamente. Se me ocurrió investigar un poco y encontré el <a href="http://es.wikipedia.org/wiki/Algoritmo_de_Euclides" class="wiki">Algoritmo de Euclides</a>. La implementación básica en Haskell es:</p>
 
<code><pre>
algEuclid :: Int -> Int -> Int
algEuclid a b	| c &lt; 0 	= algEuclid b a
		| c == 0	= b
		| c >= b 	= algEuclid c b
		| c &lt; b		= algEuclid b c
		where c = a - b
</pre></code>

<p>La versión en Haskell es super clara, pero se me pedía implementarla en Java y quedo así:</p>

<code><pre>
public class Ej {

	public static void main (String[] args) {
		//Ej8. Maximo Comun Divisor de 2 numeros
		System.out.println(&#8221;Ej8:&#8221;);
		System.out.println( TP4.algEuclid(64, 48));
	}


	public static int algEuclid( int a, int b) {
		int c = a - b;
		if ( c &lt; 0) {
			return algEuclid(b, a);
		} else if (c == 0) {
			return b;
		} else if ( c >= b ) {
			return algEuclid(c, b);
		} //(c &lt; b)
			return algEuclid(b, c);
	}
	
}
</pre></code>

<p>Lo interesante es que <a href="http://es.wikipedia.org/wiki/Euclides" class="wiki">Euclides</a> hace su demostración en términos puramente geométricos y en términos geométricos existen magnitudes a las que no es posible aplicarles esta formula. En particular <a href="http://es.wikipedia.org/wiki/Raiz_cuadrada_de_2" class="wiki">raíz cuadrada de 2</a>, es decir que no son <a href="http://es.wikipedia.org/wiki/Conmensurabilidad#Conmensurabilidad" class="wiki">conmensurables</a>. Esto tuvo profundas implicancias en el desarrollo de la matemática, porque durante siglos al existir relaciones que no podían ser expresadas puramente en números (tal y como pretendían los <a href="http://es.wikipedia.org/wiki/Pitagoricos" class="wiki">pitagóricos</a>) los griegos decidieron priorizar la geometría sobre otras formas de razonamiento matemático. Fue necesario un salto de <a href="http://es.wikipedia.org/wiki/Paradigma" class="wiki">paradigma</a>, en el sentido de <a href="http://es.wikipedia.org/wiki/Thomas_Kuhn" class="wiki">Kuhn</a>, a saber la aceptación de los <a href="http://es.wikipedia.org/wiki/Irracionales">números irracionales</a> como objetos matemáticos por derecho propio para poder continuar avanzando en diversas áreas de la matemática. </p>
<p>En definitiva, si la historia de las matemáticas demuestra algo, es que si hay algo que no podemos entender actualmente o que parece que nos lleva a un callejón sin salida, en algún momento quizás con un enfoque nuevo probablemente podremos integrarlo a un sistema explicativo de orden superior.</p>
<h3>Referencias</h3>
<a href="http://www.amazon.com/Journey-through-Genius-Theorems-Mathematics/dp/014014739X/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1244160494&#038;sr=8-1" class="amazon">Journey through Genius: The Great Theorems of Mathematics</a>; William Dunham; Penguin Books; 1990]]></content:encoded>
			<wfw:commentRss>http://www.metonymie.com/apuntes/2009/06/04/implementacion-del-algoritmo-de-euclides.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>Armonizando escalas con Haskell</title>
		<link>http://www.metonymie.com/apuntes/2009/05/22/armonizando-escalas-con-haskell.html</link>
		<comments>http://www.metonymie.com/apuntes/2009/05/22/armonizando-escalas-con-haskell.html#comments</comments>
		<pubDate>Fri, 22 May 2009 20:03:19 +0000</pubDate>
		<dc:creator>admin</dc:creator>
		
		<category><![CDATA[Haskell]]></category>

		<category><![CDATA[Armonía]]></category>

		<category><![CDATA[Música]]></category>

		<guid isPermaLink="false">http://www.metonymie.com/apuntes/?p=38</guid>
		<description><![CDATA[Un pequeño programita para armonizar escalas en Haskell.]]></description>
			<content:encoded><![CDATA[<p>Este es el primer programita en Haskell que hice por gusto propio, principalmente para afianzar un poco conceptos y además para probar tipos de datos y sobre todo de pensar desde Haskell. Lo fantástico es que estas cosas las hacia a mano, cuando tenía 17 años y estaba aprendiendo armonía (Por mi cuenta, obviamente).</p>

<p>Primero definí un tipo de datos Nota y una función sucesor cíclica (dado que estoy interesado en relaciones puramente armónicas).</p> 
<pre><code>
data Nota = A | Bb | B | C | Db | D | Eb | E | F | Gb | G | Ab deriving (Eq)

suc :: Nota -> Nota
suc A = Bb; suc Bb = B; suc B = C; suc C = Db; suc Db = D; suc D = Eb; suc Eb = E; suc E = F; suc F = Gb; suc Gb = G; suc G = Ab; suc Ab = A;
</code></pre>

<p>Después hice que el tipo de datos Nota fuera instancia de la clase show, dando una definición especifica de la función show para mi tipo de datos para tratar los problemas del doble nombre de determinadas notas ( <a href="http://en.wikipedia.org/wiki/Enharmonic" class="wiki">equivalencias enarmonicas</a> ).</p>

<pre><code>
instance Show Nota where
	show A = show "A"
	show Bb = show "A#/Bb"
	show B = show "B"
	show C = show "C"
	show Db = show "C#/Db"
	show D = show "D"
	show Eb = show "D#/Eb"
	show E = show "E"
	show F = show "F"
	show Gb = show "F#/Gb"
	show G = show "G"
	show Ab = show "G#/Ab"
</code></pre>

<p>A partir de esto puedo definir la función intervalo, que toma un número natural (de 0 a 11, aunque se puede considerar al tipo Nota y a la función intervalo como compartiendo propiedades con la aritmética mod(12), por lo que n puede tomar valores mayores a 11 y los resultados van a ser los mismos a <code class="inline">intervalo _ (n mod (12))</code>). En un principio había pensado que se podía pensar como un <a href="http://en.wikipedia.org/wiki/Isomorphic" class="wiki">isomorfismo</a>, pero no estoy convencido, aunque si tomamos aplicación parcial de <code class="inline">intervalo x</code> como una función en si misma, ahí si podría serlo.</p>

<pre><code>
intervalo :: Nota -> Integer -> Nota
intervalo a 0 = a
intervalo a 1 = suc(a)
intervalo a n = suc( intervalo a (n-1))
</code></pre>

<p>No intente definir los intervalos a partir de sus nombres usuales sino simplemente desde su distancia (ascendente) a partir de la nota base. O sea, se sobreentiende que si le doy un valor de uno representa a una segunda menor, de 4 a una tercera mayor, etc. (Por otro lado es como siempre me acerque al concepto de <a href="http://en.wikipedia.org/wiki/Interval_(music)" class="wiki">intervalo</a>).</p>

<p>Paso siguiente construir funciones para definir las cuatro triadas básicas.</p>

<pre><code>
type Triada = (Nota, Nota, Nota) 

maj :: Nota -> Triada
maj a = (a, intervalo a 4, intervalo a 7)

men :: Nota -> Triada
men a = (a, intervalo a 3, intervalo a 7)

aug :: Nota -> Triada
aug a = (a, intervalo a 4, intervalo a 8 )

dim :: Nota -> Triada
dim a = (a, intervalo a 3, intervalo a 6)
</code></pre>

<p>Y luego definir las escalas y modos básicos.</p>

<pre><code>
escala :: Nota -> [Integer] -> [Nota]
escala a [] = []
escala a (x:xs) = intervalo a x : escala a xs

escala_cromatica :: Nota -> [Nota]
escala_cromatica a = escala a [0..11]

escala_mayor :: Nota -> [Nota]
escala_mayor a = escala a [0,2,4,5,7,9,11]

escala_menor :: Nota -> [Nota]
escala_menor a = escala a [0,2,3,5,7,8,10]

escala_menor_armonica :: Nota -> [Nota]
escala_menor_armonica a = escala a [0,2,3,5,7,8,11]

escala_menor_melodica :: Nota -> [Nota]
escala_menor_melodica a = escala a [0,2,3,5,7,9,11]

modo_dorico :: Nota -> [Nota]
modo_dorico a = escala a [0,2,3,5,7,9,10]

modo_frigio :: Nota -> [Nota]
modo_frigio a = escala a [0,1,3,5,7,8,10]

modo_lidio :: Nota -> [Nota]
modo_lidio a = escala a [0,2,4,6,7,9,11]

modo_mixolidio :: Nota -> [Nota]
modo_mixolidio a = escala a [0,2,4,5,7,9,10]

modo_locrio :: Nota -> [Nota]
modo_locrio a = escala a [0,1,3,5,6,8,10]

escala_disminuida :: Nota -> [Nota]
escala_disminuida a = escala a [0,2,3,5,6,8,9,11]

escala_aumentada :: Nota -> [Nota]
escala_aumentada a = escala a [0,2,4,6,8,10]
</code></pre>

<p>Dado que voy a intentar hacer reconocimiento de acordes, se vuelve necesario definir la función distancia (que es distancia ascendente).</p>

<pre><code>
distancia :: Nota -> Nota -> Integer
distancia a b 	| (intervalo a 0) == b 	= 0
		| otherwise 		= 1 + (distancia (suc a) b)
</code></pre>


<p>Probar de Reconocer Acordes.</p>
<pre><code>
es_triada_mayor :: Triada -> Bool
es_triada_mayor (a,b,c) | (distancia a b) == 4 &#038;&#038; (distancia a c) == 7 = True
			| otherwise = False

es_triada_menor :: Triada -> Bool
es_triada_menor (a,b,c) | (distancia a b) == 3 &#038;&#038; (distancia a c) == 7 = True
			| otherwise = False

es_triada_disminuida :: Triada -> Bool
es_triada_disminuida (a,b,c) 	| (distancia a b) == 3 &#038;&#038; (distancia a c) == 6 = True
				| otherwise = False

es_triada_aumentada :: Triada -> Bool
es_triada_aumentada (a,b,c) 	| (distancia a b) == 4 &#038;&#038; (distancia a c) == 8 = True
				| otherwise = False
</code></pre>
<p>Ejemplo de uso:</p>
<pre><code>
*Main> es_triada_mayor (A,Db,E)
True
*Main> es_triada_mayor (A,C,E)
False
</code></pre>

<p><strong>Aclaración:</strong> Como el tipo de datos es cíclico a partir de la función <code class="inline">suc</code> y estamos trabajando con <a href="http://en.wikipedia.org/wiki/Triad_(music)" class="wiki">triadas</a> básicas, no importan las diferentes <a href="http://en.wikipedia.org/wiki/Inversion_(music)#Inverted_chords" class="wiki">inversiones de los acordes</a>.</p>


<p>Ver si una triada existe en una escala:</p>
<pre><code>
esta_triada_en_escala :: [Nota] -> Triada -> Bool
esta_triada_en_escala xs (a,b,c)	| elem a xs &#038;&#038; elem b xs &#038;&#038; elem c xs = True
					| otherwise = False
{- 
*Main> esta_triada_en_escala (men A) (modo_dorico A)
True
-}
</code></pre>

<p>Ahora ya puedo armonizar escalas por un método de Brute Force, no muy elegante, pero por lo pronto efectivo. Primero creo todas las posibles triadas (4*12 = 48) y después filtro las que corresponden a la escala, además de crear una función que muestre los resultados de una forma visualmente más agradable.</p>

<pre><code>
show_triada :: Triada -> String
show_triada (a,b,c) 	| es_triada_mayor (a,b,c) = strip_slashes(show a) ++ " maj"
			| es_triada_menor (a,b,c) = strip_slashes(show a) ++ " min"
			| es_triada_aumentada (a,b,c) = strip_slashes(show a) ++ " aug"
			| es_triada_disminuida (a,b,c) = strip_slashes(show a) ++ " dim"
			| otherwise = strip_slashes(show (a,b,c)) ++ " No es Triada"
			where 
				strip_slashes :: [Char] -> [Char]
				strip_slashes [] = []
				strip_slashes (x:xs) 	| x == &#8216;\&#8221;&#8216; = strip_slashes xs
							| otherwise = x : strip_slashes xs		

todas_las_triadas :: Nota -> [Triada]
todas_las_triadas a = concat( map hacer_triadas_de (escala_cromatica a))
			where
			hacer_triadas_de :: Nota -> [Triada]
			hacer_triadas_de a = [(dim a),(men a),(maj a),(aug a)]
armonizar_escala :: [Nota] -> [String]
armonizar_escala (x:xs) = map show_triada (filter (esta_triada_en_escala (x:xs)) (todas_las_triadas x))

{-
*Main> armonizar_escala (modo_dorico A)
["A min","B min","C maj","D maj","E min","F#/Gb dim","G maj"]
*Main> armonizar_escala (escala_menor_armonica E)
["E min","F#/Gb dim","G aug","A dim","A min","B maj","B aug","C dim","C min","C maj","D#/Eb dim","D#/Eb aug"]
*Main> armonizar_escala (escala_aumentada E)
["E aug","F#/Gb aug","G#/Ab aug","A#/Bb aug","C aug","D aug"]
*Main> armonizar_escala (escala_disminuida E)
["E dim","F#/Gb dim","F#/Gb min","F#/Gb maj","G dim","A dim","A min","A maj","A#/Bb dim","C dim","C min","C maj","C#/Db dim","D#/Eb dim","D#/Eb min","D#/Eb maj"]
-}

</code></pre>
<p><strong>Detalle:</strong> otro ejemplo de currying en <code class="inline">esta_triada_en_escala (x:xs)</code>.</p>
<p>Obviamente esto un principio y hay un montón de ideas que se me ocurrieron mientras hacia esto. Así que, sera continuado.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.metonymie.com/apuntes/2009/05/22/armonizando-escalas-con-haskell.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>Funciones de Orden Superior Y Combinadores</title>
		<link>http://www.metonymie.com/apuntes/2009/05/19/funciones-de-orden-superior-y-combinadores.html</link>
		<comments>http://www.metonymie.com/apuntes/2009/05/19/funciones-de-orden-superior-y-combinadores.html#comments</comments>
		<pubDate>Tue, 19 May 2009 20:52:59 +0000</pubDate>
		<dc:creator>admin</dc:creator>
		
		<category><![CDATA[Haskell]]></category>

		<category><![CDATA[Programación Funcional]]></category>

		<category><![CDATA[Combinators]]></category>

		<category><![CDATA[Higher Order Functions]]></category>

		<guid isPermaLink="false">http://www.metonymie.com/apuntes/?p=37</guid>
		<description><![CDATA[Una función de orden superior es una función que devuelve otra función.
Un Combinador es un función de orden superior que encapsula un determinado comportamiento de una clase de funciones y provee un template para la creación de estas. Ej:

iter :: (Integer -> Integer -> Integer) -> Integer -> ( Integer -> Integer )
iter op e [...]]]></description>
			<content:encoded><![CDATA[<p>Una <a href="http://en.wikipedia.org/wiki/Higher_order_function" class="wiki">función de orden superior</a> es una función que devuelve otra función.</p>
<p>Un Combinador es un función de orden superior que encapsula un determinado comportamiento de una clase de funciones y provee un template para la creación de estas. Ej:</p>
<pre><code>
iter :: (Integer -> Integer -> Integer) -> Integer -> ( Integer -> Integer )
iter op e = fun
	where 
	fun 0	= e
	fun m@(n + 1) = op m (fun n)

factorial :: Integer -> Integer
factorial = iter (*) 1

sumatorio :: Integer -> Integer
sumatorio = iter (+) 0
</code></pre>
<h3>Referencias</h3>

<p><a class="biblio" href="http://www.lcc.uma.es/~blas/pfHaskell/">Razonando con Haskell</a>;Blas C. Ruiz,  Francisco Gutiérrez, Pablo Guerrero y  José E. Gallardo;Thomson Editores Spain;2004</p>]]></content:encoded>
			<wfw:commentRss>http://www.metonymie.com/apuntes/2009/05/19/funciones-de-orden-superior-y-combinadores.html/feed</wfw:commentRss>
		</item>
	</channel>
</rss>
