0

I am doing project euler and i am at problem 15 now, here is a link: https://projecteuler.net/problem=15 . I am trying to solve this with binomial coefficient. Here is a site that explains it: http://www.mathblog.dk/project-euler-15/ . You can find it at the bottom.

My question is, why is the following code wrong? Since this follows the mathematical algorithm I think: n-k+i/i

        int grid = 20;
        long paths = 1;
        for (int i = 0; i < grid; i++)
        {
            paths *= (grid * 2) - (grid + i)
            paths /= (i + 1);
        }
        Console.WriteLine(paths);
        Console.ReadKey();

And why is this code wrong? This is exactly as the mathblog site but in 1 line.

        int grid = 20;
        long paths = 1;
        for (int i = 0; i < grid; i++)
        {
            paths *= ((grid * 2) - i) / (i + 1);
        }
        Console.WriteLine(paths);
        Console.ReadKey();

But why is this code right then? Isnt it the same as the previous code? And it doesn't exactly follow the mathematical algorithm does it? Because it's n-k+i/i, and this code does n-i/i

       int grid = 20;
        long paths = 1;
        for (int i = 0; i < grid; i++)
        {
            paths *= ((grid * 2) - i);
            paths /=  (i + 1);
        }
        Console.WriteLine(paths);
        Console.ReadKey();

Thnx guys!

Mathijs
  • 177
  • 3
  • 18
  • Try using `double paths` instead of `long`. As long is an integer, your problem could be the round up in the division – Magnetron Oct 25 '16 at 15:34
  • Your second block of code is not the same as what is in the URL you linked. Should be `paths = (paths * (grid * 2) - i) / (i + 1);` if you want to one-line it. What you wrote is the same as `paths = paths * (((grid * 2) - i) / (i + 1));` – Glorin Oakenfoot Oct 25 '16 at 15:37
  • The last code works, but I don't understand why :P Because in my eyes if i follow the mathematical algorithm correctly i should use the first code in my comment. (I am not a mathematician so i could be wrong). On top of that, isn't the 2nd code and the last code the same? Either way, the last code does work. – Mathijs Oct 25 '16 at 15:37
  • Ok, but why isn't it (grid * 2) - (grid + i) instead of (grid * 2) - i ? – Mathijs Oct 25 '16 at 15:38
  • 1
    (grid * 2) - (grid + i) => (2 * grid - grid) - i => grid - i – PaulF Oct 25 '16 at 15:39
  • But it's still (grid * 2) - i? and not grid - i – Mathijs Oct 25 '16 at 15:44
  • 1
    The reason why the 2nd code & last code are NOT the same is that you are using integer arithmetic. – PaulF Oct 25 '16 at 15:44
  • 1
    No it isn't - just stick some numbers in - grid = 20, i = 1 then you will see that (2 * 20) - (20 -1) = (40 - 19) = 21, (2 * 20) - 1 = 39 – PaulF Oct 25 '16 at 15:47
  • for one thing, I think your n=2*grid and your k=grid, right? In the formula n-k+i, you should thus get (2*grid)-grid+i = (2*grid)-(grid-i) and /not/ (2*grid)-(grid+i) – Arnaud Oct 25 '16 at 21:16
  • then, continuing analysing the formula on the blog, you'll notice that i has to run from 1 to k but your i runs from 0 to k-1 – Arnaud Oct 25 '16 at 21:21

2 Answers2

2

If you want to combain the calculation it should be like this

paths = (path *((grid * 2) - i))/(i + 1);
volkinc
  • 2,143
  • 1
  • 15
  • 19
0

By convention, in many programming languages, int/int gives an int,* not a floating point number. Your method implies that 'paths' should take values that are not int. In fact none of the three methods should work but by a happy coincidence, the last one worked: basically because all intermediate values of 'paths' happen to be binomial coefficients too.

Advice for debugging: ask your program to output the intermediate values. This helps a lot.

*: As a mathematician, I almost never need that feature. In fact the other convention (int/int -> double) would have made my life as a programmer easier on average.


I had a look at the blog you mention. This makes your message much more understandable. The blog mentions a formula : the product for i from 1 to k of (n-k+1)/i. So to mimick it you would need to write

    for (int i = 1; i <= grid; i++) // bounds!
    {
        paths *= (grid * 2) - (grid - i) // minus sign!
        paths /= (i + 1);
    }

About the fact that this works with ints: this is an accident due to the fact that in the intermediate values of the product (at the end of each loop) are binomial coefficients all along the computation. If you would compute the products and divisions in another order, you may very well get non-integers so the computation would fail with an integer variable type for path because of the convention int/int -> int. The blog is not very helpful in not mentionning that.

Arnaud
  • 247
  • 1
  • 8
  • I don't understand the minus sign though, because i would think to mimick (n-k+i)/i I would need to use the plus sign instead of the minus sign like this: `paths *= (grid * 2) - (grid + i)` – Mathijs Oct 26 '16 at 17:43
  • n-k+i means (n-k) + i, not n - (k+i) : in usual math /and/ in programming, the minus operator has precedence over the plus operator – Arnaud Oct 26 '16 at 20:00