Ver Mensaje Individual
  #5 (permalink)  
Antiguo 25/06/2014, 13:25
Avatar de NSD
NSD
Colaborador
 
Fecha de Ingreso: mayo-2012
Ubicación: Somewhere
Mensajes: 1.332
Antigüedad: 12 años
Puntos: 320
Respuesta: matriz 3x5 niveles forzada

Hola, propongo otra forma diferente de pensarlo a ver que les parece

Las dimensiones de una matriz son de NxM (Para este caso particular de 3x5), ahora bien, toda matriz puede ser transformada a una lista, y por ende toda lista puede ser transformada a una matriz, es un caso particular de re-dimensionamiento de matrices donde una de las matrices tiene una única fila (o columna).

Sabemos que una base de datos puede con una consulta bien armada, retornar fácilmente una lista de valores ordenados la cual con un simple loop, podemos guardar en un array, esto nos permite que podamos ver a un Array de PHP con claves numéricas correlativas como una lista ordenada (Aunque internamente sea una tabla hash...).

Si tenemos en una lista (Array) los datos de los patrocinadores y de los referidos de forma ordenada, tal que, los patrocinadores esten al inicio y luego sus referidos, podemos por lo dicho al principio, convertir esa lista en una matriz de NxM.

¿Y esto como se come? Bueno, vamos al codigo.

Esta primer parte es una carga manual de los patrocinadores y referidos, notese que puede automatizarce con un loop que obtenga resultados de una base de datos
Código PHP:
Ver original
  1. <?php
  2.     // Consideremos al usuario A como el primer eslabón de los referidos.
  3.     // Es decir, como el patrocinador base.
  4.     $listUsrA = ["A"];
  5.  
  6.     // Nota: Si los datos vienen de una base de datos, esto sera solo un loop ya que se pueden obtener de forma simple por sql.
  7.     // Ahora, agregamos a la lista los referidos directos del usuario A.
  8.     $listUsrA[] = "Referido de A - 1";
  9.     $listUsrA[] = "Referido de A - 2";
  10.     $listUsrA[] = "Referido de A - 3";
  11.     $listUsrA[] = "Referido de A - 4";
  12.     // ... Tantos como halla.
  13.     // ... Notese que no interesa la cantidad en ningun momento, solo se agrega uno tras otro.
  14.     // Notese tambien, que estan ordenados, primero los del primer patrocinador, luego los de sus referidos.
  15.  
  16.     // Ahora, de forma ordenada agrego los referidos de los referidos de A
  17.     $listUsrA[] = "Referido de A1 - 1";
  18.     $listUsrA[] = "Referido de A1 - 2";
  19.     $listUsrA[] = "Referido de A1 - 3";
  20.     $listUsrA[] = "Referido de A1 - 4";
  21.     $listUsrA[] = "Referido de A2 - 1";
  22.     $listUsrA[] = "Referido de A2 - 2";
  23.     $listUsrA[] = "Referido de A3 - 1";
  24.     $listUsrA[] = "Referido de A4 - 1";
  25.     $listUsrA[] = "Referido de A4 - 2";
  26.     // ... Tantos como halla y asi siguiendo indefinidamente pero siempre de forma ordenada.

Pueden observar que lo anterior es muy simple de automatizar, el unico punto de importancia es que el referido 3, va despues del referido 2, NUNCA antes, y los mismos sus sub-referidos, primero van los sub-referidos del referido 2 y luego los sub-referidos del referido 3, el orden ascendente es importante.

Ahora vamos a lo interesante, la funcion que pasa la lista a una matriz de NxM:
Código PHP:
Ver original
  1. function listToMatriz($list, $n, $m)
  2. {
  3.     // Nota: Esto puede realizarce perfectamente con un LIMIT en la consulta SQL.
  4.     if(count($list) > pow($n,$m)) // Si hay mas elementos que los que admite la matriz
  5.        $list = array_slice($list, 0, pow($n,$m)); // La trunco.
  6.  
  7.     $levels = []; // Array temporal con los niveles.
  8.     $level  = 0; // Nivel actual.
  9.    
  10.     while($level <= $m) // Mientras estemos en un nivel valido.
  11.     {
  12.         $tmp = array_splice($list, 0, pow($n, $level)); // Obtenemos la parte de la lista que corresponde al nivel.
  13.         if(count($tmp) > $n) // Si hay mas elementos que los que se admiten.
  14.             $tmp = array_chunk($tmp, $n); // Se los parte en grupos.
  15.        
  16.         if($tmp) // Esto es para no generar niveles vacios y ocupar espacio inutilmente, solo se guardan los niveles con datos.
  17.             $levels[] = $tmp; // Agregar el nivel.
  18.            
  19.         $level++; // Incrementar el nivel.
  20.     }
  21.    
  22.     $level = count($levels)-1; // Empezamos a recorrer el arbol por las hojas del ultimo nivel.
  23.    
  24.     while($level > 2) // Los dos primeros niveles son casos particulares y se resuelven juntos despues.
  25.     {
  26.         $grupo = 0; // Por que grupo voy.
  27.         foreach($levels[$level-1] as &$patrocinadores) // Recorro los patrocinadores del nivel anterior.
  28.         {
  29.             $tmp = []; // Aca va a ir la información de cada patrocinador.
  30.             foreach($patrocinadores as $patrocinador) // A cada patrocinador le asigno los referidos del grupo correspondiente.
  31.             {
  32.                 $tmp[$patrocinador] = (isset($levels[$level][$grupo]) ? [$levels[$level][$grupo] => []] : []);
  33.                 $grupo++; // Incrementar el grupo.
  34.             }
  35.             $patrocinadores = $tmp; // Al los patrocinadores lo redefino con sus referidos.
  36.         }
  37.         unset($levels[$level]); // Esto lo libero ya que no se usa mas.
  38.         $level--; // Subo un nivel en el arbol.
  39.     }
  40.  
  41.     // Nivel 0 y Nivel 1.
  42.     $matriz = []; // Crear matriz vacia.
  43.     $matriz[$levels[0][0]] = array_combine($levels[1], $levels[2]); // Resolver ambos niveles de forma particular.
  44.  
  45.     return $matriz; // Retornar la matriz.
  46. }

Esa función pasa la lista a una matriz de NxM, pero como en este caso la matriz es de 3x5 la llamamos asi:
Código PHP:
Ver original
  1. $matriz = listToMatriz($listUsrA, 3, 5); // Finalmente llamamos a la funcion con las dimenciones de la matriz.
  2.  
  3. var_dump($matriz);

Como sin duda ya se percataron, las dimensiones de la matriz son irrelevantes y pueden ser modificadas en cualquier momento, lo unico que queda por saber es.. ¿Como esta formada esa matriz?

La respuesta es:
Cita:
array (size=1)
'A' =>
array (size=3)
'Referido de A - 1' =>
array (size=3)
'Referido de A - 4' =>
array (size=1)
'Referido de A4 - 2' =>
array (size=0)
empty
'Referido de A1 - 1' =>
array (size=0)
empty
'Referido de A1 - 2' =>
array (size=0)
empty
'Referido de A - 2' =>
array (size=3)
'Referido de A1 - 3' =>
array (size=0)
empty
'Referido de A1 - 4' =>
array (size=0)
empty
'Referido de A2 - 1' =>
array (size=0)
empty
'Referido de A - 3' =>
array (size=3)
'Referido de A2 - 2' =>
array (size=0)
empty
'Referido de A3 - 1' =>
array (size=0)
empty
'Referido de A4 - 1' =>
array (size=0)
empty
Es una array, donde las claves de cada nivel corresponden a los patrocinadores y en cada una de esas claves hay un array que contiene a los referidos en el mismo formato.

La funcion tambien puede resolverse por recursividad, pero se me ocurrio plantearla asi, quizas alguien si esta interesado pueda hacerla como para comparar ambos metodos y buscar la exelencia aunque a fines practicos no es muy relevante.
__________________
Maratón de desafíos PHP Junio - Agosto 2015 en FDW | Reglamento - Desafios