Outside Context Problem
Grove Positioning System

Now, this one has been the bane of my life from an optimisation standpoint.

It's not a difficult one to comprehend or implement, but everything I did seemed slow in comparison to other puzzle run-times.

I tried a self-implemented circular linked list, a circular list based upon List<T>, then simply a List<T> which I thought got me as far is I could go.

I think I was at around the ~250ms execution time when I just couldn't see how to make it faster. This was annoying, because it isn't actually doing much... just many repetitions.

The Optimisation

Unfortunately, this one doesn't really have a clever optimisation from spotting something in the puzzle that didn't need to be done or finding patterns.

Instead, I went down to the metal and looked at List<T> to see what it was doing.

List<T> is basically backed by an array. However, because it is generic, it has to perform many checks on how to determine equivalence, boundary checks, etc...

As I knew the size of my array and the type stored, there was no need for these to consume precious processor cycles.

So, long story short, I ditched the List<T> for an array.

Here's the meat of the change.

- private readonly List<Number> _numbers = new();
+ private Number[] _numbers;

...

- var oldIndex = _numbers.IndexOf(number);
+ var oldIndex = 0;
+
+ for (var i = 0; i < _length; i++)
+ {
+     if (_numbers[i] == number)
+     {
+         oldIndex = i;
+
+         break;
+     }
+ }

...

- _numbers.RemoveAt(oldIndex);
-
- _numbers.Insert(newIndex, number);
+ if (oldIndex < newIndex)
+ {
+     Array.Copy(_numbers, oldIndex + 1, _numbers, oldIndex, newIndex - oldIndex);
+ }
+ else
+ {
+     Array.Copy(_numbers, newIndex, _numbers, newIndex + 1, oldIndex - newIndex);
+ }
+
+ _numbers[newIndex] = number;

It's difficult to say exactly as the run-times do differ from execution to execution (I thought computers were deterministic...), but I think this shaved ~100ms off the run-time on average.

A win, but it's my last remaining puzzle that exceeds 100ms... can I let this go?