랜덤 균등 분배 알고 리즘 아시는분 있나요??

만약 100이라는 숫자가 있다면 

 

20개의 필드에 

 

각각 숫자가 랜덤하게 들어가는데 

 

나중에 총합은 100이 나와야 합니다. 

 

자바스크립트나 PHP. 혹은 이론만 말씀해 주셔도 됩니다. 

 

아....수학 공부 해야 되는데.

|

댓글 11개

일단, 친숙한 규식씨 말고, 방정식씨를 한 번 써보시는 게... 차원이 좀 높아지는 건 함정이긴 한데, 생각을 방정식으로 기술한다 생각하시면 됩니다. 그걸 나중에 언어로써 옮겨놓으면 프로그래밍 거의 다 한 겁니다.
숫자 (a) = 100
필드 (b) = 20
a / b = c
각 필드에 c 대입
a % b = d
d 가 0 이상이라면 20개의 필드중 아무곳에나 넣기
<?

$range = 20;

for($i = 1; $i <= $range; $i++) {

$total = array_sum($num); //배열총합
$min= $range- $i; // 1이 들어갈때의 최소값

$num[] = rand(1, 100 - $total - $min);

}

print_r($num);
echo "배열총합 : ". array_sum($num);

?>

Array ( [0] => 32 [1] => 49 [2] => 2 [3] => 1 [4] => 1 [5] => 1 [6] => 1 [7] => 1 [8] => 1 [9] => 1 [10] => 1 [11] => 1 [12] => 1 [13] => 1 [14] => 1 [15] => 1 [16] => 1 [17] => 1 [18] => 1 [19] => 1 )
배열총합 : 100

근데 이형태의 코드는 문제가 범위에 비해서 최대값이 작으면 하나의 셀에서 큰값이 랜덤으로 나와버리면 나머지는 꽤 많은 셀에서
1이 분배되는 현상이 생기네요

이걸 원하시는건진 모르겠는데 그냥 대충 짜봤습니다.

원리는 소스보시면 이해되실듯 합니다.

하나의 셀마다 순차로 loop하되
조건을 부여해서 남은 셀수에 최소한의 값이 1이 들어갈수 있는 범위 내에서 셀마다
랜덤의 범위를 지정하는겁니다.

이론은 맞는거 같은데 결과도 나오긴 하는데 1이 너무 많이 나오네요.
군포돼지 //
네 저도 저 비슷하게 짜봤는데 균등하게 분배가 안되더라구요.
ㅠ.ㅠ
100% 은 아니지만,
원하시는 영역이 없다면 rand(4,8)) 을 mt_rand(0,100) 로 바꿔 보세요.

$field = array_fill(0, 20, 0);
for ($i=0;$i<=19; $i++) {
$field[$i] = mt_rand(4,rand(4,8)); <--- 이부분을 원하시는 영역으로 조절
if( array_sum($field) > 100 ) {
$field[$i] = 0;
$field[$i] = 100-array_sum($field);
break;
}
if($i==19 && array_sum($field)<100) $field[$i] += 100-array_sum($field);
}


Array
(
[0] => 4
[1] => 5
[2] => 5
[3] => 8
[4] => 4
[5] => 5
[6] => 4
[7] => 4
[8] => 7
[9] => 6
[10] => 4
[11] => 4
[12] => 4
[13] => 5
[14] => 7
[15] => 4
[16] => 4
[17] => 6
[18] => 5
[19] => 5
)
100
감사합니다. 응용해서 해보겠습니다.
이런 고급진 방법이 있군요~
저는 아마도 배열 탐색을 하지 않았을까... ㅡㅡ;; 머리 쓰는 건 정말 자신이 없어요.
아... 완전 찰진 코드네역? 좋네요.ㅋ
골고루 하는 방법이 100% 은 아니지만, 좀더 가공한 재귀호출입니다...
위의 소스보다는 낳지만, 100% 가 아니니....일하러....후다다닥
전문 알고리즘 구현하시는분이 보시면 저 두들겨 맞은껄 알지만...

function func_radom($cnt) {
$vmin = 4;
$vmax = 6;
$field = array_fill(0, 20, 0);
for ($i=0;$i<=19; $i++) {
$field[$i] = mt_rand($vmin,rand($vmin+1,$vmax));
if( array_sum($field) > 100 ) {
$field[$i] = 0;
$field[$i] = 100-array_sum($field);
break;
}
}

if($i==20) {
if( array_sum($field)<100 ) $field[19] += 100-array_sum($field);
if( $field[19]>$vmax || $field[19]<$vmin ) {
if($cnt < 30) { <----- 30 회 제한을 준것 .... 가끔 사용하시는거라면 숫자 더 주세요
$cnt++;
return func_radom($cnt);
}
}
}

return $field;
}

$data = func_radom(0);

Array
(
[0] => 5
[1] => 6
[2] => 4
[3] => 5
[4] => 4
[5] => 6
[6] => 6
[7] => 4
[8] => 5
[9] => 6
[10] => 6
[11] => 4
[12] => 4
[13] => 5
[14] => 4
[15] => 4
[16] => 5
[17] => 5
[18] => 6
[19] => 6
)
100
감사드립니다.
역시 엄청 잘하시네요.
음 알고리즘 이라는 부분이 나오는 결과값에 대해서 조건별로 범위 제한을 해서 되는 부분인가 싶으네요

가령 이를테면 균등 분배라고 해서 평균적으로 5가 나와야 하기 때문에 min과 max를 4 6으로 지정한다면

이미 각 필드에 각각의 숫자가 랜덤하게 들어가야 한다는 조건에서 어느정도 벗어나있지 않나 싶습니다.

최대한 랜덤하게 부여하면서 고르게 분포를 시키고자 한다면 확률에 의존하는수 밖에 없지 않나 싶습니다.

최대와 최소를 부여해서 편차를 낮춘다면 100이라는 숫자와 20개의 셀이라는값이 유동적으로 변할때

적용할 수 있는 부분에 한계가 생기게 됩니다.

<?
$loop = 100;
$range = 20;

for($i=0; $i < 100; $i++){

$key = mt_rand(1,$range);
$num[$key]++;

}

print_r($num);
?>

이렇게 간단히 처리하는 방법도 있습니다만 개별로 아무래도 범위가 커지면
rand냐 mt_rand냐의 특성도 많이 타게되는 경향도 있습니다.
댓글을 작성하시려면 로그인이 필요합니다. 로그인

자유게시판

+
제목 글쓴이 날짜 조회
11년 전 조회 1,800
11년 전 조회 1,221
11년 전 조회 1,704
11년 전 조회 1,278
11년 전 조회 1,105
11년 전 조회 1,382
11년 전 조회 1,128
11년 전 조회 1,672
11년 전 조회 2,036
11년 전 조회 1,820
11년 전 조회 1,128
11년 전 조회 1,147
11년 전 조회 1,826
11년 전 조회 1,225
11년 전 조회 9,053
11년 전 조회 1,391
11년 전 조회 1,287
11년 전 조회 1,812
11년 전 조회 1,997
11년 전 조회 1,117
11년 전 조회 1,801
11년 전 조회 2,448
11년 전 조회 1,971
11년 전 조회 1,192
11년 전 조회 1,172
11년 전 조회 1,177
11년 전 조회 1,219
11년 전 조회 1,569
11년 전 조회 1,376
11년 전 조회 1,205
🐛 버그신고