Freeciv-3.3
Loading...
Searching...
No Matches
utility
distribute.c
Go to the documentation of this file.
1
/***********************************************************************
2
Freeciv - Copyright (C) 2004 - The Freeciv Project
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; either version 2, or (at your option)
6
any later version.
7
8
This program is distributed in the hope that it will be useful,
9
but WITHOUT ANY WARRANTY; without even the implied warranty of
10
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
GNU General Public License for more details.
12
***********************************************************************/
13
14
#ifdef HAVE_CONFIG_H
15
#include <fc_config.h>
16
#endif
17
18
/* utility */
19
#include "
log.h
"
/* fc_assert */
20
21
#include "
distribute.h
"
22
23
/************************************************************************/
34
void
distribute
(
int
number,
unsigned
groups,
const
unsigned
*
ratios
,
35
int
*result)
36
{
37
int
i
, sum = 0,
rest
[groups],
max_groups
[groups],
max_count
, max;
38
#ifdef FREECIV_DEBUG
39
const
int
original_number
= number;
40
#endif
41
42
/*
43
* Distribution of a number of items into a number of groups with a given
44
* ratio. This follows a modified Hare/Niemeyer algorithm (also known
45
* as "Hamilton's Method"):
46
*
47
* 1) distribute the whole-numbered part of the targets
48
* 2) sort the remaining fractions (called rest[])
49
* 3) divide the remaining source among the targets starting with the
50
* biggest fraction. (If two targets have the same fraction the
51
* target with the smaller whole-numbered value is chosen. If two
52
* values are still equal it is the _first_ group which will be given
53
* the item.)
54
*/
55
56
for
(
i
= 0;
i
< groups;
i
++) {
57
sum +=
ratios
[
i
];
58
}
59
60
/* 1. Distribute the whole-numbered part of the targets. */
61
for
(
i
= 0;
i
< groups;
i
++) {
62
result[
i
] = number *
ratios
[
i
] / sum;
63
}
64
65
/* 2a. Determine the remaining fractions. */
66
for
(
i
= 0;
i
< groups;
i
++) {
67
rest
[
i
] = number *
ratios
[
i
] - result[
i
] * sum;
68
}
69
70
/* 2b. Find how much source is left to be distributed. */
71
for
(
i
= 0;
i
< groups;
i
++) {
72
number -= result[
i
];
73
}
74
75
while
(number > 0) {
76
max =
max_count
= 0;
77
78
/* Find the largest remaining fraction(s). */
79
for
(
i
= 0;
i
< groups;
i
++) {
80
if
(
rest
[
i
] > max) {
81
max_count
= 1;
82
max_groups
[0] =
i
;
83
max =
rest
[
i
];
84
}
else
if
(
rest
[
i
] == max) {
85
max_groups
[
max_count
] =
i
;
86
max_count
++;
87
}
88
}
89
90
if
(
max_count
== 1) {
91
/* Give an extra source to the target with largest remainder. */
92
result[
max_groups
[0]]++;
93
rest
[
max_groups
[0]] = 0;
94
number--;
95
}
else
{
96
int
min = result[
max_groups
[0]],
which_min
=
max_groups
[0];
97
98
/* Give an extra source to the target with largest remainder and
99
* smallest whole number. */
100
fc_assert
(
max_count
> 1);
101
for
(
i
= 1;
i
<
max_count
;
i
++) {
102
if
(result[
max_groups
[
i
]] < min) {
103
min = result[
max_groups
[
i
]];
104
which_min
=
max_groups
[
i
];
105
}
106
}
107
result[
which_min
]++;
108
rest
[
which_min
] = 0;
109
number--;
110
}
111
}
112
113
#ifdef FREECIV_DEBUG
114
number =
original_number
;
115
for
(
i
= 0;
i
< groups;
i
++) {
116
fc_assert
(result[
i
] >= 0);
117
number -= result[
i
];
118
}
119
fc_assert
(number == 0);
120
#endif
/* FREECIV_DEBUG */
121
}
incite_cost
char * incite_cost
Definition
comments.c:76
distribute
void distribute(int number, unsigned groups, const unsigned *ratios, int *result)
Definition
distribute.c:34
distribute.h
log.h
fc_assert
#define fc_assert(condition)
Definition
log.h:177
Generated on Sun Dec 22 2024 22:30:38 for Freeciv-3.3 by
1.9.8