我希望尽可能远离彼此。
假设数组的长度为360.
Element 1 goes at position 0.
Element 2 goes at position 180.
Element 3 goes at position 90 (or 270).
Element 4 goes at position 270 (or 90).
Element 5 goes at position 45.
Element 6 goes at position 135.
Element 7 goes at position 225.
Element 8 goes at position 315.
Element 9 goes at position 23.
Element 10 goes at position 68.
等等。
我们说长度是100。
Element 1 goes at position 0.
Element 2 goes at position 50.
Element 3 goes at position 25 (or 75).
Element 4 goes at position 75 (or 72).
Element 5 goes at position 13.
Element 6 goes at position 38 (or 75).
Element 7 goes at position 63.
等等。
用户将传入数组长度和元素编号。所以f(2,360)将返回180而f(7,100)将返回63。
给定数组长度和元素编号输出位置的方法是什么?
编辑:我的具体应用是,在我知道将会有多少元素之前,我试图为每个元素选择不同色调的颜色,等间距。
编辑2:我的问题陈述造成了一些混乱。为简单起见,我在演示解决方案中使用了整数,当时我并不想要整数输出。我的错。我会将解决这个问题的解决方案标记为正确,但我应该警告我自己没有检查过。我的答案在下面我已经检查过并且有效,尽管它是0索引并返回小数。
答案 0 :(得分:2)
// Returns the position of element n
// as far away as possible from other elements
// with total space totalSpace
function getPlacement(n, totalSpace) {
if (n == 0) return 0;
var divisions = Math.pow(2, log2Floor(n) + 1);
var position = ((2 * (n + 1 - (divisions / 2))) - 1);
return position * ( totalSpace / divisions );
}
// Quickly returns the floor of the base 2 log
function log2Floor(x) {
if (x === 0) return -Infinity;
for (var i = 0; i < 32; ++i) {
if (x >>> i === 1) return i;
}
}
答案 1 :(得分:0)
您正在寻找的这个函数,我们称之为f(i,n)
,可以按如下方式递归定义(假设索引从0开始,log(x)
输出{{1}的基数2对数的下限}}):
x
希望这有帮助!
答案 2 :(得分:0)
只要0 < i <= n
,这是一个不重复的非递归解决方案。它是尽可能以语言无关的方式编写的,所以如果你不了解ruby它应该无关紧要:
# round, but if fraction is .5 then floor.
def round2 x
double = 2*x
double == double.round ? x.floor : x.round
end
# i is 1-based. 0 < n.
def f( i, n )
j = (i-1) % n # convert to 0-based and mod n index j
nsig = 1 << Math.log2(n).floor # highest bit in n
if (j&nsig) == 0
j2 = 1 << Math.log2((j<<1)|1).floor # smallest power of 2 > j
angle = n*(j2^((j<<1)|1)) / j2.to_f # to_f converts to float
return angle.round
else
return round2(n*((nsig^j)+0.5)/(nsig^n))
end
end
[360,100].each do |n|
puts "\nFor array length #{n}:\n"
(1..12).each do |i|
puts 'Element %d goes to position %d.' % [ i, f(i,n) ]
end
end
输出:
For array length 360:
Element 1 goes to position 0.
Element 2 goes to position 180.
Element 3 goes to position 90.
Element 4 goes to position 270.
Element 5 goes to position 45.
Element 6 goes to position 135.
Element 7 goes to position 225.
Element 8 goes to position 315.
Element 9 goes to position 23.
Element 10 goes to position 68.
Element 11 goes to position 113.
Element 12 goes to position 158.
For array length 100:
Element 1 goes to position 0.
Element 2 goes to position 50.
Element 3 goes to position 25.
Element 4 goes to position 75.
Element 5 goes to position 13.
Element 6 goes to position 38.
Element 7 goes to position 63.
Element 8 goes to position 88.
Element 9 goes to position 6.
Element 10 goes to position 19.
Element 11 goes to position 31.
Element 12 goes to position 44.
基本思想是可视化圆圈周围项目的位置。如果你查看基于0的索引的位,那么你可以快速查看索引的位长和它们放在圆周的位置之间的模式。
例如,元件5,6,7,8如下放置。首先,减去1使它们基于0,并观察位:
4: 100
5: 101
6: 110
7: 111
这些是长度为3(位大小)的所有索引。它们放置在圆周围的45°,135°,225°,315°位置。然后只是算术和舍入以转换为圆形数组中的索引。
这是JavaScript中的一个版本:http://jsfiddle.net/gfj7Lpya/3/
OP编辑1&amp; 2,在JavaScript中:
// i is 0-based. Return value in [0,1).
function f( i )
{
if( i === 0 ) return 0;
var ndigits = Math.floor(Math.log(i)/Math.LN2); // in base 2
return ((1<<ndigits^i)<<1|1) / (2<<ndigits);
}
JSFiddle:http://jsfiddle.net/gfj7Lpya/4/
例如,要将此值应用于360的数组“长度”,只需将输出乘以:
360 * f(8) // 22.5