2010-06-26 8 views
5

Estoy empezando a responder a las preguntas en el proyecto Euler, y me gustaría abordarlo con un estilo TDD, pero tengo problemas para encontrar la respuesta numérica a la pregunta que no responde Incluya el código. ¿Hay algún recurso con esos datos para poder hacer casos de prueba que me digan si he resuelto el problema correctamente?Realización de pruebas unitarias para el proyecto Euler

Mi motivación para esto es que siento que el algoritmo es la respuesta, no el número. Si miro la muestra de código de otra persona, se arruina el desafío de averiguar cómo para resolver el problema.

Editar: Estoy buscando específicamente el número de respuestas sin contexto o algoritmo para poder hacer algo como lo siguiente. Sé que es más detallado, pero me gustaría poder tener un resultado de aprobado/reprobado para decirme si mi algoritmo es correcto o no, en lugar de mirar el ejemplo de código de otra persona para saber si lo hice correctamente.

import unittest 
class ProblemOneTest(unittest.TestCase): 
    def test_me(self): 
     self.assertEquals(solve_problem_one(),233168) 

if __name__ == '__main__': 
    print "Problem 1 possible answer: %d" % solve_problem_one() 
    sys.exit(unittest.main()) 
+0

Tener respuestas arruinaría la parte del desafío. Lo que podría hacer es ejecutar múltiples "soluciones" y comparar sus resultados. –

+2

Para mí siento lo opuesto. El número no tiene sentido sin el algoritmo. Siento que el código en sí es la respuesta, y ver cómo alguien más lo hizo arruina el desafío de descubrir * cómo * resolverlo. – Daenyth

+3

No está ingresando el número en la página de contexto y obteniendo el "¡lo resolvió!" pantalla suficiente? Realmente no veo cómo las pruebas unitarias podrían ayudar allí. Pruebe en cambio escribir diferentes algoritmos, modificarlos para renderizarlos más rápido, o simplemente más elegantes. – nico

Respuesta

4

La página del problema en el sitio web del proyecto Euler tiene una entrada para verificar su respuesta. Eso es todo lo que realmente necesito.

11

TDD y proyectos Las asignaciones de Euler no necesariamente van bien juntas. En primer lugar, TDD no lo ayudará a resolver ningún problema de proyecto de Euler (PE). Esto me recuerda el conocido intento de un chico de "resolver Sudoku" por using TDD.

TDD no es una técnica de diseño. Puede ser muy útil cuando corresponda, pero no lo piense como una bala de plata.

Un problema de PE por lo general implica un gran cálculo que termina en un solo número, que es la respuesta. Para aplicar TDD a conciencia, recomiendo usarlo para las utilidades matemáticas que desarrollará como parte de sus esfuerzos para resolver problemas de PE. Por ejemplo, mi módulo utils para PE consta de funciones para calcular números primos, dividir números en dígitos, verificar palindrómicos, y así sucesivamente. Este módulo tiene un conjunto de pruebas, porque estas funciones son general suficientes para ser probadas. Las propias soluciones de PE no tienen pruebas, la única prueba real que se necesita para ellas es generar finalmente la respuesta correcta.

+0

Lo siento, debería haber sido más claro. Estoy buscando el número por sí mismo sin contexto para poder hacer algo como 'assertEquals (my_solution(), expected_answer)'. Actualizaré la pregunta – Daenyth

+0

+1 las pruebas de escritura para problemas de Project Euler solo tienen sentido si ya tiene la respuesta y desea optimizarla. –

+1

Puede probar el algoritmo para resolver el problema con un límite menor contra un valor derivado de la fuerza bruta (a menudo lo hice). – starblue

1

La prueba de unidad ES la respuesta.

Los problemas suelen ser tan simples (no en términos de dificultad, pero al menos en el diseño del código) que dividirlos en varios métodos/clases suele ser una tontería.

+0

Supongo que es excesivo, pero también está motivado por querer aprender a usar pruebas unitarias en Python. También me gusta poder verificar mi trabajo sin hacer referencia al código de otra persona. Básicamente, solo quiero tener una declaración correcta/incorrecta relacionada con mi algoritmo. – Daenyth

+0

No puedo decir que estoy completamente de acuerdo. En parte en las preguntas anteriores, esto es cierto para estar seguro. Pero a medida que las cosas se vuelven más complejas y necesita desglosar los componentes, necesitará/querrá probar componentes individuales. Por supuesto, algunas personas pueden escribir un programa muy corto para responder a las preguntas y, en ese caso, la respuesta es correcta, pero la mayoría de las personas (humanas) van a dividir el problema en pedazos más pequeños. –

2

Sí, puede configurar las pruebas unitarias contra los datos de prueba que dar.

Parece que está usando Python para resolver los problemas (como yo). Lo que hago para validar los diferentes componentes es hacer declaraciones simples 'assert' con los datos de ejemplo. Funciona bien y hay menos tiempo sobrecarga. Además, no necesita ejecutar todo el conjunto de pruebas cuando solo necesita saber si sus nuevos cambios para el problema 30 son correctos.

Using Assertions Effectively

+0

Sé que tengo casi 3 años de retraso en la fiesta, pero este es el camino a seguir. – chucksmash

1

Yo sé que soy 3 años tarde a la fiesta pero pensé que iba a compartir cómo me estoy acercando Proyecto Euler a través de TDD.

Estoy trabajando en Python, si eso te importa.

Lo que hago es la siguiente:

  • Cada problema se vuelve (como mínimo) su propia función que sirve como punto de entrada/salida, no importa cuán trivial o tonto que se puede sentir. Los problemas también pueden obtener funciones auxiliares si el problema requiere algún tipo de funcionalidad que usted crea que podría necesitar en el futuro.
  • La mayoría de las preguntas de Project Euler incluyen un pequeño problema de demostración/prueba en la prueba en sí. Este problema de prueba ilustra lo que más resuelve, pero en una escala más pequeña.
  • Planifica la configuración de tu función de entrada/salida con un parámetro que permita que la función resuelva tanto la versión de juguete del problema como la versión de escala completa más dura. Por ejemplo, en problem 12 mi punto de entrada (ridículamente nombrado) es get_triangle_num_with_n_or_more_divisors (n).
  • En este momento no he implementado la función, simplemente la he nombrado. Ahora escribiré dos pruebas para este problema: test_example y test_problem. Decoraré test_problem con @unittest.skip('Unimplemented') por ahora ya que no sabemos la respuesta. Su archivo de prueba podría ser algo como el mío:

    import unittest 
    
    from problems.p0014 import get_triangle_num_with_n_or_more_divisors 
    
    class TestHighlyDivisibleTriangleNumber(unittest.TestCase): 
        def test_example(self): 
         self.assertEquals(get_triangle_num_with_n_or_more_divisors(1), 
              1) 
         self.assertEquals(get_triangle_num_with_n_or_more_divisors(2), 
              3) 
         self.assertEquals(get_triangle_num_with_n_or_more_divisors(6), 
              28) 
    
        @unittest.skip('Unimplemented') 
        def test_problem(self): 
         self.assertEquals(get_triangle_num_with_n_or_more_divisors(500), 
              'TODO: Replace this with answer') 
    

Ahora se están haciendo Proyecto Euler, estilo TDD. Está utilizando los ejemplos de casos dados para probar su código de implementación. Realmente, el único truco es escribir su implementación de una manera lo suficientemente flexible como para que se pueda usar tanto para la versión de práctica como para la versión real.

Me siento y escribo get_triangle_num_with_n_or_more_divisors. Una vez que pasa el test_example, trato de resolver el problema real; si funciona, actualizo mi caso test_problem con la respuesta real y bam tienes una prueba de regresión completa para arrancar.

Pensamiento
0

me gustaría compartir mi método:

Hackerrank, que tiene una Project Euler section, se conoce con el paradigma de TDD. Puntúa tu algoritmo usando casos de prueba desconocidos. Proporcionan un caso de prueba de muestra para que comiences. Desarrollo fuera de línea y escribo algunos casos de prueba para validar mi solución para obtener comentarios más rápidos y precisos.

¿Dónde se encontrarían esos casos? Puedes hacerlos a mano y quizás generarlos a partir de tu propio código de fuerza bruta que se ejecuta localmente. La belleza de esto es que debes contabilizar los casos límites por ti mismo, lo cual es más típico de un escenario de la vida real.

Ejemplo de pruebas en JavaScript:

var cases = [ 
    {input: '1\n15', output: '45'}, 
    ... 
]; 

describe('Multiples of 3 and 5', function() { 
    cases.forEach((v, i) => { 
    it('test case #' + i, function() { 
     assert.equal(unit(v.input), v.output); 
    }) 
    }); 
}); 

Aunque Hackerrank utiliza entrada y salida estándar, todavía tratan de aislar el código principal en una función y emplear la programación funcional.