<?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"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>La Sombra de Dijkstra</title>
	<atom:link href="http://www.programando.org/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.programando.org/blog</link>
	<description>Sobre el arte y la práctica de la programación</description>
	<lastBuildDate>Fri, 29 Jul 2011 11:23:04 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Una buena idea</title>
		<link>http://www.programando.org/blog/2011/07/una-buena-idea/</link>
		<comments>http://www.programando.org/blog/2011/07/una-buena-idea/#comments</comments>
		<pubDate>Fri, 29 Jul 2011 11:23:04 +0000</pubDate>
		<dc:creator>ediaz</dc:creator>
				<category><![CDATA[Herramientas]]></category>
		<category><![CDATA[control de versiones]]></category>
		<category><![CDATA[dropbox]]></category>
		<category><![CDATA[git]]></category>

		<guid isPermaLink="false">http://www.programando.org/blog/?p=343</guid>
		<description><![CDATA[GIT es una gran herramienta de control de versiones distribuido, podemos trabajar en la casa y en la oficina y sincronizar nuestros repositorios de código fuente. Pero está siempre el problema de donde alojar un servidor central donde colocar nuestro repositorio. GitHub permite arrendar espacio en sus servidores para alojar nuestros repositorios, y hay otros servicios por ahí. Pero una alternativa bastante ingeniosa es usar DropBox, alojar nuestros repositorios en la carpeta compartida de Dropbox, crear repositorios limpios (bare repositories) y hacer git pull/pull localmente sobre esa carpeta compartida. La idea aparece en este post (en inglés), y es bastante simple y potente. Supongo que esto también puede servir con otros gestores de control de versiones, como Mercurial o Bzr, pero incluso es una buena idea que se podría aplicar con gestores más tradicionales como Subversion. Si alguien lo implementa con esos sistemas lo invito a comentar y compartir la experiencia.]]></description>
			<content:encoded><![CDATA[<p><a href="http://git-scm.com/">GIT</a> es una gran herramienta de <a href="http://www.lnds.net/blog/2010/07/control-de-versiones-distribuido.html">control de versiones distribuido</a>, podemos trabajar en la casa y en la oficina y sincronizar nuestros repositorios de código fuente. Pero está siempre el problema de donde alojar un servidor central donde colocar nuestro repositorio.</p>
<p><a href="http://www.github.com">GitHub</a> permite arrendar espacio en sus servidores para alojar nuestros repositorios, y hay otros servicios por ahí. Pero una alternativa bastante ingeniosa es usar <a href="http://db.tt/3IdZpmw">DropBox</a>, alojar nuestros repositorios en la carpeta compartida de <a href="http://db.tt/3IdZpmw">Dropbox</a>, crear repositorios limpios (bare repositories) y hacer git pull/pull localmente sobre esa carpeta compartida. La idea aparece en <a href="http://random-rails.blogspot.com/2009/08/on-version-control.html">este post</a> (en inglés), y es bastante simple y potente.</p>
<p>Supongo que esto también puede servir con otros gestores de control de versiones, como Mercurial o Bzr, pero incluso es una buena idea que se podría aplicar con gestores más tradicionales como Subversion. Si alguien lo implementa con esos sistemas lo invito a comentar y compartir la experiencia.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.programando.org/blog/2011/07/una-buena-idea/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Capítulo 20, dispositivos</title>
		<link>http://www.programando.org/blog/2011/07/capitulo-20-dispositivos/</link>
		<comments>http://www.programando.org/blog/2011/07/capitulo-20-dispositivos/#comments</comments>
		<pubDate>Sun, 24 Jul 2011 00:57:12 +0000</pubDate>
		<dc:creator>ediaz</dc:creator>
				<category><![CDATA[Sin categoría]]></category>

		<guid isPermaLink="false">http://www.programando.org/blog/?p=340</guid>
		<description><![CDATA[Ya se encuentra disponible el capítulo 20 de nuestro curso de programación, dispositivos. http://www.programando.org/aprende-a-programar/segunda-parte/arquitectura-de-computadores/dispositivos.html Este capítulo cierra la parte dedicada a la arquitectura de computadores. A continuación retomaremos el objetivo de la segunda parte del curso, que es construir una versión gráfica de nuestro juego.]]></description>
			<content:encoded><![CDATA[<p>Ya se encuentra disponible el capítulo 20 de nuestro curso de programación, dispositivos.</p>
<p><a href="http://www.programando.org/aprende-a-programar/segunda-parte/arquitectura-de-computadores/dispositivos.html">http://www.programando.org/aprende-a-programar/segunda-parte/arquitectura-de-computadores/dispositivos.html</a></p>
<p>Este capítulo cierra la parte dedicada a la arquitectura de computadores. A continuación retomaremos el objetivo de la segunda parte del curso, que es construir una versión gráfica de nuestro juego.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.programando.org/blog/2011/07/capitulo-20-dispositivos/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Capitulo 19, interpretando el código de máquina</title>
		<link>http://www.programando.org/blog/2011/06/capitulo-19-interpretando-el-codigo-de-maquina/</link>
		<comments>http://www.programando.org/blog/2011/06/capitulo-19-interpretando-el-codigo-de-maquina/#comments</comments>
		<pubDate>Wed, 22 Jun 2011 02:40:53 +0000</pubDate>
		<dc:creator>ediaz</dc:creator>
				<category><![CDATA[Aprendiendo a programar]]></category>

		<guid isPermaLink="false">http://www.programando.org/blog/?p=332</guid>
		<description><![CDATA[He completado el capitulo 19 del curso. Tal como les adelanté, estoy usando el nuevo formato para el curso, así que para leerlo deben ir a la siguiente dirección: http://www.programando.org/aprende-a-programar/segunda-parte/arquitectura-de-computadores/interpretando-el-codigo-de-maquina.html En este capítulo implemento el interprete del lenguaje assembler que hemos definido para nuestra máquina virtual (definida en el capítulo 17: Código de Máquina). Lo interesante es que implementamos un interprete de una forma totalmente funcional, lo que permite mayor flexibilidad y un código más simple y &#8220;mantenible&#8221;. Los comentarios los pueden dejar en este post. Disculpas por la demora, vamos a retomar el ritmo del curso en estas semanas.]]></description>
			<content:encoded><![CDATA[<p>He completado el capitulo 19 del curso. Tal como les adelanté, estoy usando el nuevo formato para el curso, así que para leerlo deben ir a la siguiente dirección:</p>
<p><a href="http://www.programando.org/aprende-a-programar/segunda-parte/arquitectura-de-computadores/interpretando-el-codigo-de-maquina.html">http://www.programando.org/aprende-a-programar/segunda-parte/arquitectura-de-computadores/interpretando-el-codigo-de-maquina.html</a></p>
<p>En este capítulo implemento el interprete del lenguaje assembler que hemos definido para nuestra máquina virtual (definida en el capítulo 17: <a href="http://www.programando.org/aprende-a-programar/segunda-parte/arquitectura-de-computadores/codigo-de-maquina.html">Código de Máquina</a>).</p>
<p>Lo interesante es que implementamos un interprete de una forma totalmente funcional, lo que permite mayor flexibilidad y un código más simple y &#8220;mantenible&#8221;.</p>
<p>Los comentarios los pueden dejar en este post.</p>
<p>Disculpas por la demora, vamos a retomar el ritmo del curso en estas semanas.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.programando.org/blog/2011/06/capitulo-19-interpretando-el-codigo-de-maquina/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Nueva versión del curso</title>
		<link>http://www.programando.org/blog/2011/06/nueva-version-del-curso/</link>
		<comments>http://www.programando.org/blog/2011/06/nueva-version-del-curso/#comments</comments>
		<pubDate>Wed, 08 Jun 2011 03:45:04 +0000</pubDate>
		<dc:creator>ediaz</dc:creator>
				<category><![CDATA[Aprendiendo a programar]]></category>

		<guid isPermaLink="false">http://www.programando.org/blog/?p=327</guid>
		<description><![CDATA[Ya terminé la traducción a Sphinx de los posts del curso, los 18 capítulos publicados hasta ahora se encuentran en su nuevo formato, pueden acceder en esta dirección: http://www.programando.org/aprende-a-programar/ En los próximos días retomo los capítulos que siguen. Dado que a partir de ahora sólo usaré sphinx para escribir el curso usaremos el blog para anunciar la incorporación de nuevos capítulos, y para que ustedes hagan sus comentarios. Esta es la versión 0.1a del texto, agradeceré sus comentarios y correcciones. El layout, estilo gráfico irá cambiando, está con las opciones por default. Además faltan varios elementos de indexado. Si algún lector conoce Sphinx y quiere ayudarme en crear los marcadores para los índices agradeceré su colaboración.]]></description>
			<content:encoded><![CDATA[<p>Ya terminé la traducción a Sphinx de los posts del curso, los 18 capítulos publicados hasta ahora se encuentran en su nuevo formato, pueden acceder en esta dirección: <a href="http://www.programando.org/aprende-a-programar/">http://www.programando.org/aprende-a-programar/</a></p>
<p>En los próximos días retomo los capítulos que siguen. Dado que a partir de ahora sólo usaré sphinx para escribir el curso usaremos el blog para anunciar la incorporación de nuevos capítulos, y para que ustedes hagan sus comentarios.</p>
<p>Esta es la versión 0.1a del texto, agradeceré sus comentarios y correcciones. El layout, estilo gráfico irá cambiando, está con las opciones por default. Además faltan varios elementos de indexado. Si algún lector conoce Sphinx y quiere ayudarme en crear los marcadores para los índices agradeceré su colaboración.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.programando.org/blog/2011/06/nueva-version-del-curso/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Cambio de formato</title>
		<link>http://www.programando.org/blog/2011/05/323/</link>
		<comments>http://www.programando.org/blog/2011/05/323/#comments</comments>
		<pubDate>Mon, 16 May 2011 02:09:34 +0000</pubDate>
		<dc:creator>ediaz</dc:creator>
				<category><![CDATA[Sin categoría]]></category>

		<guid isPermaLink="false">http://www.programando.org/blog/?p=323</guid>
		<description><![CDATA[He recibido algunos comentarios en el sentido de que es dificil seguir el curso de programación en el blog. Efectivamente, cuando uno está leyendo un tutorial o curso se hace necesario poder seguir el orden de los capítulos, acceder a la tabla de contenidos y saber que viene antes y que viene después. El formato del blog no permite esto. Así que con el fin de remediar esta incomodidad he decidido traspasar el texto del curso a un formato distinto. He decidido que voy a usar Sphinx, una herramienta bastante popular entre los desarrolladores Pyhton, de hecho es usada para escribir la documentación de Python. Esto tiene varias ventajas adicionales, entre otras: Podré mantener el texto en un repositorio Git. Es facil con Sphinx generar otros formatos, como PDF, por ejemplo. Permitirá separar el contenido del blog con el del curso. Así que les pido un poco de paciencia, mientras hago este cambio, pronto retomaremos el curso. Lo bueno es que podremos tocar otros temas en el blog.]]></description>
			<content:encoded><![CDATA[<p>He recibido algunos comentarios en el sentido de que es dificil seguir el curso de programación en el blog. Efectivamente, cuando uno está leyendo un tutorial o curso se hace necesario poder seguir el orden de los capítulos, acceder a la tabla de contenidos y saber que viene antes y que viene después. El formato del blog no permite esto. Así que con el fin de remediar esta incomodidad he decidido traspasar el texto del curso a un formato distinto.</p>
<p>He decidido que voy a usar <a href="http://sphinx.pocoo.org/">Sphinx</a>, una herramienta bastante popular entre los desarrolladores Pyhton, de hecho es usada para escribir la documentación de Python.</p>
<p>Esto tiene varias ventajas adicionales, entre otras:</p>
<ol>
<li>Podré mantener el texto en un repositorio Git.</li>
<li>Es facil con Sphinx generar otros formatos, como PDF, por ejemplo.</li>
<li>Permitirá separar el contenido del blog con el del curso.</li>
</ol>
<p>Así que les pido un poco de paciencia, mientras hago este cambio, pronto retomaremos el curso. Lo bueno es que podremos tocar otros temas en el blog.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.programando.org/blog/2011/05/323/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Cargando el código de máquina</title>
		<link>http://www.programando.org/blog/2011/04/cargando-el-codigo-de-maquina/</link>
		<comments>http://www.programando.org/blog/2011/04/cargando-el-codigo-de-maquina/#comments</comments>
		<pubDate>Wed, 27 Apr 2011 12:01:45 +0000</pubDate>
		<dc:creator>ediaz</dc:creator>
				<category><![CDATA[Aprendiendo a programar]]></category>
		<category><![CDATA[archivos]]></category>
		<category><![CDATA[assembler]]></category>
		<category><![CDATA[curso]]></category>
		<category><![CDATA[map]]></category>
		<category><![CDATA[máquina virtual]]></category>
		<category><![CDATA[open]]></category>
		<category><![CDATA[with]]></category>

		<guid isPermaLink="false">http://www.programando.org/blog/?p=308</guid>
		<description><![CDATA[Si recuerdan en el capítulo anterior, de nuestro curso de programación, definimos una máquina virtual con un código, o lenguaje de máquina bien preciso. En el diagrama sin embargo aparece una componente que no explicamos, se trata del módulo loader. Acá está la figura para que la recuerden: El módulo loader se encarga de cargar un programa, escrito en el lenguaje ensamblador, a la memoria de nuestra máquina virtual, para su posterior ejecución. Si recuerdan, uno de los ejemplos que vimos es este programa ensamblador que despliega la tabla de multiplicad del 5: AR0 5 AR1 0 INCR1 RMUL IMPR RES 50 SSC 13 SALTA 4 ALTO Notarán algunos cambios. Las lineas las empezamos a contar a partir de cero (0), esto obliga a modificar las direcciones de los saltos.La función del módulo loader es traducir de este lenguaje con instrucciones y números al código binario que entiende la máquina. Para programar nuestra máquina virtual escribiremos varios programas en archivos, al igual como lo hacemos con nuestros programas en python. Si los archivos que contienen código en python los grabamos con la extensión &#8216;.py&#8217;, nuestros programas los almacenaramos en archivos con la extensión &#8216;.a&#8217;, por assembler. En cada linea de estos [...]]]></description>
			<content:encoded><![CDATA[<p>Si recuerdan en el <a href="http://www.programando.org/blog/2011/04/codigo-de-maquina/">capítulo anterior</a>, de nuestro <a href="http://www.programando.org/blog/aprende-a-programar/">curso de programación</a>, definimos una <strong>máquina virtual</strong> con un código, o lenguaje de máquina bien preciso. En el diagrama sin embargo aparece una componente que no explicamos, se trata del <strong>módulo loader. </strong>Acá está la figura para que la recuerden:<br />
<a href="http://www.programando.org/blog/wp-content/uploads/2011/04/programando-cpu1.png"><img class="aligncenter size-full wp-image-289" title="programando-cpu" src="http://www.programando.org/blog/wp-content/uploads/2011/04/programando-cpu1.png" alt="" width="564" height="302" /></a></p>
<p>El módulo <strong>loader </strong>se encarga de cargar un programa, escrito en el lenguaje ensamblador, a la memoria de nuestra máquina virtual, para su posterior ejecución.</p>
<p>Si recuerdan, uno de los ejemplos que vimos es este programa ensamblador que despliega la tabla de multiplicad del 5:</p>
<blockquote>
<ol start="0">
<li>
<pre>AR0</pre>
</li>
<li>
<pre>5</pre>
</li>
<li>
<pre>AR1</pre>
</li>
<li>
<pre>0</pre>
</li>
<li>
<pre>INCR1</pre>
</li>
<li>
<pre>RMUL</pre>
</li>
<li>
<pre>IMPR</pre>
</li>
<li>
<pre>RES</pre>
</li>
<li>
<pre>50</pre>
</li>
<li>
<pre>SSC</pre>
</li>
<li>
<pre>13</pre>
</li>
<li>
<pre>SALTA</pre>
</li>
<li>
<pre>4</pre>
</li>
<li>
<pre>ALTO</pre>
</li>
</ol>
</blockquote>
<p>Notarán algunos cambios. Las lineas las empezamos a contar a partir de cero (0), esto obliga a modificar las direcciones de los saltos.La función del módulo <strong>loader </strong>es traducir de este lenguaje con instrucciones y números al código binario que entiende la máquina. </p>
<p>Para programar nuestra máquina virtual escribiremos varios programas en archivos, al igual como lo hacemos con nuestros programas en python. Si los archivos que contienen código en python los grabamos con la extensión <strong>&#8216;.py&#8217;</strong>, nuestros programas los almacenaramos en archivos con la extensión <strong>&#8216;.a&#8217;</strong>, por assembler.</p>
<p>En cada linea de estos archivos escribiremos las instrucciones o números de nuestro programa. El programa de arriba se almacena en un archivo que llamaremos <strong>&#8216;tabla_cinco.a&#8217;</strong>, es importante notar que este archivo no lleva los números. El contenido del archivo sería el siguiente:</p>
<blockquote><p>
<code>AR0<br />
5<br />
AR1<br />
0<br />
INCR1<br />
RMUL<br />
IMPR<br />
RES<br />
50<br />
SSC<br />
13<br />
SALTA<br />
4<br />
ALTO</code>
</p></blockquote>
<p>Una instrucción por linea. A las instrucciones también se les llama códigos nemotécnicos, o simplemente <strong>nemónicos</strong>. AR1 es un nemónico que significa <em>&#8216;almacena el valor que sigue en el registro R1&#8242;</em></p>
<p>Los nemónicos en nuestro lenguaje ensamblador están resumidos en esta tabla:</p>
<blockquote><p>0: ALTO<br />
1: LIM<br />
2: ACUM<br />
3: MUL<br />
4: RES<br />
5: DIV<br />
6: IMPR<br />
7: LEER<br />
8: ALM<br />
9: RR0<br />
10: RR1<br />
11: RSUM<br />
12: RMUL<br />
13: RRES<br />
14: RDIV<br />
15: AR0<br />
16: AR1<br />
17: INC<br />
18: DEC<br />
19: INCR0<br />
20: DECR0<br />
21: INCR1<br />
22: DECR1<br />
23: SALTA<br />
24: SSC<br />
25: SSN<br />
26: SSN<br />
27: SRMA<br />
28: SRME<br />
29: SRIG
</p></blockquote>
<p>La definición de cada uno de estos comandos o nemónicos, está en el capítulo <a href="http://www.programando.org/blog/2011/04/codigo-de-maquina/">código de máquina</a>.</p>
<p>Vamos a almacenar estos nemónicos en un lista en python, del siguiente modo:</p>
<pre name="code" class="python:nocontrols">
nemonicos = ['ALTO','LIM','ACUM','MUL','RES','DIV','IMPR',
        'LEER','ALM','RR0','RR1','RSUM','RMUL','RRES','RDIV',
        'AR0','AR1','INC','DEC','INCR0','DECR0','INCR1','DECR1',
        'SALTA','SSC','SSN','SSN','SRMA','SRME','SRIG']
</pre>
<p>De este modo si ejecutamos las siguiente instrucciones obtenemos el código de máquina correspondiente al nemónico:</p>
<pre name="code" class="python:nocontrols">
&gt;&gt;&gt;nemonicos.index('DEC')
18
&gt;&gt;&gt;nemonicos.index('SRME')
28
</pre>
<p>Esto nos da una idea de que hacer para leer nuestro archivo, en esencia, el <strong>algoritmo </strong>para leer el archivo con instrucciones en assembler sería:</p>
<ol>
<li>Abrir el archivo</li>
<li>Leer todas las lineas en el archivo</li>
<li>Por cada linea leida:</li>
<ul>
<li>Si la linea es un nemónico, entonces traducir la linea al código numérico respectivo</li>
<li>De lo contrario debe ser un número</li>
<li>almacenar ese resultado en la memoria</li>
</ul>
</ol>
<p>Vamos re escribiendo ese algoritmo a python por partes:</p>
<pre name="code" class="python:nocontrols">
def loader(nombre_archivo):
   # archivo = abrir archivo(nombre_archivo)
   # lineas = leer lineas en archivo
   for linea in lineas:
      if linea in nemonicos:
         # agregar_a_memoria (nemonicos.index(linea))
      else:
          # agregar_a_memoria( int(linea))
</pre>
<p>La memoria es simplemente una lista de enteros:</p>
<pre name="code" class="python:nocontrols">
memoria = []
</pre>
<p>Así que agregar a memoria es bastante simple: memoria.append(codigo).</p>
<p>Por otro lado, un archivo en Python se maneja usando el tipo predefinido <strong>file</strong>, un objeto de tipo file tiene un método que permite leer todas las lineas de un archivo las que se retornan en una lista, con esto nuestro código para loader queda así:</p>
<pre name="code" class="python:nocontrols">
memoria = []

def loader(nombre_archivo):
   archivo = open(nombre_archivo)
   lineas = archivo.readlines()
   archivo.close()
   for linea in lineas:
      codigo = linea.strip()
      if codigo in nemonicos:
         memoria.append(nemonicos.index(codigo))
      else:
          memoria.append( int(codigo) )
</pre>
<p>La función <strong>open()</strong> &#8216;abre&#8217; un archivo para ser leido. Retorna un objeto de tipo <strong>file</strong>.<br />
El objeto retornado tiene un método <strong>readlines()</strong> que lee todas las lineas y las retorna en una lista, que almacenamos en el arreglo <strong>lineas</strong>. Después de leer las lineas &#8216;cerramos&#8217; el archivo. Esto es importante, más adelante aprenderemos sobre los recursos del sistema operativo y porque es importante esto de <em>cerrar</em> el archivo.</p>
<p>Notarán que usé una variable auxiliar llamada <strong>codigo</strong>, lo que pasa es que los archivos almacenan cada linea con un carácter especial invisible, conocido como fin de linea, este carácter debe ser eliminado para poder buscarlo en la lista de nemónicos, o de lo contrario no podrá ser identificado. Esto se logra usando <strong>linea.strip()</strong>. </p>
<p>He subido a mi <a href="https://github.com/lnds/programando.org">repositorio en GitHub</a> el código de la función loader, junto con un archivo de ejemplo, pueden descargarlo desde <a href="https://github.com/lnds/programando.org/tree/master/curso-de-programacion-cap-19">acá</a>.</p>
<p><strong>Ejercicio</strong></p>
<p>El siguiente programa hace lo mismo que  el anterior pero de un modo avanzado:</p>
<pre name="code" class="python:nocontrols">
nemonicos = ['ALTO','LIM','ACUM','MUL','RES','DIV','IMPR','LEER','ALM','RR0','RR1','RSUM','RMUL','RRES','RDIV',
        'AR0','AR1','INC','DEC','INCR0','DECR0','INCR1','DECR1','SALTA','SSC','SSN','SSN','SRMA','SRME''SRIG']

def traduce(codigo):
	return nemonicos.index(codigo) if codigo in nemonicos else int(codigo)

def loader(nombre_archivo):
	with open(nombre_archivo) as archivo:
		return map(traduce, [linea.strip() for linea in archivo.readlines()]) 

memoria = loader('tabla_cinco.a')
</pre>
<p>¿Puedes explicar qué hace este programa? Pistas: la documentación de Python 3 se encuentra <a href="http://docs.python.org/py3k/index.html">acá</a>. Averigua sobre qué hace la función <strong>map()</strong>. </p>
<p>La instrucción <strong>with </strong>es muy útil con recursos que deben ser liberados, como pasa con los archivos.</p>
<pre name="code" class="python:nocontrols">
with open(nombre_archivo) as archivo:
    instrucciones...
</pre>
<p>es equivalente a hacer esto:</p>
<pre name="code" class="python:nocontrols">
archivo = open(nombre_archivo)
instrucciones...
archivo.close()
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.programando.org/blog/2011/04/cargando-el-codigo-de-maquina/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Código de Máquina</title>
		<link>http://www.programando.org/blog/2011/04/codigo-de-maquina/</link>
		<comments>http://www.programando.org/blog/2011/04/codigo-de-maquina/#comments</comments>
		<pubDate>Sat, 23 Apr 2011 10:43:59 +0000</pubDate>
		<dc:creator>ediaz</dc:creator>
				<category><![CDATA[Aprendiendo a programar]]></category>
		<category><![CDATA[Fundamentos]]></category>
		<category><![CDATA[assembly]]></category>
		<category><![CDATA[código de máquina]]></category>
		<category><![CDATA[fundamentos]]></category>
		<category><![CDATA[lenguaje ensamblador]]></category>
		<category><![CDATA[programación de bajo nivel]]></category>

		<guid isPermaLink="false">http://www.programando.org/blog/?p=270</guid>
		<description><![CDATA[En el  capítulo anterior de nuestro curso de programación vimos algo de la historia del desarrollo del computador digital. Pero, ¿cómo funciona un computador? Para responder esta pregunta vamos a simular el funcionamiento de un computador usando Python. Lo que vamos a construir es un modelo de máquina, un híbrido entre máquina de Turing y de Von Neumann. Si recuerdan bien, la idea de Turing era construir una máquina que opera leyendo símbolos desde una larga cinta de papel, y escribiendo en esta misma cinta los resultados de las operaciones, las que dependen obviamente de la interpretación de estos símbolos. En el caso de la arquitectura de Von Neumann tenemos una memoria principal, esta memoria contiene las instrucciones a ejecutar. Lo que hace una computadora es ir interpretando las instrucciones que están almacenadas en la memoria una por una. ¿Cómo son estas instrucciones? Bueno, depende del tipo de computador. Hay computadores más sofisticados que otros, y esto define el tipo de instrucciones. De todas maneras, estas instrucciones son bastantes primitivas. Por ejemplo, imaginemos un conjunto de instrucciones para sumar 20 y 45 en una máquina hipotética: LIMPIAR ACUMULAR 20 ACUMULAR 45 IMPRIMIR ALTO La instrucción LIMPIA en la linea 1 [...]]]></description>
			<content:encoded><![CDATA[<p>En el  <a href="http://www.programando.org/blog/2011/04/la-maquina-universal/">capítulo anterior</a> de nuestro <a href="http://www.programando.org/blog/aprende-a-programar/">curso de programación</a> vimos algo de la historia del desarrollo del computador digital. Pero, ¿cómo funciona un computador? Para responder esta pregunta vamos a <strong>simular</strong> el funcionamiento de un computador usando Python. Lo que vamos a construir es un <strong>modelo de máquina</strong>, un híbrido entre máquina de Turing y de Von Neumann.</p>
<p>Si recuerdan bien, la idea de Turing era construir una máquina que opera leyendo símbolos desde una larga cinta de papel, y escribiendo en esta misma cinta los resultados de las operaciones, las que dependen obviamente de la interpretación de estos símbolos. En el caso de la arquitectura de Von Neumann tenemos una memoria principal, esta memoria contiene las instrucciones a ejecutar. Lo que hace una computadora es ir interpretando las instrucciones que están almacenadas en la memoria una por una.</p>
<p><strong>¿Cómo son estas instrucciones?</strong></p>
<p>Bueno, depende del tipo de computador. Hay computadores más sofisticados que otros, y esto define el tipo de instrucciones. De todas maneras, estas instrucciones son bastantes primitivas.</p>
<p>Por ejemplo, imaginemos un conjunto de instrucciones para sumar 20 y 45 en una máquina hipotética:</p>
<blockquote>
<ol>
<li style="text-align: left;">
<pre>LIMPIAR</pre>
</li>
<li style="text-align: left;">
<pre>ACUMULAR</pre>
</li>
<li style="text-align: left;">
<pre>20</pre>
</li>
<li style="text-align: left;">
<pre>ACUMULAR</pre>
</li>
<li style="text-align: left;">
<pre>45</pre>
</li>
<li style="text-align: left;">
<pre>IMPRIMIR</pre>
</li>
<li style="text-align: left;">
<pre>ALTO</pre>
</li>
</ol>
</blockquote>
<p>La instrucción LIMPIA en la linea 1 coloca en cero algún área interna usada para guardar resultados intermedios, como la memoria de una calculadora, por ejemplo. La instrucción ACUMULA de la linea 2 indica al computador que deberá sumar el dato que sigue en la memoria de trabajo. La linea 3 contiene el primer dato, en este caso 20. La instrucción ACUMULA de la linea 4 indica al computador que deberá sumar el dato que sigue a la memoria de trabajo. La linea 5 contiene el segundo dato: 45. La instrucción IMPRIME de la linea 6 le pide a la máquina que muestre por algún dispositivo de salida (la pantalla, por ejemplo), el resultado guardado en el area intermedia. La instrucción ALTO en la linea 7 le indica a la máquina que debe detenerse.</p>
<p>Este es un ejemplo de lo que llamamos <strong>código de máquina</strong>. Este es el código que entienden directamente las computadoras. Aunque en realidad lo escrito arriba es una representación para que podamos entender, a esta representación la llamamos <strong>código ensamblador</strong>, o <strong>assembly</strong>,  el verdadero código de máquina está representado por números, porque la computadora sólo procesa números, los que se escriben en binario. Supongamos que en nuestra máquina cada instrucción esta codficada de acuerdo a la siguiente tabla:</p>
<blockquote>
<pre>INSTRUCCION VALOR   EN BINARIO (*)
ALTO: <strong>          0   0000 00000</strong>
LIMPIAR:        <strong>1   0000 0000</strong>1
ACUMULAR:   <strong>    2   0000 00010</strong>
IMPRIMIR:       <strong>3   0000 00011</strong></pre>
</blockquote>
<p style="text-align: left;">Entonces nuestra lista de instrucciones para sumar 20 y 45 se <strong>codificaría</strong> como la lista de números siguiente:<strong> 1,2,20,2,45,3,0</strong>, la que se expresaría en código de máquina en binario de la siguiente forma:</p>
<blockquote>
<pre><strong>0000 0001</strong>
<strong>0000 0010</strong>
<strong>0001 0100</strong>
<strong>0000 0010</strong>
<strong>0010 1101</strong>
<strong>0000 0011</strong>
<strong>0000 0000</strong></pre>
</blockquote>
<p>(*) Hablamos de los números binarios en  <a href="http://www.programando.org/blog/2011/03/partir-desde-cero/">este capítulo</a>.<strong><br />
</strong></p>
<p><strong>Nuestra propia máquina virtual</strong></p>
<p style="text-align: left;">Nuestro objetivo es construir un programa en Python que simule una máquina que interprete este tipode de código de máquina. Para simplificar vamos a definir una máquina imaginaria, esquemáticamente nuestra máquina tendrá la siguiente <strong>arquitectura:</strong></p>
<p><strong> </strong></p>
<p><strong> </strong></p>
<p><strong> </strong></p>
<div id="attachment_271" class="wp-caption aligncenter" style="width: 574px"><strong><a href="http://www.programando.org/blog/wp-content/uploads/2011/04/programando-cpu.png"></a><a href="http://www.programando.org/blog/wp-content/uploads/2011/04/programando-cpu1.png"><img class="alignright size-full wp-image-289" title="programando-cpu" src="http://www.programando.org/blog/wp-content/uploads/2011/04/programando-cpu1.png" alt="" width="564" height="302" /></a><br />
</strong><p class="wp-caption-text">Diagrama de Bloques de nuestra máquina virtual</p></div>
<p>&nbsp;</p>
<p><strong> </strong></p>
<p><strong> </strong>La figura corresponde a un <strong>diagrama de bloques, </strong>un tipo de dibujo muy usado en el modelamiento de sistemas informáticos. La posición de cada bloque, o caja, nos indica el grado de dependencia de cada parte del sistema.</p>
<p><a href="http://www.programando.org/blog/wp-content/uploads/2011/04/cajonera1.gif"><img class="alignright size-medium wp-image-275" title="cajonera" src="http://www.programando.org/blog/wp-content/uploads/2011/04/cajonera1-169x300.gif" alt="" width="169" height="300" /></a>El primer bloque, o componente, de nuestra máquina es la <strong>memoria</strong>. Imaginen que la memoria es como una gran <em>cajonera</em>. Dentro de cada cajón de nuestra memoria se almacenan  <strong>palabras </strong>(word en inglés), que corresponden a instrucciones o datos. Además imaginaremos que cada cajón ha sido numerado partiendo, como siempre, desde cero. (Estos cajones son llamados también celdas de memoria).</p>
<p>La <strong>unidad de control</strong> (<strong>CU </strong>por Control Unit, en inglés) es como un sirviente que va abriendo los cajones, uno por uno, y lee las palabras que se encuentra en cada cajón. ¿Cómo sabe la <strong>CU</strong> cuál cajón abrir? Para eso nuestra máquina tiene una variable especial que llamaremos el puntero de instrucciones (instruction pointer, <strong>IP</strong>). Si el IP es cer0, entonces la siguiente palabra a leer está en la cajonera cero.</p>
<p>La CU va interpretando estas palabras, si la palabra es una instrucción se ejecuta, si la palabra es un dato este dato puede ser el argumento de una instrucción. Cuando se ejecuta una instrucción el IP cambia su valor, este nuevo valor va a depender del tipo de instrucción, hay instrucciones que simplemente incrementan el IP en 1, hay otras que permiten cambiar el valor del IP con un valor arbitrario, estas son conocidas como instrucciones de salto.  Otras instrucciones requieren argumentos, los que se encuentran en celdas de memoria contigua. Por ejemplo, si una función necesita un dato adicional entonces esta instrucción lee el dato desde la posición IP+1 e incrementa el valor IP en 2. Todo esto va a quedar más claro cuando construyamos nuestro simulador.</p>
<p>Hay instrucciones que representan operaciones aritméticas o lógicas, estas son ejecutadas por la <strong>Unidad Aritmético Lógica</strong>, o <strong>ALU</strong> por sus siglas en inglés: Aritmetic Logic Unit. Nuestra ALU cuenta con <strong>varios cajones especiales, </strong>hay uno que llamaremos el <strong>acumulador</strong>. El acumulador sólo guarda valores enteros. Inicialmente, al <em>encenderse nuestra máquina</em>, el acumulador tiene el valor cero (0). Hay dos cajones adicionales: R0 y R1, son los <strong>registros auxiliares</strong>, muy útiles en otras instrucciones.</p>
<p>Con esto tenemos todos los elementos básicos de nuestra máquina. Por cierto, esta máquina tiene mecanismos para recibir datos, y para leer datos. Estas instrucciones son manejadas con los módulos <strong>input</strong> y <strong>output</strong>.</p>
<p>Lo que vamos a construir se conoce como una <strong>máquina virtual</strong>,  una simulación de una máquina o computadora real, implementada mediante  software. Lo que aprenderemos en este y el próximo capítulo es la base  conceptual de cosas tan avanzadas como la <a href="http://es.wikipedia.org/wiki/M%C3%A1quina_virtual_Java">Java Virtual Machine</a>, o el ambiente <a href="http://es.wikipedia.org/wiki/Common_Language_Runtime">CLR de Microsoft.Net</a>. Como veremos más adelante el mismo Python utiliza este tipo de mecanismos.</p>
<p>En los párrafos anteriores describimos brevemente las componentes de nuestra máquina. Lo que falta es describir el tipo de instrucciones específicas que soporta nuestra máquina.</p>
<p><strong> </strong></p>
<p><strong>Nuestro código de máquina</strong></p>
<p>Vamos a ver que para poder realizar cálculos relativamente complejos se requiere un conjunto bastante pequeño de instrucciones. Por ahora, y para simplificar nuestro diseño, nuestra máquina sólo operarará con números enteros<strong>, </strong>por lo tanto nuestro set de instrucciones se remite  a este tipo de datos y opera sobre los elementos de la arquitectura descrita anteriormente.<strong><br />
</strong></p>
<p>Nuestra computadora tendrá las siguientes instrucciones (las abreviaturas van entre paréntesis):</p>
<ul>
<li><strong>ALTO</strong>: Detiene la máquina.<br />
<strong> </strong></li>
<li><strong>LIMPIAR (LIM): </strong>coloca el acumulador en cero. Se abrevia <strong>LIM</strong></li>
<li><strong>ACUMULAR (ACUM): </strong>suma la palabra que sigue al acumulador. Se abrevia <strong>ACUM</strong></li>
<li><strong>MULTIPLICAR  (MUL)</strong>: multiplica el valor del acumulador por la palabra que sigue.</li>
<li><strong>RESTAR (RES)</strong>: resta el valor de la siguiente palabra de memoria del acumulador.</li>
<li><strong>DIVIDIR (DIV):</strong> divide el valor del acumulador por el valor de la próxima palabra.</li>
<li><strong>IMPRIMIR (IMPR)</strong>: imprime el valor del acumulador en pantalla.</li>
<li><strong>LEER:</strong> lee un valor desde el teclado y lo guarda en el acumulador</li>
<li><strong>ALMACENAR (ALM): </strong>almacena el valor del acumulador en la posición de memoria indicada por la siguiente palabra.</li>
<li><strong>RECUPERAR R0 (RR0)</strong>: almacena el valor en la posición de memoria indicada por la siguiente palabra en el registro R0</li>
<li><strong>RECUPERAR R1 (RR1)</strong>: almacena el valor en la posición de memoria indicada por la siguiente palabra en el registro R1.</li>
</ul>
<p>Hay versiones de las operaciones matemáticas que operan con los registros R0 y R1 y dejan el resultado en el acumulador</p>
<ul>
<li><strong>RSUM</strong><strong>:</strong> suma los valores en los registros R0 y R1 y deja el resultado en el acumulador</li>
<li><strong>RMUL</strong>: multiplica los valores en registros R0 y R1 y deja el resultado en el acumulador</li>
<li><strong>RRES</strong>: resta al valor del registro R0 el valor del registro R1 y deja el resultado en el acumulador</li>
<li><strong>RDIV</strong>: divide el valor del registro R0 por el valor del registro R1 y deja el resultado en el acumulador</li>
</ul>
<p>Hay 2 instrucciones especiales que sirven para guardar valores en R0 y R1:</p>
<ul>
<li><strong>AR0:</strong> almacena el valor que sigue en el registro R0</li>
<li><strong>AR1: </strong>almacena el valor que sigue en el registro R0</li>
</ul>
<p>Y hay instrucciones especiales con los registros:</p>
<ul>
<li><strong>INC</strong>: incrementa en 1 el acumulador</li>
<li><strong>DEC</strong>: decrementa en 1 el acumulador</li>
<li><strong>INCR0</strong>: incerementa en 1 el registro R0</li>
<li><strong>DECR0</strong>: decrementa en 1 el registro R0</li>
<li><strong>INCR1</strong>: incrementa en 1 el registro R1</li>
<li><strong>DECR1</strong>: decrementa en 1 el registro R1</li>
</ul>
<p>Hay instrucciones de salto, estas permiten cambiar el valor del IP, es decir, cambiar desde que posición en memoria se leerá la siguiente instrucción:</p>
<ul>
<li><strong>SALTA:</strong> Salta a la posición definida por la palabra siguiente. Es decir, cambia el valor del IP.</li>
<li><strong>SALTA SI CERO (SSC): </strong>Salta a la posición definida por la palabra siguiente si el valor del acumulador es cero.</li>
<li><strong>SALTA SI NEGATIVO (SSN): </strong>Salta a la posición definida por la palabra siguiente si el valor del acumulador es negativo.</li>
<li><strong>SALTA SI POSITIVO (SSN): </strong>Salta a la posición definida por la palabra siguiente si el valor del acumulador es positivo (mayor que 0).</li>
<li><strong>SRMA: </strong>Salta a la posición definida por la palabra siguiente si el registro R0 es mayor que el registro R1<strong><br />
</strong></li>
<li><strong>SRME:</strong> Salta a la posición definida por la palabra siguiente si el registro R0 es menor que el registro R1</li>
<li><strong>SRIG</strong>: Salta a la posición definida por la palabra siguiente si el registro R0 es igual al registro R1</li>
</ul>
<p>&nbsp;</p>
<p><strong>Ejemplos</strong></p>
<p>Los siguientes son   &#8220;programas&#8221; escritos en el código de máquina de nuestra máquina:</p>
<p><strong>Ejemplo 1:</strong> este programa suma  2+3:</p>
<blockquote>
<ol>
<li>
<pre>ACUM</pre>
</li>
<li>
<pre>2</pre>
</li>
<li>
<pre>ACUM</pre>
</li>
<li>
<pre>3</pre>
</li>
<li>
<pre>IMPR</pre>
</li>
<li>
<pre>ALTO</pre>
</li>
</ol>
</blockquote>
<p>La instrucción de la linea 1 ACUM hace que la CU lea la siguiente palabra, en este caso 2, y la almacene en el acumulador. La instrucción de la linea 3 ACUM hace que se sume el valor de la siguiente palabra, en este caso el número 3, al acumulador. La instrucción de la linea 5 imprime el valor del acumulador (5), y la instrucción de la linea 6 detiene la máquina.</p>
<p><strong>Ejemplo 2:</strong> Multiplica un número ingresado por el usuario por 2:</p>
<blockquote>
<ol>
<li>
<pre>LEER</pre>
</li>
<li>
<pre>MUL</pre>
</li>
<li>
<pre>2</pre>
</li>
<li>
<pre>IMPR</pre>
</li>
<li>
<pre>ALTO</pre>
</li>
</ol>
</blockquote>
<p>La instrucción en la linea 1 permite ingresar un número y guardarlo en el acumulador. Luego la instrucción MUL seguida de la palabra &#8220;2&#8243;, permiten multiplicar el valor ingresado por 2. La instrucción en la linea 4 imprime el valor del acumulador. Y la instrucción 5 detiene la máquina.</p>
<p>Ejemplo 3: Multiplicar 2 números ingresados por el usuario</p>
<blockquote>
<ol>
<li>
<pre>LEER</pre>
</li>
<li>
<pre>ALMACENAR</pre>
</li>
<li>
<pre>20</pre>
</li>
<li>
<pre>LEER</pre>
</li>
<li>
<pre>ALM</pre>
</li>
<li>
<pre>21</pre>
</li>
<li>
<pre>RECUPERAR R0</pre>
</li>
<li>
<pre>20</pre>
</li>
<li>
<pre>RR1</pre>
</li>
<li>
<pre>21</pre>
</li>
<li>
<pre>RMUL</pre>
</li>
<li>
<pre>IMPRIMIR</pre>
</li>
<li>
<pre>ALTO</pre>
</li>
</ol>
</blockquote>
<p>Este ejemplo es más complejo. La linea 1 solicita al usuario que ingrese un número. La instruccion ALMACENAR en la linea 2 lleva el valor del acumulador a la celda de memoria número 20. La instrucción en la linea 4 solicita al usuario que ingrese otro número, el que es almacenado en la celda de memoria número 21. La instrucción 7 recupera el valor en la celda de memoria 20 en el registro R0 (este es el primer número ingresado por el usuario).  La instrucción en la linea 9 recupera el valor de la celda de memoria 21 y lo deja en el registro R1 (este es el segundo número ingresado por el usuario). En la lina 11 multiplicamos ambos registros, y el resultado queda en el acumulador.  La instrucción de la linea 12 imprime el resultado, y la instrucción de la linea 13 detiene la máquina.</p>
<p><strong>Ejemplo 5:</strong> imprime la tabla del 5 por pantalla.</p>
<p>&nbsp;</p>
<blockquote>
<ol>
<li>
<pre>AR0</pre>
</li>
<li>
<pre>5</pre>
</li>
<li>
<pre>AR1</pre>
</li>
<li>
<pre>0</pre>
</li>
<li>
<pre>INCR1</pre>
</li>
<li>
<pre>RMUL</pre>
</li>
<li>
<pre>PRINT</pre>
</li>
<li>
<pre>RES</pre>
</li>
<li>
<pre>50</pre>
</li>
<li>
<pre>SSC</pre>
</li>
<li>
<pre>14</pre>
</li>
<li>
<pre>SALTA</pre>
</li>
<li>
<pre>5</pre>
</li>
<li>
<pre>ALTO</pre>
</li>
</ol>
</blockquote>
<p>&nbsp;</p>
<p>Este es otro ejemplo complejo que usa instrucciones de salto. La instrucción de la linea 1 almacena en el registro 0 el número 5. La instrucción de la linea 3 almacena en el registro 1 el valor 0. Luego, en la linea 5 incrementamos el valor del registro 1. En la linea 6 multiplicamos los registros R0 y R1 entre sí, el valor queda en el acumulador. La instrucción 7 imprime el resultado. En la linea 8 restamos 50 al valor del acumulador. Esta resta valdrá cero sólo cuando el acumulador llegue a valer 50, eso se produce cuando multipliquemos 5 * 10, es decir, esta es la condición que nos permite terminar el programa (la tabla va desde el 5 al 50). La linea 10 chequea si el valor del acumulador es 0, si eso se da entonces salta a la instrucción 14. Si no la linea 12 instruye que se salte a la linea 5. Esto es una manera de implementar un loop usando código de máquina.</p>
<p>Vamos a realizar una <strong>traza</strong>, es decir, vamos a simular el comportamiento del programa del ejemplo 5. Vamos es escribir en una tabla los valores del registro en la medida que se ejecuta el programa:</p>
<blockquote>
<ul>
<li>
<pre>Al inicio: ACUM = 0; R0 = ?; R1 = ?.</pre>
</li>
<li>
<pre>Después de ejecutamos linea 1, ACUM = 0; R0 = 5; R1 = ?.</pre>
</li>
<li>
<pre>Ejecutamos linea 3: ACUM= 0; R0 = 5; R1 = 0.</pre>
</li>
<li>
<pre>Ejecutamos linea 5: ACUM = 0; R0 = 5; R1 = 1.</pre>
</li>
<li>
<pre>Ejecutamos linea 6: ACUM = 5; R0 = 5; R1 = 1.</pre>
</li>
<li>
<pre>Linea 7 imprime 5 en pantalla.</pre>
</li>
<li>
<pre>Ejecutamos linea 8: ACUM = -45; R0 = 5; R1 =1.</pre>
</li>
<li>
<pre>Linea 10  compara acumulador con 0, como ACUM=-45,
la condición no se cumple entonces pasa a la linea 12.</pre>
</li>
<li>
<pre>Linea 12, salta a la linea 5.</pre>
</li>
</ul>
<ul>
<li>
<pre>Ejecutamos linea 5: ACUM = -45; R0 = 5; R1 = 2.</pre>
</li>
<li>
<pre>Ejecutamos linea 6: ACUM = 10; R0 = 5; R1 = 2.</pre>
</li>
<li>
<pre>Linea 7 imprime 10 en pantalla.</pre>
</li>
<li>
<pre>Ejecutamos linea 8: ACUM = -40; R0 = 5; R1 =2.</pre>
</li>
</ul>
<ul>
<li>
<pre>Linea 10  compara acumulador con 0, como ACUM=-45,
la condición no se cumple entonces pasa a la linea 12.</pre>
</li>
<li>
<pre>Linea 12, salta a la linea 5.</pre>
</li>
</ul>
<ul>
<li>
<pre>Ejecutamos linea 5: ACUM = -40; R0 = 5; R1 = 3.</pre>
</li>
<li>
<pre>Ejecutamos linea 6: ACUM = 15; R0 = 5; R1 = 3.</pre>
</li>
<li>
<pre>Linea 7 imprime 15 en pantalla.</pre>
</li>
<li>
<pre>Ejecutamos linea 8: ACUM = -35; R0 = 5; R1 =3.</pre>
</li>
</ul>
<ul>
<li>
<pre>...... continua así hasta que en algun momento R1 = 9</pre>
</li>
</ul>
<ul>
<li>
<pre>Ejecutamos linea 5: ACUM = -5; R0 = 5; R1 = 10.</pre>
</li>
</ul>
<ul>
<li>
<pre>Ejecutamos linea 6: ACUM = 50; R0 = 5; R1 = 10.</pre>
</li>
<li>
<pre>Linea 7 imprime 50 en pantalla.</pre>
</li>
<li>
<pre>Ejecutamos linea 8: ACUM =0; R0 = 5; R1 =10.</pre>
</li>
<li>
<pre>Linea 10  compara acumulador con 0, como ACUM=0,
la condición esta vez se cumple entonces pasa a la linea 14</pre>
</li>
<li>
<pre>Linea 14: <strong>ALTO</strong>, la máquina se detiene, ACUM = 0; R0 = 5, R1 = 10.</pre>
</li>
</ul>
</blockquote>
<p><strong>Programación de bajo nivel</strong></p>
<p>Como pueden ver programar en lenguaje de máquina es una tarea bastante ardua. Afortunadamente no tenemos que hacerlo, por eso contamos con lenguajes como Python, los llamados lenguajes de alto nivel. Cuando programamos instrucciones de máquina directamente decimos que estamos programando a<strong> bajo nivel.</strong></p>
<p>Creo que hemos visto muchas cosas en este capítulo, y asimilarlas puede ser complejo, eso lo reconozco, pero es así como funcionan realmente los computadores, y es bastante dificil simplificar aún más los conceptos. Si quieres aprender más de esto te recomiendo leer:</p>
<ul>
<li>La <a href="http://es.wikipedia.org/wiki/Lenguaje_ensamblador">página en wikipedia sobre lenguaje ensamblador</a>, es un buen punto de partida.</li>
<li>El <a href="http://www.asmcommunity.net/book/">ASM Book</a> es un esfuerzo para escribir un libro comunitario donde se explica el lenguaje ensamblador.</li>
<li>El libro <a href="http://www.amazon.com/gp/product/0735611319/ref=as_li_qf_sp_asin_tl?ie=UTF8&amp;tag=lanaturaledel-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0735611319">Code: The Hidden Language of Computer Hardware and Software</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=lanaturaledel-20&amp;l=as2&amp;o=1&amp;a=0735611319" border="0" alt="" width="1" height="1" /> (Código: El Lenguaje Oculto del Hardware y Software del Computador), es una excelente introducción sobre como funcionan las cosas. En ese libro se profundiza aún a más bajo nivel lo expuesto en este capítulo, pero de una manera gradual y bastante didáctica.</li>
</ul>
<p><strong>Ejercicios</strong></p>
<ol>
<li>Asigna un código numérico a cada una de las instrucciones que definimos y transcribe los ejemplos como listas de números. Luego expresa esos números en binario.</li>
<li>Escribe un programa en nuestro código de máquina que le pida al usuario 2 números y los divida. Asegurate de no dividir por cero.</li>
<li>Escribe un programa, en nuestro código de máquina, que solicite al usuario primero un número indicando el tipo de operación que desea realizar: 1 para sumar, 2 para restar, 3 para multiplicar y 4 para dividir. Si el usuario ingresa 0 (cero) entonces el programa se detiene. Una vez elegida la operación el programa debe solicitar los dós números y ejecutar la operación deseada, finalmente debe mostrar el resultado y volver a empezar.</li>
</ol>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.programando.org/blog/2011/04/codigo-de-maquina/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>La máquina universal</title>
		<link>http://www.programando.org/blog/2011/04/la-maquina-universal/</link>
		<comments>http://www.programando.org/blog/2011/04/la-maquina-universal/#comments</comments>
		<pubDate>Sun, 17 Apr 2011 19:11:55 +0000</pubDate>
		<dc:creator>ediaz</dc:creator>
				<category><![CDATA[Algoritmos]]></category>
		<category><![CDATA[Aprendiendo a programar]]></category>
		<category><![CDATA[Fundamentos]]></category>

		<guid isPermaLink="false">http://www.programando.org/blog/?p=247</guid>
		<description><![CDATA[En la primera parte de nuestro curso de programación aprendimos los elementos básicos para construir programas simples. Fuimos aprendiendo esto en la medida que ibamos construyendo un juego de naipes. Pero este juego tiene una interfaz de usuario bastante básica basada en texto. Aunque ustedes no lo crean un programa idéntico a este fue usado en un proyecto de juegos para telefonía móvil usando SMS. Del mismo modo se podría usar para jugar en twitter, las posibilidades están abiertas a vuestra imaginación como desarrolladores. Sin embargo, creo que sería más interesante contar con una interfaz gráfica de usuario para nuestro juego, y después podemos extender nuestro juego para que sea jugado por muchas personas a través de la web. Así que la segunda parte de nuestro curso tiene por objetivo construir una versión gráfica del juego de BlackJack, para ser jugada en un computador personal con un sistema operativo moderno (como Ubuntu, Mac OSX, o Windows 7). En la tercera parte del curso llevaremos nuestro juego a la web. Para poder lograr nuestro objetivo tenemos que aprender un poco más de cómo funcionan los computadores, y a esta exploración vamos a dedicar nuestras siguientes lecciones.Vamos a partir con un poco [...]]]></description>
			<content:encoded><![CDATA[<p>En la primera parte de <a href="http://www.programando.org/blog/aprende-a-programar/">nuestro curso de programació</a>n aprendimos los elementos básicos para construir programas simples. Fuimos aprendiendo esto en la medida que ibamos construyendo un juego de naipes. Pero este juego tiene una interfaz de usuario bastante básica basada en texto. Aunque ustedes no lo crean un programa idéntico a este fue usado en un proyecto de juegos para telefonía móvil usando <a href="http://es.wikipedia.org/wiki/Servicio_de_mensajes_cortos">SMS</a>. Del mismo modo se podría usar para jugar en twitter, las posibilidades están abiertas a vuestra imaginación como <strong>desarrolladores</strong>.</p>
<p>Sin embargo, creo que sería más interesante contar con una interfaz gráfica de usuario para nuestro juego, y después podemos extender nuestro juego para que sea jugado por muchas personas a través de la web. Así que la segunda parte de nuestro curso tiene por objetivo construir una versión gráfica del juego de BlackJack, para ser jugada en un computador personal con un sistema operativo moderno (como Ubuntu, Mac OSX, o Windows 7). En la tercera parte del curso llevaremos nuestro juego a la web.</p>
<p>Para poder lograr nuestro objetivo tenemos que aprender un poco más de cómo funcionan los computadores, y a esta exploración vamos a dedicar nuestras siguientes lecciones.Vamos a partir con un poco de historia, no se preocupen, no es aburrida, involucra algo de acción y espionaje, y drama humano <img src='http://www.programando.org/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<div id="attachment_248" class="wp-caption alignright" style="width: 160px"><a href="http://www.programando.org/blog/wp-content/uploads/2011/04/Alan_Turing.jpg"><img class="size-thumbnail wp-image-248" title="Alan_Turing" src="http://www.programando.org/blog/wp-content/uploads/2011/04/Alan_Turing-150x150.jpg" alt="" width="150" height="150" /></a><p class="wp-caption-text">Alan Turing el padre de la computación</p></div>
<p><strong>La máquina universal</strong></p>
<p>En 1931 un joven de 24 años, Alan Turing decidió reformular ciertos resultados de la lógica matemática expresando las formulaciones de teoremas en términos de algoritmos que podían ser interpretados por una máquina teórica.</p>
<p>Un algoritmo es &#8221;<em>un conjunto preescrito de instrucciones o reglas bien definidas, ordenadas y finitas que permite realizar una actividad mediante pasos sucesivos que no generen dudas a quien deba realizar dicha actividad.</em>&#8221; O sea, un programa <img src='http://www.programando.org/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Lo que pretendía Turing era estudiar los límites de las máquinas que realizaban cálculos automáticos. Era un tiempo en que se estaban sentando las bases de cómo serían los computadores. Ya era posible contar con los elementos para construir estas máquinas y Turing quería ver cual era el poder de estas máquinas. Hasta que punto estas máquinas serían capaces de ayudarnos a resolver problemas complejos.</p>
<p>Turing describió una máquina teórica que manipula los símbolos escritos una larga cinta de acuerdo a una tabla de reglas. La máquina de Turing consta de un cabezal que puede leer y/o escribir en una cinta infinita de papel. La máquina puede realizar sólo las siguientes operaciones: avanzar el cabezal hacia la dercha, avanzar el cabezal hacia la izquierda, leer el contenido de una celda de la cinta, borrar el contenido de una celda y escribir en la cinta.</p>
<div id="attachment_249" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.programando.org/blog/wp-content/uploads/2011/04/Maquina-de-Turing.png"><img class="size-medium wp-image-249" title="Maquina de Turing" src="http://www.programando.org/blog/wp-content/uploads/2011/04/Maquina-de-Turing-300x166.png" alt="" width="300" height="166" /></a><p class="wp-caption-text">Representación artística de la Máquina de Turign</p></div>
<p style="text-align: left;">Con este dispositivo tan simple Turing  tuvo éxito en su empeño. No sólo sentó las bases teóricas para la construcción de estas máquinas, sino que estableció la formalización del concepto de algoritmo, lo que llevaría al desarrollo de los lenguajes de programación, descubrió la manera de determinar la complejidad de los problemas que pueden ser abordados por una máquina de este tipo, e incluso planteó un tipo de test para verificar operacionalmente  una máquina es inteligente, el famoso <a href="http://es.wikipedia.org/wiki/Test_de_Turing">Test de Turing</a>.</p>
<p style="text-align: left;">Es a partir de los trabajos de Turing que contamos con el concepto de máquina universal, capaz de resolver cualquier problema. Una máquina que es capaz de emular muchos de nuestros procesos mentales. Turing pensaba que era posible un día descubrir los algoritmos que gobiernan nuestra forma de ser y pensar, y que eso podría ser transferido a una máquina.</p>
<p style="text-align: left;">Polémico y todo, esta idea ha sido el motor de gran parte del desarrollo de la inteligencia artificial. Personalmente creo que Turing se equivocaba en esta idea, y probablemente, como <a href="http://www.edge.org/3rd_culture/lanier/lanier_index.html">plantea Jaron Lanier</a>,  los traumas y problemas de <a href="http://www.lnds.net/blog/2011/03/galeano-sobre-alan-turing.html">la vida personal de Turing </a>fueron los impulsores de esta obsesión del grán lógico inglés. Pero estamos divagando.</p>
<p style="text-align: left;">Lo importante es que entendamos que este concepto de <strong>máquina universal</strong> se concretó y hoy tenemos computadores en todas partes, en el refrigerador, en nuestros televisores, en el automóvil y nuestros teléfonos móviles. Todos tienen un computador, una máquina universal de Turing que gobierna sus acciones, que decide en forma algorítimica como reaccionar ante el nuevo estímulo que recogen desde el exterior.</p>
<p style="text-align: left;"><strong>Enigma y la guerra que lo cambió todo</strong></p>
<div id="attachment_251" class="wp-caption alignright" style="width: 160px"><a href="http://www.programando.org/blog/wp-content/uploads/2011/04/Enigma.jpg"><img class="size-medium wp-image-251" title="Enigma" src="http://www.programando.org/blog/wp-content/uploads/2011/04/Enigma-214x300.jpg" alt="" width="150" height="210" /></a><p class="wp-caption-text">La máquina Enigma</p></div>
<p style="text-align: left;">Durante la segunda guerra mundial Turing se vió involucrado en un proyecto secreto de alto impacto, tan importante se considera este proyecto que se dice que gran parte del resultado de la guerra, y la  derrota final de los Nazis, se debe al trabajo de este selecto equipo de científicos. Durante ese tiempo Turing y el equipo de <a href="http://www.bletchleypark.org.uk/">Bletchey Park</a> trabajaron descifrando los mensajes secretos del ejército alemán. Durante ese tiempo las fuerzas germánas contaban con  máquinas de encriptación muy poderosas, como <a href="http://en.wikipedia.org/wiki/Enigma_machine">Enigma</a> y la máquina <a href="http://en.wikipedia.org/wiki/Lorenz_SZ_40/42">Lorenz</a>. La máquina Enigm era usada principalmente por la armada y los famosos submarinos <a href="http://en.wikipedia.org/wiki/U-boat">u-boat</a> alemanes. El grupo Hut 8 era el encargado de decodificar estos mensajes y a cargo de este estaba Alan Turing.</p>
<p style="text-align: left;">Durante ese tiempo el equipo de Bletchey Park construyeron una serie de máquinas para ayudar en el trabajo de descifrado automático de los mensajes captados por los servicios de inteligencia.</p>
<p style="text-align: left;">Entre las máquinas construidas por los ingleses se encontraba el Colossus Mark 2, probablemente el primer computador digital semi programable.</p>
<p style="text-align: left;">&nbsp;</p>
<div id="attachment_252" class="wp-caption alignleft" style="width: 250px"><a href="http://www.programando.org/blog/wp-content/uploads/2011/04/Colossus.jpg"><img class="size-full wp-image-252 " title="Colossus" src="http://www.programando.org/blog/wp-content/uploads/2011/04/Colossus.jpg" alt="" width="240" height="159" /></a><p class="wp-caption-text">Colossus Mark II</p></div>
<p>Mucho del trabajo de estas máquinas se mantuvo en secreto por años, y por esta razón fueron ignorados por mucho tiempo.</p>
<p style="text-align: left;">En esos tiempos los ingléses desarrollaron una serie de computadores, y el mismo Turing trabajó en el desarrollo de algunos de estos.</p>
<p style="text-align: left;">Todos los computadores de ese tiempo eran programados mediante cableado, el concepto revolucionario vino desde el otro lado del atlántico y sentó las bases para la estructura de los modernos computadores.</p>
<p style="text-align: left;">Recordemos que en aquel tiempo los norteamericanos estaban desarrollando el famoso proyecto Manhattan que llevaría a la creación de la primera bomba atómica.</p>
<p style="text-align: left;"><strong>La computadora humana de Feynmann</strong></p>
<p style="text-align: left;">Richard Feynmann cuenta que necesitaban hacer complicados cálculos matemáticos y mientras no contaran con un computador decidieron hacerlo con ayuda de personal humano:</p>
<blockquote>
<p style="text-align: left;">&#8220;Desarrollamos el programa, pero no teníamos ninguna máquina para probarlo. De modo que lo que hicimos fue llenar una habitación con chicas, cada una de ellas con una Marchant [una calculadora]. Pero <em>ella</em> era el multiplicador, y <em>ella</em> era el sumador, y ésta elevaba al cubo; teníamos tarjetas, tarjetas con índices y todo lo que ella hacía era elevar al cubo un número y pasárselo a la siguiente. Ésta hacía de multiplicador, la siguiente hacía de sumador; recorríamos el ciclo, eliminábamos todos los errores. Bien, así lo hicimos. Y resultó que podíamos hacerlo a gran velocidad. Nunca antes se había hecho cálculo en serie; cualquiera que hubiera hecho cálculos antes alguna vez había realizado todos los pasos por si mismo. Pero Ford(*) tuvo una buena idea, la maldita cosa trabajaba mucho más rápidamente que de la otra forma, y con este sistema llegamos a alcanzar una velocidad igual a la predicha para la máquina IBM: exactamente la misma.&#8221;</p>
</blockquote>
<p style="text-align: left;">(*) Se refiere a Henry Ford y su idea del producción en serie.</p>
<p style="text-align: left;"><a href="http://www.programando.org/blog/wp-content/uploads/2011/04/JohnvonNeumann-LosAlamos.gif"><img class="alignright size-medium wp-image-253" title="JohnvonNeumann-LosAlamos" src="http://www.programando.org/blog/wp-content/uploads/2011/04/JohnvonNeumann-LosAlamos-230x300.gif" alt="John Von Neumann en Los Alamos" width="138" height="180" /></a>Entre los hombres que estaban en Los Alamos en aquel tiempo se encontraba un brillante matemático de origen Húngaro: John von Neumann. Considerado un halcón, por sus visiones políticas y su involucramiento en el desarrollo de armas atómicas (como la bomba de hidrógeno), John von Neumman estableció la primera arquitectura efectiva para construir computadores que pudieran ser programados en forma efectiva, es decir, sin tanto <em>cableado</em>.</p>
<p style="text-align: left;">La principal idea que propuso Von Neumann fue que los datos y los programas fueran ambos almacenados en la memoria principal de la computadora.</p>
<p style="text-align: left;">La arquitectura de Von Neumann se decribe en el artículo &#8220;<a href="http://qss.stanford.edu/~godfrey/vonNeumann/vnedvac.pdf">The first draft report on the EDVAC</a>&#8221; y corresponde, esencialmente, a la arquitectura usada por la mayor parte de las computadoras que usamos en la actualidad:</p>
<p style="text-align: left;"><a href="http://www.programando.org/blog/wp-content/uploads/2011/04/420px-Von_Neumann_architecture.png"></a><a href="http://www.programando.org/blog/wp-content/uploads/2011/04/420px-Von_Neumann_architecture1.png"></a><a href="http://www.programando.org/blog/wp-content/uploads/2011/04/420px-Von_Neumann_architecture2.png"><img class="aligncenter size-full wp-image-257" title="420px-Von_Neumann_architecture" src="http://www.programando.org/blog/wp-content/uploads/2011/04/420px-Von_Neumann_architecture2.png" alt="" width="616" height="320" /></a></p>
<p>Von Neumann estableció que la memoria es una sola unidad que contiene el programa y los datos sobre los que actuará el computador. Existe un módulo que llamó la unidad de control (CU por control unit) que lee las instrucciones desde la memoria y las ejecuta una a una. Otra unidad llamada la unidad de lógica y aritmética (ALU por su sigla en inglés) se encarga de los cálculos. La ALU lee los datos de un cálculo y escribe los resultados en la memoria. Juntas la unidad de control (CU) y la unidad aritmético lógica (ALU) conforman la Unidad Central de Proceso (<strong>CPU</strong>). Para comunicarse con el exterior la CPU se enlaza a los dispositivos de entrada (INPUT), como los teclados, sensores, mouse, unidades  de disco, etc, y a los dispositivos de salida (OUTPUT) como las pantallas, impresoras, parlantes, etc.</p>
<p style="text-align: left;">Más adelante vamos a aprender sobre este modelo en más detalle pues es esencial para lograr cumplir con los futuros proyectos de nuestro curso.</p>
<p style="text-align: left;"><strong>Los destinos diversos de dos hombres notables.</strong></p>
<p style="text-align: left;">A pesar de que las contribuciones de Turing y Von Neumann fueron fundamentales para el desarrollo de las computadoras, no se puede imaginar dos tipos de personajes tan distintos.</p>
<p style="text-align: left;">Von Neumann desarrollo principalmente computadores para mejorar los cálculos necesarios para desarrollar la bomba atómica. Aunque hizo notables contribuciones en el ámbito de las matemáticas y la ciencia de la computación. Ayudó a desarrollar el método de Montecarlo y varias técnicas de simulación con números seudoaleatorios (el algoritmo de números aleatorios que usamos en nuestro juego viene de los trabajos de este matemático). Es probablemente el científico que más influyó en el establecimiento del concepto de <a href="http://es.wikipedia.org/wiki/Estrategia_de_las_armas_nucleares">destrucción mutua asegurada</a>, que estableció el equilibrio en términos nucleares entre las super potencias durante el periodo de la guerra fría. El favorecía la idea de un ataque nuclear preventivo a la Unión Sovietica para evitar que esta potencia adquiriera la bomba atómica. Von Neumann murió de cancer. Sus biógrafos han escrito:  &#8221;c<em>uando von Neumann se enteró de que estaba incurablemente enfermo, su lógica le forzaba a darse cuenta de que cesaría de existir, y por tanto que cesaría de tener pensamientos…<em>Su amigo Edward Teller dijo, &#8216;Pienso que von Neumann sufrió más cuando su mente dejo de funcionar que lo que había nunca visto sufrir a ningún ser humano&#8217;. El sentido de la invulnerabilidad de von Neumann, o simplemente el deseo de vivir se enfrentaba con hechos inalterables. Pareció tener un gran miedo de morir hasta el final… Ningún logro y ninguna clase de influencia podían salvarle ahora, como había tenido siempre en el pasado. Johnny von Neumann, que supo como vivir tan plenamente, no supo como morir.&#8221;</em></em></p>
<p style="text-align: left;">Alan Turing siguió investigando en diversos temas, en 1952 escribió <a href="http://www.lnds.net/blog/2008/01/ajedrez.html">un programa de ajedrez</a>, pero era imposible correrlo en ningún computador de esa época, y el actuaba como CPU humana. Sus últimos años los dedicó a la biología matemática, tratando de entender por que se daban secuencias de números de fibonacci en las estructuras vegetales. Alan Turing era homosexual, una condición que era condenada en la Inglaterra de los 1950s. Durante el proceso en que se investigaba una denuncia que él mismo interpuso por robo, tuvo que confesar su homosexulidad y el acusador pasó a ser acusado de &#8220;indecencia grave y perversión sexual&#8221;. La opción era ir a prisión o someterse a un tratamiento hormonal, que incluía la inyección de estrógeno, lo que le provocó la aparición de pechos, impotencia y otras molestias. En 1954 muere por envenenamiento por cianuro al comer una manzana. El acto se considera oficialmente un suicidio, pero su madre insistió en que fue un accidente.</p>
<p style="text-align: left;"><strong>Los fundamentos</strong></p>
<p style="text-align: left;">Si recuerdan la idea del computador humanos de Feynmann, podrán ver que las tarjetas que pasaban las operadoras corresponden a la memoria, las chicas con sus calculadoras correspondían a la unidad lógico aritmética, y Feynman y sus colegas actuaban como unidad de control. No es necesario saber de micro chips, o relés, para entender como funcionan los computadores.</p>
<p style="text-align: left;">Esta breve disgresión histórica tiene por objetivo presentarles un modelo de computador básico. El modelo de Von Neumman y la máquina de Turing sirven para entender en forma conceptual cómo operan los computadores. Seguiremos explorando esto en los próximos capítulos.</p>
<p style="text-align: left;"><strong>Lecturas recomendadas</strong></p>
<ul>
<li><a href="http://www.amazon.com/gp/product/0470229055/ref=as_li_tf_tl?ie=UTF8&amp;tag=lanaturaledel-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0470229055">The Annotated Turing: A Guided Tour Through Alan Turing&#8217;s Historic Paper on Computability and the Turing Machine</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=lanaturaledel-20&amp;l=as2&amp;o=1&amp;a=0470229055" border="0" alt="" width="1" height="1" /> por Charles Petzolds, para entender el artículo original de Alan Turing.</li>
<li>Una historia sobre la máquina Enigma se encuentra en este sitio: <a href="http://www.kriptopolis.org/la-maquina-enigma">Kriptópolis la máquina Enigma</a></li>
<li><a href="http://www.lnds.net/blog/2010/06/la-maquina-de-turing-explicada-por-el-mismo-turing.html">Este video</a> es un fragmento de la película <a href="http://www.imdb.com/title/tt0115749/">Breaking The Code</a>, donde Turing explica el concepto detrás de la máquina de Turing.</li>
<li>Una biografía de Von Neumman se encuentra <a href="http://www.astroseti.org/articulo/4101/biografia-de-john-von-neumann">en este sitio</a>, de donde sacamos algunas citas.</li>
<li>&#8220;El Placer de Descubrir&#8221; por Richard Feynman, Editorial Crítica Barcelona, año 2000.</li>
</ul>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.programando.org/blog/2011/04/la-maquina-universal/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Gracias</title>
		<link>http://www.programando.org/blog/2011/04/gracias/</link>
		<comments>http://www.programando.org/blog/2011/04/gracias/#comments</comments>
		<pubDate>Thu, 14 Apr 2011 00:56:28 +0000</pubDate>
		<dc:creator>ediaz</dc:creator>
				<category><![CDATA[Sin categoría]]></category>

		<guid isPermaLink="false">http://www.programando.org/blog/?p=243</guid>
		<description><![CDATA[Hemos completado lo básico en el curso de programación y pronto vamos a retomarlo, les pido paciencia. Al respecto me gustaría que me ayudaran con sus comentarios, críticas, y observaciones. También quiero pedirles que me ayuden a difundir este material. Ya llevo más de un mes con este nuevo proyecto, y les quiero agradecer el apoyo, los retweets, y los comentarios positivos que he recibido. También a los 22 primeros fans en la página de facebook. Pueden enviarme sugerencia de otros temas técnicos que les gustaría que tratara. Este es un espacio para difundir información técnica en nuestro idioma, hay mucho que hacer. Si quieren ayudar aportando con temas, escribir algún artículo son bienvenidos, sólo déjenme un mensaje en los comentarios. Este pequeño post es para agradecerles su paciencia y tiempo. ¿Qué se les ocurre que podríamos hacer para difundir más nuestro curso de programación? ¿Que les ha parecido el material publicado hasta ahora?]]></description>
			<content:encoded><![CDATA[<p>Hemos completado lo básico en el <a href="http://www.programando.org/blog/aprende-a-programar/">curso de programación</a> y pronto vamos a retomarlo, les pido paciencia. Al respecto me gustaría que me ayudaran con sus comentarios, críticas, y observaciones. También quiero pedirles que me ayuden a difundir este material.</p>
<p>Ya llevo más de un mes con este nuevo proyecto, y les quiero agradecer el apoyo, los retweets, y los comentarios positivos que he recibido. También a los 22 primeros fans en la <a href="https://www.facebook.com/pages/La-Sombra-de-Dijkstra/193081984063924">página de facebook</a>.</p>
<p>Pueden enviarme sugerencia de otros temas técnicos que les gustaría que tratara. Este es un espacio para difundir información técnica en nuestro idioma, hay mucho que hacer. Si quieren ayudar aportando con temas, escribir algún artículo son bienvenidos, sólo déjenme un mensaje en los comentarios.</p>
<p>Este pequeño post es para agradecerles su paciencia y tiempo.</p>
<p>¿Qué se les ocurre que podríamos hacer para difundir más nuestro curso de programación?<br />
¿Que les ha parecido el material publicado hasta ahora?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.programando.org/blog/2011/04/gracias/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>La lógica del juego de BlackJack</title>
		<link>http://www.programando.org/blog/2011/04/la-logica-del-juego-de-blackjack/</link>
		<comments>http://www.programando.org/blog/2011/04/la-logica-del-juego-de-blackjack/#comments</comments>
		<pubDate>Thu, 07 Apr 2011 12:50:22 +0000</pubDate>
		<dc:creator>ediaz</dc:creator>
				<category><![CDATA[Aprendiendo a programar]]></category>
		<category><![CDATA[blackjack]]></category>
		<category><![CDATA[curso]]></category>
		<category><![CDATA[juego]]></category>

		<guid isPermaLink="false">http://www.programando.org/blog/?p=233</guid>
		<description><![CDATA[En el capítulo anterior, de nuestro curso de programación, escribimos las rutinas necesarias para interactuar con el usuario. Además escribimos la función blackjack() que es la rutina principal de nuestro juego. Ahora nos vamos a concentrar en la lógica del juego. Volvamos a revisar la función blackjack(): def blackjack(pozo, apuesta_minima): print ("Bienvenido al juego de black jack") apuesta = solicitar_apuesta(pozo, apuesta_minima) while apuesta_minima]]></description>
			<content:encoded><![CDATA[<p>En el <a href="http://www.programando.org/blog/2011/04/interfaz-de-usuario-black-jack/">capítulo anterior</a>, de nuestro curso de programación, escribimos las rutinas necesarias para interactuar con el usuario. Además escribimos la función <strong>blackjack()</strong> que es la <strong>rutina principal</strong> de nuestro juego.</p>
<p>Ahora nos vamos a concentrar en la lógica del juego. Volvamos a revisar la función <strong>blackjack()</strong>:</p>
<pre name="code" class="python:nocontrols">
def blackjack(pozo, apuesta_minima):
     print ("Bienvenido al juego de black jack")
     apuesta = solicitar_apuesta(pozo, apuesta_minima)
     while apuesta_minima <= apuesta <= pozo:
         resultado = jugar_mano(apuesta, pozo)
         pozo  += resultado
         mostrar_resultado(resultado, pozo)
         apuesta = solicitar_apuesta(pozo, apuesta_minima)
     print ("Gracias por participar, su pozo final es: ", pozo)
</pre>
<p>Lo que vamos a escribir a continuación es la función <strong>jugar_mano()</strong>.</p>
<p>Escribamos primero lo que debe hacer en una serie de frases:</p>
<ol>
<li>Barajar las cartas.</li>
<li>Repartir cartas al jugador.</li>
<li>Repartir cartas al croupier.</li>
<li>Si la mano es un blackjack:
<ul>
<li>Finalizar la mano y retornar como resultado el doble de la apuesta</li>
</ul>
</li>
<li>En caso contrario  solicitar al jugador su próxima jugada, la que puede ser: 'R' para retirarse, 'D' para doblar, 'O' para pedir otra carta, y 'M' para mantener sus cartas.</li>
<ul>
<li>
Dependiendo de la opción se le entregan más cartas al jugador.
</li>
<li>Cuando el jugador ha dejado de pedir cartas entonces juega el croupier, solicitando cartas hasta completar 17.</li>
</ul>
<li>Se determina el resultado del juego y se retorna la ganancia o pérdida obtenida</li>
</ol>
<p>Todo lo anterior se refleja en la siguiente función <strong>jugar_mano()</strong>:</p>
<pre name="code" class="python:nocontrols">
def jugar_mano(apuesta, pozo):
	print ("Nueva mano, apuesta $", apuesta, " pozo $", pozo-apuesta, "\n")
	baraja = baraja_mezclada()
	mano_jugador, mano_couprier  = [next(baraja), next(baraja)], [next(baraja), next(baraja)]
	ganancia = 0
	if valor_mano(mano_jugador) == 21:
		mostrar_manos(mano_jugador, mano_couprier)
		print ("¡Jugador tienen black jack!")
		ganancia = (3*apuesta)//2
	else:
		jugada = 'I'
		while jugada in ['I', 'O']:
			mostrar_manos(mano_jugador, mano_couprier)
			jugada = solicitar_jugada(jugada)
			if jugada == 'M':
				mano_couprier = jugar_couprier(mano_couprier, baraja)
			elif jugada == 'D':
				mano_jugador.append(next(baraja))
				mano_couprier = jugar_couprier(mano_couprier, baraja)
			elif jugada == 'O':
				mano_jugador.append(next(baraja))
				if valor_mano(mano_jugador) > 21:
					jugada = 'R'
		mostrar_manos(mano_jugador, mano_couprier)
		ganancia = determinar_ganancia(mano_jugador, mano_couprier, apuesta, jugada)
	return ganancia
</pre>
<p>La función <strong>baraja_mezclada()</strong> en la línea 3 corresponde a una variación de la función con el mismo nombre que vimos en el <a href="http://www.programando.org/blog/2011/03/juegos-de-azar/">capítulo 12</a>, recuerden que esta función es una función generadora, esto nos permite usar la función primitiva <strong>next()</strong>. Con la función next() podemos obtener el siguiente elemento de un generador.</p>
<p>El if en la linea 6 sirve para controlar la situación en que tengamos 21 en la primera jugada, eso es un black jack, con lo que el resultado se paga 3 a 2.</p>
<p>A partir de la linea 10 tenemos el caso en que no hay black jack. </p>
<p>El ciclo while requiere atención. Fíjense que partimos con el valor de la variable <strong>jugada</strong> en 'I', con esto podemos "pasar" por la condición inicial del while y se ejecuta de inmediato las funciones <strong>mostrar_jugada()</strong> y <strong>solicitar_jugada()</strong>. Pero, atención, 'I' no es una opción de las posibles, la razón por la que usamos 'I' es que la función <strong>solicitar_jugada()</strong> tienen un comportamiento distinto al principio del juego (ver más abajo).</p>
<p>Determinar la condición adecuada para colocar en un ciclo while no es fácil y más adelante vamos a dedicar unos capítulos a entender este tema. Les sugiero revisar este ciclo while y simular su comportamiento con papel y lapiz, anoten el valor de la variable jugada y estudien qué pasa al principio del ciclo y como varía el comportamiento del programa dependiendo de la opción que elija el jugador.</p>
<p>Si recuerdan en el <a href="http://www.programando.org/blog/2011/04/interfaz-de-usuario-black-jack/">capítulo anterior</a> escribimos una versión de la función <strong>solicitar_jugada()</strong>, bueno, la versión definitiva de esa función es la siguiente:</p>
<pre name="code" class="python:nocontrols">
def solicitar_jugada(jugada):
	if jugada == 'I':
		prompt = "Jugada? ('R':Retirarse, 'D':Doblar, 'O':Otra carta, 'M': Mantener cartas) --> "
		opciones = ['R','D','O','M']
	else:
		prompt = "Jugada? ('R':Retirarse, 'O':Otra carta, 'M': Mantener cartas) --> "
		opciones = ['R','O','M']

	opcion = input(prompt).strip().upper()
	while opcion not in opciones:
		print("opción incorrecta")
		opcion = input(prompt).strip().upper()
        print("Opción elegida: ", opcion, "\n")
	return opcion
</pre>
<p>Queda claro que el menú es distinto al principio del juego, pues sólo se puede doblar la apuesta en ese instante, de ahí en adelante la opción 'D' ya no se puede usar.</p>
<p>La función <strong>mostrar_manos()</strong> es muy sencilla, sólo llama a la función <strong>mostrar_mano()</strong> del capítulo anterior, dos veces, una por la mano del jugador y otra para mostrar la mano del couprier.</p>
<pre name="code" class="python:nocontrols">

def mostrar_mano(prompt, mano):
	print("\t", prompt,
	      " ".join ( str(carta[0])+"-"+carta[1] for carta in mano),
		  " ( Valor: ", valor_mano(mano), ")\n")

def mostrar_manos(mano_jugador, mano_couprier):
	mostrar_mano("Cartas Jugador:  ", mano_jugador)
	mostrar_mano("Cartas Couprier: ", mano_couprier)
</pre>
<p>La función <strong>jugar_couprier()</strong> respeta la regla de que el couprier pide cartas hasta completar 17:</p>
<pre name="code" class="python:nocontrols">
def jugar_couprier(mano, baraja):
	while valor_mano(mano) < 17:
		mano.append(next(baraja))
	return mano
</pre>
<p>Por último la función <strong>determinar_ganancia()</strong> nos entrega la ganancia (o pérdida si es negativa) de acuerdo a la comparación del valor de las manos del jugador y el couprier:</p>
<pre name="code" class="python:nocontrols">
def determinar_ganancia(mano_jugador, mano_couprier, apuesta, jugada):
	if jugada == 'R':
		ganancia = -apuesta
	else:
		jugador, couprier = valor_mano(mano_jugador), valor_mano(mano_couprier)
		ganancia = 0
		if jugador <= 21 < couprier or couprier < jugador <= 21:
			ganancia = apuesta
		elif couprier <= 21 < jugador or jugador < couprier <= 21:
			ganancia = -apuesta
		if jugada == 'D':
			ganancia *= 2
	return ganancia
</pre>
<p>Con esto completamos nuestro programa que juega black jack. Este es el código completo del programa, te sugiero grabarlo como blackjack1.py y probarlo en tu ambiente:</p>
<pre name="code" class="python:nocontrols">
import random  

def baraja_mezclada():
	palos = ['C', 'D', 'T', 'P']
	valores = ['A'] + [v for v in range(2,11)] + ['J', 'Q', 'K']
	baraja = [(valor, palo) for palo in palos for valor in valores]
	random.shuffle(baraja)
	while len(baraja) > 0:
		yield baraja.pop(0)

def valor_mano(cartas):
	valor = 0
	ases = False
	for carta in cartas:
		valor_carta = carta[0]
		if  valor_carta in ('J','Q','K'):
			valor += 10
		elif valor_carta == 'A':
			ases = True
			valor += 1
		else:
			valor += valor_carta

	if ases and (valor + 10) <= 21:
		valor += 10

	return valor

def solicitar_jugada(jugada):
	if jugada == 'I':
		prompt = "Jugada? ('R':Retirarse, 'D':Doblar, 'O':Otra carta, 'M': Mantener cartas) --> "
		opciones = ['R','D','O','M']
	else:
		prompt = "Jugada? ('R':Retirarse, 'O':Otra carta, 'M': Mantener cartas) --> "
		opciones = ['R','O','M']

	opcion = input(prompt).strip().upper()
	while opcion not in opciones:
		print("opción incorrecta")
		opcion = input(prompt).strip().upper()
        print("Opción elegida: ", opcion, "\n")
	return opcion

def mostrar_mano(prompt, mano):
	print("\t", prompt,
	      " ".join ( str(carta[0])+"-"+carta[1] for carta in mano),
		  " ( Valor: ", valor_mano(mano), ")\n")

def mostrar_manos(mano_jugador, mano_couprier):
	mostrar_mano("Cartas Jugador:  ", mano_jugador)
	mostrar_mano("Cartas Couprier: ", mano_couprier)

def jugar_couprier(mano, baraja):
	while valor_mano(mano) < 17:
		mano.append(next(baraja))
	return mano

def determinar_ganancia(mano_jugador, mano_couprier, apuesta, jugada):
	if jugada == 'R':
		ganancia = -apuesta
	else:
		jugador, couprier = valor_mano(mano_jugador), valor_mano(mano_couprier)
		ganancia = 0
		if jugador <= 21 < couprier or couprier < jugador <= 21:
			ganancia = apuesta
		elif couprier <= 21 < jugador or jugador < couprier <= 21:
			ganancia = -apuesta
		if jugada == 'D':
			ganancia *= 2
	return ganancia

def jugar_mano(apuesta, pozo):
	print ("Nueva mano, apuesta $", apuesta, " pozo $", pozo-apuesta, "\n")
	baraja = baraja_mezclada()
	mano_jugador, mano_couprier  = [next(baraja), next(baraja)], [next(baraja), next(baraja)]
	ganancia = 0
	if valor_mano(mano_jugador) == 21:
		mostrar_manos(mano_jugador, mano_couprier)
		print ("¡Jugador tienen black jack!")
		ganancia = (3*apuesta)//2
	else:
		jugada = 'I'
		while jugada in ['I','O']:
			mostrar_manos(mano_jugador, mano_couprier)
			jugada = solicitar_jugada(jugada)
			if jugada == 'M':
				mano_couprier = jugar_couprier(mano_couprier, baraja)
			elif jugada == 'D':
				mano_jugador.append(next(baraja))
				mano_couprier = jugar_couprier(mano_couprier, baraja)
			elif jugada == 'O':
				mano_jugador.append(next(baraja))
				if valor_mano(mano_jugador) > 21:
					jugada = 'R'
		mostrar_manos(mano_jugador, mano_couprier)
		ganancia = determinar_ganancia(mano_jugador, mano_couprier, apuesta, jugada)
	return ganancia

def mostrar_resultado(resultado, pozo):
	if resultado > 0:
	   print("Jugador gana $", resultado)
	elif resultado < 0:
		print("Jugador pierde $", -resultado)
	else:
		print("Empate")
	print ("Su pozo es: $", pozo, "\n")

def solicitar_apuesta(pozo, apuesta_minima):
	valor = -1
	if pozo < apuesta_minima:
		print ("Su pozo no le alcanza para seguir jugando, inténtelo de nuevo en otra oportunidad")
	else:
		prompt = "\nIngrese su apuesta (min: "+str(apuesta_minima)+", max: "+str(pozo)+", 0 para finalizar juego): "
		while valor != 0 and not (apuesta_minima <= valor <= pozo):
			valor = int(input(prompt))
	print ("")
	return valor

# black jack
def black_jack(pozo, apuesta_minima):
	# ciclo principal del programa
	print ("Bienvenido al juego de black jack")
	apuesta = solicitar_apuesta(pozo, apuesta_minima)
	while apuesta_minima <= apuesta <= pozo:
		resultado = jugar_mano(apuesta, pozo)
		pozo += resultado
		mostrar_resultado(resultado, pozo)
		apuesta = solicitar_apuesta(pozo, apuesta_minima)
	print ("Gracias por participar, tu pozo final es: ", pozo)

# llamada a blackjack() con pozo inicial y apuesta minima
black_jack(500, 10) # este es el punto de entrada del programa
</pre>
<p>Son 134 líneas de código. Por cierto, este programa tiene algunos defectos que vamos a resolver más adelante (¿puedes identificarlos?)</p>
<p>Esta vez no habrá ejercicios, la tarea es analizar cómo funciona este programa y entenderlo, te sugiero probar cambiando algunas cosas de este programa. Si algo no quedó claro te pido que me hagas consultas en los comentarios. Si identifican algún error por favor escríbanlo en los comentarios. El código fuente se encuentra en GitHub y lo pueden descargar desde allá en esta dirección: <a href="https://github.com/lnds/programando.org/tree/master/curso-de-programacion-cap-15-blackjack">https://github.com/lnds/programando.org/tree/master/curso-de-programacion-cap-15-blackjack</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.programando.org/blog/2011/04/la-logica-del-juego-de-blackjack/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

