martes, 13 de mayo de 2014

TuentiChallenge4: Diario de un developer yonki (3): Ejercicios más chungos y conclusiones

¡OJO!: Esta entrada es la última parte de una saga que empieza en:
TuentiChallenge4: Diario de un developer yonki (1)

Los fuentes Java de mis soluciones están disponibles en Github.

Día 7

Querido diario:

Hoy el día ha sido muy largo. O quizá debería decir la noche. Después del bajón del día de ayer, decidí que lo mejor que podía hacer era descansar muchas horas y dedicar la noche a hacer un ejercicio más, ¡pero hacerlo bien!. Así que dediqué la mayor parte del día a descansar y a la tranquila vida familiar.

A última hora de la tarde, encendí el ordenador y le reté a un duelo de miradas. Esta vez iba a darlo todo.

de vergag.com

Entonces me puse con el ejercicio 14, Train Empire, que propone un juego de trenes con combustible limitado, en el que se incluyen rutas, estaciones y vagones con puntuaciones si consiguen alcanzar una estación de destino. Se trata de obtener la máxima puntuación posible a partir de un estado inicial dado. El ejercicio ha confirmado que estamos ya en fase chunga, y hay que darle bastantes vueltas para resolverlo.

He planteado la resolución en dos fases. En la primera, por cada vagón obtengo todas las posibles combinaciones que llevarían a que ese vagón llegara a su destino, sin tener en cuenta la estación en la que comience el tren. En la segunda, pruebo todas las permutaciones de las posibilidades de cada estación, probando también a cambiar el orden en el que se obtendrá cada vagón. Al hacerlo, recorro antes las posibilidades que exploran primero los vagones con más puntuación, porque así es más fácil obtener rápidamente una solución buena. En cuanto una permutación no sea ya capaz de mejorar la mejor puntuación obtenida hasta el momento, se descarta.



Esta prueba de cada permutación tiene una sutileza con la que hay que tener cuidado: al mover un tren anterior, puede que en parte de su camino no necesite llevar ningún vagón con puntos, por lo que cabe la posibilidad de que el tren esté libre para mover un vagón en su recorrido y dejarlo en alguna estación intermedia. Así que en dicho caso hay que ver cuál de esas estaciones va a ser más adelante la más cercana a su destino, y considerarlo para la situación inicial del siguiente tren. Tengo la impresión de que esta sutileza era la gran dificultad del ejercicio, y que puede hacer que mucha gente no resuelva bien el ejercicio.

En el enunciado se dice que no va a haber más de 2 trenes, por lo que seguramente exista alguna solución más sencilla que la mía que tenga en cuenta esto. La mía es genérica, valdría lo mismo para 2 trenes que para más, aunque por supuesto el rendimiento se resentiría mucho en caso de haber muchos trenes.

Al ejecutarlo crucé los dedos para ver si era lo suficientemente rápido, pensando que el hecho de que solo hubiera 2 trenes debería ser suficiente, y efectivamente ha ejecutado la entrega en 10 segundos. Muy satisfecho con mi solución, a pesar de no ser demasiado elegante, llegó el momento que ya había vivido varias veces estos últimos días: las tantas de la noche, agotado, lo normal sería irse a dormir, aunque eso supusiera ya el final del concurso. Pero ains, volví a caer... me he leído el enunciado del siguiente ejercicio y como buen developer yonki... ¡tenía que hacerlo!.


Y tenía que hacerlo porque el ejercicio 15, Take a corner, es... ¡¡¡un Othello!!!, o sea... ¡¡¡un Reversi!!!. ¡¡¡Me encanta el Reversi!!!. ¡Con mi primer ZX Spectrum, hace ya potorrón de siglos, venía de regalo un juego de Reversi!. Pero es que hay más... ¡YO tengo programado un juego de Reversi!. Lo hice hace un montón de años para JavaME, y lo pasé a Android el año pasado.

Mi Reversi, ¡snif!

En el ejercicio se plantea una solución inicial y se pide qué movimiento hay que hacer para que en N jugadas más, haga lo que haga el contrario, se gane una esquina. Mi juego es malo con ansia, así que no cubría esa posibilidad, pero sí he aprovechado para copiar el código de gestión del tablero de Reversi y que obtiene los posibles movimientos a partir de una situación. Una vez teniendo eso, he hecho una sencilla exploración de todas las posibilidades, considerando que cuando le toca mover al jugador inicial basta conque un movimiento sea exitoso, y cuando le toca mover al contrario tienen que serlos todos.

Estaba tan emocionado ante la posibilidad de reutilizar el mismo código por tercera vez (soy un gran fan de la reutilización) que me recreé especialmente en la solución. ¡Y qué demonios!, ¡¡¡se lo iba a contar a mi amigo el revisor de Tuenti!!!

/**
 * Dear Tuenti Engineer:
 * I've programmed a solution a bit more elegant this time, thinking that this one
 * was going to be the last. I'm not 100% sure, although it's almost 6:00 in the
 * morning and I think this week has been exhausting enough.
 * Thanks for your work and please keep doing things like this.
 * I need a bed. Now!
 * Good night!
 */


Ahora ya sí, con mi consciencia perdiéndose en ovejillas saltando vallas, ¿qué debería haber hecho?: dormir. ¿Qué he hecho?: pffff, está claro... ¡leerme el siguiente ejercicio!


Y así he llegado al ejercicio 16, ÑAPA. Y, ¡ay!... me volví a picar. El ejercicio se trataba de calcular cuántos círculos intersectan entre un mogollón que te dan (potencialmente millones). La solución obvia era... ¡tan obvia!. Recorrerlos todos entre sí y hacer un sencillo cálculo de colisiones, aplicando para ello el teorema de Pitágoras... sí, ese mismo que habría hecho bien en aplicar en el ya lejano ejercicio 3 en lugar de las malditas interpolac... ¡¡¡AGH, NO QUIERO PENSAR EN ESO!!!.


El caso es que... qué demonios, igual no había trampa. Igual en Tuenti querían premiar a la gente que había llegado hasta aquí y ponerles algo facilón. Las ovejas me decían que no había otra solución posible. Y, bueno, me daba tiempo a probar. Los tests iniciales me funcionaban suficientemente rápido. ¿Qué pasaría con la entrega?. Por supuesto, tenía que compartir esto con mi amigo el revisor de Tuenti:

/**
 * Dear Tuenti engineering:
 * 
 * Ouch! I shouldn't have read this challenge... just when I was dreaming on my
 * feet and ready to go to bed, I had the terrible idea of reading it. And...
 * bad idea, really really bad idea, because it's quite easy! Actually, I think it's
 * the easiest challenge!... unless you pretend to process the 8 million points in
 * a reasonable time and there's a hidden trick, but I don't think so (maybe 
 * that's because I'm almost asleep). I'll see it right now. I'm scared. If
 * there's a trick, you are very clever, my friend... hmmm maybe "painting" the
 * points in a grid with the limited 100x100 space, maybe?, and so iterating
 * points in order N -and not N!-, and after that iterating the 100x100 points?...
 * yeeks, I'll better not think on it, it's late!.
 * 
 * I'll try as well to NOT reading the next challenge. Seriously. Promised. Or so.
 * I don't think I have enough time to solve it, anyway...
 * 
 * P.S.: Ooooooooook, I got it! I have and idea, will I correct it in time???
 * 
 * Sincerely,
 * @author andres
 */

Probé y... nada. Se tiraba mogollón de tiempo (ni sé cuánto, pero apuesto a que horas). Como se puede ver al final del comentario, dejé de escuchar a las ovejas y se me ocurrió una solución. Tampoco era demasiado complicado de hacer, aunque el tiempo se me estaba acabando, incluso aunque no durmiera nada.

Se trataría de dividir el espacio, que tiene unos límites definidos (y que no era ni mucho menos 100x100 como pongo en el comentario, prueba inequívoca de que estaba ya en babia), en varias zonas cuadradas. Cada cuadrado se recorre enterito combinando todos los círculos que tenga dentro. Al pasar al siguiente cuadrado, se guardan en un hash las colisiones que se han detectado, porque los mismos dos círculos que colisionan en una zona pueden colisionar también en la siguiente, y no queremos contarla dos veces. Para que el hash no tenga demasiados elementos, calculamos el rectángulo que contiene la intersección de la colisión, y cuando estemos en la zona que contiene la esquina inferior derecha, lo quitamos del conjunto hash. Esto es así porque las zonas las recorría de arriba a abajo y de izquierda a derecha.

Conseguí que la ejecución se hiciera en solo unos segundos, pero al hacerlo el resultado dejó de ser correcto. Creo que la solución que he planteado está muy bien y seguramente sea "la buena", pero he debido hacer algo mal en la implementación. Posiblemente al dividir el espacio en zonas, no sé.

Ya no podía seguir, se me había acabado el tiempo, a pesar de que al final no he dormido nada. Me ha fastidiado no poder entregar correctamente el ejercicio, porque creo que ya casi lo tenía, pero así es la vida...


Conclusiones

El concurso es... mortal. Requiere muchas energías, son demasiados ejercicios, y no son sencillos. Incluso aunque le dediques solo ratos sueltos, si tienes un trabajo exigente y poco tiempo libre, te va a dejar agotado. Mi gran problema, además, es que cuando leía un ejercicio me picaba, independientemente de la hora que fuera. Y si algo he aprendido en este concurso es que cuando llegas a cierto nivel de cansancio y falta de sueño es mejor parar, porque las soluciones que encuentres no van a ser buenas, y te va a costar mucho pensar.

Personalmente preferiría que el concurso tuviera pocos ejercicios y que fueran los más difíciles. Que cada ejercicio que resuelvas tenga su mérito. Solo eso ya es suficiente para hacer un concurso chulo.

Aparte de eso, tengo que decir que el concurso es también muy interesante. Los ejercicios, aparte de algún enunciado ambiguo o no suficientemente definido, están bastante bien, y algunos son realmente divertidos de resolver.


Por otra parte, mi crítica va también a la forma en la que estoy viendo que Tuenti trata el concurso una vez acabado. Mientras estábamos concursando teníamos un ranking con el número de ejercicios que había entregado cada uno, aun sin saber cuántos estaban bien o mal. En cuanto el concurso acabó, el ranking desapareció. Vale que se supone que la puntuación final tiene un componente subjetivo que le dan los revisores de Tuenti a la limpieza de cada solución, pero creo que un simple ranking automático en base al número de ejercicios resueltos por cada uno nos hubiera encantado a todos los participantes. Aunque luego no fuera definitivo y los ganadores no tuvieran por qué ser los primeros puestos de dicho ranking. Creo que basta con dejarlo claro. Es que así es tan... ¡cortarrollos!

Por mi parte, en el ranking provisional de ejercicios entregados sin corregir creo recordar que quedé en el puesto 25. Luego por email me han confirmado que estoy entre los 50 primeros, aunque no haya aún un ranking definitivo (que no tengo muy claro que al final vaya a existir).

No me siento especialmente orgulloso de mi participación, creo que he hecho demasiados ejercicios con demasiado sueño, y quizá debería haberme centrado en hacer menos ejercicios pero con más calma y energías. Pero sí estoy contento con cómo planteé los últimos ejercicios que hice, los que comento en esta tercera parte del mega-artículo. Y oye, quedar entre los 50 primeros está bastante bien.

Pero qué demonios, aun con todo, tengo que decir que lo más importante es que me lo he pasado genial.

de protocoloipv6.blogspot.com

viernes, 9 de mayo de 2014

TuentiChallenge4: Diario de un developer yonki (2): la cosa se pone chunga

¡OJO!: Esta entrada es continuación directa de
TuentiChallenge4: Diario de un developer yonki (1)

Los fuentes Java de mis soluciones están disponibles en Github.

Día 4

Hoy me he puesto otro rato con el concursillo de marras, para no variar.

Primero he empezado con el ejercicio 5, Tribblemaker, que se trata de implementar el Juego de la Vida (aunque no lo decían explícitamente, pero se daban pistas más que obvias), y detectar ciclos en la evolución. El ejercicio resultaba bastante entretenido de programar y daba para hacer código ordenadito, así que me he recreado en eso.

El siguiente, el ejercicio 6, Man in the Middle, me ha encantado. Se trataba de crear un servicio que se metiera en medio de la comunicación encriptada entre un cliente y un servidor, basada en claves que se van intercambiando entre ellos.


Para poder resolverlo, se proporciona el código fuente tanto de la parte cliente como de la parte servidor... en Javascript, o sea, NodeJs. Para alguien con conocimientos de seguridad y que sepa NodeJs imagino que el ejercicio estaba chupado. Para los que no, el ejercicio resultaba realmente divertido. Y mira que yo de criptografía ni flowers, nada de nada.

El ejercicio se podía hacer sin problemas en otros lenguajes, pero teniendo ya los fuentes en Javascript, lo normal es que sea mucho más sencillo resolverlo así. De esta forma, se trata de instalar NodeJs, ver cómo funciona, probarlo, revisar ambos códigos fuentes, hacerte tus esquemas de cómo funciona su intercambio de claves, y finalmente programar la solución, que básicamente se hace mezclando el código del cliente y el del servidor. Podría hacerse incluso sin saber Javascript ni nada de criptografía, que es lo que me parece más genial de este ejercicio. La clave en mi caso para que todo resultara más fácil fue crear un objeto diferenciado para el cliente y otro para el servidor, de forma que todo se hace bastante lógico y comprensible. Crecidito por lo bien que se me estaba dando el día, no he parado ahí.

El siguiente ha sido el ejercicio 7, Yes we scan, en el que se trata de encontrar una relación entre dos elementos a partir de un montón de conexiones. Temía que ya tuviera que ir pensando más en temas de rendimiento y algorítmica. Sin embargo, la verdad es que sólo con usar un par de hashes y tener un poco de cuidado con la forma en la que se obtienen nuevas conexiones indirectas por cada conexión nueva, conseguí que la prueba de entrega se resolviera en solo 10 segundos.


Y entonces me he crecido: ¡leche, en cuanto he dormido un poco qué bien me ha ido todo!. Eran ya las 3 y pico de la mañana, así que llegó ese momento que también conocen los jugadores de poker que están en racha: el momento de retirarse y continuar otro día. Por supuesto... ¡yo no lo hice!.

Así que toma porrazo con el ejercicio 8, Tuenti Reestructuration. Se trata de reorganizar posiciones de personas en mesas, basadas en permutaciones, hasta llegar a una situación final. O sea, segundo momento importante de la noche: ese en el que me doy cuenta de que posiblemente me encuentre ante un ejercicio típico de recorrido de caminos posibles, de esos que en algorítmica tienen tan trillados, pero que yo nunca me entero de cómo lo resuelvo. ¡Ains, ya estoy como siempre!

Lo peor es que el enunciado me ha parecido muy confuso, no deja muy claro cuáles son los movimientos posibles, así que estoy perdiendo muchísimo tiempo sólo para enterarme... y ya se está haciendo de día. ¡Mierda, con lo bueno que era el día! A dormir.


Día 5

Esto de dejarse un ejercicio a medias no mola nada, he estado todo el tiempo dándole vueltas al dichoso ejercicio hasta que me he podido poner con él. Por fin estoy seguro de qué movimientos son los válidos, y le he puesto las heurísticas que se me han ido ocurriendo para que no fuera demasiado lento: probar primero el camino que se acerque más a la solución, control para dejar de recorrer un camino cuando ya tengamos uno mejor, detectar estados ya recorridos... total, que entre unas cosas y otras me he tirado un montón de tiempo con el tema. Al final la entrega se ha tirado varios minutos de ejecución, así que imagino que habrá soluciones mejores, pero para no saber nada de algorítmica creo que ha quedado bastante decente. Eso sí, esto está empezando a complicarse de verdad.

Esto lo confirmó el ejercicio 9, Bendito Caos, que tenía tela. Se trataba de averiguar cuántos coches pueden llegar en una hora desde un punto a otro, calculándolo a partir de las velocidades de los caminos entre cada par de vértices. En este caso estoy aún más seguro de que existen algoritmos que implementan esto sin problema. Pero a mi me iba a tocar hacerlo a lo bruto.

Me ha llevado un rato sacar las reglas de mezcla de las velocidades, para saber cómo se puede calcular la velocidad global entre el vértice de inicio y el de fin, combinando las de todos los caminos posibles. También había que tener cuidado con los bucles. Pero sobre todo no tenía ni idea de cuál sería el rendimiento de mi sencilla solución. En el ejemplo iba rápido, pero el enunciado de este ejercicio no era, la verdad, demasiado bueno. No sólo la explicación era un poco confusa (no tanto como el anterior pero casi), sino que sobre todo, no dejaba claro en ningún momento cuáles eran los límites en número de nodos y de caminos. ¡Tercer WTF del concurso!

Yo, siempre optimista, lo interpreté como que eso sería que no le iban a meter mucha caña. Gran error. Lo puse a ejecutar y eso seguía y seguía y no acababa. ¿Qué pasaría si lo cortaba a medias e intentaba arreglarlo?. Hice la prueba y vi que aparentemente se podía. Hice un cambio en la línea de comando para obtener más información y lo volví a ejecutar. Grandísima cagada. Me equivoqué al poner la línea de comando, así que lo ejecuté de forma incorrecta, pero la entrega se consideró válida.

Por culpa del ejercicio casi llego tarde al cine, donde pude desengrasar un poco mis pobres neuronas viendo a Spider-man pegando tortazos a troche y moche. Mano de santo, oiga, que el dolor de cabeza que se me había quedado hoy era tremendo.

Spidey sí que sabe cómo hay que enfrentarse a los Challenges del Tuenti
¡¡¡A tortazos!!!

Al volver a casa le he echado un vistazo al siguiente ejercicio, con la firme intención de no ponerme con él. Y ha resultado ser un WTF con todas las de la ley. A ver si mañana entiendo algo, porque hoy lo veo realmente negro.


Día 6

El ejercicio 10, Random Password, es tan tan tan WTF, que el enunciado apenas dice: 

It seems to be a random password... how could it be?
Get the key for your input. Start at: http://random.contest.tuenti.net/?input=INPUT

¡¡¡¡¿¿¿Eeeeeeeeeeeeeeeeeeeeeeeeeeeeh???!!!! Espera que lo lea otra vez... sí. Ya veo. Entendido. Entendido que no entiendo nada, quiero decir. Probé a mirar el código fuente del servidor y poco más se me ocurrió. Como ya he dicho, no tengo ni idea sobre seguridad, que es de lo que obviamente trataba esto, así que tras estar un buen rato dándole vueltas, lo descarté.

El ejercicio 11, Pheasant, insiste en la seguridad. ¡Otra vez!. Aunque en este caso parece que algo se puede hacer sin saber nada de encriptación. Se trata de averiguar una clave AES en la que faltan 3 posiciones, a partir de datos conocidos. Lo único que se me ha ocurrido es probar todas las combinaciones en esas 3 posiciones hasta dar con la buena. En lugar de hacerlo con el fichero entero, creo que lo importante es hacerlo solo con los 32 primeros bytes, que he visto que era suficiente en cualquier caso según los límites dados, y que agilizaba muchísimo el proceso. Al hacer la entrega he visto que se ha tirado bastantes minutos, pero sin conocer cómo funciona el AES creo que era imposible hacer nada mejor. También sospecho que la implementación de AES que he usado, que es la que viene por defecto en Java (JCE), debe ser bastante lenta.

El ejercicio 12, Taxi Driver, volvía a ser algorítmico. Es más, en el fondo el problema era muy muy similar al número 8, el de la reestructuración de mesas que tanto tiempo me llevó y que no me quedó demasiado rápido, y que seguro que conociendo los algoritmos típicos se hace en un momentín... ¡¡¡Otra vez el mismo problema de siempre, el que he hecho millones de veces y nunca bien!!!.


He entrado en tal estado de enajenación que he decidido comunicarle mi frustración a un posible corrector. Así que he puesto este comentario en el código, con un par:

/**
 * NOTE
 * ===============
 * 
 * Dear Tuenti Engineer:
 * 
 * Oh, no, the same problem... again! This is almost the same as challenge 8!
 * I'm pretty tired of doing the same problem, and not finding a really GREAT
 * solution to avoid loops in a proper way and find good heuristics (I could
 * swear I've found it also other times in my past... in Google Code Jam, maybe?).
 * 
 * This time, I've decided to program a reusable solution, in the form of this
 * PathFinder class. It's a pity I can't use it for challenge 8 yet, but I'm
 * in the hope that I can find this same problem again. Call it a longshot if
 * you may.
 * 
 * I'm losing some precious minutes in this, but I'm sure you will appreciate
 * it. Enjoy it, my friend.
 * 
 * @author andres
 *
 */

He hecho una preciosa clase PathFinder capaz de resolver todos estos problemas similares. Como ya he dicho, la falta de sueño y el dolor de cabeza que me habían causado los problemillas me han hecho entrar en un grave estado de enajenación. Y tanto, no sabía hasta qué punto...

El caso es que al ejecutar la entrega, sintiéndome en pleno deja vú, veo que eso sigue ejecutando... y sigue ejecutando... y sigue ejecutando... y no para. Mato el proceso, cambio la línea de comando, vuelvo a ejecutar y... adivina.

¡¡¡Sí!!!. ¡¡¡Vuelvo a equivocarme al modificar la línea de comando!!!.

Otra entrega a freír espárragos. Para una vez que me pongo a hacer una clase más genérica, primero la hago demasiado lenta y luego la dejo a medias por pura torpeza... qué grande.

Ejercicio 13, Tuenti Timing Auth.Con los ojos ardiendo en fuego, miro el siguiente ejercicio, con la esperanza de que sirviera para redimirme. ¿Y qué encuentro?.

¡¡¡Otro ejercicio de seguridad, similar al otro que me salté!!!
(en este caso sobre "side channels", tema sobre el que sé lo mismo que el anterior, o sea, nada).

No me lo podía creer.

Tras darle vueltas al tema la correspondiente ración de tiempo inútil, desistí.
¡¡¡¡¡WTF doble, diablos!!!!!

Al rato me levanté, tembloroso, casi sin fuerzas. En la espuma a mis pies yacían dos mundos muertos. Con mi propósito casi olvidado tras el torbellino de violencia, miré estúpidamente a la pantalla. Al poco, recuperé mi raciocinio. Buscaba venganza. ¿Podía aprovechar de alguna forma las circunstancias?...



¡OJO!
: Esta entrada continúa en:





miércoles, 7 de mayo de 2014

TuentiChallenge4: Diario de un developer yonki (1)

Los fuentes Java de mis soluciones están disponibles en Github:
https://github.com/andresviedma/tuentichallenge4

Día 0

Querido diario:

Hoy he decidido que voy a presentarme al concursillo de programación que organiza Tuenti. Ya que no pude presentarme al Code Jam de Google como otros años porque estaba de viaje, voy a intentarlo con uno más patrio. No sé ni cómo va, y la verdad es que entre el curro y el finde que me he pegado de viajes y de dormir poco estoy bastante cansado. Pero pone que dura una semana y está el puente, así que seguro que hay tiempo de sobra para resolver los problemas que te pongan. ¡¡¡Esto lo gano fijo!!!.



Como voy a andar bien de tiempo creo que voy a hacerlo en algún otro lenguaje que no sea Java. ¿Qué tal en Dart, ya que le estoy dando caña últimamente?. O si no podría hacerlos en Groovy... bueno, bah, ya lo pienso cuando me ponga con ello.

¿Serán algorítmicos como los de Google?. Igual debería mirarme cosas de algorítmica, lo del backtracking, los A estrella, recorridos de grafos y todas esas mandangas, que lo di en la Facultad hace un mollón de años pero no me acuerdo de nada. Y siempre estoy igual, que oye, molaría poner cara de molón y decir: "¡Voy a resolverlo en un momentín con el algoritmo Magicflush!". O igual debería mirarme los problemas que han puesto otros años para hacerme una idea de cómo van... aunque bueno, seguro que estos serán facilones. Va, aunque sean las 8 de la tarde me voy a dormir una siesta y luego lo pienso.


Día 1

Querido diario:

Ayer al final también dormí muy poco, me quedé dormido cuando sonó el despertador de la siesta porque estaba baldado, y luego me desperté a la 1 o así y ya no me pude volver a dormir hasta casi por la mañana. Necesito un fin de semana para recuperarme del fin de semana. Menos mal que viene el puente y podré descansar.

Ya empezó el concursito de marras. Cuando he vuelto del teatro, aunque era ya tarde y yo estaba cansado, he mirado el primer ejercicio para ver qué pinta tienen los ejercicios. ¡Había 1582 personas registradas! En fin, igual no va a ser esto tan fácil.

Por lo que he visto, hay que ejecutar unas herramientas que te pasan para ejecutar una prueba corta y ver si vas bien, y luego otra más fuerte para enviarlo, que sólo se puede hacer una vez. Cuando fui a programar en Dart, me di cuenta de que iba a tener que usar Futures para toda la entrada / salida, y me dio tal pereza solo de pensarlo que al final pasé. Descarté también Groovy, por la pereza que me daba ya solo meterme cuando realmente no tengo fluidez ninguna con el lenguaje (estoy empezando a pensar que esto de programar con sueño no es bueno). ¡Qué demonios, voy a tirar con Java y así empiezo de una vez!.

El ejercicio 1, Anonymous Poll, es bastante sencillote, no tiene mucha ciencia. En estos concursos muchas veces la gente programa las cosas con gran economía de líneas, usando arrays a tope y con un número mínimo de funciones. Como a mi eso no me va mucho y además dicen que para el concurso se valorará la calidad del código, he optado por organizar los ejercicios con sus clases, sus métodos, etc., quedará todo más claro aunque también más largo.


El ejercicio 2, F1 Bird's Eye Circuit, se trataba de recibir en una sola línea el diseño de un circuito, con sus rectas y curvas, y ensamblarlo y pintarlo ya en dos dimensiones. A pesar de que era bien tarde pensé que era facilón y lo podía hacer en un momentín. Una vez terminado de programar me he dado cuenta de una cosa: tenía trampa. Al leerlo la primera vez me pareció que el primer caracter de la cadena se suponía que estaba mirando hacia la derecha. Pero al releerlo me he dado cuenta de que no, que el que se supone que está mirando a la derecha es un caracter '#' que hay por ahí, y que se supone que es la salida. ¡En el fondo fue una suerte que la haya releído, porque en el programa de la prueba daba la casualidad que todos los casos de prueba salían correctos!.

¡Primer What The Fuck!.



Si hubiera estado más despierto probablemente hubiera optado por comenzar a leer la cadena por la posición del caracter '#' y santas pascuas. Pero no, claro, he hecho algo mucho más bizarro: cuando llega el caracter # miro en qué dirección se supone que estoy mirando y la guardo en una variable, y luego ¡giro la pista al pintarla!, cambiando unos caracteres por otros según si miramos en horizontal o en vertical, o según cómo queden las curvas al girarlas. Un poco infernal, la verdad, con la tontería me han dado las 4 de la mañana. Estoy roto. A dormir.


Día 2

Querido diariozzz:

Lo volví a hacer. Después de la charla de @adelatorrefoss en MadriAgil y de ver el fútbol, por fin, a las tantas, me he vuelto a poner con el concursillo. No sé cuántos ejercicios hay, pero esto no parece tener fin.

El ejercicio 3, The Gambler's Club, es, es, es... ¡ey, es Guybrush Threepwood!, ¡¡¡Monkey Island!!!.


Está bien, ¡TENÍA que hacerlo!. ¡La de tiempo que habré pasado yo con los monkeys!. ¡Y seguro que un ingeniero amante del Monkey Island sería un genio que habría ideado un reto divertidísimo!...

Pues no.

Resulta que una vez leído te dabas cuenta de que se trataba de, a partir de un conjunto de datos, obtener la ecuación con la que se obtienen. Si conoces algún programa matemático, esto se resuelve en un pis-pas. YO NO. ¡Llevo sin usar un programa matemático desde la Universidad, hace cuatro o cinco millones de años! (redondeando).

Hice un programa que obtuviera los datos de la web y me puse a buscar en Google. Los ojos se me cerraban, pero ey! ¡en cuanto lo encontrara podría irme a dormir!. Rosario en mano y cantándole a los angelitos, probé con Excel. ¡Meeeeeeec!. Nones. Ni conseguí sacar ecuaciones con dos variables, ni conseguí sacar una ecuación convincente con una variable dejando la otra fija. Probé entonces con Wolphram Alpha, que sabía que se podían hacer cosas de este estilo. Al ir a meter los datos, veo que la cajica está deshabilitada y tiene un bonito botoncico donde pone "Subscribe to Pro". La madre que los parió. O dicho de otra forma, ¡segundo WTF!.

Buscando, buscando, buscando, vi que la cosa estaba chunga. Y a estas horas daba una pereza tremenda ponerse a instalar nada para probar programitas matemáticos, y encima en Linux. Viendo la curva en Excel, daba la impresión de que la ecuación tenía que ser polinomial, y me extrañaba que Excel no la sacara. ¡A ver si es que había que hacer una interpolación!. Dicho y hecho, me copié una clase que encontré por ahí que hacía una interpolación trilineal y ahí que la metí. Con un par. Porque yo lo valgo. Y encima funcionaba. Qué grande soy. Pues a tomar viento, la envío y fuera.

Claro, que en cuanto la he enviado me he dado cuenta de que eso no iba a funcionar ni de coña. Te avisaban de que el programa de prueba usaba números menores o iguales a 30, que eran justo los de la muestra de datos. Y claro, en cualquier interpolación, por chunga que sea, si le pides uno de los puntos de la muestra te lo va a devolver con una precisión perfecta. Por otra parte, también te avisaban de que en los datos de prueba que se ejecutaban al enviar, se usaban todos números mayores, los de muestra llegaban solo hasta 30, y los de la prueba final llegaban hasta mil y pico. O sea, que la interpolación a hacer gárgaras. ¿Para qué demonios sirve una interpolación si todos los datos están tan alejados de la muestra?.

Deprimido al darme cuenta de lo ocurrido y después de echar un trago del peor orujo que tenía como penitencia, he decidido que no podía acostarme así.

Así que he pasado al ejercicio 4, Shape shifters, y ¡oooooooooh, es Mística!. ¡Un ingeniero amante de Mística sería un genio que habría ideado un reto divertidísimo!... obviamente.



Se trataba de tener una cadena de caracteres de inicio y otra de fin, y un conjunto de estados intermedios posibles, y de crear transiciones de estados cambiando un caracter hasta llegar al objetivo. Con un recorrido de todas las posibilidades de transiciones y un control para no pasar por estados repetidos se resolvía con cierta facilidad, aunque ya me imagino que no será lo óptimo. Son casi las 5 de la mañana pero ¡entregado!. Y veo que han puesto un "top" y aparezco ya en él en el hipotético puesto 100, absolutamente falso porque no cuenta si los ejercicios están bien o mal, solo los que se han entregado. ¡Y hay un tío que ya tiene hechos 15! Para mi que la gente no trabaja...

En cualquier caso... ¡ay!, no me quito de la cabeza al puñetero Guybrush, la madre que lo engendró... ¡y el resto de su familia, obtenida a partir de estúpidas interpolaciones trilineales!.


Día 3

Queridozzz diariozzz:

Son las 12 de la noche y acabo de volver del entrenamiento de basket. Esta mañana he tenido que madrugar un poco más porque venían a revisarme la caldera, así que creo que estoy empezando a sentirme mucho más cercano a los zombis (más majos ellos!).

Viendo las máquinas que hay en el puñetero concurso, creo que voy a ver si presento un par de ejercicios más, que... ¡diablos!, ¡¡¡he mirado y resulta que hay 20 ejercicios!!!. Y a 2 por día no me va a dar tiempo aunque, Guybrush aparte, por suerte no son excesivamente complicados.

Pero primero voy a tirarme un rato en el sofá a relajarzzzzzzzzzzzZZZZZZZZZZzzzzzzzzzzZZZZzzz


¡OJO!: Esta entrada continúa en:





cookie consent