БлогNot. Лица Экмана и проблемка с ними...

Лица Экмана и проблемка с ними...

Пол Экман - известный психолог, в частности, автор книги "Психология лжи". За последние пару дней я набросал вот такой тест по методике "Лица Экмана", инициирована эта работа г-жей Буровой :) Увы, пока не выберу времени подумать над комбинаторной проблемой, всплывшей во время написания, запишем её хоть в блог.

Что имеем: 10 актёров (занумерованы от 1 до 10), каждый из которых представляет по 6 эмоций (обозначены шестью разными буквами - a, u, s ,f , h, d). Надо вывести 10 порций по 6 картинок так, чтобы, во-первых, все 6 эмоций-букв в каждой порции были разными, во-вторых, на каждом шаге не было повторяющихся актёров.

Очевидно, что раскидывать "чисто случайно" нельзя, нельзя также избежать повторений, просто проверяя, не выбирался ли уже данный актёр для текущего шага. 6 актёров вполне могут случайно "закрыть" первые 6 шагов (распределившись по принципу определителя матрицы 6x6), а оставшиеся 4 актёра тогда не смогут закрыть оставшихся 4 шага без повторений одного актёра на части шагов.

Пока ограничился тем, что просто перетасовал как буквы-эмоции, так и цифры-актёров простой функцией

function select_random_items ($k,$arr) { 
  //выбрать $k случайных элементов из массива $arr
  $c=count($arr);
  if ($k>$c) $k=$c;
  $a = array ();
  for ($i=0; $i<$k; ) {
   $n=rand (0,$c-1);
   if (!in_array($arr[$n],$a)) {
    array_push ($a,$arr[$n]); $i++;
   }
  }
  return $a;
 }

следя, чтобы в столбцах матрицы перестановок цифр не было повторяющихся значений выше обрабатываемой строки:

$selection = array (
   array ('01','02','03','04','05','06','07','08','09','10'),
   array ('01','02','03','04','05','06','07','08','09','10'),
   array ('01','02','03','04','05','06','07','08','09','10'),
   array ('01','02','03','04','05','06','07','08','09','10'),
   array ('01','02','03','04','05','06','07','08','09','10'),
   array ('01','02','03','04','05','06','07','08','09','10')
  );
  $i=0;
  while ($i<6) {
   $selection[$i] = select_random_items (10,$selection[$i]);
   $found=true;
   for ($ii=0; $ii<$i; $ii++)
   for ($jj=0; $jj<10; $jj++) {
    if ($selection[$ii][$jj]==$selection[$i][$jj]) { $found=false; $ii=$i; break; }
   }
   if ($found==false) continue;
   else $i++;
  }

и потом соединил буквы с цифрами, образуя имена картинок. Увы, это не гарантирует вывода без повторений, вот пример:

a02,u07,s01,f10,h03,d09,
d09,f01,u06,a05,h10,s03,
s07,h09,f05,a01,u06,d08,
a03,s05,u07,d02,f09,h01,
u05,s08,h04,f03,d02,a06,
f04,h03,d02,u06,a08,s07,
s01,h04,f10,u08,a07,d05,
a10,s02,d03,h09,f05,u04,
f06,s10,a08,h04,d01,u02,
f08,s06,a09,u07,d04,h10

Актёр 9 представляет одну и ту же эмоцию на 1 и 2 шаге теста :(

Очевидно, что поступить так же с буквами-эмоциями не удастся - в их матрице всего 6 столбцов и 10 строк по числу шагов теста. Придумаю нормальный алгоритм - допишу... Кстати, если пройдёте тест до конца, получите и постоянный линк на результаты, вот что вышло у меня при тестовом прохождении: http://test.kislenko.net/ekmanfaces/result.php?id=1

P.S. пару часов спустя. Мдя, что-то я совсем затупил, но бутылка пива помогла :)

Если во всех "перемешанных" первым фрагментом строках уже правильно присутствуют цифры от 1 до 10, зачем вообще генерировать случайные перестановки ещё и для букв? Просто соединяем первую строчку с первой буквой и т.д. Потом выбираем значения по столбцам и уже набор из 6 значений сортируем. Код лишь слегка изменился и всё стало правильно.

Было:

$items='';
  for ($i=0; $i<10; $i++) {
   $fix=select_random_items (6,$prefix);
   for ($k=0; $k<6; $k++) {
    $fix[$k].=$selection[$k][$i];
    $items.=$fix[$k];
    if ($i*$k<45) $items.=',';
   }
  }

Стало:

$items='';
  for ($i=0; $i<10; $i++) {
   for ($k=0; $k<6; $k++) $fix[$k]=$prefix[$k].$selection[$k][$i];
   $fix=select_random_items (6,$fix);
   for ($k=0; $k<6; $k++) {
    $items.=$fix[$k];
    if ($i*$k<45) $items.=',';    
   }
  }

27.10.2010, 11:11 [10033 просмотра]


теги: ошибка тест памятка алгоритм php психология

К этой статье пока нет комментариев, Ваш будет первым