*/ class Dhont { /** * Los divisores de las listas/partidos. Estructura: * {identificadorLista1 => 1, identificadorLista2 => 1, ...} * * @var array */ private $divisores; /** * Devuelve un array con cantidad de eltos. = a la cantidad de bancas a repartir * en cada elto, el valor es igual al valor correspondiente en array $listas. * La metodologia para repartir es el sistema DHONT. * * @param int $bancas Cantidad de bancas/escanos. * @param array $listas Identificadores de las listas que compiten * por bancas. Estructura {'identificador' => $votosObtenidos} * * @return array distribucion de bancas a listas {banca => $lista} */ public function repartirBancas($bancas, $listas) { asort($listas); $listas = array_reverse($listas, true); $bancas = $this->_createBancasDivisores($bancas, $listas); foreach ($bancas as $key => $b) { $max = $this->_getMaxCociente($listas); $bancas[$key] = $max['identificador']; } return $bancas; } /** * Devuelve un array de bancas con eltos = false, y cantidad igual a $bancas. * y un array de divisores con claves sacadas de las claves de $listas y valores = 1 * * @param int $bancas La cantidad de bancas a repartit. * @param array $listas Las listas/partidos que se disputan bancas. Estructura: * {identificadorLista1 => $votos1, identificadorLista2 => $votos2, ...} * * @return array con estructura [$bancas, $divisores]. en detalle:
* [false, false, ...], // count = $bancas */ private function _createBancasDivisores($bancas, $listas) { $bancas = array_fill(0, $bancas, false); $this->divisores = array_combine( array_keys($listas), array_fill(0, count($listas), 1) ); return $bancas; } /** * Usa los divisores, en el estado en que se encuentren para encontrar el mayor * cociente, incrementa en 1 el divisor del mayor cociente. Esto reduce las * chances de vovler a elegir el mismo partido/lista la proxima vez. * * @param array $listas Las listas/partidos que se disputan bancas. Estructura: * {identificadorLista1 => $votos1, identificadorLista2 => $votos2, ...} * * @return array Estructutra {'identificador' => $lista, 'cociente' => $maxCociente} */ private function _getMaxCociente($listas) { $max = array('identificador' => null, 'cociente' => -1); foreach ($listas as $identificador => $votos) { $cociente = $votos / $this->divisores[$identificador]; if ($max['cociente'] < $cociente) { // si algun max cociente empata con otro, prevalece el de la lista // con mas votos. Si tambien empatan en votos (chocan con divisor 1), se jode la 2da. $max = array('identificador' => $identificador, 'cociente' => $cociente); } } $this->divisores[$max['identificador']]++; return $max; } }