avva: (Default)
[personal profile] avva

Знакомый рассказал, ему на интервью задали. Красивая задачка, но совсем не подходящая для интервью, по-моему.

Есть некий поток элементов. Вызывая снова и снова функцию getnext(), вы получаете каждый раз следующий элемент из потока, и так до тех пор, пока функция не вернет EOF, что означает, что поток закончился. Гарантировано, что все элементы, полученные таким образом, будут отличаться друг от друга. Вернуться к началу потока, или получать элементы в каком-то другом порядке, кроме как один за другим с помощью getnext(), невозможно.

Известно, что поток когда-нибудь кончается, но заранее про количество элементов ничего не известно.

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

Функция должна использовать фиксированное количество памяти (иными словами, O(1) памяти).

Update: учтите, что в комментариях уже есть правильные ответы.

Page 1 of 2 << [1] [2] >>

Date: 2007-02-21 10:17 am (UTC)
From: [identity profile] ob-ivan.livejournal.com
экспоненциальное распределение?

Date: 2007-02-21 10:18 am (UTC)
From: [identity profile] jerom.livejournal.com
напрашивается ответ: хранить 1 элемент и заменять его новым с вероятность 1/N, где N - номер шага, но в тервере всегда очевидные ответы оказываются неверными, я потом подсчитаю вероятности точнее :-)

Date: 2007-02-21 10:25 am (UTC)
From: [identity profile] avva.livejournal.com
Правильный ответ, да.

(no subject)

From: [identity profile] jerom.livejournal.com - Date: 2007-02-21 10:30 am (UTC) - Expand

(no subject)

From: [identity profile] http://users.livejournal.com/d_m_/ - Date: 2007-02-21 12:09 pm (UTC) - Expand

Классика

Date: 2007-02-21 10:19 am (UTC)
From: (Anonymous)
http://www.unix.org.ua/orelly/perl/cookbook/ch08_07.htm

Re: Классика

Date: 2007-02-21 10:25 am (UTC)
From: [identity profile] avva.livejournal.com
Хихи :) спасибо.

Date: 2007-02-21 10:19 am (UTC)
From: [identity profile] danwinter.livejournal.com
очевидно, сохранить первое значение, а потом после каждого n-го getnext() заменять его на текущее с вероятностью 1/n. разве нет?

Date: 2007-02-21 10:25 am (UTC)
From: [identity profile] avva.livejournal.com
Все верно.

(no subject)

From: [identity profile] airini.livejournal.com - Date: 2007-02-21 10:32 am (UTC) - Expand

(no subject)

From: [identity profile] avva.livejournal.com - Date: 2007-02-21 10:35 am (UTC) - Expand

Date: 2007-02-21 10:20 am (UTC)
From: [identity profile] unbe.livejournal.com
Очень похожую задачу давали коллеге на интервью в гугл. Только там не один случайный елемент нужно было выбрать, а что-то вроде выборки из N елементов, такой чтобы каждый исходный елемент имел равные шансы в нее попасть. По сути, то же самое.

Date: 2007-02-21 10:27 am (UTC)
From: [identity profile] avva.livejournal.com
Да, действительно.

(no subject)

From: [identity profile] kot-ivanovich.livejournal.com - Date: 2007-02-21 04:53 pm (UTC) - Expand

Date: 2007-02-21 10:21 am (UTC)
From: [identity profile] plakhov.livejournal.com
Легкая задача, по-моему, и на интервью вполне можно спрашивать.

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;

Date: 2007-02-21 10:32 am (UTC)
From: [identity profile] avva.livejournal.com
В этой задаче есть "изюминка": нужно догадаться, что следует хранить один элемент в качестве текущего кандидата, которого мы выдаем, если поток в сей момент кончился. Поняв это, разобраться с тем, как менять кандидатов, легче.

Я считаю, что на интервью задачи, для решения которых необходимо найти "изюминку", неправильно - потому что то, что кандидат не догадался, практически ничего не означает. Кому-то пришло в голову, кому-то не пришло. Это все равно, что оценивать знание математики по умению решать олимпиадные задачки. Гораздо лучше давать вопросы, в которых "изюминка" позволяет сделать что-то лучше и качественнее, но и без нее, просто грамотно используя свои знания и умения, можно придти к достойному ответу.

(no subject)

From: [identity profile] plakhov.livejournal.com - Date: 2007-02-21 10:45 am (UTC) - Expand
(deleted comment)

(no subject)

From: [identity profile] vinopivets.livejournal.com - Date: 2007-02-21 11:03 am (UTC) - Expand

(no subject)

From: [identity profile] 0qwerty0.livejournal.com - Date: 2007-02-21 11:16 am (UTC) - Expand

(no subject)

From: [identity profile] khatul.livejournal.com - Date: 2007-02-21 04:26 pm (UTC) - Expand

(no subject)

From: [identity profile] vinopivets.livejournal.com - Date: 2007-02-22 07:44 am (UTC) - Expand

(no subject)

From: [identity profile] airini.livejournal.com - Date: 2007-02-21 10:47 am (UTC) - Expand

(no subject)

From: [identity profile] reut.livejournal.com - Date: 2007-02-21 10:50 am (UTC) - Expand

(no subject)

From: [identity profile] airini.livejournal.com - Date: 2007-02-21 11:03 am (UTC) - Expand

(no subject)

From: [identity profile] toyvo.livejournal.com - Date: 2007-02-21 11:46 am (UTC) - Expand

(no subject)

From: [identity profile] reut.livejournal.com - Date: 2007-02-21 10:53 am (UTC) - Expand

(no subject)

From: [identity profile] mivlad.livejournal.com - Date: 2007-02-21 11:01 am (UTC) - Expand

(no subject)

From: [identity profile] faceted-jacinth.livejournal.com - Date: 2007-02-21 11:46 am (UTC) - Expand

(no subject)

From: [identity profile] alexcohn.livejournal.com - Date: 2007-02-21 12:05 pm (UTC) - Expand

(no subject)

From: [identity profile] mivlad.livejournal.com - Date: 2007-02-21 01:09 pm (UTC) - Expand

Re: Reply to your comment...

From: [identity profile] mivlad.livejournal.com - Date: 2007-02-21 12:29 pm (UTC) - Expand

(no subject)

From: [identity profile] kot-ivanovich.livejournal.com - Date: 2007-02-21 04:46 pm (UTC) - Expand

(no subject)

From: [identity profile] faceted-jacinth.livejournal.com - Date: 2007-02-21 07:15 pm (UTC) - Expand

(no subject)

From: [identity profile] kot-ivanovich.livejournal.com - Date: 2007-02-22 06:00 am (UTC) - Expand

(no subject)

From: [identity profile] faceted-jacinth.livejournal.com - Date: 2007-02-22 05:02 pm (UTC) - Expand

(no subject)

From: [identity profile] kot-ivanovich.livejournal.com - Date: 2007-02-22 06:01 pm (UTC) - Expand

(no subject)

From: [identity profile] http://users.livejournal.com/d_m_/ - Date: 2007-02-21 01:02 pm (UTC) - Expand

Date: 2007-02-21 10:31 am (UTC)
From: [identity profile] spartach.livejournal.com
Изначально выбрать первый элемент. При получении n-го элемента выбираем его с вероятностью p = 1/n, иначе оставляем выбранный ранее.

Date: 2007-02-21 10:32 am (UTC)
From: [identity profile] stranger-p-a.livejournal.com
Например:

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) Знакомый решил ?

Date: 2007-02-21 10:53 am (UTC)
From: [identity profile] mivlad.livejournal.com
Если интуитивно, без расчётов подходить — прочитать все элементы, откладывая каждый вместо предыдущего отложенного с вероятностью 1/n, где n — натуральный номер элемента.

Впрочем, чего тут считать… Обратная индукция на пальцах [действительно на пальцах, причём :-)] подтверждает.

не глядя в комменты

Date: 2007-02-21 10:57 am (UTC)
From: [identity profile] yorool-gui.livejournal.com
1. для потока из одного элемента - вероятность выбора этого элемента 1. Выбираем его.
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

Date: 2007-02-21 11:00 am (UTC)
vitus_wagner: My photo 2005 (Default)
From: [personal profile] vitus_wagner
По-моему вполне для собеседования задачка. Знание правильного ответа свидетельствует о том, что человек читал хотя бы одну классическую книжку по программированию (например, в "The Unix Programming Environment" Кернигана и Пайка этот алгоритм разбирается) и может при необходимости вспомнить прочитанное.

Date: 2007-02-21 11:05 am (UTC)
From: [identity profile] avva.livejournal.com
Ну вот я читал Кернигана и Пайка, но этот алгоритм оттуда совершенно не помнил. Правда, решил сам, когда мне знакомый рассказал ее. Но тем не менее.

(no subject)

From: [personal profile] vitus_wagner - Date: 2007-02-21 01:36 pm (UTC) - Expand

Date: 2007-02-21 11:13 am (UTC)
From: [identity profile] 0qwerty0.livejournal.com
int size = 1;
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...

Date: 2007-02-21 11:35 am (UTC)
From: [identity profile] alaev.livejournal.com
Тут можно занудливо заметить, что если N заранее неограничено, то O(1) памяти всё равно не хватит даже для хранения этого N. Если же оно чем-то ограничено, то задача вырождается.

Возможно, имело бы смысл условие, что длина памяти ограничена O(N), если мы знаем, что элемент потока на шаге N тоже имеет длину не больше N.

Date: 2007-02-21 11:51 am (UTC)
From: [identity profile] toyvo.livejournal.com
ага, ага я тоже подмал:) log(N) при условии что размер элемента O(log(N))

(no subject)

From: [identity profile] alaev.livejournal.com - Date: 2007-02-21 12:16 pm (UTC) - Expand

(no subject)

From: [identity profile] toyvo.livejournal.com - Date: 2007-02-21 12:27 pm (UTC) - Expand

Date: 2007-02-21 11:36 am (UTC)
From: [identity profile] slobin.livejournal.com
Я эту задачку узнал из perl cookbook.

... Наша профессия не для дураков ...

(deleted comment)

Date: 2007-02-21 12:33 pm (UTC)
From: [identity profile] toyvo.livejournal.com
Аааааа!!!!!!!!!!!!!!!! :)))))))))))))))))))))))))))))))))))))))))))
Клёво!:)

(no subject)

From: [identity profile] toyvo.livejournal.com - Date: 2007-02-21 12:35 pm (UTC) - Expand
(deleted comment)

(no subject)

From: [identity profile] toyvo.livejournal.com - Date: 2007-02-21 12:58 pm (UTC) - Expand
(deleted comment)

(no subject)

From: [identity profile] toyvo.livejournal.com - Date: 2007-02-21 01:06 pm (UTC) - Expand

(no subject)

From: [identity profile] dimrub.livejournal.com - Date: 2007-02-21 12:36 pm (UTC) - Expand

(no subject)

From: [identity profile] toyvo.livejournal.com - Date: 2007-02-21 12:40 pm (UTC) - Expand
(deleted comment)

(no subject)

From: [identity profile] dimrub.livejournal.com - Date: 2007-02-21 12:51 pm (UTC) - Expand
(deleted comment)

(no subject)

From: [identity profile] toyvo.livejournal.com - Date: 2007-02-21 01:11 pm (UTC) - Expand

:)

From: [identity profile] yurilax.livejournal.com - Date: 2007-02-21 02:05 pm (UTC) - Expand

Re: :)

From: [identity profile] toyvo.livejournal.com - Date: 2007-02-21 02:13 pm (UTC) - Expand

Date: 2007-02-21 12:43 pm (UTC)
From: [identity profile] toyvo.livejournal.com
А зачем это условие: "Гарантировано, что все элементы, полученные таким образом, будут отличаться друг от друга." ?

Date: 2007-02-21 02:19 pm (UTC)
From: [identity profile] avva.livejournal.com
Чтоб не надо было думать о вероятностях повторяющихся элементов.

Date: 2007-02-21 02:34 pm (UTC)
From: [identity profile] nikto.livejournal.com
Полностью согласен, что задача не очень подходит для интервью (хотя, смотря на какую позицию...). Она ведь не на технологию, а на теорию вероятности. Я попытался ее решить (не смог) - а когда заглянул в комментарии, стало понятно почему. Что надо выбирать значения и хранить их в каком-то конечном буфере - это очевидно, а вот для того, чтобы сделать следующий шаг - догадаться заменять значение новым с вероятностью 1/N - для этого обязательно надо знать и помнить теорию.

Date: 2007-02-21 03:04 pm (UTC)
From: [identity profile] airini.livejournal.com
Полностью согласен, что задача не очень подходит для интервью (хотя, смотря на какую позицию...). Она ведь не на технологию, а на теорию вероятности.

Технологии меняются, а теория вероятности остаётся. :)

(no subject)

From: [identity profile] nikto.livejournal.com - Date: 2007-02-21 03:48 pm (UTC) - Expand

(no subject)

From: [identity profile] tobe-determined.livejournal.com - Date: 2007-02-21 06:00 pm (UTC) - Expand

(no subject)

From: [identity profile] airini.livejournal.com - Date: 2007-02-21 06:29 pm (UTC) - Expand

(no subject)

From: [identity profile] tobe-determined.livejournal.com - Date: 2007-02-21 07:11 pm (UTC) - Expand

(no subject)

From: [identity profile] airini.livejournal.com - Date: 2007-02-21 07:39 pm (UTC) - Expand

еще тупое решение

From: [identity profile] nikto.livejournal.com - Date: 2007-02-21 04:20 pm (UTC) - Expand

(no subject)

From: [identity profile] mivlad.livejournal.com - Date: 2007-02-21 07:33 pm (UTC) - Expand

(no subject)

From: [identity profile] nikto.livejournal.com - Date: 2007-02-21 08:35 pm (UTC) - Expand

Date: 2007-02-21 03:48 pm (UTC)
From: [identity profile] ilyabo.livejournal.com
пусть поток выдает буквы ABCDE и т.д.
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
и т.д

Date: 2007-02-21 04:51 pm (UTC)
From: [identity profile] kot-ivanovich.livejournal.com
Красивая задачка, но совсем не подходящая для интервью, по-моему.
Задачка простая для того, кто хоть когда-нибудь такими вещами занимался. А подходит или нет для интервью – вопрос того, на какую позицию человека интервьюировали...

Date: 2007-02-21 05:44 pm (UTC)
From: [identity profile] ---des---.livejournal.com
(честно до чтения комментов) - а разве "бросание монетки" (50/50) для каждого элемента не подойдет?

Date: 2007-02-21 05:48 pm (UTC)
From: [identity profile] ---des---.livejournal.com
упс. Очевидно, не понял я задачи - конкретно, не понял, что функция должна возвращать только один элемент из всего потока.

Date: 2007-02-21 05:59 pm (UTC)
From: [identity profile] angerona.livejournal.com
А почему не подходящая для интервью? Мне друг ее задал как-то, я довольно быстро решила, и это при том, что уже давно не программирую и задачки не решаю :).

Date: 2007-02-21 06:16 pm (UTC)
From: [identity profile] ygam.livejournal.com
Кажется, мне ее в 1999 году задали на интервью.

Date: 2007-02-21 09:27 pm (UTC)
From: [identity profile] egorfine.livejournal.com
Это слишком просто. :)

А я вот ставлю другую задачу, очень прикольную на тему посмотреть ход мыслей кандидата.

"Какая программа или какой алгоритм или какая задача теоретически на двухпроцессорной машине будет работать более чем в два раза быстрее чем на однопроцессорной".

Задача теоретическая и теоретически же правильный ответ существует, но интересно то, как к нему приходят или не приходят кандидаты. :)

А еще прекрасный вопрос для программистов: "зачем придумали подоконник". Удивительно небольшое количество людей отвечает правильно.

Date: 2007-02-22 01:39 am (UTC)
From: [identity profile] avva.livejournal.com
Ну, первое, видимо, связано с размерами кэшей, а также задачами, где параллельное вычисление позволяет каждому потоку многократно пользоваться в процессе вычисления промежуточными результатами других потоков (так что при однопроцессорной работе процессор не может запускать их один за другим, а вынужден симулировать одновременную работу в той или иной степени, и тратить время на переключение контекстов итд.).

А второе... гм, я бы сказал, что подоконник первоначально никто не придумывал, а просто стены были намного толще, чем окна, которые в них вставлялись. Не так?

(no subject)

From: [identity profile] egorfine.livejournal.com - Date: 2007-02-22 07:14 am (UTC) - Expand

(no subject)

From: [identity profile] doppeltes.livejournal.com - Date: 2007-03-02 03:12 pm (UTC) - Expand

(no subject)

From: [identity profile] egorfine.livejournal.com - Date: 2007-03-02 03:15 pm (UTC) - Expand

Date: 2007-02-22 03:06 am (UTC)
From: [identity profile] pingva.livejournal.com
с вероятностью 1/k назначать k-ый элемент кандидатом на возвращение, и так до конца файла.

Равновероятность элементов легко показывается рекурсивно, начиная с конца, т.е.: у последнего элемента вероятность быть выбраным -- 1/N. Соответственно, у остальных N-1 элементов она 1/(N-1), и их равновероятность ясна из ...(тут следует рекурсия)
Page 1 of 2 << [1] [2] >>

January 2026

S M T W T F S
    1 2 3
4 5 6 7 8 910
11 12 1314151617
18192021222324
25262728293031

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jan. 15th, 2026 02:02 pm
Powered by Dreamwidth Studios