За последние 24 часа нас посетил 20431 программист и 1092 робота. Сейчас ищут 917 программистов ...

Расчет шансов (спорный вопрос)

Тема в разделе "Решения, алгоритмы", создана пользователем 4online, 21 окт 2015.

  1. 4online

    4online Новичок

    С нами с:
    21 окт 2015
    Сообщения:
    3
    Симпатии:
    0
    Приветствую.

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

    Задача:
    Код:
    https://github.com/RomanAngelovskij/Auslogics2015/blob/master/2/array.php
    Код (Text):
    1. <?php
    2. $Array = array(
    3.     'a' => 1/2,
    4.     'b' => 1/8,
    5. );
    6.  
    7. $Chances = new Chances($Array);
    8. $Result = array();
    9. for ($i = 0; $i < 1001; $i++){
    10.     $index = $Chances->call();
    11.     if (!isset($Result[$index])){
    12.         $Result[$index] = 0;
    13.     }
    14.     $Result[$index]++;
    15. }
    16.  
    17. echo '<pre>';
    18. var_dump($Result);
    19. echo '</pre>';
    20.  
    21. class Chances{
    22.  
    23.     private $__Data;
    24.  
    25.     private $__calls = 0;
    26.  
    27.     public function __construct($Data){
    28.         if (empty($Data)){
    29.             throw new Exception('Передан пустой массив');
    30.         }
    31.  
    32.         $sum = array_sum($Data);
    33.         foreach ($Data as $key => $chance){
    34.             $this->__Data[$key] = array(
    35.                 'chance' => $chance,
    36.                 'calls' => 0,
    37.                 'percent' => $chance/$sum*100,
    38.             );
    39.         }
    40.     }
    41.  
    42.     public function call(){
    43.         $this->__calls++;
    44.         foreach ($this->__Data as $key => $Data){
    45.             if ($Data['calls'] < $this->__calls/100*$Data['percent']){
    46.                 $Result[] = $key;
    47.             }
    48.         }
    49.  
    50.         $index = $Result[rand(0, count($Result)-1)];
    51.         $this->__Data[$index]['calls']++;
    52.         return $index;
    53.     }
    54. }
    55. ?>
    Ответ проверяющего программиста:
    Правильное ли замечание он сделал? Я проверял с разными значениями массива, с разным количеством вызовов. Все работало идеально. Где я допустил ошибку?

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

    runcore Старожил

    С нами с:
    12 окт 2012
    Сообщения:
    3.625
    Симпатии:
    158
    тут даже в задаче несостыковка.
    1/8 это 12,5% процентов случаев
    1/2 это 50% процентов случаев
    итого 62,5 %
    о каких 20% и 80% оворится в условии мне непонятно. т.е. в 37% случаев запуска вообще ничего не должно выводиться. или я чегото непонял
     
  3. 4online

    4online Новичок

    С нами с:
    21 окт 2015
    Сообщения:
    3
    Симпатии:
    0
    runcore, если внимательно посмотрите, то значением массива будет не обыкновенная дробь, а десятичная (кавычек нет, будет результат деления). Тоесть 1/8 = 0,125, 1/2 = 0,5. Тоесть 0,625 берем за 100%. С этим разобрались. Я скорее всего неправильно понял задание. Тоесть хранить количество вызова функции не надо, а надо рассчитывать шанс возврата каждого элемента. По-крайней мере мне так объяснили на другом форуме
     
  4. MiksIr

    MiksIr Активный пользователь

    С нами с:
    29 ноя 2006
    Сообщения:
    2.340
    Симпатии:
    44
    Тестирующий программист, конечно, ступил. Хотя вам урок - не нужно писать классы и исполняющий код в одном файле.
    Ну и решение спорное. Ибо требует сохранение состояния между вызовами. Что, вообще-то, теории вероятности не требуется =)
    Плюс, стиль режет глаз, то переменные с заглавной, то нет. Осильте PSR.
     
  5. runcore

    runcore Старожил

    С нами с:
    12 окт 2012
    Сообщения:
    3.625
    Симпатии:
    158
    а, там про пропорции. невнимательность моя
     
  6. 4online

    4online Новичок

    С нами с:
    21 окт 2015
    Сообщения:
    3
    Симпатии:
    0
    Ну с алгоритмом мы разобрались на другом форуме, я неправильно понял ТЗ.

    Но вот это
    уточните, о какой части PSR вы говорите. В частности про именование свойств класса. То, что код класса не в отдельном файле, ничего страшного для тестового задания не вижу (в других задачах этого задания, классы идут отдельными скриптами)
     
  7. runcore

    runcore Старожил

    С нами с:
    12 окт 2012
    Сообщения:
    3.625
    Симпатии:
    158
    поделитесь плиз. у меня в голове есть решение, но оно не подразумевает использования функций типа rand(), а использует функцию зависимости шанса выпадения отдельного символа исходя из истории выпадения предыдущих раз. т.е. функция должна хранить историю выпадения каждого символа, и просто стремиться найти тот у которого отношение пропорции реального выпадения будет наиболее отличаться от заданного на входе.
     
  8. Maputo

    Maputo Активный пользователь

    С нами с:
    30 июл 2015
    Сообщения:
    1.136
    Симпатии:
    173
    1. Приводите все дроби к общему знаменателю
    2. Сохраняете в экземпляре класса два массива с вычесленными числителями (исходный и рабочий)
    3. При вызове функции берете случайным образом элемент рабочего массива со значением > 0
    3.1. Если все значения рабочего массива равны нулю - сбрасываете его значения до исходных и возвращаетесь к п.3
    4. отнимаете от его значения 1 в рабочем массиве.
    5. Возвращаете индекс элемента массива.