Решение проблем методом Резиновой Утки

Любительский перевод этой статьи

Прошу строго не судить 🙂 Замечания приветствуются 🙂

Решение проблем методом резиновой утки

На Stack Exchange мы настаиваем на том, чтобы люди, которые задают вопросы, вкладывали немного усилий в свой вопрос, и в этом деле мы зануды. А именно, перед тем, как задать вопрос, ты должен…

  • Достаточно подробно описать происходящее, чтобы мы могли повторить твои шаги. Предоставь нам необходимую базовую информацию, чтобы понять, что происходит, даже если мы не являемся экспертами в данной области.
  • Рассказать нам, для чего тебе нужно знать ответ. Что привело тебя сюда? Это праздное любопытство или это как-то препятствует выполнению твоего проекта? Нам не нужна вся твоя биография, просто дай нам некоторый контекст.
  • Поделись своими исследованиями по этой проблеме; что ты нашел на текущий момент? Почему это не сработало? А если ты не проводил никаких исследований … стоит ли тебе вообще спрашивать? Если ты приглашаешь нас потратить наше драгоценное время на помощь тебе, будет честно только если ты потрудишься и потратишь разумное количество своего драгоценного времени на то, чтобы твой вопрос выглядел прилично. Помоги нам помочь тебе!

У нас есть отличная страница Как Задавать Вопросы, которая объясняет все это, и на которую щедро ссылаются по всей сети. (И на Stack Overflow, благодаря массивному объему вопросов, мы, в действительности, заставляем новых пользователей кликать через эту страницу прежде, чем задать свой первый вопрос. Ты и сам можешь увидеть это, задав вопрос в качестве нового пользователя.)

Прежде всего, мы хотим избежать одноразовых вопросов, на которые невозможно ответить. Они никому не помогут, а если их оставлять в таком бесполезном виде, то могут погубить любой Q&A сайт, превратив его виртуальный город призраков. На Stack Exchange лишенные информации и контекста вопросы, на которые невозможно дать разумный ответ, будут сразу же закрыты, и если их не улучшат, в конце концов удалены.

Как я сказал, в этом деле мы зануды. Но по уважительной причине: мы явным образом пытаемся помочь тебе помочь себе, научив тебя решению проблем методом Резиновой Утки. И это всегда работает. На протяжении многих лет я получил тонны отзывов о том, как люди, в процессе тщательного, детализированного написания вопросов, для Stack Overflow или другого Stack Exchange сайта, находили ответ на свой вопрос.

Довольно частый случай. Смотри сам:

Как мне отблагодарить сообщество за решение своих собственных проблем?

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

Почему правильно сформулированный вопрос часто приводит тебя к ответу?

Я не знаю сколько раз это случалось:

  • У меня проблема
  • Я решил обратиться с этим на stack overflow
  • Я неуклюже пишу свой вопрос
  • Я осознаю, что вопрос не имеет никакого смысла
  • Я трачу 15 минут на то, чтобы заново подумать, как задать свой вопрос
  • Я осознаю, что решаю проблему совсем не с той стороны.
  • Я начинаю с нуля и быстро нахожу решение.

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

Начальная формулировка вопроса, на самом деле, помогает мне самостоятельно определить и решить мою проблему

Начальная формулировка вопроса, на самом деле, помогает мне самостоятельно определить и решить мою проблему, особенно пытаясь сформулировать понятное и достаточно детальное тело вопроса для того, чтобы получить качественные ответы. У кого-нибудь было такое?

Это не новая концепция и наверное каждое сообщество в итоге приходит к этому, но «Спроси Утку» является очень мощной техникой решения проблем.

Боб указал в угол кабинета. «Там, — сказал он, — утка. Я хочу, чтобы ты задал этой утке свой вопрос.»

Я посмотрел на утку. На самом деле, это было чучело, совсем мертвое. Но даже если бы утка не была мертвой, это был бы не лучший источник конструктивной информации. Я посмотрел на Боба. Тот был абсолютно серьезным. Он также был моим начальником, а я не хотел терять работу.

Я неуклюже подошел к утке, стал рядом и, как будто в молитве, склонил к ней голову, чтобы побеседовать. «Что ты делаешь?» — требовательно спросил Боб.

«Я задаю утке свой вопрос», — ответил я.

Один из начальников Боба был в его кабинете. Этот ублюдок улыбался, с зубочисткой во рту. «Энди, — сказал он, — я не хочу, чтобы ты молился утке. Я хочу, чтобы ты задал ей свой вопрос».

Я облизнул губы. «Вслух?» — спросил я.

«Вслух», — твердо ответил Боб.

Я прочистил горло. «Утка», — начал я.

«Ее зовут Боб Младший», — подсказал начальник Боба. Я криво взглянул на него.

«Утка», — продолжил я, — «я хочу знать, когда я использую подвесной хомут, что не дает трубе разбрызгивателя выскочить из него, когда хомут разжимается, в результате чего труба…»

На середине моего вопроса утке меня осенило. Подвесной хомут крепится к конструкции сверху длинным стержнем с резьбой. Если слесарь вкручивает стержень с резьбой так, что он упирается в верх трубы, это по сути и будет держать трубу в хомуте и не даст ей выскочить.

Я повернулся и взглянул на Боба. Боб кивал. «Ты знаешь, так ведь?», — сказал он.

«Ты вкручиваешь стержень с резьбой к верху трубы», — сказал я.

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

«Хорошо», — сказал я и вернулся к работе.

Мне нравится конкретно эта история, потому что она кристально чисто проясняет, что самая важная часть решения проблем методом резиновой утки — это обязательно задать тщательно сформулированный, детальный вопрос у воображаемого человека или неодушевленного предмета. Да, даже если ты в итоге отбросишь вопрос, потому что ты в конце концов поймешь, что сделал какую-то глупую ошибку. Попытка кого-то воображаемого пройтись по твоей проблеме, шаг за шагом в деталях, это то, что часто приведет тебя к решению. Если ты не хочешь прилагать усилий, чтобы полностью объяснить проблему и как ты ее решал, ты не сможешь пожинать плоды глубокого мышления над своей проблемой перед тем, как спросить у других.

Если у тебя нет друга программиста (а он обязательно должен быть), ты можешь применить технику решения проблем Резиновой Утки, чтобы выяснить проблемы самостоятельно, или пользуясь большим Интернет сообществом. Даже если ты не получил ответ, который хотел, заставляя себя полностью объяснить свою проблему — в идеале, письменно — зачастую приведет тебя к новым идеям и открытиям.

Источник: http://blog.codinghorror.com/rubber-duck-problem-solving/

Реклама
Решение проблем методом Резиновой Утки

Задача про 100-этажный дом

Имеется 100-этажное здание и две стеклянные бутылки. Если выбросить бутылку из окна какого-нибудь этажа, то она или разобьется или нет. За какое минимальное количество бросков можно определить этаж, начиная с которого, бутылки разбиваются? Не разбившуюся бутылку можно бросать повторно.

1. Бинарный поиск не подходит т.к. бутылки всего две.

2. Решение в общем виде сводится к следующему:

— мы разделяем здание на секции (например, 10 секций по 10 этажей).

— используем первую бутылку, чтобы определить в какой секции бутылки начинают разбиваться, (т.е. бросаем бутылку с 10, 20, 30, … , 100 этажа, пока не разобьется, или же если не разбивается на 100-м этаже, значит крепкие бутылки оказались).

— используем вторую бутылку, чтобы определить конкретный этаж секции (т.е. например бутылка разбилась на 40 этаже; начиная с 31 этажа и выше последовательно бросаем вторую бутылку, пока не определим искомый этаж).

В данном примере максимальное количество бросков составит 19 раз (т.е. в худшем случае 10 секций = 10 раз + 9 раз для перебора всех этажей в секции).

Теперь рассмотрим вариант более оптимального разделения этажей здания.

Упростим задачу. Пусть будет одноэтажный дом. Сколько потребуется бросков? Один. А если два этажа? Два броска. А если три?

| 1 | 2 | 3 |

Если будет одна секция (т.е. все три этажа в одной секции), то следуя вышеуказанному алгоритму, бросаем с 3, этажа, если разбивается, бросаем с 1-го, если не разбивается, бросаем со 2-го. Получается 3 броска.

Разделим на две секции

| 1 | 2 |    | 3 |     (можно и так    | 1 |     | 2 | 3 |  но в данном случае все равно 3 броска — с 1-го, 3-го, 2-го, т.е. не годится)

Итак, бросаем со 2-го, не разбилась — бросаем с 3-го, разбилась — бросаем с 1-го. Итого 2 броска.

Далее, путем увеличения количества этажей и перебора возможных вариантов их разделения на секции, можно сделать несколько выводов:

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

2. Максимальное количество бросков равно количеству этажей в самой первой секции.

3. Появляется некая закономерность, не ясно только как ее вычислить

Кол-во этажей | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | … | 100 |…

—————————————————————————————————————————————

Кол-во бросков | 1 | 2 | 2 | 3 | 3 | 3 | 4 | 4 | 4 |  4  |  5  |  5  |  5  |  5  |  5  |  6  |  6  |  6  |  6  |  6  |  6  |  7  | … |  14  |…

Таким образом, 100-этажное здание мы разделяем, на следующие 12 секций (первая секция 14 этажей, вторая 13, и т.д., последняя 1 этаж)

| 1 .. 14 |  | 15 .. 27 |  | 28 .. 39 |  | 40 .. 50 | | 51 .. 60 |  | 61 .. 69 | | 70 .. 77 |  | 78 .. 84 |  | 85 .. 90 |  | 91 .. 95 | | 96 .. 99 | | 100 |

При таком разделении максимальное число бросков будет равно 14.

А сам метод поиска минимального количества бросков может выглядеть как-то так


int CalculateAttempts(int floors)
{
int sum = 0, i = 1;
for (; i <= floors; i++)
{
sum += i;
if (sum >= floors) return i;
}
return -1;
}

Задача про 100-этажный дом