Ir al contenido (saltar navegación)

Preguntas frecuentes

¡Acepta el reto! es un almacén ("repositorio") de problemas de programación en español, con un juez en línea incorporado. Cualquier usuario puede resolver los problemas propuestos y enviar su solución al juez para comprobar si es correcta.

Todos los problemas del almacén son aplicaciones de consola que reciben datos por la entrada estándar y envían los resultados por la salida estándar. Desde el punto de vista de programación, esto significa que deben leer del teclado y escribir texto en la pantalla.

El objetivo es que los usuarios pongan en práctica sus habilidades de programación básica, de algoritmos y estructuras de datos. Por tanto, ninguno de los problemas hace uso de interfaces gráficos de usuario, ni ficheros.

Dicho esto, el abanico de problemas es amplio y toca una gran variedad de temas. Puedes comprobarlo recorriendo las categorías.

Para cada problema, el juez dispone de un conjunto de casos de prueba que mantiene en secreto. Cuando recibe el código de una supuesta solución, lo compila y lo ejecuta, enviándole por la entrada estándar los casos de prueba que posee.

El programa escribirá en la salida estándar los resultados, que serán comparados por el juez con los resultados correctos, especificados por el autor del problema. El veredicto emitido dependerá del resultado de esa comparación.

La evaluación de los envíos se realiza en una plataforma Intel 80x86 (32 bits) sobre un sistema operativo GNU/Linux.

El juez en línea compila utilizando gcc para C/C++ y OpenJDK 1.7 para Java. La compilación de C++ incluye el flag -std=c++11 para soporte del estándar de 2011.

Sí, desde luego. Puedes utilizar el sistema operativo y entorno de desarrollo que prefieras. Pero deberás tener en cuenta que en ocasiones hay algunas diferencias entre los compiladores, lo que puede ocasionar que una solución que te funcione en tu ordenador no compile en el juez. En ese caso, el juez te ayuda indicándote, en la página del envío, el mensaje de error mostrado por el compilador del servidor para que puedas adaptar tu código.

Estas diferencias son más habituales en C y C++ que en Java. Si quieres intentar reducir la probabilidad de tener este tipo de problemas sin utilizar GNU/Linux, puedes utilizar una versión de la suite del compilador GCC en Windows. Una de tales implementaciones es MinGW, que incorpora muchas otras herramientas de GNU. El problema es que requiere su uso en consola, que para muchos no es muy amigable.

Otra opción es usar CodeBlocks, que es un entorno de desarrollo (gráfico) que puede usar MinGW como backend para compilar. Para ponerlo en marcha, lo mejor es descargarse la versión que incorpora el paquete CodeBlocks + MinGW para no tener que instalar y configurar cada cosa por separado.

Hay algunas otras alternativas como cygwin, aunque normalmente son más complicadas que CodeBlocks.

Si programas en C/C++ podrás hacer uso únicamente de la biblioteca matemática, junto con cualquier otra biblioteca estándar que no requiera el enlazado de nada particular para la construcción del ejecutable final. Ejemplos de ficheros de cabecera permitidos son stdio.h, stdlib.h, string.h y math.h. En el caso de C++, también se puede hacer uso de la biblioteca estándar (iostream, vector, etcétera).

En Java, se puede hacer uso de cualquier paquete estándar salvo los relacionados con el interfaz gráfico (awt, swing, etcétera). Tampoco se permite utilizar la clase java.lang.Thread.

Ten en cuenta que algunas bibliotecas o paquetes podrían incluirse sin dar error de compilación, pero luego fallar en ejecución porque el juez no permita su uso.

No. El objetivo principal de la gran mayoría de los problemas es que pongas en práctica tus conocimientos de programación, no que pierdas tiempo en detalles poco importantes como la entrada.

Si en el enunciado de un problema dice, por ejemplo, que cada caso de prueba estará compuesto de un número positivo, no necesitas comprobar que es así; al fin y al cabo, ¿qué harías si no lo fuera? Por tanto, puedes confiar plenamente en que la entrada seguirá el formato especificado y no preocuparte de reaccionar dignamente si no es así.

La contrapartida es que el juez exige lo mismo en la salida. Tu programa debe ser totalmente estricto en el formato de la salida. No añadas texto adicional para ser "amigable" con el usuario (tipo "Introduce el siguiente número"), porque despistarán al juez y no dará por bueno el resultado. Sigue a pies juntillas el formato de salida, incluídos los espacios.

No es que puedas, ¡es que debes! Antes de enviar tu solución al juez on-line deberías probarla en tu ordenador para tener una cierta esperanza de que esté bien.

Para eso, puedes descargarte la entrada y salida de ejemplo del enunciado. Basta con que pases el ratón por encima de los ejemplos, y verás aparecer una "barra de herramientas" para seleccionar todo (y poderlo copiar), o para descargarte un archivo comprimido con los dos ficheros (el ejemplo de la entrada y de la salida).

A partir de ahí, dependiendo de la opción que elijas, tendrás que actuar de una manera u otra. Quizá lo más sencillo sea lanzar tu programa en una consola, pegar el texto copiado de la entrada y luego comprobar manualmente que la salida es correcta.

La otra alternativa es que hagas uso de las redirecciones del shell. Por ejemplo en GNU/Linux:

$ ./a.out < sample.in > miSalida
$ diff sample.out miSalida

Consulta la documentación de tu sistema operativo para obtener más información. Ten en cuenta que los ficheros de ejemplo descargados tienen los saltos de línea en modo Unix, por lo que podrías ver falsas diferencias que desaparecerán al enviar tu código al juez on-line.

¡No! Todos los enunciados contienen un ejemplo de entrada y un ejemplo de salida que se separan por claridad y simplicidad. Pero las soluciones enviadas no tienen que leer toda la entrada, procesarla y luego escribir toda la salida. ¡Más bien al contrario! Hacerlo así requeriría que el programa utilizara más memoria para guardar toda la entrada antes de empezar a hacer algo útil.

Te animamos a que tus programas tengan, a alto nivel, un esquema similar a éste:

mientras(leerSiguienteCasoDePrueba())
	procesarCasoActual();

De ese modo, si pruebas tu programa de manera interactiva (escribiendo los casos de prueba por teclado) al introducir cada uno, el programa responderá inmediatamente sin esperar a leer los siguientes. Posteriormente, el juez on-line será capaz cuando pruebe tu código de independizar la entrada y la salida sin problema.

En la página Plantillas de código para las soluciones te proporcionamos esqueletos en distintos lenguajes de programación que puedes usar como punto de partida. Ninguno de ellos lee toda la entrada antes de empezar a procesar los casos.

Algunos problemas tienen que leer de la entrada números con decimales, y en el ejemplo de entrada los números que salen utilizan el punto como separador (2.00 o 15.33). Sin embargo, si programas en Java es posible que para probar tu solución tengas que utilizar una coma (2,00 o 15,33).

En principio, puedes ignorar este problema. El juez está configurado de manera que tu programa leerá, sin hacer nada especial, los números decimales usando el punto en lugar de la coma.

Si, a pesar de todo, quieres probar que funciona, puedes imitar la configuración del juez en tu propio ordenador, y así podrás utilizar los ficheros de ejemplo del ejercicio sin modificación. Para eso tienes dos opciones. La primera es configurar de manera adecuada las clases que utilices para leer la entrada. Por ejemplo, si usas la clase Scanner puedes hacer algo así:

in = new java.util.Scanner(System.in);
in.useLocale(java.util.Locale.UK);

La otra opción es configurar la máquina virtual de Java en el momento de lanzarla:

java -Duser.language=en ClaseConLaSolucion

Sí. Salvo que el enunciado diga lo contrario, la última línea de la salida será igual que cualquier otra, por lo que deberá terminar con un fin de línea ('\n'). Si tu solución es correcta salvo por este detalle, el juez dará como veredicto PE (Presentation Error, error de presentación).

El juez emite un veredicto por cada envío, en función de su corrección. El resultado más deseado es AC (Accepted, aceptado), pero hay otros, como WA (Wrong answer, respuesta incorrecta) o RTE (Runtime error, error durante la ejecución).

Puedes ver una explicación detallada de cada uno y, más importante, algunas pistas sobre por qué pueden aparecer en la sección de veredictos.

Cuando ejecuta una supuesta solución, el juez en línea realiza un control exhaustivo sobre las operaciones que ésta realiza, y pone límites estrictos a su ejecución.

Por ejemplo, el juez denegará cualquier intento de acceso a ficheros, a la red o a operaciones del sistema operativo diferentes a las de la lectura y escritura por la entrada y salida estándar. Si el programa trata de hacer cualquiera de estas cosas (consideradas potencialmente peligrosas), detendrá inmediatamente la ejecución y dará como veredicto RF (Restricted Function, función restringida). Ten en cuenta que cualquier intento de ejecutar otro proceso también será prohibido. Eso ocurre automáticamente si en C/C++ pones código como:

system("pause");

Si programas en C/C++, otra posible causa del veredicto RF es el uso de fflush(stdin). Existe cierta tendencia a utilizarlo después de los scanf() para consumir el resto de la línea, especialmente si más adelante se va a hacer uso de gets() (función desaconsejada, por otro lado). Sin embargo, el estandar ISO (sección 7.9.5.2) sólo especifica el comportamiento de fflush() para ficheros de entrada. Puedes leer más detalles aquí.

El equivalente a fflush(stdin) en C++ es cin.sync() que tampoco debe utilizarse (también genera como veredicto RF). La sincronización de cin suele utilizarse para "consumir el resto de la entrada", útil normalmente para recuperarse ante una entrada no esperada. Sin embargo, su uso está desaconsejado, pues el comportamiento exacto no es estándar, y podría incluso variar en la misma plataforma dependiendo de si se ha redirigido o no la entrada. Además, dado que el juez siempre utiliza entradas correctas no debes preocuparte de "arreglar" la entrada nunca. Si estás completamente convencido de que lo necesitas, entonces plantéate utilizar cin.get() o cin.ignore(...) en su lugar para evitar que el juez cancele tu ejecución.

Si programas en Java, causas habituales del veredicto RF son intentar utilizar las librerías AWT o Swing (todos los problemas son de consola y no se necesitan), intentar hacer uso de hebras (incluso aunque sea únicamente Thread.sleep(...)) o intentar acelerar la entrada/salida haciendo uso de los identificadores de los "ficheros" abiertos para los streams de System.in y System.out.

Por último, se imponen restricciones de tiempo máximo de uso de procesador y de memoria. Los límites específicos dependerán del problema, y se muestran en la parte superior de su enunciado.

Cada problema impone una limitación "en tiempo y en espacio" a las soluciones para poderlas considerar válidas. En concreto, limita el tiempo máximo de uso de procesador y la cantidad máxima de memoria de los que puede hacer uso el programa. La limitación de tiempo se especifica en segundos, y la de memoria en KiB (1024 bytes).

Cuando te enfrentes a un problema, presta atención a ambos valores. En ocasiones, la dificultad del problema está precisamente en esos límites, exigiendo soluciones imaginativas para no romperlos.

Algunos problemas indican un rango en el tiempo y/o en la memoria máxima. Eso se debe a que muchos problemas contienen más de una batería de pruebas que los envíos deben superar, por lo que cada solución recibida se ejecutará más de una vez. Si los límites para las diferentes baterías de prueba son diferentes, se muestra el rango en el que oscilan.

Las soluciones enviadas a ¡Acepta el reto! se ejecutan varias veces. Como mínimo, se ejecutará una primera vez con el ejemplo del enunciado, y una segunda con una batería de pruebas secreta. Los autores de los problemas pueden, llegado el caso, crear más de un lote de pruebas, y cada uno supondrá una ejecución adicional.

Como se decía antes la potencial existencia de varias baterías de prueba es la razón por la que en los límites de algunos problemas aparece un rango en lugar de un único valor. Y esta es también la causa de que a veces los envíos parezcan tardar más tiempo de lo permitido. El límite indica el máximo tiempo que se permite a una solución ejecutarse para una batería de pruebas de las creadas por los autores del problema. Pero el tiempo mostrado en los detalles de un envío es el acumulado en todas las ejecuciones. Si los detalles de un envío indican un tiempo de ejecución superior al límite del enunciado y aun así no sufre TLE, puedes estar seguro de que ese problema tiene varios lotes de casos de prueba. Eso sí, es suficiente con que el límite se supere en un lote para que el veredicto sea TLE, aunque en el resto de ejecuciones sobre mucho tiempo.

Ten en cuenta que el consumo de memoria no se acumula. La memoria consumida por un envío es la máxima que haya consumido entre todas las ejecuciones que se hayan realizado durante su evaluación. Como antes, es suficiente que se supere el límite de memoria en una de ellas para que el veredicto sea MLE.

Sí. El juez muestra diferentes listas de envíos recibidos: últimos envíos, últimos envíos de un problema concreto (en las estadísticas), últimos envíos de un usuario, o últimos envíos de un usuario para un problema. En todas ellas, la primera columna es el identificador del envío. Si es tuyo, será un enlace que te llevará a los detalles de ese envío, donde podrás ver el código fuente asociado.

No. El código fuente de un envío sólo puede verlo el usuario que lo mandó.

Cuando realizas un envío, puedes añadir un comentario en texto. El juez no utilizará en ningún caso ese texto, y no será visible para otros usuarios.

Es útil para diferenciar ese envío de otros. Por ejemplo, si resuelves el mismo problema de varias formas, puedes añadir alguna indicación en el comentario asociado a cada envío para recordártelo.

El comentario de un envío se puede cambiar a posteriori en la página de los detalles de un envío, algo que, obviamente, no se puede hacer con el código (necesitarás hacer un envío nuevo). Esta posibilidad es muy útil especialmente en los envíos fallidos. Si mandas una solución y el juez te responde, por ejemplo, WA (Wrong Answer), es interesante que, cuando descubras por qué esa solución estaba mal, te lo resumas a ti mismo a modo de documentación en el comentario asociado a ella. Así en el futuro podrás volver y saber qué le pasaba sin tener que analizar el código de nuevo.

Los comentarios de los envíos se ven en la lista de tus últimos envíos (generales o de un problema específico). No son visibles en la lista de todos los envíos recibidos por el juez, pues ahí se muestran también los de otros usuarios, y no podrás ver sus comentarios.

La columna AC/Envíos indica la relación entre el número de envíos aceptados y el total de envíos. Esta información es útil para hacernos una idea sobre la dificultad del problema: cuanto más alto sea el porcentaje de envíos aceptados más fácil será, normalmente, un problema. El porcentaje da una pista de lo fácil que es conseguir resolver el problema a la primera.

La columna AC/Usuarios (que sólo aparece en las listas de problemas) indica el número de usuarios que han resuelto correctamente un problema de todos los que lo han intentado. El porcentaje de aceptados en este caso indica la probabilidad de que, al final, resuelvas el problema. Su inverso es el porcentaje de usuarios que, de momento, han dado el problema por imposible.

El número de aceptados en ambas columnas no tiene por qué ser igual. Si un usuario envía el mismo problema correctamente dos veces, contará por dos en la primera columna, y por uno en la segunda.

Por ejemplo, imagina un problema fácil, pero que tiene alguna trampa sutil difícil de ver a la primera. Podría ocurrir que la mayoría de los usuarios que lo intentan fallaran en su primer envío, pero luego se dieran cuenta del error y lo resolvieran al segundo. En ese caso la relación AC/Envíos sería del 50% (un envío válido de cada dos), mientras que la relación AC/Usuarios sería del 100% (todos los usuarios terminan consiguiendo resolverlo, aunque sea a la segunda).

Las categorías a las que pertenece un problema pueden constituir una gran ayuda a la hora de enfrentarse a un problema, pudiendo incluso arruinar el objetivo del propio problema de forzar a reflexionar.

Debido a ello, las categorías no son visibles en el enunciado del problema para evitar que se lean "por error" sin desearlo.

Ten en cuenta que no pretendemos con esto ocultar las categorías de los problemas, como muestra el hecho de la existencia del recorrido por categorías. Pero cuando alguien usa el recorrido por categorías está explícitamente buscando algo concreto, y no consideramos que encontrar un problema asociado a una categoría determinada sea arruinarlo.

Si activas esta casilla de verificación, tu navegador recordará tu nombre del usuario tras abrir la sesión. Así, la próxima vez que vuelvas no tendrás que escribirlo.

Esta opción es cómoda, y sigue siendo bastante segura porque la contraseña tendrás que escribirla de todas formas. No obstante, en ordenadores compartidos se aconseja no activarla, para que usuarios posteriores no puedan conocer tu nombre de usuario e intentar un ataque de diccionario o de fuerza bruta sobre la contraseña o se entretengan en reiniciártela si usaste como identificador tu dirección de correo.

Siempre puedes conseguir que el navegador olvide tu nombre de usuario si haces login en cualquier momento con la casilla de verificación desmarcada. La próxima vez que vuelvas, tendrás que escribir también tu nombre de usuario.