I use this reverse-bit method of iteration for rendering tasks in one dimension, the goal being to iterate through an array with the bits of the iterator reversed so that instead of computing an array slowly from left to right the order is spread out. I use this for instance when rendering the graph of a 1D function, because this reversed bit iteration first computes values at well-spaced intervals a representative image appears only after a very small fraction of all the values are computed.
So after only a partial rendering we already have a good idea of how the final graph will look. Now I want to apply the same principle to 2D rendering, think raytracing and such, the idea is having a good overall view of the image being rendered even from an early stage. The problem is that making the same idea work as a 2D iteration isn't trivial.
Here's how I do it in 1D:
#include <stdio.h>
#include <stdint.h>
#include <math.h>
static const uint8_t ffo_lut[2048] = {
0,
1,
2, 2,
3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11
};
int32_t log2_ffo32(uint32_t x) // returns the number of bits up to the most significant set bit so that 2^return > x >= 2^(return-1)
{
uint32_t y;
y = x >> 21; if (y) return ffo_lut[y] + 21;
y = x >> 10; if (y) return ffo_lut[y] + 10;
return ffo_lut[x];
}
uint32_t reverse_bits32(uint32_t v)
{
v = ((v >> 1) & 0x55555555) | ((v & 0x55555555) << 1);
v = ((v >> 2) & 0x33333333) | ((v & 0x33333333) << 2);
v = ((v >> 4) & 0x0F0F0F0F) | ((v & 0x0F0F0F0F) << 4);
v = ((v >> 8) & 0x00FF00FF) | ((v & 0x00FF00FF) << 8);
return (v >> 16 ) | ( v << 16);
}
uint32_t reverse_n_bits32(uint32_t v, int n)
{
return reverse_bits32(v) >> (32 - n);
}
uint32_t reverse_iterator_bits32(int *i, uint32_t count) // i should not be the for loop iterator but rather a variable that starts from 0 and isn't touched outside of this function
{
uint32_t ir;
ir = reverse_n_bits32(*i, log2_ffo32(count-1)); // reverse the correct number of bits
(*i)++; // iterate i for the next call to this function
if (ir >= count) // if ir is too large
ir = reverse_iterator_bits32(i, count); // get the next ir in the sequence
return ir;
}
int main()
{
int i, i2, ir, count = 13;
for (i2 = i = 0; i < count; i++)
{
ir = reverse_iterator_bits32(&i2, count);
printf("%d -> %d\n", i, ir);
}
return 0;
}
So there's the main iterator i which iterates normally from 0 to count-1, there's i2 which iterates from 0 to the next power of 2 of count minus 1 with gaps, and there's ir which is the reverse bit iterator. For a count of 13 we get this ir sequence: 0 8 4 12 2 10 6 1 9 5 3 11 7. Note that it's the same sequence as if we had count of 16 with the 3 higher values missing.
But sadly a naive approach to 2D iteration leaves to be desired, one axis will complete entire lines in one stretch, whereas I want the points to be well spread out in 2D. I tried making a 1D iterator (over the full pixel count) that has its bits reversed and then using division and modulo turn this into 2D coordinates, but the quality of the results depend on the dimensions, with power-of-2 dimensions this solves nothing.
For an image of 8x8, ideally the first pixel calculated would be (0,0), then (4,4), (2,2), (2,6), (6,2), (6,6), (1,1), (1,5), (5,1) and so on, but I just can't figure out an elegant way to make a loop that iterates in 2D in such a sequence.
Reversing the bits achieves the expected effect in 1D, you could combine this shuffling technique with another one where you get the x and y coordinates be selecting the even, resp. odd, bits of the resulting number. Combining both methods in a single shuffle is highly desirable to avoid costly bit twiddling operations.
You could also use Gray Codes to shuffle values with n significant bits into a pseudo random order. Here is a trivial function to produce gray codes:
uint32_t gray(uint32_t x) { return x ^ (x - 1); }
Based on chqrlie's idea I used one iterator then distributed its bits in reverse order to x and y coordinates. I used a pretty dumb loop to do the shuffling and maybe that could be improved, but I can't think of anything obvious.
#include <stdio.h>
#include <stdint.h>
#include <math.h>
static const uint8_t ffo_lut[2048] = {
0,
1,
2, 2,
3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11 };
int32_t log2_ffo32(uint32_t x) // returns the number of bits up to the most significant set bit so that 2^return > x >= 2^(return-1)
{
uint32_t y;
y = x>>21; if (y) return ffo_lut[y]+21;
y = x>>10; if (y) return ffo_lut[y]+10;
return ffo_lut[x];
}
typedef struct { int x, y; } xyi_t;
#define MAXN(x, y) (((x) > (y)) ? (x) : (y))
#define get_bit(word, pos) (((word) >> (pos)) & 1)
xyi_t reverse_iterator_bits_2d(uint64_t *i, xyi_t dim)
{
xyi_t ir, dim_bits;
int ib, sh, shift;
shift = log2_ffo32(MAXN(dim.x, dim.y) - 1) - 1; // number of bits needed for each dimension
shuffle_start:
// Shuffle bits from i into ir.x and ir.y
ir.x = 0;
ir.y = 0;
sh = shift;
for (ib=0; *i >> ib; ib++, sh--)
{
ir.x |= get_bit(*i, ib) << sh;
ib++;
ir.y |= get_bit(*i, ib) << sh;
}
(*i)++; // iterate i for the next call to this function
if (ir.x >= dim.x || ir.y >= dim.y) // if ir is too large
goto shuffle_start; // get the next ir in the sequence
return ir;
}
int main()
{
xyi_t ip, dim = { 7 , 5 };
uint64_t i, i2, ir;
uint64_t count = dim.x*dim.y;
for (i2 = i = 0; i < count; i++)
{
ip = reverse_iterator_bits_2d(&i2, dim);
printf("(%d,%d) ", ip.x, ip.y);
if ((i&7)==7) printf("\n");
}
return 0;
}
The resulting pattern gives a fairly uniform image. Here's how it looks on a 320x240 render as it progresses:
Epilogue
I found it useful to fill in the blanks as it renders, by which I mean that every new pixel calculated is rendered as a block of the appropriate size given the current stride so that there is no visible black background unlike in the animation above. Here's an example of a loop that does this:
int max_bits = log2_ffo32(MAXN(dim.x, dim.y) - 1);
int stride = 4096; // initial value only used for first pixel at (0,0)
for (i2=i=0; i < pix_count; i++)
{
ip = reverse_iterator_bits_2d(&i2, dim);
source_pixel = pixel_rendering_function(ip);
int i2_bits = log2_ffo32(i2-2); // log2_ffo64 would be better
// When we change strides (block sizes)
if (i2-1 == (1 << i2_bits) && (i2_bits & 1) == 0)
{
int stride_shift = max_bits - (i2_bits>>1) - 1;
//stride_shift--; // a cool fractal pattern emerges
stride = 1 << stride_shift;
}
// Fill block of unset pixels around the new pixel
if (stride > 1)
{
xyi_t ib, start, end;
start = sub_xyi(ip, set_xyi(stride >> 1));
end = add_xyi(start, set_xyi(stride));
start = max_xyi(start, XYI0);
end = min_xyi(end, dim);
for (ib.y = start.y; ib.y < end.y; ib.y++)
for (ib.x = start.x; ib.x < end.x; ib.x++)
image_buffer[ib.y * dim.x + ib.x] = source_pixel;
}
}
Functions ending in _xyi to handle 2D vectors of int are not included but are fairly obvious.
I'm trying to find a certain path through my 2d array
My array could look like this:
temp = [
["placeholder", 2, 0],
["placeholder", 1, 7, 3],
["placeholder", 4, 5, 8],
["placeholder", 6, 3, 5, 2],
["placeholder", 7],
["placeholder", 3, 0],
]
The inner arrays contain a placeholder followed by a variable amount of integers. These integers range in value between 0-19 (0 and 19 both included)
I wanna find a path from top to bottom through these inner arrays where no number is used more than once.
At temp[0] i can choose my 1st value either 2 or 0
At temp[1] i can choose my 2nd value either 1, 7 or 3
At temp[2] i can choose my 3rd value either 4, 5 or 8
At temp[3] i can choose my 4th value either 6, 3, 5 or 2
Notice at this step I cannot pick 2 if I had already chosen 2 in the 1st step
I cannot pick 3 if I had already chosen 3 in the 2nd step
I cannot pick 5 if I had already chosen 5 in the 3rd step
etc.
These are some legal paths:
2-1-4-6-7-3
0-1-4-5-7-3
These are some illegal paths:
2-1-4-2-7-3 (2 is touched twice)
0-1-4-5-7-0 (0 is touched twice)
I want my function to output a completely legal path.
I just want my function to return false if no path is found.
I've tried to write my own recursive solution to this problem, which I think is working, but suffers from heavy inefficiency and therefore takes literal ages to complete.
The size of my intended array is more like 20 x 1..20
So far my code looks like this (written in Python 3) (and with a temp array):
temp= [
["placeholder", 7, 3],
["placeholder", 3, 3],
["placeholder", 4, 3],
["placeholder", 3, 8],
["placeholder", 1, 3],
]
def findpath(array, path = []):
if path and path.count(path[-1]) > 1:
return False
if len(path) == len(array):
print(path)
return True
routes = array[len(path)][1:]
for route in routes:
path.append(route)
if findpath(array, path):
return True
path.pop(-1)
findpath(temp)
This code prints: [7, 3, 4, 8, 1]
This approach is brute-forcing through every possibility until a solution is reached. In a worst-case scenario, my temp array would contain 20 arrays all containing 20 values each, that would make for 20! possible solutions, or in other words 2.432.902.008.176.640.000 possible paths. Let's exaggerate and say my pc takes 1 ms to process a single iteration of this function. My math could be wrong but that would mean this process could take 77,146,816.6 years to complete (not accounting for leap years), and imma be honest, I don't got this kinda time.
There must be a smarter way to approach this problem.
One thing I've noticed is that if the function encounters an inner array at step e.g. 15, containing only a single int e.g. 2, then the function will try adjusting its latest picks (first step 14 then step 13) one at a time, without realizing it has already picked 2 at step 2. In this situation by going back to step 2 and change the value from 2 to something else will save a f*** ton of iteration. The only problem is I have no idea how to implement this, nor any idea how to optimize this further.
Here is a real example array (not sure if it contains a solution)
temp = [
['placeholder', 2, 6, 11, 14, 15, 16, 18],
['placeholder', 2, 6, 7, 10, 11, 14, 15, 16, 17, 18, 19],
['placeholder', 2, 6, 10, 11, 14, 15, 16, 18, 19],
['placeholder', 2, 6, 11, 14, 15, 16, 18, 19],
['placeholder', 2, 6, 11, 14, 15, 16],
['placeholder', 2, 6, 7, 10, 11, 14, 15, 16, 18, 19],
['placeholder', 2, 6, 7, 8, 9, 10, 11, 14, 15, 16, 17, 18, 19],
['placeholder', 11, 15, 16],
['placeholder', 11, 14, 15, 16],
['placeholder', 0, 1, 2, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
['placeholder', 11, 15],
['placeholder', 2, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
['placeholder', 1, 2, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
['placeholder', 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
['placeholder', 2, 6, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19],
['placeholder', 2, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
['placeholder', 15],
['placeholder', 0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
['placeholder', 2, 11, 14, 15, 16],
['placeholder', 2, 6, 7, 8, 10, 11, 14, 15, 16, 17, 18, 19]
]
Hope you can help me learn <3
functional heritage
Recursion is a functional heritage and so using it with functional style yields the best results. This means avoiding mutations like .append and .pop and other side effects.
Below we use a set to efficiently skip invalid combinations and a tuple to store the path. A new set and tuple are constructed for each recursion -
def traverse(t, s = set(), p = ()):
if not t:
yield p
else:
[ [_, *values], *more ] = t
for v in values:
if v not in s:
yield from traverse(more, {*s, v}, (*p, v))
Using the data in your sample program -
temp = \
[ ["placeholder", 7, 3]
, ["placeholder", 3, 3]
, ["placeholder", 4, 3]
, ["placeholder", 3, 8]
, ["placeholder", 1, 3]
]
for p in traverse(temp):
print(p)
(7, 3, 4, 8, 1)
(7, 3, 4, 8, 1)
And using the data in your original question -
temp = \
[ ["placeholder", 2, 0]
, ["placeholder", 1, 7, 3]
, ["placeholder", 4, 5, 8]
, ["placeholder", 6, 3, 5, 2]
, ["placeholder", 7]
, ["placeholder", 3, 0]
]
for p in traverse(temp):
print(p)
(2, 1, 4, 6, 7, 3)
(2, 1, 4, 6, 7, 0)
(2, 1, 4, 3, 7, 0)
(2, 1, 4, 5, 7, 3)
(2, 1, 4, 5, 7, 0)
(2, 1, 5, 6, 7, 3)
(2, 1, 5, 6, 7, 0)
(2, 1, 5, 3, 7, 0)
(2, 1, 8, 6, 7, 3)
(2, 1, 8, 6, 7, 0)
(2, 1, 8, 3, 7, 0)
(2, 1, 8, 5, 7, 3)
(2, 1, 8, 5, 7, 0)
(2, 3, 4, 6, 7, 0)
(2, 3, 4, 5, 7, 0)
(2, 3, 5, 6, 7, 0)
(2, 3, 8, 6, 7, 0)
(2, 3, 8, 5, 7, 0)
(0, 1, 4, 6, 7, 3)
(0, 1, 4, 5, 7, 3)
(0, 1, 4, 2, 7, 3)
(0, 1, 5, 6, 7, 3)
(0, 1, 5, 2, 7, 3)
(0, 1, 8, 6, 7, 3)
(0, 1, 8, 5, 7, 3)
(0, 1, 8, 2, 7, 3)
generators are lazy
Because we're using a generator, we can stop generating the paths at any time. Perhaps you only want to find the first valid path -
def first_valid_path(t):
for path in traverse(t):
return path
temp = \
[ ["placeholder", 2, 0]
, ["placeholder", 1, 7, 3]
, ["placeholder", 4, 5, 8]
, ["placeholder", 6, 3, 5, 2]
, ["placeholder", 7]
, ["placeholder", 3, 0]
]
print(first_valid_path(temp))
(2, 1, 4, 6, 7, 3)
optimisation
One such optimisation we can make is to sort the input array by the number of possibilities, least posibilities first, as these are the most difficult to fulfill -
temp.sort(key=len)
print(temp)
[ ['placeholder', 15]
, ['placeholder', 11, 15]
, ['placeholder', 11, 15, 16]
, ['placeholder', 11, 14, 15, 16]
, ['placeholder', 2, 11, 14, 15, 16]
, ['placeholder', 2, 6, 11, 14, 15, 16]
, ['placeholder', 2, 6, 11, 14, 15, 16, 18]
, ['placeholder', 2, 6, 11, 14, 15, 16, 18, 19]
, ['placeholder', 2, 6, 10, 11, 14, 15, 16, 18, 19]
, ['placeholder', 2, 6, 7, 10, 11, 14, 15, 16, 18, 19]
, ['placeholder', 2, 6, 7, 10, 11, 14, 15, 16, 17, 18, 19]
, ['placeholder', 2, 6, 7, 8, 10, 11, 14, 15, 16, 17, 18, 19]
, ['placeholder', 2, 6, 7, 8, 9, 10, 11, 14, 15, 16, 17, 18, 19]
, ['placeholder', 2, 6, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19]
, ['placeholder', 2, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
, ['placeholder', 2, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
, ['placeholder', 1, 2, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
, ['placeholder', 0, 1, 2, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
, ['placeholder', 0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
, ['placeholder', 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
]
I didn't measure it, but a solution is found instantly (less than one second) -
print(first_valid_path(temp))
(15, 11, 16, 14, 2, 6, 18, 19, 10, 7, 17, 8, 9, 13, 12, 4, 1, 0, 5, 3)
To put the path in correct order, it would need to be un-sorted. There are a number of ways this can be done and I will consider updating the post later with a proposed solution. For now, that is left as an exercise for the reader :D
unsort
If you made it this far, great! Above I proposed a sorting and unsorting process and below I'll show one such way to handle the unsorting -
def traverse(init):
def sort(t):
z = list(enumerate(t))
z.sort(key=lambda _: len(_[1]))
return z
def unsort(p):
p.sort(key=lambda _: _[0])
return tuple(v for (_, v) in p)
def loop(t, s, p):
if not t:
yield unsort(p)
else:
[ (k, [_, *values]), *more ] = t
for v in values:
if v not in s:
yield from loop(more, {*s, v}, [*p, (k, v)])
yield from loop(sort(init), set(), [])
This works by creating an intermediate representation with sort -
[ (16, ['placeholder', 15])
, (10, ['placeholder', 11, 15])
, (7, ['placeholder', 11, 15, 16])
, (8, ['placeholder', 11, 14, 15, 16])
, (18, ['placeholder', 2, 11, 14, 15, 16])
, (4, ['placeholder', 2, 6, 11, 14, 15, 16])
, (0, ['placeholder', 2, 6, 11, 14, 15, 16, 18])
, (3, ['placeholder', 2, 6, 11, 14, 15, 16, 18, 19])
, (2, ['placeholder', 2, 6, 10, 11, 14, 15, 16, 18, 19])
, (5, ['placeholder', 2, 6, 7, 10, 11, 14, 15, 16, 18, 19])
, (1, ['placeholder', 2, 6, 7, 10, 11, 14, 15, 16, 17, 18, 19])
, (19, ['placeholder', 2, 6, 7, 8, 10, 11, 14, 15, 16, 17, 18, 19])
, (6, ['placeholder', 2, 6, 7, 8, 9, 10, 11, 14, 15, 16, 17, 18, 19])
, (14, ['placeholder', 2, 6, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19])
, (11, ['placeholder', 2, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19])
, (15, ['placeholder', 2, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19])
, (12, ['placeholder', 1, 2, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19])
, (9, ['placeholder', 0, 1, 2, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19])
, (17, ['placeholder', 0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19])
, (13, ['placeholder', 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19])
]
The paths are made up of tuples (sort_key, value) and unsorted using the sort_key -
[(16, 15), (10, 11), (7, 16), (8, 14), (18, 2), (4, 6), (0, 18), (3, 19), (2, 10), (5, 7), (1, 17), (19, 8), (6, 9), (14, 13), (11, 12), (15, 4), (12, 1), (9, 0), (17, 5), (13, 3)]
Finally the sort_key is removed and only the value path we care about is yielded. Now we can see the path in the correct order. The result is instantly computed (less than one second) -
print(first_valid_path(temp))
(18, 17, 10, 19, 6, 7, 9, 16, 14, 0, 11, 12, 1, 3, 13, 4, 15, 5, 2, 8)
all valid paths
Above we use find_first_path but our sorting/unsorting technique is also efficient at finding all solutions -
for p in traverse(temp):
print(p)
For this particular input, there is only one valid path. However this program terminates quickly (less than one second), signalling that all possibilities have been exhausted.