A Django site.
November 18, 2007

Gustavo Picón
tabo
tabo :: para todos y para nadie
» Optimizando solución a problema de edificio de Google

Hace una semana publicaba la solución a un problema de entrevista tipo que hacen en google, la pregunta era la siguiente:



La solución que publiqué no solo daba la solución si no que brindaba los pisos desde los que se debía arrojar los objetos. Antonio Ognio complementó mi solución con una muy buena explicación del problema.

Ya había dado por cerrado el tema, hasta que Eduardo Morales, el ingeniero de Google que presentó el problema, dejó unos comentarios interesantes.

El principal reparo de Eduardo con mi solución es que no es eficiente. Es un algoritmo "O(n^2)". Como le comentaba a Eduardo, no era mi propósito hacer una solución eficiente, solo necesitaba una solución y nada más. La optimización prematura es la raiz de todos los males mencioné parafraseando a Knuth, y en este caso no necesitaba de ninguna optimización, ya que el enunciado del problema no pide un algoritmo óptimo (solo pide hayar una solución rompiendo el menor número de objetos). Para este problema, en mi opinión, optimizar representaba un costo (mi tiempo) y ningún beneficio.

Pero al mencionar Eduardo que el problema se puede optimizar hasta O(1), pues me pareció un buen ejercicio, y la optimización de código, cuando es estrictamente necesaria, puede ser bastante gratificante. Tenía entonces ahora un beneficio para optimizar: podía publicar el proceso de optimización, dedicado especialmente para aquellos que mostraron interés en mi solución original (y varios al parecer, según me comentan por privado, están leyendo a Knuth :-)

Así que veamos el proceso de optimización, si no lo han hecho, pediría que lean primero mi (ineficiente) solución original y la explicación detallada de Antonio.

Comencemos entonces por la primera optimización:

Problema edificio google: O(n)

Gracias a este algoritmo tenemos esta solución en Python:

def findworst(num):
for res in range(1, num+1):
if res*(res+1)/2 >= num:
break
return res
que es una solución O(n)

Pero esto se puede optimizar aún mas, como podemos apreciar:

Problema edificio google: O(1)

Lo que nos deja con este código en Python:

def findworst_o1(num):
return math.ceil((math.sqrt(num*8+1)-1)/2)



que es una solución O(1), constante, y en una línea de código.

Podemos sacar algunas lecciones con todo esto:

  1. La optimización prematura no es necesaria. El algoritmo original, a pesar de no ser óptimo, nos daba una solución correcta. El costo de optimizar (tiempo) era mas alto que los beneficios (nulos). Esto cambió con los comentarios de Eduardo ya que apareció un beneficio: mostrar el proceso de optimización para los lectores.
  2. Tener una base matemática es muy importante. De no haber aplicado matemáticas la solución se hubiera hallado con "fuerza bruta" pero no con eficiencia.
Muchas gracias Eduardo por tus comentarios, espero que estos posts despierten el interés de mis lectores técnicos para investigar estos temas. Y para mis lectores no técnicos (se supone que este es mi blog no-nerd), mil disculpas, prometo volver pronto a la normalidad ;-)

Comentarios?

tags: , , , , , , , , ,

» Solucion a quiz de google

Para hacer la historia corta:

Soplín fue a una charla de Google y publicó un slide con una pregunta típica de las entrevistas laborales en Google:



Este quiz provocó un total alboroto chichero solucionando el problemita. Yo había publicado ya un rudimento del algoritmo y la respuesta, pero había dejado pendiente detallar la solución, asi que aqui va:

Algoritmo de solucion a problema de entrevista de google (edificio)

Y la solución programada y lista para usar:

#!/usr/bin/env python

def findsteps(numpisos):
res = 1
while True:
l = []
val = 0
for step in range(res, 0, -1):
val += step
if val >= numpisos:
l.append(numpisos)
break
l.append(val)
if val >= numpisos:
break
res += 1
return l

if __name__ == '__main__':
import sys
if len(sys.argv) > 1:
try:
numpisos = int(sys.argv[1])
except ValueError, errmsg:
sys.stdout.write('ERROR: num de pisos debe ser un entero\n')
sys.exit(-1)
else:
numpisos = 100
if numpisos < 1:
sys.stdout.write('ERROR: num de pisos debe ser un >= 1\n')
sys.exit(-1)
print '# Pisos-intervalo para edificio de %d pisos: \n' % (numpisos,)
res = findsteps(numpisos)
print res
print '# %d intentos en el peor escenario' % (res[0],)



Con este programita pueden encontrar la solución óptima para un edificio de cualquier altura, pero veamos los pasos necesarios para el edificio de 100 pisos del problema original:


# Pisos-intervalo para edificio de 100 pisos:
[14, 27, 39, 50, 60, 69, 77, 84, 90, 95, 99, 100]
# 14 intentos en el peor escenario


Cumplido mis queridos chicheros, ahora espero que Soplín cumpla su promesa de publicar las otras preguntas!

(y creo que es aparente que si las empresas locales hicieran este tipo de preguntas en vez de "tiene un mcse?", el nivel de empleo local sería CERO!)

Por cierto: GRACIAS TIO KNUTH! No hubiera podido resolver esto sin ti!

Actualización: Antonio Ognio, demostrando sus capacidades de docente, hace una explicación for dummies del algoritmo del problema. Denle una mirada si no la captaron con mi dibujito y el código en Python ;-)

Actualización2: Optimizaciones, algoritmo O(n^2) es ahora O(1)

tags: , , , , , ,

November 13, 2007

Gustavo Picón
tabo
tabo :: para todos y para nadie
» Ateismo y Algoritmos (Knuth es fundamental)

El fin de semana sin querer me metieron en yet another discusión sobre religión en donde empezaron a meter a la Biblia. Para variar, esta persona, MUY RELIGIOSA, no había leido la Biblia mas alla de las partes lindas, asi que no andaba muy enterada del comportamiento real de su propio dios en las partes no-lindas, que es muy bien descrito por Mr Dawkins como misógino, homofóbico, racista, infanticida, genocida, filicida, pestilente, megalomaníaco, sado-masoquista, caprichoso y malévolo matón. Al final, un tercero presente en la discusión le dijo algo así como "mejor discute cuando hayas leido la Biblia". Que alguien me explique la ironía de un creyente que no lee su propio libro sagrado y un ateo que lo lee para asombrarse de las barbaridades en las que cree la gente.

EN FIN.

Ese "mejor lee el libro sagrado antes de opinar" me hizo pensar en las N discusiones sobre algoritmos y cosas de programación que he tenido durante años. También en las soluciones totalmente delirantes que han dejado en el blog de Soplín como respuesta al problema de Google sobre el que escribí hace unos días.

Asi que voy a implementar una nueva House Rule, que llamaremos la ley de tabo para la ociosidad mental cada vez que discuta con alguien:

  1. Si discutes sobre la biblia, y no la has leido, no esperes que te tome muy en serio.
  2. Si discutes sobre algoritmos, y no has leido a Knuth, no esperes que te tome muy en serio.

Asi como leer la biblia cuando niño me hizo abrir los ojos sobre la religión, el leer a Knuth me abrió un mundo fascinante lleno de belleza, exactitud y perfección.

Asi que desde este blog, que se supone es mi blog no-nerd, quiero hacer un pequeño homenaje a este gran hombre que cambió mi manera de verlo todo (colgándome de un homenaje que le acaba de hacer XKCD).

Homenaje a Donald Knuth por XKCD

KNUTH ES FUNDAMENTAL!

tags: , , , ,