*/ 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;
    }
}