2010-07-22 2 views
5

У меня есть набор вопросов для викторины в базе данных sql (javascript и sqlite на самом деле). Все вопросы имеют уровень сложности от 1 до 5, 5 из них сложнее. Вот упрощенная визуализация данных ...Как сделать контролируемый заказ «тасования»?

 

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

Теперь я могу тасовать этот штраф в SQL или коде, так что они находятся в случайном порядке без каких-либо повторов, но я также хочу, чтобы иметь контроль над тем, как трудностями поле упорядочено.

Так, например, я мог бы перемешиваются набор вопроса, где порядок уровня сложности выглядит следующим образом ...

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

У этого есть несколько «комков» трудности, это не то, что я хочу. Пользователь, играющий в игру, получит несколько групп подобных вопросов. Порядок, как это было бы лучше ...

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

Я хочу, чтобы гарантировать, что вопросы перемешиваются, но без труда комков. Равномерное распространение трудности, когда их мало, если есть какие-либо «комки». Любая помощь по MySQL/javascript (или PHP) будет отличной.

+0

Я не уверен, что вы подразумеваете под «clumps». Вы имеете в виду, что вам нужны случайные вопросы без последовательных повторных трудностей? Может ли он начинаться с любого значения сложности или он всегда должен начинаться с 1? –

+0

Это может начаться с каких-либо затруднений, и да, я имею в виду, не имея непрерывных трудностей. Сгустки будут непрерывными. – jfountain

+1

Я думаю, что слово, которое вы ищете, «работает», а не «clumps». Является ли размер ввода фиксированным? Например. вам нужно взять N вопросов и переупорядочить их, чтобы не было прогонов? Или вы хотите извлечь N вопросов из набора M, где N nicolaskruchten

ответ

5

Вместо того, чтобы группировать все идентификаторы вместе, почему бы вам не группировать их по сложности, рандомизировав каждый раздел, а затем вытащить их один за другим. Или, как только они сортируются случайным образом, вы можете вытащить их из случайной трудности, а затем удалить этот уровень сложности, пока у вас не возникнет вопрос от каждого.

Это то, о чем я думал в ответ на sje397, поэтому добавлю его к своему ответу.

Пока все остальные варианты составляют до наибольшей группы минус один, у вас не будет комков (при условии, что ваш алгоритм верен). Однако алгоритм будет в основном принимать форму выбора из A (группа с наибольшим количеством вариантов), выбирать из другой группы, выбирать из A и т. Д., Пока A не будет равен размеру других групп. Таким образом, лучший алгоритм будет проверять, чтобы найти самую большую группу и выбрать из нее. Затем он выбирает из другой группы, затем проверяет, какая группа является самой большой, а затем выбирайте ее, если она не выбрана ранее.

+0

+1 потому что это решение обрабатывает наборы данных, которые не могут избежать группировки лучше, чем решение njk. Вы можете изменить решение, чтобы он учитывал пропорции элементов в каждой группе, когда определял, какую группу выбрать из следующей. Это даст вам оптимальный результат. –

+0

Истинный самый простой в обращении - если в каждой сложности есть четное количество вопросов, но из примера я не думаю, что это так. Поэтому потребуется дополнительная работа. – qw3n

+0

Некоторые комки должны происходить, если одна группа больше остальных, но не обязательно, если две группы равного размера больше остальных. В любом случае вам просто нужно выбирать из самой большой группы чаще - выберите, как вы предлагали, но с вероятностью, основанной на размере элементов, оставшихся в группе. – sje397

1

Ну в действительно случайном образце «clumps» do естественно появляются. Поэтому, если вы хотите их удалить, вам необходимо принудительно выполнить что-то вручную, например. указать шаблон сложности и выбрать случайный вопрос, соответствующий каждому уровню сложности.

1

Итерации через случайно перемешанный массив ввода и всякий раз, когда вы нажимаете на элемент с тот же уровень сложности, что и перед ним, замените следующим элементом, который не имеет одинакового уровня сложности. Как раз в моей голове, я думаю, что это превратило бы ваш первоначальный вклад в: 1,5,1,2,3,2,3,2,4,2

В зависимости от ввода этот подход может вызвать сбой при конец, но может быть достаточно хорош ...

Если ваш вход больше, чем вам нужно, вы также можете просто удалить любой элемент с той же сложностью, что и перед ним.

+0

+1 Я был на полпути, набрав что-то очень похожее. –

+0

Чтобы еще меньше сжать, обработайте массив как круглый, и, когда вы ищете кандидата подкачки, остановитесь, когда вернетесь в текущую позицию. – nicolaskruchten

+0

Не будет ли это просто подталкивать комки до конца? – Dolphin

2

Как насчет следующей стратегии в коде: (следующий маркированный список, но я не мог получить код, появляющийся после того, как маркированный список отображался правильно - я полностью ненавижу этот мусор с «уценкой», который использует этот сайт)

заказ вопросы по сложности

разделить вопросы на полпути в двух списках, «легкий» список и «жесткий» список

отвечать на вопросы по одному из простых и жестких списков, чередуя между два. (Это будет означать, что вы бы небольшую тенденцию перехода от простого к сложному по последовательности вопросов, которые вы можете или не может быть хорошо с.)

Примитивный реализация:

$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]; 
} 

Теперь $questions является массив, содержащий упорядоченные вопросы, как я предложил.

+0

FYI: соглашайтесь с дефолтной вещью, ключ: должен быть как минимум 1 видимый символ между списком маркеров и блоком кода. Раньше я прибегал к одной точке на линии. – Wrikken

+0

+1 для ненависти Markdown. ;) – Svante

0

Очень простое решение (это не очень эффективно, хотя) будет делать:

<?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; 
     } 

?> 

Это необходимо потому, что группа в MySQL, всегда возвращают одинаковые идентификаторы, независимо от того, если вы заказали ранее (даже в подзапросе.)

Хорошо, что он не гарантирует «комков» (при потенциальной стоимости возврата пустым для окончательного вопроса, который создавал бы «clump», вы могли бы использовать специальный случай, который, однако)

Плохо то, что лет вам нужно больше, чем один запрос, и что упорядочение по rand() ужасно неэффективно, но если ваша таблица мала, это, вероятно, на самом деле не имеет значения.

Смежные вопросы