Human Resource Machine/Year 22

Strategy
Naturally, in order to solve this problem, you need to know exactly what the Fibonacci Sequence is. In the field of mathematics, the function is expressed as:

Fn = Fn-1 + Fn-2

With the first three seed values constant:

F(0) = 0, F(1) = 1, F(2) = 1

Then every number after that is the sum of the previous two numbers. So:

F(3) = 1 + 1 = 2, F(4) = 1 + 2 = 3, F(5) = 2 + 3 = 5, ...

For this level it is safe to assume a) you will only receive positive integers, b) none of them will be less than 3, and c) your output sequence begins from F(1) not F(0).

To correctly write this program, we'll need to focus on three parts: the initialization, the mathematics logic, and the need to update the memory.

Initialization
Part of the work needed for this problem is the setup. As described above, the next number in the Fibonacci series is calculated by adding the two previous numbers together. The question is, where do the first two numbers come from? The first two numbers are one, and you have to basically fabricate them. Once you have 1 and 1, the rest of the number are just calculated.

All we have at the start of the program is a zero in box 9. There are two ways to think about initialization. One is to say in order to calculate the third number, we need to start with a 1 and a 1. The other is to say the first number is 1, and the second number is 0 + 1. The choice you make here will have an impact on how fast the program runs. For now, we'll take the second approach since it requires less code. So we'll copy the zero from box 9, to boxes 0 and 1, and we'll bump box 1 once. This way we start with our 0 and 1. On top of that, we know that we need a 1 in the OUTBOX, so we'll copy that newly bumped 1 over as well.

The other aspect that you need to consider, is that this program must not generate a number in the Fibonacci series that is higher than the input provided. So when we grab something off the conveyor belt, we need to cache it somewhere so we can test whether we've gone past the input. So we'll copy that number into box 5. The start of our program looks like this:

a:   INBOX COPYTO  5 COPYFROM 9 COPYTO  0 COPYTO  1 BUMPUP  1 OUTBOX

Mathematics
Throughout this process, we're going to be adding the contents in box 0 with the contents of box 1, and put the answer in box 2. That's how we get the next number in the Fibonacci series. However, before we copy that answer to the outbox, we need to test whether that number is greater than the INBOX number or not.

Since we only have JUMP IF NEGATIVE instead of a "jump if positive" command, we need to subtract the numbers in a way that lets us know whether we need to stop or not while making use of only one jump command. So we have to take the inbox number and subtract the value in box 2 from it. If the answer is negative, we're done counting, and we need to start at the top. Otherwise, we can keep going.

The middle portion of this program now looks like this:

b:   COPYFROM 1 ADD     0 COPYTO  2 COPYFROM 5 SUB     2 JUMPN   a

Memory update
For the code above to work, we always assume that we're adding the contents of box 0 with the contents of box 1. However, after adding the two numbers, the next number is calculated by adding the content of box 1 to the content of box 2. So we have to slide those values over.

We'll copy the content of box 1 to box 0, and the content of box 2 to box 1. At that time, we'll happen to be holding the very value that we need to send to the OUTBOX, so that's a good time to take care of it before we jump back to add some more numbers. The complete code for this solution looks like this:

a:   INBOX COPYTO  5 COPYFROM 9 COPYTO  0 COPYTO  1 BUMPUP  1 OUTBOX b:   COPYFROM 1 ADD     0 COPYTO  2 COPYFROM 5 SUB     2 JUMPN   a    COPYFROM 1 COPYTO  0 COPYFROM 2 COPYTO  1 OUTBOX JUMP    b

Optimizing
The above program will actually meet both the size and the speed challenges. However, it's worth pointing out that by adding a few more lines of code, its actually possible to make the program much faster.

Remember above that we had to choose between starting with 0 and 1, or with 1 and 1. We chose 0 and 1 because it helped keep the size of the code down. Starting with 1 and 1 takes a little more work in the initialization phase, but it will result in a much faster program since you don't take any time to calculate that 0 + 1 = 1. The program for this looks as follows:

a:   INBOX COPYTO  5 COPYFROM 9 COPYTO  0 BUMPUP  0 OUTBOX COPYFROM 0 b:   COPYTO   1 OUTBOX COPYFROM 1 ADD     0 COPYTO  2 COPYFROM 5 SUB     2 JUMPN   a    COPYFROM 1 COPYTO  0 COPYFROM 2 JUMP    b

If you're looking to go above and beyond the speed challenge, you can actually cache (or in other words, calculate and store,) values of the sequence first, and then do comparisons with the previously computed values. We are limited by the number of spaces we can copy to, but, luckily, it is enough to pass all the test cases. This would make the program unnecessarily long due to the lack of arrays, but would also dramatically increase the speed of the program after the first loop. Such a program would look as follows:

BUMPUP  9 COPYTO  8 ADD     8 COPYTO  7 ADD     8 COPYTO  6 ADD     7 COPYTO  5 ADD     6 COPYTO  4 ADD     5 COPYTO  3 ADD     4 COPYTO  2 ADD     3 COPYTO  1 a: b: c: d: e: f: g: h: i: j:   INBOX COPYTO  0 SUB     9 JUMPN   a    COPYFROM 9 OUTBOX COPYFROM 0 SUB     8 JUMPN   j    COPYFROM 8 OUTBOX COPYFROM 0 SUB     7 JUMPN   i    COPYFROM 7 OUTBOX COPYFROM 0 SUB     6 JUMPN   h    COPYFROM 6 OUTBOX COPYFROM 0 SUB     5 JUMPN   g    COPYFROM 5 OUTBOX COPYFROM 0 SUB     4 JUMPN   f    COPYFROM 4 OUTBOX COPYFROM 0 SUB     3 JUMPN   e    COPYFROM 3 OUTBOX COPYFROM 0 SUB     2 JUMPN   d    COPYFROM 2 OUTBOX COPYFROM 0 SUB     1 JUMPN   c    COPYFROM 1 OUTBOX JUMP    b