2010-11-23 76 views
3

我有一個數組包含0到360之間的許多值(如圓度),但分佈不均勻:如何從Perl數組值中獲得均勻分佈的示例?

1,45,46,47,48,49,50,51,52,53,54 ,55,100,120,140,​​188,210,280,355

現在我需要將這些值減小到eg只有4個,但儘可能均勻的分佈值。

如何做到這一點?

感謝, 揚

+1

你需要更仔細的話你的問題。目前它沒有什麼意義。 – singingfish 2010-11-23 02:12:18

回答

3

放在一個圓圈的數字,就像一個時鐘。現在建立一個邏輯交叉點,例如12點,3點,6點和9點。把12放在第一個數字。現在找到哪些數字最接近3,6和9點,並記錄第一個數字旁邊的三個數字的距離的總和。

通過順時針旋轉十字的頂端 - 12點鐘的點 - 直到它與下一個數字完全對齊爲止。再次測量最近的數字與其他三個交叉點的距離,並將該分數記錄在當前12點的數字旁邊。

重複,直到你到達12點鐘已經一路旋轉至原來的3點鐘,此時你就大功告成了。無論哪個號碼具有分配給它的最低總和,都決定了獲勝配置。

該解決方案推廣到任何值的範圍R 您希望減少設置的任何數量的N個最終點。在「跨界」每個點是R/N遠離彼此,而你只需要旋轉,直到你的十字架的頂部到達下一個手臂是在原來的位置。所以如果你想要6分,你會有一個六角十字,每相隔60度,而不是四角十字,相隔90度。如果您的範圍不同,您仍然執行相同的操作。這樣,你不需要物理時鐘和交叉來實現這個算法:它可以用於任何R和N.

我感到很難從Perl的角度來看這個答案,因爲我已經沒有設法包括任何美元簽署解決方案。 :)

+1

第1步:從Perl數組值中獲取均勻分佈的示例。第2步。 ???。第3步。** $$$ ** – 2010-11-23 06:25:28

1

使用clustering algorithm將數據分成均勻分佈的分區。然後從每個集羣中獲取一個隨機值。下面$datafile看起來是這樣的:

1 1 
45 45 
46 46 
... 
210 210 
280 280 
355 355 

第一列是一個標籤,第二列是數據。運行與$K = 4以下:

use strict; use warnings; 
use Algorithm::KMeans; 

my $datafile = $ARGV[0] or die; 
my $K  = $ARGV[1] or 0; 
my $mask  = 'N1'; 

my $clusterer = Algorithm::KMeans->new(
    datafile => $datafile, 
    mask  => $mask, 
    K  => $K, 
    terminal_output => 0, 
); 

$clusterer->read_data_from_file(); 

my ($clusters, $cluster_centers) = $clusterer->kmeans(); 

my %clusters; 

while (@$clusters) { 

    my $cluster = shift @$clusters; 
    my $center = shift @$cluster_centers; 

    $clusters{"@$center"} = $cluster->[int rand(@$cluster - 1)]; 
} 

use YAML; print Dump \%clusters; 

返回此:

120: 120 
199: 188 
317.5: 355 
45.9166666666667: 46 

第一列是羣集的中心,第二個是從羣集中的選擇的值。各中心的彼此距離應根據Expectation Maximization algorithm最大化。