A Django site.
Diciembre 27, 2009
» 21 días – Aprendé a programar en 10 años – ES_AR

Esta es una traducción al español Argentino del famoso artículo de Peter Norvig Teach Yourself Programming in Ten Years. Hay una versión en español de España pero está desactualizada. Creo que es un artículo que cualquiera que gusta de la programación debería leer.

Aprendé a programar en diez años

Por Peter Norvig.  Teach Yourself Programming in Ten Years.

Traducción libre al español Argentino por Juan José Conti – actualizado con el original a Diciembre de 2009
Originalmente basado en la versión de Calos Rueda

¿Por qué están todos tan apurados?

Entrá a cualquier librería y vas a encontrar  Aprende Java en 7 Días y demás variaciones interminables ofreciendo enseñar Visual Basic, Windows, Internet, etc., en unos pocos días u horas. Yo hice la siguiente búsqueda avanzada (power search) en Amazon.com :

pubdate: after 1992 and title: days and (title: learn or title: teach yourself)

y obtuve 248 ítems de resultado. Los primeros 78 fueron libros de computación (el número 79 era Aprende Bengali en 30 días Learn Bengali in 30 days ). Remplacé “days” (días) por “hours” (horas) y sorprendentemente obtuve resultados similares: 253 libros más, con 77 libros de computación seguidos de Aprende Gramática y Estilo en 24 horas (Teach Yourself Grammar and Style in 24 Hours) en el número 78. Del total de los primeros 200, el  96% fueron libros de computación.

La conclusión es que, o bien la gente está muy apurada por saber de computadoras, o bien las computadoras son algo fabulosamente fácil de aprender, más que cualquiera otra cosa. No hay libros sobre cómo aprender Beethoven, o Física Cuántica, o incluso Estética Perruna en pocos días. Felleisen et al. asienten esta tendencia en su libro How to Design Programs, cuando dicen “La programación mala es fácil. Los idioitas pueden aprenderla en 21 días, incluso si son tontos” (original: “Bad programming is easy. Idiots can learn it in 21 days, even if they are dummies.)

Analicemos lo que podría significar un título como Aprende C++ en Tres Días (Learn C++ in Three Days):

  • Aprende: En 3 días no vas a tener tiempo de escribir varios programas significativos, y de aprender de tus aciertos y errores con ellos. No vas a tener tiempo de trabajar con un programador experimentado y entender lo que es vivir en un ambiente de C++. En resumen, no vas a tener tiempo de aprender mucho. Así que esos libros sólo podrán lograr una familiaridad superficial, no un entendimiento profundo. Como dijo Alexander Pope, poco aprendizaje es una cosa peligrosa.
  • C++: En 3 días puedes aprender la sintaxis de C++ (si ya sabés otro lenguaje), pero no vas a poder aprender mucho sobre cómo usar el lenguaje. En síntesis, si fueras, digamos, un programador Basic, podrías aprender a escribir programas en el estilo de Basic usando la sintaxis de C++, pero no aprenderías para qué C++ es realmente bueno (o malo). Entonces ¿cuál es el punto? Alan Perlis dijo alguna vez: “Un lenguaje que no afecte tu manera de pensar acerca de la programación, no merece ser aprendido”. Un objetivo posible es que tienes que aprender un poco de C++ (o más probablemente, algo como Visual Basic o JavaScript) porque necesitas tener una interface con una herramienta existente para realizar una cierta tarea. Pero entonces no estás aprendiendo cómo programar; estás aprendiendo
    cómo realizar esa tarea.
  • en Tres Días: Desafortunadamente, no son suficientes, como se describe en la siguiente sección.

Aprendé a programar en diez años

Algunos investigadores (Bloom (1985), Bryan & Harter (1899), Hayes (1989), Simmon & Chase (1973)) han mostrado que toma aproximadamente diez años desarrollar habilidades en cualquiera de una amplia variedad de áreas,  incluyendo jugar al  ajedrez, componer música, pintar, tocar el piano, operar un telégrafo, nadar, jugar al tenis, u investigar en neurosicología y topología. La clave es la práctica deliberada: no solo hacerlo una y otra vez, sino desafiarte con una tarea que es un poco más dificil que tu habilidad actual, intentando, analizando tu performance mientras lo hacés y corrigiendo cualquier error. Luego repetir. Y volver a repetir. Parece no haber atajos: incluso a Mozart, prodigio musical a los 4 años, le tomó 13 más empezar a producir música de calidad mundial. En otro género, parece que los Beatles llegan a escena apareciendo en el espectáculo de Ed Sullivan en 1964. Pero ellos habían estado tocando desde 1957, y aunque tenían una masa de seguidores desde antes, su primer gran éxito, Sgt. Peppers, apareció en 1967. Malcolm Gladwell reportó que un estudio en la Academia de Música de Berlín separó a los mejores, los del meido y los peores de la clase y les preguntó cuánto practicaban:

Todas las personas, las de los tres grupos, empezar a tocar casi al mismo tiempo (alrededor de la edad de 5 años). En esos primeros pocos años, todos practicaron casi la misma cantidad (dos o tres horas por semana). Pero a la edad de ocho, empezaro a surgir las verdaderas diferencias. Los estudiantes que terminarían en el mejor tercio de la clase empezaron a practicar más que los demás: seis horas a la semana a los nueve, ocho a los 12, 16 a los 14, y más y más hasta que a la edad de 20, los músicos elite alcanzaraon las 10000 horas de práctica en el curso de sus vidas. Los estudiantes que solo eran buenos sumaron 8000 horas y los futuros profesores de música solo 4000.

Entonces, deben ser esas 10000 horas, no los 10 años, el número mágico. Samuel Johnson (1709-1784) pensaba que llevaba más: “La excelencia en cualquier área solo puede lograrse con la labor de toda la vida; no debe ser comprada a un precio menor” . Y Chaucer (1340-1400) se quejaba de que  “la vida era muy corta, y el trabajo largo de aprender”. Hipócrates (c. 400BC) es conocido por la frase “ars longa, vita brevis”, qué es parte de una cita más larga: “Ars longa, vita brevis, occasio praeceps, experimentum periculosum, iudicium difficile”, que significa algo como “La vida es corta, el trabajo largo, la oportunidad fugaz, experimentar es traicionero, el juicio dificil”. Aunque en Latin, ars puede significar tanto arte como trabajo, en el original griego “techne” solo puede significar “destreza”, no “arte”.

Aquí está mi receta para el éxito en programación:

  • Interesate en la programación y programá, porque es divertida. Asegúrate de que siga siendo divertida, tanto que podrías invertir diez años haciéndolo.
  • Habla con otros programadores. Lee otros programas. Esto es más importante que cualquier libro o curso.
  • Programa. El mejor tipo de aprendizaje es aprender haciendo (learning by doing) . Para decirlo más técnicamente, “El máximo nivel de desempeño de los individuos en un dominio dado, no se logra automáticamente como función de experiencia extendida, sino que el nivel de desempeño puede incrementarse incluso en individuos altamente experimentados como resultado de esfuerzos deliberados por mejorar.”(p.
    366)
    y “el aprendizaje más efectivo requiere una tarea bien definida con un apropiado nivel de dificultad acorde con el individuo, retroalimentación informativa, y oportunidades de repetición y corrección de errores.” (p. 20-21) El libro Cognition in Practice: Mind, Mathematics, and Culture in Everyday Life es una interesante referencia sobre este punto de vista.
  • Si querés, dedica cuatro o cinco años en una universidad (o más en una escuela de graduados). Esto te dará acceso a algunos posiciones que requieren credenciales, y te dará un entendimiento más profundo del campo, pero si no disfrutas la escuela, puedes (con algo de dedicación) obtener una experiencia similar trabajando. Como sea, la lectura de libros por sí sola no será suficiente. “La educación en computación no puede hacer a nadie un experto programador más que el estudio de pinceles y pigmentos puede hacer a alguien un pintor experto” dice Eric Raymond, autor de The New Hacker’s Dictionary. Unos de los mejores programadores que yo haya contratado alguna vez tenía sólamente un grado de bachiller (High School); pero ha producido una gran cantidad de excelentes programas , tiene su propio grupo de noticias (news group) , y sin duda es mucho más rico de lo que yo llegue a ser.
  • Trabajá en proyectos con otros programadores. Sé el mejor programador en algunos proyectos; sé el peor en otros. Cuando sos el mejor, ponés a prueba tus habilidades para liderar un proyecto y para inspirar a otros con tu visión. Cuando sos el peor, aprendés lo que los maestros hacen, y aprendes lo que a ellos no les gusta hacer (ya que te ponen a hacerlo a vos).
  • Trabajá en proyectos después de otros programadores. Proponete entender un programa escrito por otra persona. Mirá cuánto toma entenderlo y hacele correcciones cuando los programadores originales no estén allí. Pensá cómo diseñar tus programas para facilitarles el trabajo a los que deban mantenerlo después de vos.
  • Aprende por lo menos una media docena de lenguajes de programación.mIncluye uno con soporte para abstracciones de clases (como Java o C++),
    uno que dé soporte a la abstracción funcional (como Lisp o ML), uno que dé soporte a la abstracción sintáctica (como Lisp), uno que dé soporte a especificationes declarativas (como Prolog o plantillas C++), uno que dé soporte a corutinas (como Icon o Scheme), y uno que dé soporte al paralelismo (como Sisal).
  • Recordá que hay una “computadora” en “ciencia de la computación”. Conoce cuánto le toma a tu computadora ejecutar una instrucción, alcanzar una palabra de la memoria (con y sin cache), leer palabras consecutivas del disco, y ubicar una nueva localización en disco. (Respuestas más abajo)
  • Participá de un plan de estandarización de algún lenguaje. Podría ser en el mismo comité ANSI C++, o podría ser simplemente decidir si tu estilo de codificación tendrá niveles de identación de 2 ó 4 espacios. Como sea, averiguá lo que les gusta a otras personas en un lenguaje, cómo lo perciben, y quizá incluso un poco de por qué lo perciben como lo hacen.
  • Tené el buen juicio para lanzar el plan de estandarización del lenguaje tan pronto como sea posible.

Con todo lo anterior en mente, es cuestionable qué tan lejos puedes llegar sólo leyendo libros. Antes de que naciera mi primer hijo, leí todos los libros Aprende a (How To), y sin embargo me sentía como un tonto principiante. 30 meses después, cuando nació mi segundo hijo, ¿acaso regresé a los libros? No.

Al contrario, me apoyé en mi experiencia personal, que me resultó mucho más útil y confiable que las miles de páginas escritas por los expertos.

Fred Brooks, en su ensayo No Silver Bullets, identificó un plan de tres partes para encontrar grandes diseñadores de programas:

  1. Sistemáticamente identificar a los diseñadores líderes lo más pronto posible.
  2. Asignar un tutor de carrera para que sea responsable del desarrollo del prospecto y mantené un cuidadoso registro de todo.
  3. Ofrecer oportunidades a los diseñadores en crecimiento para que interactúen y se motiven mutuamente.

Esto asume que algunas personas ya tienen las cualidades necesarias para ser grandes diseñadores; la tarea es persuadirlos apropiadamente.
Alan Perlis lo dice de manera más sucinta: “A cualquiera se le puede enseñar a esculpir: A Miguel Angel habría que habérsele enseñado cómo no hacerlo. Así pasa con los grandes programadores”.

Así que adelante, compra ese libro de Java; probablemente obtendrás algo de él. Pero no cambiará tu vida o tus verdaderas habilidades como programador en 24 horas, días o incluso meses.

Referencias

Bloom, Benjamin (ed.) Developing Talent in Young People, Ballantine, 1985.

Brooks, Fred, No Silver Bullets, IEEE Computer, vol. 20, no. 4, 1987, p. 10-19.

Hayes, John R., Complete Problem Solver Lawrence Erlbaum, 1989.

Lave, Jean, Cognition in Practice: Mind, Mathematics, and Culture in Everyday Life, Cambridge University Press, 1988.

Respuestas

Tiempos de demora de varias operaciones en una PC típica de 1GHz, verano de 2001:

execute single instruction 1 nsec = (1/1,000,000,000) sec
fetch word from L1 cache memory 2 nsec
fetch word from main memory 10 nsec
fetch word from consecutive disk location 200 nsec
fetch word from new disk location (seek) 8,000,000nsec = 8msec

Apéndice: Elección del lenguaje

Muchas personas me preguntaron qué lenguaje de programación deberían aprender primero. No hay una única respuesta, pero considerá estos puntos:

  • Usá a tus amigos. Cuando me preguntan “qué sistema operativo debería usar, Windows, Unix, o Mac”, mi respuesta suele ser : “usá lo que tus amigos usen”. La ventaja que tenés de aprender de tus amigos compensará cualquier diferencia intrínsica entre  entre sistemas operativos o entre lenguajes de programación. También considerá a tus futuros amigos: la comunidad de programadores de la que vas a ser parte si continuás. ¿Tu lenguaje elejido tiene una comunidad amplia y en crecimiento o una pequeña y agonizante? ¿Hay libros, sitios web y foros en línea de dónde obtener respuestas? ¿Te caen bien las personas en esos foros?
  • Mantenelo simple. Los lenguajes de programación como C++  y Java están diseñados para que desarrollen grandes equipos de programadores profesionales preocupados por la eficiencia en  tiempo de ejecución de su código. Como resultado, estos lenguajes tienen partes complicadas diseñadas para estas circunstancias. Vos estás preocupado en aprender a programar. No necesitás esas complicaciones. Querés un lenguaje diseñado para ser fácil de aprender y recordar para un programador nuevo.
  • Jugá. ¿De qué forma preferirías aprender a tocar el piano: de la forma normal, interactiva, en la que escuchás cada nota inmediatamente después de apretar una tecla, o en modo “batch”, solo escuchando las notas después de terminar de teclear una canción entera? Claramente, el modo interactivo hace que el aprendizaje de tocar el piano sea más fácil; también de la programación. Intentá con lenguajes que tengan un modo interactivo y usalo.

Con estos criterios, mis recomendaciones para un promer lenguaje de programacion serían Python o Scheme.Pero tus circunstancias pueden variar, y hay otras buenas opciones. Si tu edad es de un solo dígito, tal vez prefieras Alice o Squeak (aprendices mayores también apreciarían este). Lo importante es que hagas la elección y empieces.

Apéndice: Libros y otros recursos

Varias personas me preguntaron qué libros y páginas web utilizar para su aprendizaje. Repito que el aprendizaje solitario con un libro no es suficiente, pero puedo recomendar los siguientes:

Notas

T. Capey señala que la página Complete Problem Solver en Amazon hoy tiene a los libros “Teach Yourself Bengali in 21 days” y “Teach Yourself Grammar and Style” bajo la sección “Los clientes que compraron este item, también compraron estos items”. Supongo que una gran cantidad de personas que miran ese libro vienen de esta página. Gracias a Ross Cohen por ayudar con Hipócrates.

Peter Norvig (Copyright 2001)

Diciembre 6, 2009
» Primera vez con Ruby

El viernes por la tarde salí del trabajo y me fuí a escuchar la charla de César Ballardini, El modelo de objetos de Ruby, reflexiones sobre la reflexión. La daba en el marco del evento acts_as_rubylit, el cual se llevó a cabo en la Facultad de Ingeniería y Ciencias Hídricas, Universidad Nacional del Litoral de la ciudad de Santa Fe.

Nunca antes vi nada de Ruby. Bueno, casi, pero la última vez no pasé del Hola Mundo!juanjo_ruby_800

César empezó su charla explicando la Paradoja de Blub, de Paul Graham. Blub es un lenguaje de programación hipotético. No es el lenguaje de programación más poderoso, pero tampoco es Cobol o lenguaje de máquina. Un programador Blub está parado más o menos en el medio de la ladera de una montaña; hacia abajo están los lenguajes menos poderosos que Blub, él se da cuenta de esto, por supuesto, a todos esos lenguajes le faltan distintas características que nuestro programador usa en Blub para resolver sus problemas. En cambio, cuando mira para arriba (y ve lenguajes más poderosos que Blub), en realidad no se da cuenta que está mirando hacia arriba, simplemente piensa que está mirando a unos locos, hippies de pelos parados haciendo cosas raras. Cuando los programadores que están más arriba en la montaña miran hacia Blub se pregunta, ¿cómo puede alguien estar usando Blub? Ni siquiera tiene la funcionalidad X tan útil para resolver Y!

Por inducción se concluye que solo el programador que esté en la punta de la montaña, es decir el que conoce el lenguaje más poderoso, es capaz de distinguir las distintas posibilidades que se tienen con diferentes lenguajes. El programador Blub no puede verlo, por lo que solo sabe pensar en Blub, no se a enfrentado a problemas que le permitan pensar diferente.

La moraleja de la historia es que uno debería aprender lenguajes que lo obliguen a cambiar su forma de pensar y de resolver problemas (Alan J. Perlis).

Con esto terminó la primera parte de la charla, luego César hizo una explicación de pizarrón sobre qué es la Programación Orientada a Objetos ( y escribió con su fibrón: un objeto tiene Identidad, encapsula Estado y define Comportamiento). Según César, es un error que en la enseñanza de la POO se empiece por las Clases. ¿En qué parte de “Programación Orientada a Objetos” dice “Clase”? Las clases son solo una forma de crear objetos, pero hay muchas otras. Por ejemplo, existen muchos lenguajes OO basados en prototipos, como JavaScript.

Después de haber shockeado a la audiencia desarrollando estas dos ideas en un tono casi de declaración de principios, estábamos listos para ver cómo el Modelo de Objetos de Ruby podía cambiar nuestra forma de pensar.
Lo que sigue no son los ejemplos exactos que desrrolló César con su notebook, solo los que recuerdo. Mezclo los recuerdos de su sesión interactiva de Ruby con mi propio camino de aprendizaje, que arranca ni siquiera teniendo el intérprete instalado :)

Para empezar los ejemplos, tipeó en la terminal

irb

. Hice lo mismo, pero no estaba instalado, por lo que instalé ese paquete y presté atención a sus dependencias:

juanjo@fenix:~$ irb
El programa «irb» no está instalado actualmente.  Puede instalarlo escribiendo:
sudo apt-get install irb
bash: irb: orden no encontrada
juanjo@fenix:~$ sudo apt-get install irb
[sudo] password for juanjo:
Leyendo lista de paquetes... Hecho
Creando árbol de dependencias
Leyendo la información de estado... Hecho
Se instalarán los siguientes paquetes extras:
  irb1.8 libreadline-ruby1.8 ruby1.8
Paquetes sugeridos:
  ruby1.8-examples rdoc1.8 ri1.8
Se instalarán los siguientes paquetes NUEVOS:
  irb irb1.8 libreadline-ruby1.8 ruby1.8
0 actualizados, 4 se instalarán, 0 para eliminar y 0 no actualizados.
Necesito descargar 119kB de archivos.
Se utilizarán 664kB de espacio de disco adicional después de esta operación.
¿Desea continuar [S/n]?
Des:1 http://ar.archive.ubuntu.com jaunty-updates/main ruby1.8 1.8.7.72-3ubuntu0.1 [24,0kB]
Des:2 http://ar.archive.ubuntu.com jaunty-updates/universe libreadline-ruby1.8 1.8.7.72-3ubuntu0.1 [10,4kB]
Des:3 http://ar.archive.ubuntu.com jaunty-updates/universe irb1.8 1.8.7.72-3ubuntu0.1 [79,1kB]
Des:4 http://ar.archive.ubuntu.com jaunty/universe irb 4.2 [5138B]
Descargados 119kB en 2s (58,0kB/s)
Seleccionando el paquete ruby1.8 previamente no seleccionado.
(Leyendo la base de datos ...
248649 ficheros y directorios instalados actualmente.)
Desempaquetando ruby1.8 (de .../ruby1.8_1.8.7.72-3ubuntu0.1_i386.deb) ...
Seleccionando el paquete libreadline-ruby1.8 previamente no seleccionado.
Desempaquetando libreadline-ruby1.8 (de .../libreadline-ruby1.8_1.8.7.72-3ubuntu0.1_i386.deb) ...
Seleccionando el paquete irb1.8 previamente no seleccionado.
Desempaquetando irb1.8 (de .../irb1.8_1.8.7.72-3ubuntu0.1_all.deb) ...
Seleccionando el paquete irb previamente no seleccionado.
Desempaquetando irb (de .../apt/archives/irb_4.2_all.deb) ...
Procesando disparadores para man-db ...
Procesando disparadores para menu ...
Configurando ruby1.8 (1.8.7.72-3ubuntu0.1) ...
Configurando libreadline-ruby1.8 (1.8.7.72-3ubuntu0.1) ...
Configurando irb1.8 (1.8.7.72-3ubuntu0.1) ...

Configurando irb (4.2) ...
Procesando disparadores para menu ...

Entonces irb no es Ruby. ¿Qué es?

NAME
       irb1.8 - interactive ruby

SYNOPSIS
       irb [options]

DESCRIPTION
       irb stands for ‘interactive ruby’. irb is a tool to execute interactively ruby expressions read from stdin.  Use of irb is easy if
       you know ruby.  Executing irb, prompts are displayed as follows. Then, enter expression of ruby. A input is executed  when  it  is
       syntacticaly completed.

Ahora si puedo empezar!

Objetos y mensajes

Un lenguaje OO consta de objetos y mensajes entre objetos. Algunas veces los mensajes están un poco camuflados, pero siempre están ahí:

irb(main):001:0> 1 + 2
=> 3
irb(main):002:0> 1.+ 2
=> 3
irb(main):003:0> 1.+(2) # para los lisperos que extrañan los paréntesis
=> 3

Identidad

Enviando el mensaje

object_id

, podemos preguntarle su identidad a un objeto:

irb(main):001:0> 1.object_id
=> 3
irb(main):002:0> "hola".object_id
=> -605926728

Clases

Enviando el mensaje

class

a un objeto, podemos preguntarle quién es su clase:

irb(main):005:0> 1.class
=> Fixnum
irb(main):006:0> 1.class.class
=> Class
irb(main):007:0> 1.class.class.class
=> Class

Podemos ver que la clase Fixnum es una instancia de la clase Class; y la clase Class también es instancia de la clase Class.
Enviando el mensaje

superclass

a una clase, podemos saber cual es su superclase, es decir, qué clase extiende.

irb(main):010:0> 1.class.superclass
=> Integer
irb(main):011:0> 1.class.superclass.superclass
=> Numeric
irb(main):012:0> 1.class.superclass.superclass.superclass
=> Object

Luego, la clase de Object es obviamente Class, pero… ¿cuál es su superclase?

irb(main):019:0> 1.class.superclass.superclass.superclass
=> Object
irb(main):020:0> 1.class.superclass.superclass.superclass.superclass
=> nil

Creo recordar que en SmallTalk también era así. Parece un chiste de los diseñadores :) nil ni siquiera es una clase:

irb(main):021:0> 1.class.superclass.superclass.superclass.superclass.superclass
NoMethodError: undefined method `superclass' for nil:NilClass
	from (irb):21
	from :0
irb(main):022:0> 1.class.superclass.superclass.superclass.superclass.class
=> NilClass
irb(main):023:0> 1.class.superclass.superclass.superclass.superclass.class.superclass
=> Object
irb(main):024:0> 1.class.superclass.superclass.superclass.superclass.class.class
=> Class

y la jerarquía de clases se cierra. Es para leer tranquilo y pensarlo.

El resto de la charla abarcó varias cosas más, pero creo que sería demasiado para desarrollarlo en un post y lo que mostré ya es suficiente para abrirle el apetito a los que estén buscando algún lenguaje para aprender y les produzca un cambio en su forma de pensar :) . Si César postea sus ejemplos, los voy a estar referenciando desde aquí o voy a intentar hacer uno o dos posts más.

Gracias al Grupo de Usuarios de Ruby del Litoral por organizar el evento!

Setiembre 18, 2009
» Ejercicio 16 – proyecto Euler

De vez en cuando se me da por hacer saries de posts en el blog. Sagas. Una de las últimas fue la saga sobre resoluciones a problemas del proyecto Euler. Lo que intentaba era resolverlos con alguna característica interesante de Python y luego explicarla. Luego de los primeros, los ejercisios se volvieron más matemáticos y encontraba menos cosas interesantes de Python que comentar, así que dejé de postear mis soluciones. Acabo de encontrar esta entre mis archivos y creo que tiene algo de originalidad como para merecer ser publicada:

¿Cuál es la suma de los dígitos del número 2^(1000)?

>>> 2**1000
107150860718626732094842504906000[algunos números fueron intencionalmente borrados]
>>> a = 2**1000
>>> sum((int(x) for x in list(str(a))))
1366

¿A alguien se le ocurre otra forma?

Julio 2, 2009
» Euler 8 (Python)

Enunciado 8

Encontrar el mayor producto de cinco dígitos consecutivos en este número de 100 dígitos:

73167176531330624919225119674426574742355349194934
96983520312774506326239578318016984801869478851843
85861560789112949495459501737958331952853208805511
12540698747158523863050715693290963295227443043557
66896648950445244523161731856403098711121722383113
62229893423380308135336276614282806444486645238749
30358907296290491560440772390713810515859307960866
70172427121883998797908792274921901699720888093776
65727333001053367881220235421809751254540594752243
52584907711670556013604839586446706324415722155397
53697817977846174064955149290862569321978468622482
83972241375657056057490261407972968652414535100474
82166370484403199890008895243450658541227588666881
16427171479924442928230863465674813919123162824586
17866458359124566529476545682848912883142607690042
24219022671055626321111109370544217506941658960408
07198403850962455444362981230987879927244284909188
84580156166097919133875499200524063689912560717606
05886116467109405077541002256983155200055935729725
71636269561882670428252483600823257530420752963450

Solución

>>> b = 7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450
>>> s = str(b)
>>> s
'7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450'
>>> l = list(s)
>>> l
['7', '3', '1', '6', '7', '1', '7', '6', '5', '3', '1', '3', '3', '0', '6', '2', '4', '9', '1', '9', '2', '2', '5', '1', '1', '9', '6', '7', '4', '4', '2', '6', '5', '7', '4', '7', '4', '2', '3', '5', '5', '3', '4', '9', '1', '9', '4', '9', '3', '4', '9', '6', '9', '8', '3', '5', '2', '0', '3', '1', '2', '7', '7', '4', '5', '0', '6', '3', '2', '6', '2', '3', '9', '5', '7', '8', '3', '1', '8', '0', '1', '6', '9', '8', '4', '8', '0', '1', '8', '6', '9', '4', '7', '8', '8', '5', '1', '8', '4', '3', '8', '5', '8', '6', '1', '5', '6', '0', '7', '8', '9', '1', '1', '2', '9', '4', '9', '4', '9', '5', '4', '5', '9', '5', '0', '1', '7', '3', '7', '9', '5', '8', '3', '3', '1', '9', '5', '2', '8', '5', '3', '2', '0', '8', '8', '0', '5', '5', '1', '1', '1', '2', '5', '4', '0', '6', '9', '8', '7', '4', '7', '1', '5', '8', '5', '2', '3', '8', '6', '3', '0', '5', '0', '7', '1', '5', '6', '9', '3', '2', '9', '0', '9', '6', '3', '2', '9', '5', '2', '2', '7', '4', '4', '3', '0', '4', '3', '5', '5', '7', '6', '6', '8', '9', '6', '6', '4', '8', '9', '5', '0', '4', '4', '5', '2', '4', '4', '5', '2', '3', '1', '6', '1', '7', '3', '1', '8', '5', '6', '4', '0', '3', '0', '9', '8', '7', '1', '1', '1', '2', '1', '7', '2', '2', '3', '8', '3', '1', '1', '3', '6', '2', '2', '2', '9', '8', '9', '3', '4', '2', '3', '3', '8', '0', '3', '0', '8', '1', '3', '5', '3', '3', '6', '2', '7', '6', '6', '1', '4', '2', '8', '2', '8', '0', '6', '4', '4', '4', '4', '8', '6', '6', '4', '5', '2', '3', '8', '7', '4', '9', '3', '0', '3', '5', '8', '9', '0', '7', '2', '9', '6', '2', '9', '0', '4', '9', '1', '5', '6', '0', '4', '4', '0', '7', '7', '2', '3', '9', '0', '7', '1', '3', '8', '1', '0', '5', '1', '5', '8', '5', '9', '3', '0', '7', '9', '6', '0', '8', '6', '6', '7', '0', '1', '7', '2', '4', '2', '7', '1', '2', '1', '8', '8', '3', '9', '9', '8', '7', '9', '7', '9', '0', '8', '7', '9', '2', '2', '7', '4', '9', '2', '1', '9', '0', '1', '6', '9', '9', '7', '2', '0', '8', '8', '8', '0', '9', '3', '7', '7', '6', '6', '5', '7', '2', '7', '3', '3', '3', '0', '0', '1', '0', '5', '3', '3', '6', '7', '8', '8', '1', '2', '2', '0', '2', '3', '5', '4', '2', '1', '8', '0', '9', '7', '5', '1', '2', '5', '4', '5', '4', '0', '5', '9', '4', '7', '5', '2', '2', '4', '3', '5', '2', '5', '8', '4', '9', '0', '7', '7', '1', '1', '6', '7', '0', '5', '5', '6', '0', '1', '3', '6', '0', '4', '8', '3', '9', '5', '8', '6', '4', '4', '6', '7', '0', '6', '3', '2', '4', '4', '1', '5', '7', '2', '2', '1', '5', '5', '3', '9', '7', '5', '3', '6', '9', '7', '8', '1', '7', '9', '7', '7', '8', '4', '6', '1', '7', '4', '0', '6', '4', '9', '5', '5', '1', '4', '9', '2', '9', '0', '8', '6', '2', '5', '6', '9', '3', '2', '1', '9', '7', '8', '4', '6', '8', '6', '2', '2', '4', '8', '2', '8', '3', '9', '7', '2', '2', '4', '1', '3', '7', '5', '6', '5', '7', '0', '5', '6', '0', '5', '7', '4', '9', '0', '2', '6', '1', '4', '0', '7', '9', '7', '2', '9', '6', '8', '6', '5', '2', '4', '1', '4', '5', '3', '5', '1', '0', '0', '4', '7', '4', '8', '2', '1', '6', '6', '3', '7', '0', '4', '8', '4', '4', '0', '3', '1', '9', '9', '8', '9', '0', '0', '0', '8', '8', '9', '5', '2', '4', '3', '4', '5', '0', '6', '5', '8', '5', '4', '1', '2', '2', '7', '5', '8', '8', '6', '6', '6', '8', '8', '1', '1', '6', '4', '2', '7', '1', '7', '1', '4', '7', '9', '9', '2', '4', '4', '4', '2', '9', '2', '8', '2', '3', '0', '8', '6', '3', '4', '6', '5', '6', '7', '4', '8', '1', '3', '9', '1', '9', '1', '2', '3', '1', '6', '2', '8', '2', '4', '5', '8', '6', '1', '7', '8', '6', '6', '4', '5', '8', '3', '5', '9', '1', '2', '4', '5', '6', '6', '5', '2', '9', '4', '7', '6', '5', '4', '5', '6', '8', '2', '8', '4', '8', '9', '1', '2', '8', '8', '3', '1', '4', '2', '6', '0', '7', '6', '9', '0', '0', '4', '2', '2', '4', '2', '1', '9', '0', '2', '2', '6', '7', '1', '0', '5', '5', '6', '2', '6', '3', '2', '1', '1', '1', '1', '1', '0', '9', '3', '7', '0', '5', '4', '4', '2', '1', '7', '5', '0', '6', '9', '4', '1', '6', '5', '8', '9', '6', '0', '4', '0', '8', '0', '7', '1', '9', '8', '4', '0', '3', '8', '5', '0', '9', '6', '2', '4', '5', '5', '4', '4', '4', '3', '6', '2', '9', '8', '1', '2', '3', '0', '9', '8', '7', '8', '7', '9', '9', '2', '7', '2', '4', '4', '2', '8', '4', '9', '0', '9', '1', '8', '8', '8', '4', '5', '8', '0', '1', '5', '6', '1', '6', '6', '0', '9', '7', '9', '1', '9', '1', '3', '3', '8', '7', '5', '4', '9', '9', '2', '0', '0', '5', '2', '4', '0', '6', '3', '6', '8', '9', '9', '1', '2', '5', '6', '0', '7', '1', '7', '6', '0', '6', '0', '5', '8', '8', '6', '1', '1', '6', '4', '6', '7', '1', '0', '9', '4', '0', '5', '0', '7', '7', '5', '4', '1', '0', '0', '2', '2', '5', '6', '9', '8', '3', '1', '5', '5', '2', '0', '0', '0', '5', '5', '9', '3', '5', '7', '2', '9', '7', '2', '5', '7', '1', '6', '3', '6', '2', '6', '9', '5', '6', '1', '8', '8', '2', '6', '7', '0', '4', '2', '8', '2', '5', '2', '4', '8', '3', '6', '0', '0', '8', '2', '3', '2', '5', '7', '5', '3', '0', '4', '2', '0', '7', '5', '2', '9', '6', '3', '4', '5', '0']
>>> i = [int(x) for x in l]
>>> i
[7, 3, 1, 6, 7, 1, 7, 6, 5, 3, 1, 3, 3, 0, 6, 2, 4, 9, 1, 9, 2, 2, 5, 1, 1, 9, 6, 7, 4, 4, 2, 6, 5, 7, 4, 7, 4, 2, 3, 5, 5, 3, 4, 9, 1, 9, 4, 9, 3, 4, 9, 6, 9, 8, 3, 5, 2, 0, 3, 1, 2, 7, 7, 4, 5, 0, 6, 3, 2, 6, 2, 3, 9, 5, 7, 8, 3, 1, 8, 0, 1, 6, 9, 8, 4, 8, 0, 1, 8, 6, 9, 4, 7, 8, 8, 5, 1, 8, 4, 3, 8, 5, 8, 6, 1, 5, 6, 0, 7, 8, 9, 1, 1, 2, 9, 4, 9, 4, 9, 5, 4, 5, 9, 5, 0, 1, 7, 3, 7, 9, 5, 8, 3, 3, 1, 9, 5, 2, 8, 5, 3, 2, 0, 8, 8, 0, 5, 5, 1, 1, 1, 2, 5, 4, 0, 6, 9, 8, 7, 4, 7, 1, 5, 8, 5, 2, 3, 8, 6, 3, 0, 5, 0, 7, 1, 5, 6, 9, 3, 2, 9, 0, 9, 6, 3, 2, 9, 5, 2, 2, 7, 4, 4, 3, 0, 4, 3, 5, 5, 7, 6, 6, 8, 9, 6, 6, 4, 8, 9, 5, 0, 4, 4, 5, 2, 4, 4, 5, 2, 3, 1, 6, 1, 7, 3, 1, 8, 5, 6, 4, 0, 3, 0, 9, 8, 7, 1, 1, 1, 2, 1, 7, 2, 2, 3, 8, 3, 1, 1, 3, 6, 2, 2, 2, 9, 8, 9, 3, 4, 2, 3, 3, 8, 0, 3, 0, 8, 1, 3, 5, 3, 3, 6, 2, 7, 6, 6, 1, 4, 2, 8, 2, 8, 0, 6, 4, 4, 4, 4, 8, 6, 6, 4, 5, 2, 3, 8, 7, 4, 9, 3, 0, 3, 5, 8, 9, 0, 7, 2, 9, 6, 2, 9, 0, 4, 9, 1, 5, 6, 0, 4, 4, 0, 7, 7, 2, 3, 9, 0, 7, 1, 3, 8, 1, 0, 5, 1, 5, 8, 5, 9, 3, 0, 7, 9, 6, 0, 8, 6, 6, 7, 0, 1, 7, 2, 4, 2, 7, 1, 2, 1, 8, 8, 3, 9, 9, 8, 7, 9, 7, 9, 0, 8, 7, 9, 2, 2, 7, 4, 9, 2, 1, 9, 0, 1, 6, 9, 9, 7, 2, 0, 8, 8, 8, 0, 9, 3, 7, 7, 6, 6, 5, 7, 2, 7, 3, 3, 3, 0, 0, 1, 0, 5, 3, 3, 6, 7, 8, 8, 1, 2, 2, 0, 2, 3, 5, 4, 2, 1, 8, 0, 9, 7, 5, 1, 2, 5, 4, 5, 4, 0, 5, 9, 4, 7, 5, 2, 2, 4, 3, 5, 2, 5, 8, 4, 9, 0, 7, 7, 1, 1, 6, 7, 0, 5, 5, 6, 0, 1, 3, 6, 0, 4, 8, 3, 9, 5, 8, 6, 4, 4, 6, 7, 0, 6, 3, 2, 4, 4, 1, 5, 7, 2, 2, 1, 5, 5, 3, 9, 7, 5, 3, 6, 9, 7, 8, 1, 7, 9, 7, 7, 8, 4, 6, 1, 7, 4, 0, 6, 4, 9, 5, 5, 1, 4, 9, 2, 9, 0, 8, 6, 2, 5, 6, 9, 3, 2, 1, 9, 7, 8, 4, 6, 8, 6, 2, 2, 4, 8, 2, 8, 3, 9, 7, 2, 2, 4, 1, 3, 7, 5, 6, 5, 7, 0, 5, 6, 0, 5, 7, 4, 9, 0, 2, 6, 1, 4, 0, 7, 9, 7, 2, 9, 6, 8, 6, 5, 2, 4, 1, 4, 5, 3, 5, 1, 0, 0, 4, 7, 4, 8, 2, 1, 6, 6, 3, 7, 0, 4, 8, 4, 4, 0, 3, 1, 9, 9, 8, 9, 0, 0, 0, 8, 8, 9, 5, 2, 4, 3, 4, 5, 0, 6, 5, 8, 5, 4, 1, 2, 2, 7, 5, 8, 8, 6, 6, 6, 8, 8, 1, 1, 6, 4, 2, 7, 1, 7, 1, 4, 7, 9, 9, 2, 4, 4, 4, 2, 9, 2, 8, 2, 3, 0, 8, 6, 3, 4, 6, 5, 6, 7, 4, 8, 1, 3, 9, 1, 9, 1, 2, 3, 1, 6, 2, 8, 2, 4, 5, 8, 6, 1, 7, 8, 6, 6, 4, 5, 8, 3, 5, 9, 1, 2, 4, 5, 6, 6, 5, 2, 9, 4, 7, 6, 5, 4, 5, 6, 8, 2, 8, 4, 8, 9, 1, 2, 8, 8, 3, 1, 4, 2, 6, 0, 7, 6, 9, 0, 0, 4, 2, 2, 4, 2, 1, 9, 0, 2, 2, 6, 7, 1, 0, 5, 5, 6, 2, 6, 3, 2, 1, 1, 1, 1, 1, 0, 9, 3, 7, 0, 5, 4, 4, 2, 1, 7, 5, 0, 6, 9, 4, 1, 6, 5, 8, 9, 6, 0, 4, 0, 8, 0, 7, 1, 9, 8, 4, 0, 3, 8, 5, 0, 9, 6, 2, 4, 5, 5, 4, 4, 4, 3, 6, 2, 9, 8, 1, 2, 3, 0, 9, 8, 7, 8, 7, 9, 9, 2, 7, 2, 4, 4, 2, 8, 4, 9, 0, 9, 1, 8, 8, 8, 4, 5, 8, 0, 1, 5, 6, 1, 6, 6, 0, 9, 7, 9, 1, 9, 1, 3, 3, 8, 7, 5, 4, 9, 9, 2, 0, 0, 5, 2, 4, 0, 6, 3, 6, 8, 9, 9, 1, 2, 5, 6, 0, 7, 1, 7, 6, 0, 6, 0, 5, 8, 8, 6, 1, 1, 6, 4, 6, 7, 1, 0, 9, 4, 0, 5, 0, 7, 7, 5, 4, 1, 0, 0, 2, 2, 5, 6, 9, 8, 3, 1, 5, 5, 2, 0, 0, 0, 5, 5, 9, 3, 5, 7, 2, 9, 7, 2, 5, 7, 1, 6, 3, 6, 2, 6, 9, 5, 6, 1, 8, 8, 2, 6, 7, 0, 4, 2, 8, 2, 5, 2, 4, 8, 3, 6, 0, 0, 8, 2, 3, 2, 5, 7, 5, 3, 0, 4, 2, 0, 7, 5, 2, 9, 6, 3, 4, 5, 0]
>>> def mult(lista):
...     return reduce(mul, lista, 1)
...
>>> mult([])
1
>>> mult([1,2,3])
6
>>> for x in range(1001-5):
...     m = mult(i[x:x+5])
...     if m > maxmult:
...             maxmult = m
...
>>> maxmult
40824

Junio 18, 2009
» Euler 7 (Python)

Enunciado 7

Listando los primeros seis números primos: 2, 3, 5, 7, 11,y 13, podemos ver que el 6° primo es el 13.

¿Cuál es el 10001° primo?

Solución

La solución fue obtenida en el intérprete interactivo de Python 2.5.2:

>>> from math import sqrt
>>> def primo(n):
...     for i in xrange(2,int(sqrt(n))+1):
...         if n % i == 0:
...             return False
...     return True
>>> while i < 10002:
...     if primo(a):
...             i +=1
...     a += 1
...
>>> i
10002
>>> a
104744
>>> a-1
104743

Junio 16, 2009
» Euler 6 (Python)

Enunciado 6

La suma de los cuadrados de los primeros diez números naturales es:

12 + 22 + … + 102 = 385

El cuadrado de la suma de los primeros diez números naturales es:

(1 + 2 + … + 10)2 = 552 = 3025

Así que la diferencia entre la suma de los cuadrados de los diez primeros números naturales y el cuadrado de la suma es 3025 − 385 = 2640.

Encontrar la diferencia entre la suma de los cuadrados de los primeros cien números naturales y el cuadrado de la suma.

Solución

La solución fue obtenida utilizando el intérprete interactivo de Python 2.5.2:

>>> def a(n):
...     s = sum(xrange(1,n+1))
...     a1 = s ** 2
...     a2 = sum([x**2 for x in xrange(1,n+1)])
...     return a1, a2, a1-a2
...
>>> a(10)
(3025, 385, 2640)
>>> a(100)
(25502500, 338350, 25164150)

Python tips

  • Con ** podemos elevar un número a cualquier potencia sin necesidad de importar ningún módulo.
  • Para denotar una tupla solo hacen falta las comas (,), no los paréntesis al principio y al final.

Junio 15, 2009
» Euler 5 (Python)

Enunciado 5

2520 es el menor número que puede ser dividido sin resto por todos los números de 1 a 10.

¿Cuál es el menor número que que puede dividirse sin resto por todos los números de 1 a 20?

Solución

La solución fue obtenida ejecutando el siguiente programa Python 2.5.2:

from math import sqrt
from operator import mul, add

def primo(n):
    for i in xrange(2,int(sqrt(n))+1):
        if n % i == 0:
            return False
    return True

def factorizar(n):
    primos = [x for x in xrange(2,n+1) if primo(x)]
    factores = []
    if n == 1:
        return [1]
    for p in primos:
        if n == p:
                factores.append(p)
                return factores
        if n % p == 0:
                n /= p
                factores.append(p)
                while n % p == 0:
                    n /= p
                    factores.append(p)
    return factores

def mcm(l):
    '''Maximo comun multiplo'''
    ff = [factorizar(i) for i in l]
    singles = list(set(reduce(add,ff)))
    temp = []
    for s in singles:
        temp.extend([s] * max([f.count(s) for f in ff]))
    return reduce(mul,temp,1)

if __name__ == '__main__':
    #print mcm(range(1,11))
    print mcm(range(1,21))

Python tips

  • El módulo operator tiene varias funciones útiles equivalentes a operadores como * y + que pueden utilizarse con funciones como reduce, cuyo primer parámetro es una función.
  • reduce toma una función f de dos argumentos y una lista l. Aplica f a los dos primeros elementos de la lista y obtiene un resultado, luego aplica la función f al resultado con el tercer elemento de la lista, y así sucesivamente hasta consumir toda la lista y retornar el resultado final. Opcionalmente se le puede pasar un tercer parámetro para que la primer llamada a la función f sea aplicada sobre este y el primer elemento de la lista.

Junio 12, 2009
» Euler 4 (Python)

Enunciado 4

Un número palíndromo se lee igual en ambos sentidos. El mayor palíndromo construido a partir del producto de dos números de dos dígitos es 9009 = 91 × 99.

Encontrar el mayor palíndromo que se puede construir como el producto de dos números de tres dígitos.

Solución

La solución fue obtenida en el intérprete interactivo de Python 3.0rc1+. Necesitaba Python 3 para utilizar itertools.combinations:

juanjo@fenix:~$ python3
Python 3.0rc1+ (py3k, Oct 28 2008, 09:23:29)
[GCC 4.3.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from itertools import combinations
>>> tri = range(999, 99, -1)
>>> mults = []
>>> for a,b in combinations(tri, 2):
...     s = str(a*b)
...     if s == s[::-1]:
...             mults.append(int(s))
...
>>> max(mults)
906609

Python tips

  • combinations genera la combinación con los elementos de la lista argumento tomados de a n, si se especifica el parámetro n.
  • En Python 3 print deja de ser una sentencia para convertirse en una función, por lo que siempre debe ser llamado con parámetros.
  • unString[::-1] es un idiom usado para invertir una cadena de texto (en el ejemplo, unString). Se lee: los elementos de unString, desde el principio al final, con paso -1.

Junio 7, 2009
» Euler 3 (Python)

Enunciado 3

Los factores primos de 13195 son 5, 7, 13 y 29.

¿Cual es el mayor factor primo del número 600851475143?

Solución

La solución fue obtenida en el intérprete interactivo de Python 2.5.2:

>>> from math import sqrt
>>> the_number = 600851475143
>>> my_number = sqrt(the_number)
>>> my_number
775146.09922452678
>>> my_number = int(my_number)
>>> my_number
775146
>>> def esprimo(n):
...     for i in xrange(2,int(sqrt(n))+1):
...             if n % i == 0:
...                     return False
...     return True
...
>>> esprimo(8)
False
>>> esprimo(3)
True
>>> esprimo(6823)
True
>>> esprimo(100109)
True
>>> esprimo(100110)
False
>>> for i in xrange(1, my_number+1):
...      if the_number % i == 0 and esprimo(i):
...             print i
...
1
71
839
1471
6857

Python tips

  • xrange, en lugar de crear una lista entera de números como hace range devuelve un generador que va entregando números a medida que los necesitamos.
  • La clase int se instancia para obtener enteros. Si la llamamos con un float como parámetro, podemos usarla para forzar un entero.

Junio 4, 2009
» Euler 2 (Python)

Enunciado 2

Cada nuevo item en la secuencia de Fibonacci es generado sumando los dos términos previos. Empezando con 1 y 2, los primeros 10 términos serían:

1, 2, 3, 5, 8, 13, 21, 34, 55, 89, …

Encontrar la suma de todos los términos pares en la secuencia que no supera los 4 millones.

Solución

La solución fue obtenida en el intérprete interactivo de Python 2.5.2:

>>> MAX = 4000000
>>> def evsum(n):
...     s = 0
...     a,b = 1,2
...     while True:
...         if a >= n:
...             break
...         if a % 2 ==0:
...             print a, " ",
...             s += a
...         a,b = b,a+b
...     return s
...
>>> evsum(MAX)
2   8   34   144   610   2584   10946   46368   196418   832040   3524578
4613732

Python tips

  • La asignación múltiple es un idom muy cómodo: a,b = 1,2
  • Si agregamos una coma final a la enumeración de objetos a ser impresos con print, se logra el efecto de que no se imprima el salto de línea (\n) final.

Mayo 28, 2009
» Euler 1 (Python)

Project Euler es un sitio web que reta a los programadores a resolver problemas matemáticos mediante código. Me parece entretenido. Voy a ir resolviendo problemas y posteando mi solución en Python acompañada de comentarios sobre el código que puedan servirles a quienes están empezando a aprender el lenguaje.

Enunciado 1

Si listamos todos los números menores a 10 que son múltiplos de 3 o 5, obtenemos 3, 5, 6 y 9. La suma de esos múltiplos es 23.

Encontrar la suma de todos los múltiplos de 3 o 5 menores a 1000.

Solución

La solución fue obtenida en el intérprete interactivo de Python 2.5.2:

>>> def mults(n=10):
...     r = []
...     for i in range(1, n):
...             if i % 3 == 0:
...                     r.append(i)
...             elif i % 5 == 0:
...                     r.append(i)
...     return r
...
>>> mults()
[3, 5, 6, 9]
>>> sum(mults())
23
>>> sum(mults(n=1000))
233168

Python tips

  • En la definición de la función mults se incluye un argumento por defecto n con valor 10. Cuando más adelante se llama a esta función sin parámetros, n toma el valor por defecto.
  • La función range, incluida en el lenguaje devuelve una lista de números sobre la que se puede iterar. Muy útil para usar con la estructura for. Más información haciendo help(range) en el intérprete interactivo.

Mayo 4, 2009
» Intercambio de valores rápido en Python

Cuando empecé a cursar Ingeniería en Sistemas en el año 2003, tuvimos una materia llamada Algoritmos y Estructuras de Datos. La semana del curso estaba compuesta por una clase teórica, una clase práctica y una clase “especial” dictada por un docente de apellido Marina que tenía como objetivo hacernos pensar resolviendo problemas; en las primeras clases ni siquiera programábamos.
El lenguaje de programación de la materia era C y en una de las clases, este docente recordaba risueño que un alumno había querido intercambiar el valor de dos variables
int a = 1;
int b = 2;
haciendo:
a = b;
b = a;
El error es evidente; en a se copia el valor contenido en b (2) pisando el valor original (1) y al ejecutarse la segunda sentencia, el nuevo valor de a (2) es copiado en b.

La siguiente tabla muestra los valores que van tomando las variables a y b:

La forma correcta de intercambiar los valores habría sido utilizando una variable auxiliar en la cual mantener uno de los valores:
int aux;
int a = 1;
int b = 2;
aux = a;
a = b;
b = aux;
La siguiente tabla muestra los valores que van tomando las variables aux, a y b:

Lo gracioso del asunto es que unos años más tarde conocí otro lenguaje de programación, Python.

En Python un tipo de dato que viene con el lenguaje es la tupla. Una tupla es una secuencia (sus elementos tienen orden) inmutable (no se puede cambiar su tamaño o contenido) que puede tener dentro objetos de distinto tipo. Un ejemplo de tupla en Python (contiene tres números y dos cadenas de texto):

(1, 2, "tres", 4, "Juan")

La forma de apuntar a ese objeto desde una variable es simplemente:

a = (1, 2, "tres", 4, "Juan")

Aunque podemos obviar los paréntesis y de todas formas funcionará. Decimos que la tupla es empaquetada:

a = 1, 2, "tres", 4, "Juan"

De forma similar, podemos desempaquetar la tupla en nuevas variables:

b, c, d, e, f = a

La condición es que el número de variables en el lado izquierdo del operador = coincida con el número de elementos en la tupla.

La siguiente sentencia, empaqueta y desempaqueta:
x, y, z = "Juan", 100, 1

Y es equivalente a:
x = "Juan"
y = 100
z = 1

Finalmente, esta propiedad del lenguaje nos permite intercambiar rápidamente los valores de 2 (o n) variables:
a = 1
b = 2
a, b = b, a

Así, lo que un alumno despistado quiso hacer en 2 sentencias y Marina mostró que se hacía correctamente en 3, yo lo hago en 1 :)

Enero 3, 2009
» Los chicos malos

“Esto es lo que ocurre con la gente que piensa que odia las computadoras. Lo que realmente odia es a los malditos programadores”
— Larry Niven

Por suerte muchos mortales aún no saben de nuestra existencia :-).

Larry Niven, nacido en la ciudad de Los Angeles (EE. UU.) en 1938, es un escritor de ciencia ficción estadounidense. Conocido sobre todo como el autor de la serie Mundo Anillo y también por el universo creado bajo el nombre de Espacio Conocido (Known Space), el éxito de su carrera como escritor de ciencia ficción lo acreditan sus varios premios Hugo y Nébula. Se ha dedicado a la escritura profesionalmente desde 1963.

La mayoría de las historias de Niven tienen lugar en un universo de ficción denominado “Espacio conocido”, que presenta un escenario futuro en el que la una humanidad ultratecnificada comparte los mundos de diversos sistemas cercanos al Sol con más de una docena de razas alienígenas entre las que se incluyen especies como los agresivos kzin o los cobardes titerotes de Pierson, los subyugados kdatlyno o los pulpoides Jotoki. Muchos alienígenas son encarnados en personajes que, con frecuencia, acompañan a los protagonistas o son los propios protagonistas de las novelas de Niven.

Fuente: Wikipedia

Fans club del autor: http://www.larryniven.org

Este post es parte de Citas sobre programación.

Enero 2, 2009
» Nosotros, los programadores

“La mayoría de ustedes están familiarizados con las virtudes del programador. Son tres, por supuesto: pereza, impaciencia y orgullo desmedido”
— Larry Wall

De las tres, la pereza es la más importante. Nos impulsa a resolver problemas. Muchas veces me encuentro escribiendo programas con el objetivo de evitar hacer tareas repetitivas, difíciles de hacer “a mano” o aburridas.

Larry Wall (nacido el 27 de septiembre de 1954) es un programador, lingüista y autor, más conocido por haber creado el lenguaje de programación Perl en 1987.

Wall es el autor del programa rn (lector de artículos de Usenet) y del casi universal patch. Ha ganado el IOCCC (concurso internacional de código C ofuscado) dos veces y recibió el primer premio de la Free Software Foundation para el avance del software libre en 1998.

Más allá de sus habilidades técnicas, Wall es conocido por su irónico sentido del humor, que manifiesta en sus comentarios en el código fuente o en Usenet. Por ejemplo (traducción libre): “No me gusta hacer cosas estúpidas, excepto si son a propósito”.

Fuente: Wikipedia

Este post es parte de Citas sobre programación.

Enero 1, 2009
» Citas sobre programación

A partir de hoy, 1º de enero, van a ir apareciendo durante siete días seguidos en este blogs citas, principalmente relacionadas con el acto de programar, que en muy pocas palabras encierran conceptos muy importantes: a veces superficialmente divertidos y otras más profundos. Además de la cita, voy a completar los posts que aparezcan con información del autor, links, fotos o alguna que otra anécdota para ilustrarla.

La primera es de Alan Kay.

“La mayoría del software actual es muy parecido a una pirámide egipcia, con millones de ladrillos puestos unos encima de otros sin una estructura integral, simplemente realizada a base de fuerza bruta y miles de esclavos”
– Alan Kay

Querido programador, espero que nunca te encuentres bajo el látigo construyendo una pirámide :).

Alan Kay, es un informático estadounidense, conocido por su trabajos pioneros en la programación orientada a objetos y el diseño de sistemas de interfaz gráfica de usuario. Kay colaboró en la creación de Squeak, un entorno para la creación y experimentación multimedia en 1995 mientras trabajaba en Apple y todavía sigue colaborando con el proyecto.

Fuente: Wikipedia