задачка для программистов
Feb. 21st, 2007 12:12 pmЗнакомый рассказал, ему на интервью задали. Красивая задачка, но совсем не подходящая для интервью, по-моему.
Есть некий поток элементов. Вызывая снова и снова функцию getnext(), вы получаете каждый раз следующий элемент из потока, и так до тех пор, пока функция не вернет EOF, что означает, что поток закончился. Гарантировано, что все элементы, полученные таким образом, будут отличаться друг от друга. Вернуться к началу потока, или получать элементы в каком-то другом порядке, кроме как один за другим с помощью getnext(), невозможно.
Известно, что поток когда-нибудь кончается, но заранее про количество элементов ничего не известно.
Требуется: написать функцию, которая, когда ее вызывают (а вызывают ее один раз), возвращает выбранный случайным образом один из элементов потока, притом у каждого из элементов потока одинаковая вероятность быть возвращенным этой функцией.
Функция должна использовать фиксированное количество памяти (иными словами, O(1) памяти).
Update: учтите, что в комментариях уже есть правильные ответы.
next , собственно, не будет достаточно случайным? ;)
Date: 2007-02-21 10:16 am (UTC)Re: next , собственно, не будет достаточно случайным? ;)
Date: 2007-02-21 10:26 am (UTC)Re: next , собственно, не будет достаточно случайным? ;)
From:no subject
Date: 2007-02-21 10:17 am (UTC)no subject
Date: 2007-02-21 10:18 am (UTC)no subject
Date: 2007-02-21 10:25 am (UTC)(no subject)
From:(no subject)
From:Классика
Date: 2007-02-21 10:19 am (UTC)Re: Классика
Date: 2007-02-21 10:25 am (UTC)no subject
Date: 2007-02-21 10:19 am (UTC)no subject
Date: 2007-02-21 10:25 am (UTC)(no subject)
From:(no subject)
From:no subject
Date: 2007-02-21 10:20 am (UTC)no subject
Date: 2007-02-21 10:27 am (UTC)(no subject)
From:no subject
Date: 2007-02-21 10:21 am (UTC)Element ret = getnext();
assert( ret != EOF );
Element cur = ret;
int n = 1;
while ( cur != EOF )
{
if ( MakeRandomNumber(n) == 0 )
ret = cur;
cur = getnext();
++n;
}
return ret;
no subject
Date: 2007-02-21 10:32 am (UTC)Я считаю, что на интервью задачи, для решения которых необходимо найти "изюминку", неправильно - потому что то, что кандидат не догадался, практически ничего не означает. Кому-то пришло в голову, кому-то не пришло. Это все равно, что оценивать знание математики по умению решать олимпиадные задачки. Гораздо лучше давать вопросы, в которых "изюминка" позволяет сделать что-то лучше и качественнее, но и без нее, просто грамотно используя свои знания и умения, можно придти к достойному ответу.
(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:я как раз из доступной памяти исходил
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:Re: Reply to your comment...
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:no subject
Date: 2007-02-21 10:31 am (UTC)no subject
Date: 2007-02-21 10:32 am (UTC)1. Пишем вспомогательную функцию ВЫБОР типа ЭЛЕМЕНТ, аргументы: c1, c2 типа ЭЛЕМНТ, n - целое
Возвращает элемент c1 с вероятностью (n - 1) / n или c2 с вероятностью 1 / n (скажем, генерит случайной число от 1 до n, если выпало n - возвращает c2, иначе - c1; если n = 1 - возвращает с2)
2. В основной функции:
d1, d2 типа элемент; n типа целое
n = 1
ПОЛУЧИТЬ ИЗ ПОТОКА В d2
d1 := d2
ПОКА НЕ EOF ДЕЛАТЬ
d1 := ВЫБОР (d1, d2, n)
ПОЛУЧИТЬ ИЗ ПОТОКА В d2
КОНЕЦ ДЕЛАТЬ
ВЕРНУТЬ d1
Обоснование:
На втором шаге у нас первый элемент с вероятностью 1/2, второй - с вероятностью 1/2
На n шаге:
Первый элемент с вероятностью 1 * (1/2) * (2/3) * ... * ((n-1)/n) = 1 / n
Второй элнмент с вероятностью (1/2) * (2/3) * ... * ((n-1)/n) = 1 / n
Третий элемент с вероятностью (1/3) * (3/4) * (4/5) * (5/6) * ... * ((n-1)/n) = 1/n
...
k-й элемент с вероятностью (1/k) * (k/(k+1)) * ((k+1)/(k+2)) * ... * ((n-1)/n) = 1/n
...
n-й элемент с вероятностью 1/n
Вопрос:
1) Куда интервьюировали ? На какую должность ?
2) Знакомый решил ?
no subject
Date: 2007-02-21 10:53 am (UTC)Впрочем, чего тут считать… Обратная индукция на пальцах [действительно на пальцах, причём :-)] подтверждает.
не глядя в комменты
Date: 2007-02-21 10:57 am (UTC)2. для потока из двух элементов - выбираем второй элемент с вероятностью 1/2, а с вероятностью 1/2 оставляем первый элемент
3. для потока из 3-х - выберем третий элемент с вероятностью 1/3, а с вероятностью 2/3 - один из первых двух, полученный на шаге 2
Таким образом вероятность выбора 1-го элемента - 2/3 * 1/2 = 1/3 и то же самое для 2-го
4. из 4-х - последний - 1/4, три первых - 3/4. Из них каждый выбирается с вероятностью 1/3 как следует из шага 3. Значит вероятность выбора каждого из них - 3/4 * 1/3 = 1/4
и так далее - т.е. надо выбирать N-ный элемент с вероятностью 1/N и возвращать последний выбранный элемент при приходе EOF
А почему для интервью не подходит. Хорошая и простая задачка IMHO
no subject
Date: 2007-02-21 11:00 am (UTC)no subject
Date: 2007-02-21 11:05 am (UTC)(no subject)
From:no subject
Date: 2007-02-21 11:13 am (UTC)Element result = getnext();
if(result == EOF) throw "hey you! no cheating!";
for(Element next = result; next != EOF; next = getnext()) {
size++;
if(random()<1/size)
result = next;
}
return result;
// assuming random() returns evenly distributed random number 0..1
// btw - if we change 1/size to 1/2, it's half a gaussian. I think so...
no subject
Date: 2007-02-21 11:35 am (UTC)Возможно, имело бы смысл условие, что длина памяти ограничена O(N), если мы знаем, что элемент потока на шаге N тоже имеет длину не больше N.
no subject
Date: 2007-02-21 11:51 am (UTC)(no subject)
From:(no subject)
From:no subject
Date: 2007-02-21 11:36 am (UTC)... Наша профессия не для дураков ...
no subject
Date: 2007-02-21 12:33 pm (UTC)Клёво!:)
(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From::)
From:Re: :)
From:no subject
Date: 2007-02-21 12:43 pm (UTC)no subject
Date: 2007-02-21 02:19 pm (UTC)no subject
Date: 2007-02-21 02:34 pm (UTC)no subject
Date: 2007-02-21 03:04 pm (UTC)Технологии меняются, а теория вероятности остаётся. :)
(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:еще тупое решение
From:(no subject)
From:(no subject)
From:no subject
Date: 2007-02-21 03:48 pm (UTC)1. получаем A
2. получаем B, выбираем из A и B одну букву с вероятностью 1/2. Пусть это B.
3. получаем C, выбираем из B и C, причем, берем B с вероятностью 2/3, а C - 1/3. Пусть это B.
4. получаем D, выбираем из B и D, причем, берем B с вероятностью 3/4, а D - 1/4
и т.д
no subject
Date: 2007-02-21 04:51 pm (UTC)Задачка простая для того, кто хоть когда-нибудь такими вещами занимался. А подходит или нет для интервью – вопрос того, на какую позицию человека интервьюировали...
no subject
Date: 2007-02-21 05:44 pm (UTC)no subject
Date: 2007-02-21 05:48 pm (UTC)no subject
Date: 2007-02-21 05:59 pm (UTC)no subject
Date: 2007-02-21 06:16 pm (UTC)no subject
Date: 2007-02-21 09:27 pm (UTC)А я вот ставлю другую задачу, очень прикольную на тему посмотреть ход мыслей кандидата.
"Какая программа или какой алгоритм или какая задача теоретически на двухпроцессорной машине будет работать более чем в два раза быстрее чем на однопроцессорной".
Задача теоретическая и теоретически же правильный ответ существует, но интересно то, как к нему приходят или не приходят кандидаты. :)
А еще прекрасный вопрос для программистов: "зачем придумали подоконник". Удивительно небольшое количество людей отвечает правильно.
no subject
Date: 2007-02-22 01:39 am (UTC)А второе... гм, я бы сказал, что подоконник первоначально никто не придумывал, а просто стены были намного толще, чем окна, которые в них вставлялись. Не так?
(no subject)
From:"Температурный экран" лучшего качества.
From:(no subject)
From:(no subject)
From:no subject
Date: 2007-02-22 03:06 am (UTC)Равновероятность элементов легко показывается рекурсивно, начиная с конца, т.е.: у последнего элемента вероятность быть выбраным -- 1/N. Соответственно, у остальных N-1 элементов она 1/(N-1), и их равновероятность ясна из ...(тут следует рекурсия)