cout << “Facilitando Topcoder” << endl;
0 Comentarios Publicado por Román González 21 Julio 2008 en Herramientas, c++. english • españolDespues de culminada mi epoca de maratones de la ACM, mi equipo (Guayoyo) y yo empezamos a llenar el vacio de competencias participando en TopCoder.
La lógica de TopCoder es un poco distinta a la de los maratones de programación de la ACM, entre las diferencias encontramos que, existe un sistema diferente de evaluación de problemas (por puntajes y tiempo), e incluso de formato en el código fuente (Se definen reglas estrictas acerca de los nombres de las clases y métodos).
Para ingresar en TopCoder es necesario tener Java instalado en nuestra maquina, ya que funciona mediante Applets o Java Web Start (el cual recomiendo). A pesar de que el sistema (de ahora en adelante “la arena”) funcione muy bien, la parte de edición de código fuente no es la mas idonia para trabajar en competencias bajo presión.
Para solucionar este problema, los programadores de TopCoder ofrecieron la posibilidad de implementar Plugins que se adaptan a la arena y permiten mejorar los editores de texto (o incluso no usarlos del todo). A continuación explicaremos como instalar y configurar algunos Plugins para mejorar nuestra productividad a la hora de realizar competencias dentro de TopCoder.
-
Obtener el archivo .jws que carga la arena en nuestro computador
Para obtener la aplicación de la arena, debemos acceder a este link (Como indicamos anteriormente, se debe tener Java instalado para que este funcione).
-
Ingresar al sistema (o registrarse en caso de que no nos encontremos registrados)
En el caso de que no se encuentre registrado en el sistema, siga las indicaciones de la aplicación para registrarse
-
Descargar los Plugins que harán tu vida más fácil
Entre los Plugins que puedo recomendar, se encuentran CodeProcessorv2.0, FileEdit y moj
-
Configurar los plugins dentro de la arena
Para instalar los Plugins dentro de la arena se deben seguir los siguientes pasos:
-
Acceder al menú de “Options” y luego la opción “Editor”
-
Al abrirse la ventana de editores, debe presionar click en el botón “Add”, esto abrira otra ventana donde deben ingresar el nombre del editor (CodeProcessor en nuestro caso), en el campo EntryPoint, debemos colocar “codeprocessor.EntryPoint”, y en el campo classpath, al presionar el botón “Browse” debe buscar todos los Plugins (archivos .jar) que descargo en el paso anterior
-
Una vez instalado el nuevo editor, presionamos click en el botón “Configure”, se abrirá una nueva ventana donde se debe especificar en el campo “Editor EntryPoint” el valor “fileedit.EntryPoint”, luego presionamos el botón “Add” y en la nueva fila creada asignamos el valor “moj.moj”. Lo que hacemos aquí, es usar CodeProcessor como un manejador de Plugins, que permite usar varios Plugins (en este caso FileEdit y moj) simultaneamente.
-
Para configurar los plugins de FileEdit y moj, se debe presionar a los botones “Configure”, ahi se tendrán diferentes opciones dependiendo de cada Plugin
-
Para finalizar, ingrese a la configuración de FileEdit, y en la pestaña de “Code Template”, en la opción de C++, ingrese el siguiente contenido
$BEGINCUT$ /* $PROBLEMDESC$ */ $ENDCUT$ #line $NEXTLINENUMBER$ "$FILENAME$" #include "string" #include "vector" #include "algorithm" #include "map" #include "iterator" #include "iostream" #include "sstream" #include "cstdio" #include "cmath" #include "cstdlib" #include "queue" #include "stack" using namespace std; class $CLASSNAME$ { public: $RC$ $METHODNAME$($METHODPARMS$) { } }; $BEGINCUT$ $TESTCODE$ $DEFAULTMAIN$ $ENDCUT$
-
-
Ahora… a programar
Una vez instalados y configurados los Plugins, al momento de abrir un problema dentro de la arena, verá que el editor de texto no se encuentra en el programa de la arena, mas bien se muestra un log de acciones. Lo que ocurre es que el contenido del problema es descargado, y con este se genera un archivo que contendrá el enunciado del problema, junto con una implementación que contiene el template establecido en la configuración del FileEdit (que cambiará dependiendo del problema) y un main que ejecuta las pruebas del problema.

Pero espere… hay más
Si se encuentra en Mac OS X, puede usar este script que implementé (basado en rstakeout) que se encarga de compilar y ejecutar los archivos .cpp modificados, y luego mandar mensajes via Growl. En el momento que el programa cumpla con todas las pruebas exitosamente, saldrá un mensaje diciendo “Send It”. Para enviarlo, sólo debes presionar el botón “Compile” en la arena, y luego al botón “Submit” (Reflejados en la figura anterior).

La carita verde es una imagen que configuré manualmente, si quieren tener algo parecido por favor revisen el código fuente y establezcan el lugar donde se encuentra la imagen que quieren usar, las caritas se encuentrán aquí.
Espero que estos tips les ayuden a mejorar su rendimiento en TopCoder…
O capitalista, o Marxista, o Comunista o arroz con mango.
Es lamentable que a una herramienta de desarrollo de software o a un lenguaje se le tilde de esto o de aquello, sólo por desconocimiento. Pero lo peor es que esto se convierta en un trabajo de investigación (sin mucha base).
Mi argumentos reflejan lo que siempre he pensado del fanatismo de los desarrolladores. ¿Y usted que opina?
ata2.00. exception Emask 0×0 SAct 0×0 action 0×2 frozen al iniciar Ubuntu 8.04 (Hardy Heron) en una DELL Inspiron 530
0 Comentarios Publicado por admin 22 Junio 2008 en General. english • españolLa lentitud y los múltiples crashes de las aplicacciones en la DELL Inspiron 530 que compré para la casa a finales del año pasado hicieron que mi esposa y mi hija prácticamente me suplicaran que montara Ubuntu en la nueva máquina. Nunca pensé que tener una computadora con Windows Vista instalado fuera tan buen mercadeo para Linux ;-)
Por supuesto estaba el problema de los drivers, el monitor por sí solo es un mundo, etc. Sin embargo después de muchos fines de semana sin tiempo para respaldar, reparticionar, instalar y configurar, por fin me dediqué a instalar Ubuntu 8.04, Hardy Heron.
Sin embargo después de la instalación se me quedaba "pegada" booteando con el siguiente mensaje:
-
ata2.00: status: {DRDY}
-
ata2: soft resetting link
-
ata2.00: configured for UDMA/33
-
ata2: EH Complete
-
ata2.00. exception Emask 0x0 SAct 0x0 action 0x2 frozen
Después de mucho escarbar en internet, pude resolver el problema agregando el parámetro pci=nomsi para el arranque del kernel, no estuvo fácil así que mejor postearlo aquí para que A) No se me olvide, B) Más nadie tenga que dar tumbos en los foros de Ubuntu, el WIki de DELL para soporte a Linux y cualquier otro recurso desquiciado en internet.
De momento el equipo funciona perfectamente, y mi mayor preocupación es que Gnomad2 se dispara con unos picos duros de consumo de CPU al sincronizar el Creative Labs Zen de mi hija con su "PlaysForSure" de Microsoft ;-)
Y ahora, por fin la máquina se comporta como un Core 2 Duo de 2.33 GHz, con 2 GB de RAM y una NVIDIA GeForce de 256MB y se acabará la letanía de ¿Y esta no "ique" era más rápida?
Nginx: 4to lugar en Netcraft cortesía de WordPress.com
0 Comentarios Publicado por admin 11 Junio 2008 en General. english • españolLa gente de Netcraft reporta que para el mes de Mayo el servidor web Nginx ocupa el quinto lugar en su ranking. Esto cortesía de la gente de WordPress.com que reemplazaron Litespeed por Nginx, y que casualmente ayer generaron 36 millones de pageviews dinámicos con picos de 15k requests/sec en un pico histórico para su operación.
Capturando temperatura utilizando Sentilla Perk (II)
6 Comentarios Publicado por josevnz 24 Mayo 2008 en General, Java, sun. english • españolEn un articulo anterior les mostraba lo fácil que era utilizar el sensor (mote) de Sentilla Perk para capturar temperatura; Les comentaba también que una de las cosas más molestas del kit era que el gateway (el servidor con el cual instalamos software en los sensores y capturamos datos desde la red) sólo corre bajo Windows XP (aunque los ingenieros ya están trabajando en mejoras como drivers para Linux ys OSX).
OK, ¡suficiente habladera de tonterias!. Una forma de remediar esto es agregar otro protocolo (como TCP/IP) encima al programa original que recolectaba las temperaturas de todos los sensores, es decir lo convertimos en un servidor.
Lo primero es decidir si queremos usar un protocolo existente o si queremos reinventar la rueda; Para este experimento decidí que usar un protocolo existente con algunas modificaciones era lo más sencillo (Daytime, RFC686):
- El servidor escucha en el puerto 1973 (cualquiera sirve si está libre ;)).
- El cliente envia un paquete (vacio o no) al puerto 1973 en la máquina en donde corre el servidor
- El servidor recibe el paquete y lo descarta. Envia de vuelta uno nuevo con una lista temperatura de todos los sensores que ha escuchado hasta el momento
- El servidor no envia más temperaturas
El protocolo es sencillo, es puro texto (con una cabecera el cual el cliente utiliza como validación):
HEADER SENSORID1 SENSORCOUNT1 TEMPERATURE1 UNITS1 SENSORID2 SENSORCOUNT2 TEMPERATURE2 UNITS2 ...
Siempre es bueno encapsular los paquetes de un protocolo en una clase, para hacer más fácil su manejo:
-
package com.kodegeek.blog.pervasive.perk;
-
-
/**
-
* Simple model for temperature readings
-
* @author josevnz
-
*
-
*/
-
public final class SimpleMessage {
-
-
/**
-
* Valid status codes for the message
-
* @author josevnz@kodegeek.com
-
*/
-
public enum Units {
-
FAHRENHEIT("Fahrenheit"),
-
CELCIUS("Celcius"),
-
-
private String desc;
-
-
this.desc = desc;
-
}
-
-
return desc;
-
}
-
-
public static Units getCode(int code) {
-
for (Units codes : Units.values()) {
-
if (codes.ordinal() == code)
-
return codes;
-
}
-
}
-
-
}
-
-
private long count;
-
private long moteId;
-
private double temperature;
-
private Units units;
-
-
/**
-
* Default constructor. By default is UNKLNOWN
-
*/
-
public SimpleMessage() {
-
}
-
-
/**
-
* Parametric constructor
-
* @param count Message count
-
* @param moteId sensor id
-
* @param temperature Temperature
-
* @param isRequest Is a request or a response
-
*/
-
public SimpleMessage(long count, long moteId, double temperature, Units code) {
-
setCount(count);
-
setMoteId(moteId);
-
setTemperature(temperature);
-
setUnits(code);
-
}
-
-
/**
-
* Get the message cou
-
* @return the count
-
*/
-
public final long getCount() {
-
return count;
-
}
-
-
/**
-
* Set the message count
-
* @param count the count to set
-
*/
-
public final void setCount(long count) {
-
this.count = count;
-
}
-
-
/**
-
* Return the sensor id
-
* @return the moteId
-
*/
-
public final long getMoteId() {
-
return moteId;
-
}
-
-
/**
-
* Set the sensor id
-
* @param moteId the moteId to set
-
*/
-
public final void setMoteId(long moteId) {
-
this.moteId = moteId;
-
}
-
-
/**
-
* @return the temperature
-
*/
-
public final double getTemperature() {
-
return temperature;
-
}
-
-
/**
-
* Set the temperature
-
* @param temperature the temperature to set. No validation is made as it depends a lot on the units
-
*/
-
public final void setTemperature(double temperature) {
-
this.temperature = temperature;
-
}
-
-
/**
-
* Get the units
-
* @return The state code
-
*/
-
public final Units getUnits() {
-
return units;
-
}
-
-
/**
-
* Set the units
-
* @param code Valid code to pass
-
*/
-
public final void setUnits(Units code) {
-
this.units = code;
-
}
-
}
El siguiente paso es decidir como codificar y decodificar el mensaje que enviamos a traves de la red; En el mundo Java podemos usar RMI, Sockets + Serialization sin embargo me pareció mejor utilizar UDP, por lo pequeño de los mensajes además de que no requiero las características extras de TCP, y no serialización (hay que ser MUY cuidadoso cuando se implementa, no es sólo decir que la clase implenta la interfaz "Serializable"):
-
/**
-
*
-
*/
-
package com.kodegeek.blog.pervasive.perk;
-
-
/**
-
* Define the contract to encode / decode a temperature message.
-
* Not using the Sentilla radio protocol.
-
*/
-
import java.io.IOException;
-
import java.io.UnsupportedEncodingException;
-
import java.util.ArrayList;
-
-
/**
-
* @author josevnz
-
*
-
*/
-
public interface TemperatureCoder {
-
-
/**
-
* Decode message from wire
-
* @param buffer
-
* @return TempMessage decoded from the wire
-
*/
-
-
/**
-
* Encoded message
-
* @param e
-
* @return byte array with serialized message
-
* @throws UnsupportedEncodingException
-
*/
-
-
}
Si, una interfaz la cual va a implementar el codificador especifico (código aquí). De esta manera, si cambiamos el protocolo (usamos Java + Serialization por ejemplo), nuestra aplicación sólo tiene que cambiar la declaración del codificador concreto y listo.
¿Que viene después? Ah, envenenar al cliente original que capturaba la temperatura; Ahora va a ser un servidor El cual:
- Va a capturar constantemente nuevas temperaturas desde la inalámbrica de los sensores en una hebra separada
- Va a enviar todas las temperaturas disponibles a quien se las pida
Si bien el código del servidor no es muy largo (haga click aqui para verlo completo) prefiero mostrarle sólo las piezas críticas:
-
/**
-
* Server that collects the temperature readings of
-
* all the motes in the wireless network.
-
* @author josevnz@kodegeek.com
-
*/
-
-
package com.kodegeek.blog.pervasive.perk;
-
-
...
-
-
/**
-
* Iterative Server that collects all the temperature readings coming from the Sentilla Perk on the networks
-
* @author josevnz@kodegeek.com
-
*
-
*/
-
-
private TemperatureService() {};
-
-
private static final Logger log = Logger.getLogger(TemperatureService.class.getName());
-
-
static {
-
log.setLevel(Level.FINEST);
-
}
-
private static final int DEFAULT_PORT = 1973;
-
protected static final int BUFFER_SIZE = 65507; // 65535 bytes - IP Header(20) - UDP header (8)
-
private static final int MOTE_WAIT = MoteTemperatureReader.WAIT_TIME;
-
-
/**
-
* Capture sensor temperatures firever on a separate thread
-
*/
-
public void run() {
-
-
// Connect to the Sentilla server
-
HostClient client = new HostClient();
-
try {
-
client.connect();
-
log.log(Level.INFO, String.format("Connected to sensor gateway at %s, capturing temperatures", client.getHost()));
-
while(true) {
-
receiver.setReceive().submit().block(MOTE_WAIT);
-
if (receiver.isDone()) {
-
TempMessage tmsg = receiver.getData();
-
sensorMap.put(tmsg.moteId, tmsg); // Save every sensor update, replacing previous one
-
}
-
}
-
log.log(Level.SEVERE, "Severe error, response will be dropped", ioExp);
-
} finally {
-
try {
-
if (client != null)
-
client.disconnect();
-
log.log(Level.SEVERE, "Error while closing sensor connection", ioExp);
-
}
-
}
-
}
-
-
/**
-
* Collect the statistics from all the motes
-
* @param args
-
*/
-
...
-
-
// Start capturing temperatures
-
tempThread.start();
-
-
DatagramSocket socket;
-
TemperatureCoder coder = new TemperatureTextCoder();
-
socket = null;
-
try {
-
byte [] buffer = new byte[BUFFER_SIZE];
-
-
ArrayList<SimpleMessage>messages = new ArrayList<SimpleMessage>();
-
-
while(true) { // Wait forever for new clients
-
try {
-
socket.receive(packet); // Get the packet and discard the contents
-
// Send every available tick to the client in one shot
-
for (TempMessage tmsg : sensorMap.values()) {
-
SimpleMessage message = new SimpleMessage();
-
// Get the temperature for the sensor
-
double temp = tmsg.temperature.doubleValue(CELSIUS);
-
message.setCount(tmsg.count);
-
message.setMoteId(tmsg.moteId);
-
message.setTemperature(temp);
-
message.setUnits(SimpleMessage.Units.CELCIUS);
-
...
-
messages.add(message);
-
-
} // end for every sensor
-
-
// Send the whole pack to the client
-
buffer = coder.toWire(messages);
-
packet.setData(buffer, 0, buffer.length);
-
socket.send(packet);
-
...
Si, el servidor no es muy robusto ni soporta un gran número de clientes a la vez (es iterativo), pero para jugar un rato está bien :)
Bueno, si aún no le ha dado un ataque leyendo todo este código lo invito a que vea el cliente (código completo aqui) . Muy sencillo (sólo imprime por pantalla las temperaturas) sin embargo tiene una caracteristica muy importante: No tiene ninguna dependencia con el código de Sentilla:
-
package com.kodegeek.blog.pervasive.perk;
-
-
...
-
-
/**
-
* Simple client that will get all the temperature readings from a TemperatureServer on the network.
-
* @author josevnz@kodegeek.com
-
*
-
*/
-
public final class TemperatureClient {
-
-
...
-
-
/**
-
* @param args host (args[0]), port number (arg[1])
-
* @throws Throwable On any fatal error
-
*/
-
...
-
-
log.log(Level.INFO, "Starting TemperatureClient");