Day 7 Crab Calculus

This was all done on an iPad, which means I didn't write any notes as I went. I'll try to explain my thinking after the code fragments (which I'm not going to edit in the spirit of openness and transparency)

So, In this case, I figured we just needed to iterate over each number, working out that the distance from the target is abs(position-target). We can turn a set of positions into a set of distances, we can repeat that for every possibile position (which is simply the range from min(position) to max(position)) then we end up with a list of total fuel needed to get to the given position, and then we can find the minimum of that.

We could probably write this condensed into:

min([sum(map(lambda p: abs(position-target),positions)) for target in range(min(positions),max(positions))])

But writing out each step as a separate function makes it easier to write it a step at a time, and easier to debug (a lot easier, I got quite a number of bits wrong in here when writing this)

Onto part 2 and triangle numbers

Ok, so now we need to not just take a linear cost to move around, but a cost that is 1 to move 1 space, 1+2 to move two spaces, 1+2+3 to move the three spaces and so on.

Now I started with a simple lookup table, thinking that we'd only need to move up to 10 spaces, which took me just a couple of seconds to work out, and you can still see the results in the test that I wrote.

Before I move on to why this didn't work, lets talk about that test. On the iPad and on the online version of Jupyter (which is otherwise amazing), I can't install ipytest or pytest. That gives really nice formatted responses for assert a ==b, if it fails, you get a traceback that says "a was xxx, b was yyy" etc. Without that, the asserts just fail. So I wrote a for loop to test the expected and actual values, test the comparison, and print the values. This helped because originally I had managed to get the index wrong when putting it all in and couldn't work out why my asserts were failing.

Right, anyway, although theres a lot of code here, the only thing that actually changed was fuel_to_move_distance. Because of the way that Python Notebook works, you can't just redeclare fuel_to_move_distance and have the functions declared above re-execute, you need to rewrite them.

So what about that distance*(distance+1)//2?

I remembered when I was at school staring at a poster that talked about a boy genius who was assigned some work from the maths teacher to solve the problem 1+2+3+4...500. Everyone was solving it one number at a time. What he recognised is that this was the same as saying (500+1)+(499+2)+(498+3)... So you can also say for a given range of numbers, it's equal to the first, plus the last, multiplied by the number of numbers in the range, divided by 2. Because our range started at 1, we end up with 1+distance times distance and all divided by two.

I will admit that I remembered the problem, I rememberd the story, but I didn't remember the solution. I googled, since I knew it was a thing and found the wikpedia page for Triangle Numbers. It turns out that the story that I saw on a poster at school appears to be lacking in evidence