2010-07-22 19 views
5

que tienen una serie de preguntas juego de preguntas en una base de datos SQL (javascript y sqlite en realidad). Todas las preguntas tienen un nivel de dificultad de 1 a 5, siendo 5 las más difíciles. Aquí es una visualización simplificada de los datos ...¿Cómo hacer un orden controlado "aleatorio"?

 

+---------+--------------+ 
| id | difficulty | 
+---------+--------------+ 
| 1  |  1  |  
| 2  |  5  |  
| 3  |  2  |  
| 4  |  3  |  
| 5  |  2  | 
| 6  |  2  |  
| 7  |  4  |  
| 8  |  1  |  
| 9  |  5  |  
| 10  |  3  |  
+---------+--------------+ 

Ahora puede mezclar estos fina en SQL o código para que estén en un orden aleatorio, sin repeticiones, pero también quiero tener el control sobre la forma en la dificultad el campo está ordenado.

Así, por ejemplo, que podría tener un conjunto de preguntas barajado donde el orden nivel de dificultad se ve así ...

1,1,5,2,3,3,2,2,2,4

Esto tiene varias matas '' de dificultad, eso no es lo que quiero. El usuario que juega el juego obtendrá varios grupos de las preguntas igualmente difíciles. Una orden de estas características sería mejor ...

1,2,3,2,5,4,1,2,3,2

quiero asegurar las preguntas se barajan pero sin dificultad la formación de grumos. Una propagación uniforme de la dificultad donde hay pocos, si es que hay 'grupos'. Cualquier ayuda en MySQL/javascript (o PHP) sería genial.

+0

No estoy seguro de lo que quiere decir con 'grumos'. ¿Quiere decir que quiere preguntas aleatorias sin dificultad contigua repetida? ¿Puede comenzar con cualquier valor de dificultad o siempre debe comenzar con 1? –

+0

Puede comenzar con cualquier dificultad y sí, sin dificultad contigua. Los grupos serían una dificultad contigua. – jfountain

+1

Creo que la palabra que está buscando es "corre", no "grumos". ¿Se ha corregido el tamaño de la entrada? P.ej. ¿tiene que tomar N preguntas y reordenarlas para que no haya carreras? ¿O desea extraer N preguntas de un conjunto de M, donde N nicolaskruchten

Respuesta

5

En lugar de agrupar todos los identificadores juntos, ¿por qué no los agrupa por orden aleatorio en cada sección y luego los saca uno a uno? O una vez que estén ordenados aleatoriamente, puedes sacarlos de una dificultad aleatoria y luego eliminar ese nivel de dificultad hasta que tengas una pregunta de cada uno.

Esto es lo que estaba pensando en respuesta a sje397, así que voy a añadir a mi respuesta.

Mientras todas las otras opciones se suman a los más grandes, menos un grupo que no tendrá ningún agrupamiento (asumiendo que su algoritmo es correcto). Sin embargo, el algoritmo tomaría básicamente la forma de elegir de A (grupo con mayor número de opciones), elegir de otro grupo, elegir de A, etc. hasta que A sea igual al tamaño de los otros grupos. Entonces, el mejor algoritmo verificará para encontrar el grupo más grande y elegirlo. Luego seleccionaría de otro grupo, luego verificará qué grupo es el más grande y luego escogerá a menos que sea el elegido previamente.

+0

+1 porque esta solución maneja conjuntos de datos que no pueden evitar la agrupación mejor que la solución de njk. Puede modificar la solución para que tenga en cuenta las proporciones de elementos en cada grupo al determinar a qué grupo seleccionar a partir de ahora. Esto te daría un resultado óptimo. –

+0

Es cierto que la manera más fácil de manejar es si hay un número par de preguntas en cada dificultad, pero por el ejemplo, no creo que sea así. Por lo tanto, debería hacerse algún trabajo adicional. – qw3n

+0

Algunas aglutinaciones deben ocurrir si un grupo es más grande que el resto, pero no necesariamente si hay dos grupos de igual tamaño que el resto. De cualquier manera, solo tendrá que elegir entre el grupo más grande más a menudo: elija como lo sugirió, pero con una probabilidad basada en el tamaño de los elementos restantes en el grupo. – sje397

1

Bueno, en una muestra verdaderamente aleatoria 'grupos' hacer aparecer naturalmente. Por lo tanto, si desea eliminarlos, debe aplicar algo manualmente, p. especifique un patrón de dificultad y elija una pregunta aleatoria que coincida con cada nivel de dificultad

1

Itere a través de una matriz de entrada aleatoriamente mezclada y cada vez que golpea un elemento con el mismo nivel de dificultad que el anterior, intercambie con el siguiente elemento que no tenga el mismo nivel de dificultad. Sólo en mi cabeza, creo que esto sería dar vuelta a su entrada inicial en: 1,5,1,2,3,2,3,2,4,2

Dependiendo de la entrada, este enfoque podría causar la formación de grumos en al final, pero podría ser lo suficientemente bueno ...

Si la entrada es más grande que lo que necesita, usted podría también acaba de eliminar cualquier elemento que tiene la misma dificultad que la anterior.

+0

+1 Estaba a la mitad escribiendo algo muy similar –

+0

Para agrupar aún menos, trate la matriz como circular, y cuando busque un candidato de intercambio, deténgase cuando esté de vuelta en la posición actual. – nicolaskruchten

+0

¿Esto no solo empujará las aglomeraciones hasta el final? – Dolphin

2

¿Qué hay de la siguiente estrategia, en código: (la siguiente fue una lista con viñetas, pero no pude obtener el código que aparece después de una lista con viñetas para mostrar correctamente - Detesto a fondo esta basura "de rebajas" utiliza este sitio)

para las preguntas de dificultad

separaron las preguntas hasta la mitad en dos listas, una lista de "fácil" y una lista de "duro"

preguntas toman una a una de las listas fáciles y difíciles, alternando entre la dos. (Esto significaría que tendría una ligera tendencia de fácil a difícil durante la secuencia de preguntas, que podrían o no estar de acuerdo con.)

aplicación primitivo:

$resultset = your_preferred_query_function('SELECT id FROM question ORDER BY difficulty'); 
$questions_temp = array(); 
while ($row = mysqli_fetch_assoc()) { 
    $questions_temp[] = $row['id']; 
} 
if (count($questions) % 2) { 
    $loop_limit = (count($questions) - 1)/2; 
    $halfway = (count($questions) + 1)/2; 
    $questions[0] = $questions_temp[$loop_limit]; 
} else { 
    $loop_limit = count($questions)/2; 
    $halfway = count($questions)/2; 
    $questions = array(); 
} 
for ($i=0; $i<$loop_limit; $i++) { 
    $questions[] = $questions_temp[$i]; 
    $questions[] = $questions_temp[$halfway+$i]; 
} 

Ahora $questions es una matriz que contiene preguntas ordenadas como sugerí.

+0

FYI: estoy de acuerdo con lo de la rebaja, la clave es: tiene que haber al menos 1 carácter visible entre una lista de viñetas y un bloque de código. He recurrido a un único punto en la línea antes. – Wrikken

+0

+1 por odiar a Markdown. ;) – Svante

0

Una solución muy simple (que no es muy eficiente, aunque) sería hacer:

<?php 

     define('MAX_QUESTIONS',10); 

     $dbh = new PDO("mysql:dbname=so;host=127.0.0.1","",""); 
     $sql = "SELECT * FROM q group by difficulty order by rand()"; 
     $data = $dbh->query($sql); 
     $rows = $data->fetchAll(); 
     $ids = getIds($rows); 
     while (count($rows) < MAX_QUESTIONS) { 
       $sql = "SELECT * FROM q where id not in ". 
         "(".join(",",$ids).") group by difficulty order by rand()"; 
       $data = $dbh->query($sql); 
       $more_rows = $data->fetchAll(); 
       $rows = array_merge($rows,$more_rows); 
       $ids = getIds($rows); 
     } 
     print_r($rows); 

     function getIds($data) { 
       $ids = array(); 
       foreach ($data as $v) { 
         $ids[] = $v['id']; 
       } 
       return $ids; 
     } 

?> 

Esto es necesario porque el grupo de MySQL siempre devuelven el mismo ID, independientemente de si usted ha ordenado previamente (incluso en una subconsulta.)

Lo bueno de esto es que no garantiza 'grumos' (a un costo potencial de volver vacíos para la pregunta final que crearía un 'grupito', aunque podría ser un caso especial)

Lo malo es que tu necesitas más de una consulta, y ese orden por rand() es tremendamente ineficiente, pero si tu tabla es pequeña, probablemente no importe.

Cuestiones relacionadas