これは数学の問題です。良い解決策があります。ただし、事前にインデックスのリストを並べ替える必要があります。
アイデアは、0から15までの整数を円に配置し、軸に表示される順序で要素を取得することです。
ObjCでこれを行うのはとても面倒なので、Pythonソリューションを紹介します。
from math import pi, cos
def circlesort(N, start):
eps = 1e-8
res = range(N)
def f(x):
return -cos(2*pi*(x-start-eps)/N)
res.sort( lambda x,y:cmp(f(x), f(y)) )
return res
それから
print circlesort(15, 5)
出力
[5, 6, 4, 7, 3, 8, 2, 9, 1, 10, 0, 11, 14, 12, 13]
これは望ましい結果です。
編集
さて、ここにCの実装があります:
#include <stdlib.h>
#include <math.h>
#define sign(x) ((x)>0?1:(x)<0?-1:0)
void circlesort(int* values, int N, int start){
double f(int x)
{
return -cos(2*M_PI*((double)(x-start)-.25)/N);
}
int compare (const void * a, const void * b)
{
return sign( f(*(int*)a) - f(*(int*)b) );
}
qsort (values, N, sizeof(int), compare);
}
これにより、長さNの整数の配列がサークルソートされます。次のように使用します。
int i, N = 15;
int indexes[N];
for (i=0;i<N;i++)
indexes[i] = i;
circlesort(indexes, N, 5);
これで、配列indexes
が目的の順序で並べ替えられます。入れ子関数があるため-fnested-functions
、コンパイラフラグに追加する必要があります。
編集2
はるかに単純な解決策があるという事実を考えると(私の他の答えを参照)、これはかなり学術的です。