7

I'm starting to go through the questions in project Euler, and I'd like to approach it with a TDD style, but I'm having trouble finding the numeric answer to the question that doesn't include the code. Is there any resource with that data so that I can make test cases that will tell me if I've solved the problem correctly?

My motivation for this is that I feel like the algorithm is the answer, not the number. If I look at someone else's code sample, it ruins the challenge of figuring out how to solve the problem.

Edit: I'm looking specifically for the number of the answer with no context or algorithm with it so that I can do something like the following. I know it's more verbose, but I'd like to be able to have a pass/fail result to tell me whether or not my algorithm is correct, rather than looking at someone else's code example to know whether I've done it correctly.

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())
Air
  • 8,274
  • 2
  • 53
  • 88
Daenyth
  • 35,856
  • 13
  • 85
  • 124
  • Having answers would ruin the challenge part of it. What you could do is run multiple "solutions" and compare their output. – Hamish Grubijan Jun 26 '10 at 12:38
  • 3
    For me I feel the opposite. The number is meaningless without the algorithm. I feel like the code itself is the answer, and seeing how someone else did it ruins the challenge of figuring out *how* to solve it. – Daenyth Jun 26 '10 at 12:40
  • 3
    Isn't inputting the number in the contex page and getting the "you solved it!" screen sufficient? I don't really see how unit tests would give any help there. Try instead writing different algorithms, modify to render them faster, or simply more elegant. – nico Jun 26 '10 at 12:48
  • 1
    @nico: That would be fine, but I didn't know there was such a page. Where is it? – Daenyth Jun 26 '10 at 12:53
  • 1
    well, when you go in the problem page you can input your solution there. Say for instance: http://projecteuler.net/index.php?section=problems&id=226 (if you already solved it the solution would be marked it instead). Once you know the solution the idea is to optimise the algorithm, what's the advantage of a unit test vs. a `if` condition at the end of your code? – nico Jun 26 '10 at 12:59
  • 1
    Odd, I don't see that area. Maybe you need to be logged in? I'll try doing that. – Daenyth Jun 26 '10 at 13:01
  • Yes, definitely you need to be logged in :) – nico Jun 26 '10 at 15:50

7 Answers7

11

TDD and project Euler assignments don't necessarily go well together. First and foremost, TDD won't help you solve any project Euler (PE) problems. This reminds me of that well known attempt by a guy to "solve Sudoku" by using TDD.

TDD is not a design technique. It can be very useful when applicable, but don't think of it as a silver bullet.

A PE problem usually involves some heavy computation that ends in a single number, which is the answer. To apply TDD mindfully, I recommend using it for the mathematical utilities you will develop as parts of your endeavors to solve PE problems. For example, my utils module for PE consists of functions for computing primes, splitting numbers to digits, checking for palindromes, and so on. This module has a set of tests, because these functions are general enough to be tested. The PE solutions themselves don't have tests - the only real test needed for them is to eventually generate the correct answer.

Eli Bendersky
  • 263,248
  • 89
  • 350
  • 412
  • Sorry, I should have made myself more clear. I'm looking for the number by itself with no context so that I can do something like `assertEquals(my_solution(), expected_answer)`. I'll update the question – Daenyth Jun 26 '10 at 12:33
  • +1 writing tests for Project Euler problems only makes sense if you already have the answer and you want to optimize it. – György Andrasek Jun 26 '10 at 12:43
  • 1
    You can test the algorithm for solving the problem with a smaller limit against a value derived by brute force (I often did that). – starblue Jun 26 '10 at 18:56
4

The problem page on the project Euler website has an input to check your answer. That's all I really need.

Daenyth
  • 35,856
  • 13
  • 85
  • 124
2

Yes, you can setup your unit tests against the test data they give.

It appears that you are using Python to solve the problems (as am I). What I do to validate the different components is to do simple 'assert' statements against the example data. It works well and there is less time overhead. Besides, you don't need to run the entire test suite when you are just needing to know if your new changes for problem 30 are correct.

Using Assertions Effectively

Frank V
  • 25,141
  • 34
  • 106
  • 144
1

I know I'm 3 years late to the party but I thought I would share how I am approaching Project Euler via TDD.

I'm working in Python, if that matters to you.

What I do is this:

  • Every problem gets (at a minimum) its own function that serves as an entry/exit point, no matter how trivial or silly it may feel. Problems may also get helper functions if the problem requires some kind of functionality that you think you might need in the future.
  • Most Project Euler questions include a smaller demo/test problem in the test itself. This test problem illustrates what you most solve but on a smaller scale.
  • Plan to set up your entry/exit function with a parameter that allows the function to solve both the toy version of the problem as well as the harder full scale version. For instance, on problem 12 my (ridiculously named) entry point is get_triangle_num_with_n_or_more_divisors(n).
  • At this point I haven't implemented the function, just named it. Now I will write two tests for this problem: test_example and test_problem. I'll decorate test_problem with @unittest.skip('Unimplemented') for now since we don't know the answer. Your test file might look something like mine:

    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')
    

Now you are doing Project Euler, TDD style. You are using the example cases given to test your implementation code. Really the only trick to it is to write your implementation in a flexible enough way that it can be used to solve both the practice version and the real version.

I then sit down and write get_triangle_num_with_n_or_more_divisors. Once test_example is passing, I try to solve the real problem; if it works I update my test_problem case with the real answer and bam you've got a full blown regression test to boot.

chucksmash
  • 5,777
  • 1
  • 32
  • 41
1

The unit test IS the answer.

The problems are usually so simple (not in terms of difficulty, but at least code layout) that breaking them up into various methods/classes is usually silly.

Dominic Bou-Samra
  • 14,799
  • 26
  • 100
  • 156
  • I suppose it's overkill, but it's also motivated by wanting to learn how to use unit tests in python. I also like to be able to check my work without referencing anyone else's code. Basically I just want to have a correct/incorrect statement relating to my algorithm. – Daenyth Jun 26 '10 at 12:37
  • I can't say I agree completely. In part in the earlier questions, this is true to be sure. But as things get more complex and you need to break down components further, you'll need/want to test individual components. Of course, some people can write a very short program to answer the questions and in that case you're answer is right but most (human) peoples will be breaking the problem down in smaller chunks. – Frank V Nov 19 '13 at 21:05
0

Despite the fact that these problems are more of a challenge without an answer to steer towards, a quick google search yielded:

http://code.google.com/p/projecteuler-solutions/wiki/ProjectEulerSolutions

0

Thought I'd share my approach:

Hackerrank, which has a Project Euler section, goes by the TDD paradigm. It scores your algorithm using unknown test cases. They provide one sample test case to get you started. I develop offline and write some other test cases to validate my solution to get quicker and more precise feedback.

Where would one get those cases? You can do them by hand, and perhaps generate them from your own brute forcing code which is run locally. The beauty of this is that you must account for edge cases yourself, which is more typical of a real life scenario.

Example of tests in 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);
    })
  });
});

Although Hackerrank uses stdin and stdout, I still try to isolate the main code into a function and employ functional programming.