Комментарии 538
Ой да ну, ну с первого раза не напишу, а напишу гарантированно. Помню в универе проходили много алгоритмов сортировки. Двоичный написать понимая его просто, а понимают его все кто о нем знает, другое дело, что не все о нем знают, просто потому что не было у них таких дисциплин и сами не интересовались.
Другое дело какие-нибудь пирамидальные сортировки:), это я не напишу, хотя бы потому что не помню алгоритма, да и насколько помнь реализация не сильно короткая.
Другое дело какие-нибудь пирамидальные сортировки:), это я не напишу, хотя бы потому что не помню алгоритма, да и насколько помнь реализация не сильно короткая.
Серега, я тоже думал что напишу. Вот написал. Конечно, если пишешь его по 10 разу то никаких проблем не будет. Пост для тех, кто не писал двоичный поиск, но считает себя годным программистом.
Мне кажется годный программист, как раз этим и отличается, что может разобраться и реализовать незнакомый алгоритм. А время затраченное на это, определяет годность.
Ну так и я о том же. Конечно задача покажется легкой, если её проходили в универе и реализовывали на доске всей группой.
В детстве, на олимпиадах мы писали и двоичный поиск и волновой в графе и даже строковую арифметику «с закрытыми глазами», по памяти. При этом ни разу не обошлось без пары-тройки-четверки отладочных прогонов и обидных багов.
Так что гарантированно будут проблемы и на 10й раз и на 50й. Людям свойственно ошибаться. :)
А что до профпригодности программиста, то если он не впал в ступор от слов «бинарный поиск», то и это уже неплохо.
Так что гарантированно будут проблемы и на 10й раз и на 50й. Людям свойственно ошибаться. :)
А что до профпригодности программиста, то если он не впал в ступор от слов «бинарный поиск», то и это уже неплохо.
Буквально вот недавно закончил писать реализацию B-дерева. Вроде просто, а в процессе написания багов было отловлена целая куча
тоже в детстве писали реализацию карандашом на бумажке
кстати, а как это — без тестирования?
я даже на листике сначала придумываю и пишу тесты, а потом по ним валидный код.
иначе как, в голове все тесты держать нужно?
кстати, а как это — без тестирования?
я даже на листике сначала придумываю и пишу тесты, а потом по ним валидный код.
иначе как, в голове все тесты держать нужно?
А мы с друзьями часть алгоритмов писали просто выключая монитор и печатая на клавиатуре не глядя на то, что получается… Ни разу не получилось полностью правильно. В самом похожем на истину варианте вместо скобки "[" была напечатана "{"… Мелочь, но не компилится…
Это мне напомнило как я писал на спектруме программу вывода цветных полос для настройки телека.
Естественно, раз телек не настроен, то на нем нифига не видно :)
Но ничего, насобачился — раза с пятого уже печатал без ошибок.
Но это не показатель — во первых, программка из трех строчек, а во-вторых на спектруме не бывает опечаток в операторах.
Естественно, раз телек не настроен, то на нем нифига не видно :)
Но ничего, насобачился — раза с пятого уже печатал без ошибок.
Но это не показатель — во первых, программка из трех строчек, а во-вторых на спектруме не бывает опечаток в операторах.
Специально для тех кто сомневался в моих способностях и опустил карму:):
pastie.org/927644
pastie.org/927644
На вскидку: как минимум баг с переполнением целого там есть )
Ммм, что, где?:)
Когда размер массива превышает половину макимального значения MAX, допустимого для $m, будет получена ошибка (несмотря на то, что все входные/выходные данные не превышают MAX).
* сорри, случайно отправил не дописав до конца *
По сути это из самых незначительных багов. В стандартных условиях он и не появится. Но тем не менее — про вашу рализацию нельзя сказать, что она совсем без багов :)
По сути это из самых незначительных багов. В стандартных условиях он и не появится. Но тем не менее — про вашу рализацию нельзя сказать, что она совсем без багов :)
Баг с переполнением — это уже тонкие вещи, все остальное похоже правильно. Необычный способ.
ДА сколько же на хабре невменяемых:) Комменты плюсуют, а карму наоборот. Объясняйте хоть чего не так или просто радость слить кого-то. Обиженные с детства?:)
Как на счёт таких данных:
$array = array(10,3,0,2,1);
echo BSinArray($array, 10);
Результат -1. А должно быть 0.
$array = array(10,3,0,2,1);
echo BSinArray($array, 10);
Результат -1. А должно быть 0.
Напишете сразу и без ошибок? Без единого прогона? Я вот честно признаюсь — с ходу не напишу. С одного-двух-трех прогонов — напишу. И не думаю, что вы как программист сильно круче меня :-Р
Простой то он простой. Вот только написать его без ошибок на различных частных случаев сходу без тестирования практически невозможно
Вместо «алгоритмов сортировки» — стоит читать «алгоритмов поиска». Хотя изучали и то, и другое и много чего еще:)
unsigned int binary_find(int *arr, unsigned int max_index, int num)
{
int i = 0, j = 0, k = 0;
unsigned int ret = 0;
j = max_index;
do {
k = (i + j) / 2;
if(arr[k] == num) {
ret = arr[k];
break;
}
else if(arr[k] > num)
--j;
else if(arr[k] < num)
++i;
} while ( i
{
int i = 0, j = 0, k = 0;
unsigned int ret = 0;
j = max_index;
do {
k = (i + j) / 2;
if(arr[k] == num) {
ret = arr[k];
break;
}
else if(arr[k] > num)
--j;
else if(arr[k] < num)
++i;
} while ( i
Что-то покоцалось, лучше на Pastie, там сохраняется форматирование.
Мм, это не совсем двоичный поиск. У вас просто одна из границ плавно ползет к искомому числу, как если бы вы листали в словаре страницы. А здесь именно нужно именно на каждом шаге брать половину от предыдущего набора. Сначала есть весь массив, на слеющем шаге остается половина, потом четвертина, восьмерина. То есть: ...else if(arr[k] < num) j = k;
Имхо, ошибочка. Вместо --j и ++i должно быть j=k и i=k, в этом суть половинного деления, а вы сдвигаете на одну позицию крайние позиции.
Первая ошибка:
Если элементов в массиве непарное количество, будет нехорошо )
k = (i + j) / 2;
Если элементов в массиве непарное количество, будет нехорошо )
Язык — Javascript, если что…
На вот таком массиве повиснет: [1,2]
У меня то же самое было, а потом еще долго думал над костылем. Правильное решение красиво в этом смысле, там без костыля.
У меня то же самое было, а потом еще долго думал над костылем. Правильное решение красиво в этом смысле, там без костыля.
Подправил свой код. 3 ошибки. 2 тестовых прогона. Вроде, без костыля.
НЛО прилетело и опубликовало эту надпись здесь
Это типа умный прагматичный подход?
Вот скажем, я хочу взять программера на задачи по коллаборативной фильтрации. Хочу знать, годен ли он. Или лучше — он хочет знать, потянет ли он. Что ему, бесплатно потратить неделю своего времени на реализацию практической задачи? Нет конечно. А вот такие игрушечные задачи прекрасно позволяют оценить уровень.
Вот скажем, я хочу взять программера на задачи по коллаборативной фильтрации. Хочу знать, годен ли он. Или лучше — он хочет знать, потянет ли он. Что ему, бесплатно потратить неделю своего времени на реализацию практической задачи? Нет конечно. А вот такие игрушечные задачи прекрасно позволяют оценить уровень.
pastie.org/927546
Два прогона. Первый раз сглюкнула интендация в TextMate. Второй раз сообразил что во второй строке надо дописать
Два прогона. Первый раз сглюкнула интендация в TextMate. Второй раз сообразил что во второй строке надо дописать
+indexFrom
:)и да. Я никогда не писал двоичный поиск потому что не было необходимости изобретать велосипед. Времени потратил на написание… ну минуты три вместе с двумя прогонами.
Что произойдет в случае what = 8? :)
Ну, рекурсивно неинтересно.
Почему? это всего лишь один из способов реализации. Ну хотите я разверну рекурсию с парой индексов начало-конец и заверну это в цикл
while fromIndex < toIndex
? Ну и так можно, это всего лишь вариант решения, а по сути — идентичный алгоритм (однако рекурсия в этом случае гораздо выразительнее, т.к. алгоритм рекурсивен по своей сути). Рекурсию в таком алгоритме стыдно.
20 минут — php
http://pastie.org/927547
http://pastie.org/927547
Если искомого числа нет в массиве, то…
А если $lookingFor отсутствует в масиве?
ать, попался :)
там нужна еще проверка на пересекаемость границ
там нужна еще проверка на пересекаемость границ
Как-то так думаю pastie.org/927664
Вот только сейчас закончил)) Правда не программист, а админ и отвлекают постоянно на работе(
Вот только сейчас закончил)) Правда не программист, а админ и отвлекают постоянно на работе(
Что будет если размер массива равен нулю? (подсказка: оно вылетит с диким грохотом).
Прочитал заголовок, думал будет какой-то жутко умный алгоритм с битовыми операциями. А оказалось речь про банальную дихотомию :)
вот у меня от слова дихотомия сводит скулы. а от фразы binary search мне становится все очень быстро понятно. не надо умничать.
А почему бы не называть вещи своими именами? Прям вот от давнего греческого слова скулы сводит, а от английского не сводит. Фраза на русском «двоичный поиск» ничего не сводит?
я не умничаю, мне действительно слово «дихотомия» ближе и понятнее, чем «бинарный поиск». Видимо, тяжелое детство в физмате сказывается :)
минуту или 2
ну 5 чтоб дописать красиво
да, раньше не раз такое писал
ну 5 чтоб дописать красиво
да, раньше не раз такое писал
Ну, как бы, и что? Есть 10% программистов, умеющих писать двоичный поиск. Есть 50% знаючих PHP, есть 0,01% способных создать аналог Windows или Linux с нуля. Никто не умеет всего. Тем более, что писать двоичный поиск с нуля — странная идея при наличии библиотек под любую платформу. Этак можно сказать «только 2% помнят, как пробивать дырки на перфокартах».
Умение или неумение написать двоичный поиск с первого раза правильно — не есть формальный признак хорошего программиста.
Умение или неумение написать двоичный поиск с первого раза правильно — не есть формальный признак хорошего программиста.
Согласен. Но умение написать широко известный алгоритм, воплотив его в исходном коде — это есть то качество, которое отличает программистов от не-программистов.
Никто не умеет всего. Если человек делает сайты даже, ему нужно решать алгоритмические задачи посложнее двоичного поиска. Хорошо ли он их решает? Как узнать? Сравнить не с чем. А тут просто, пишешь за 5 минут, сравниваешь свою реализацию с классической, оцениваешь свой уровень.
Совсем не странная идея, если не подходить к этому как к упражнению или к тесту.
Совсем не странная идея, если не подходить к этому как к упражнению или к тесту.
Если человек не знает элементарных вещей, то хорошо ли он будет понимать сложные?
«Умение или неумение написать двоичный поиск с первого раза правильно»
Представляете веб-дизайнера, который умеет рисовать только темно-синие квадраты?
Я вот так же не могу представить программиста, который умеет или не умеет написать двоичный поиск. Каждый программист каждый раз решает разные задачи, и важно только общее умение программировать (сюда относим всю логику, умение концентрироваться итд итп). Дело не в том, что алгоритм так важен и «никогда не знаешь, когда придется самому с нуля его написать», а в том, что это просто пример задачи определенной сложности и коварности. Неспособность решить эту задачу означает неспособность решить более алгоритмически сложные задачи. Нехватило внимательности, чтобы самому найти ошибку (и посчитал программу завершенной, а она еще глючная). Нехватило аккуратности, чтобы предположить, что на входе — пустой массив. итд. Придумал интересный сложный тест в уме, но нехватило концентрации чтобы в уме его прогнать по своему алгоритму итд.
Все эти качества — однозначно важны для программиста, и нехватка их вредит во всех проектах.
Тут отличительная особенность — надо написать _правильный_ код, а не тот, который «вроде работает», при этом действительно у всех вокруг он работает, но где-то в Урюпинске у кого-то не работает (наверное потому что сам дурак). Потом багрепорт еще откудато. И еще. Потом наконец-то проблема отлавливается. Это нормальный процесс в наше время (обычный). А здесь необычно требуется самому закодить хоть и не очень сложный алгоритм, но сделать это правильно. И не «с первого раза» — можно хоть сто раз переписывать, но «хоть с миллионного» раза, но ДО того момента, как показал код и назвал его решением.
Представляете веб-дизайнера, который умеет рисовать только темно-синие квадраты?
Я вот так же не могу представить программиста, который умеет или не умеет написать двоичный поиск. Каждый программист каждый раз решает разные задачи, и важно только общее умение программировать (сюда относим всю логику, умение концентрироваться итд итп). Дело не в том, что алгоритм так важен и «никогда не знаешь, когда придется самому с нуля его написать», а в том, что это просто пример задачи определенной сложности и коварности. Неспособность решить эту задачу означает неспособность решить более алгоритмически сложные задачи. Нехватило внимательности, чтобы самому найти ошибку (и посчитал программу завершенной, а она еще глючная). Нехватило аккуратности, чтобы предположить, что на входе — пустой массив. итд. Придумал интересный сложный тест в уме, но нехватило концентрации чтобы в уме его прогнать по своему алгоритму итд.
Все эти качества — однозначно важны для программиста, и нехватка их вредит во всех проектах.
Тут отличительная особенность — надо написать _правильный_ код, а не тот, который «вроде работает», при этом действительно у всех вокруг он работает, но где-то в Урюпинске у кого-то не работает (наверное потому что сам дурак). Потом багрепорт еще откудато. И еще. Потом наконец-то проблема отлавливается. Это нормальный процесс в наше время (обычный). А здесь необычно требуется самому закодить хоть и не очень сложный алгоритм, но сделать это правильно. И не «с первого раза» — можно хоть сто раз переписывать, но «хоть с миллионного» раза, но ДО того момента, как показал код и назвал его решением.
Дети, ей Богу!
Не ошибается только тот, кто ничего не делает. Я например текст набираю с ошибками, но потом их правлю, правда не всегда. :) А вот программы надо просто грамотно тестировать. В этом плане мне нравиться Code Jam, где тебе дают минимальный тест, потом функциональный, а потом еще и тест на производительность.
А реализовывать поиск делением попалам надо где-то там, в школе. И тогда же читать книги Кнута, жаль что из всего 3.
Не ошибается только тот, кто ничего не делает. Я например текст набираю с ошибками, но потом их правлю, правда не всегда. :) А вот программы надо просто грамотно тестировать. В этом плане мне нравиться Code Jam, где тебе дают минимальный тест, потом функциональный, а потом еще и тест на производительность.
А реализовывать поиск делением попалам надо где-то там, в школе. И тогда же читать книги Кнута, жаль что из всего 3.
И тогда же читать книги Кнута, жаль что из всего 3
Уже 4.
А ты много вспомнишь из книг Кнута, читая их в школьном возрасте? Или высшая математика плавно перебралась в школу?
Вряд ли знание того, что алгоритм выполнятся O(log2 n * sqrt(n + n2)), сильно пригодится рядовому программисту.
Программист лишь должен пользоваться трудами других. Если стоит задача отсортировать числа, то я возьму справочник и выберу лишь тот алгоритм сортировки, который наиболее пригодный в моем случае и чья эффективность проверена математиками. Не всякий программист является математиком, так же как и не всякий математик — программистом.
Вряд ли знание того, что алгоритм выполнятся O(log2 n * sqrt(n + n2)), сильно пригодится рядовому программисту.
Программист лишь должен пользоваться трудами других. Если стоит задача отсортировать числа, то я возьму справочник и выберу лишь тот алгоритм сортировки, который наиболее пригодный в моем случае и чья эффективность проверена математиками. Не всякий программист является математиком, так же как и не всякий математик — программистом.
>Вряд ли знание того, что алгоритм выполнятся O(log2 n * sqrt(n + n2)), сильно пригодится рядовому программисту.
ARRRGH!!!
Быдлокодеру не пригодится, программисту — обязательно пригодится.
ARRRGH!!!
Быдлокодеру не пригодится, программисту — обязательно пригодится.
Как бы тебе это сказать… O(log2n * sqrt(n + n2)) = O(n * log2n)
Боюсь ты сам себя только что записал в быдлокодеры. Надеюсь твой работодатель этого не узнает.
Боюсь ты сам себя только что записал в быдлокодеры. Надеюсь твой работодатель этого не узнает.
антикульт быдлокодера уже достал. к месту и не к месту.
даже отличные программисты пишут быдлокод во многих случаях в реальной жизни.
даже отличные программисты пишут быдлокод во многих случаях в реальной жизни.
Слово некрасивое, да. Но по сути-то верно.
>даже отличные программисты пишут быдлокод во многих случаях в реальной жизни.
Халтурят в разных ситуациях все. Но хороший программист, в отличие от плохого, может написать хороший код [при желании, разумеется]. =)
>даже отличные программисты пишут быдлокод во многих случаях в реальной жизни.
Халтурят в разных ситуациях все. Но хороший программист, в отличие от плохого, может написать хороший код [при желании, разумеется]. =)
нет. то, что люди понимают как быдлокод — далеко(!) не всегда является халтурой!
ps: в тему — habrahabr.ru/blogs/development/91665/
ps: в тему — habrahabr.ru/blogs/development/91665/
статья напомнила о числе 95% :)
// lurkmore.ru/95%25
// lurkmore.ru/95%25
* ворчит *
Из приходящих на собеседование «программистов» только 10% вообще знают, что такое двоичный поиск.
Из приходящих на собеседование «программистов» только 10% вообще знают, что такое двоичный поиск.
Я помню в 14 лет пришел в контору собеседоваться. Они так снисходительно, у нас информационная система, нужно хранение документов, редактирование, доступ с любого компьютера. Как будешь делать? Я говорю, ну, хранить в XML, отдавать буду HTML (как раз только начал интересоваться вебом). Они — хаха! Да нет друг, здесь база данных нужна, Delphi. Вот ты знаешь что такое реляция? Переспрашиваю: корелляция? — Нет, ре-ля-ция. — Не знаю. — Ну иди гуляй.
А сейчас ни один человек в здравом уме не станет делать это на Delphi. С MySQL на нужном им уровне я научился работать за день. Толку от того, что я знал бы как это называется. Главное по сути понимать, или уметь освоить.
А сейчас ни один человек в здравом уме не станет делать это на Delphi. С MySQL на нужном им уровне я научился работать за день. Толку от того, что я знал бы как это называется. Главное по сути понимать, или уметь освоить.
* ворчит опять *
А очень было бы неплохо, если бы программист знал хотя бы основы реляционной алгебры… А то налепят по образцу восемь левых джойнов, а потом у них запрос к таблице в 40 записей пять минут выполняется…
А очень было бы неплохо, если бы программист знал хотя бы основы реляционной алгебры… А то налепят по образцу восемь левых джойнов, а потом у них запрос к таблице в 40 записей пять минут выполняется…
Основы реляционной алгебры никак не научат его, что каджый DROP TABLE в MySQL лочит все таблицы почти на полсекунды. Я не спорю, вы дело говорите, но есть другая сторона.
Дела не в джоинах, а в не понимании структуры БД. А даже если и знаешь ее, то с опытом все приходит.
Потом как раз начинаешь «пользоваться» фичами, когда обычный джоин нулюет запись слева, если правая нуль. Повторюсь, опыт решает.
А по теме можно сказать одно. Требовать от программиста знания чего-то просто неверно. Не зря есть такие вещи как испытательный срок. Если видишь, что человечек умненький, но чего-то не знает, это не значит, что ему что-то помешает в этом разобраться и даже стать в итоге лучше тебя… Разные фирмы работают в своих сферах, изучить все не вариант
Потом как раз начинаешь «пользоваться» фичами, когда обычный джоин нулюет запись слева, если правая нуль. Повторюсь, опыт решает.
А по теме можно сказать одно. Требовать от программиста знания чего-то просто неверно. Не зря есть такие вещи как испытательный срок. Если видишь, что человечек умненький, но чего-то не знает, это не значит, что ему что-то помешает в этом разобраться и даже стать в итоге лучше тебя… Разные фирмы работают в своих сферах, изучить все не вариант
Drop table как бы операция, которая должна выполняться на продакшене не чаще, чем раз в раз-в-патч, или лучше раз-в-релиз? Или вы дропаете их настолько часто, что это замедляет производительность?
Джоины в СУБД очень оптимизированны. У меня есть запрос с десятком Лефт Джоинов, которые получают пачку данных из таблиц по несколько тысяч записей за доли секунды.
Более того — опытные администраторы БД мне советовали пользоваться Джоинами, а не несколькими мелкими запросами. Они утверждают, что боязнь Джоинов у не очень опытных программистов от непонятия механизмов, которые работают внутри СУБД.
Более того — опытные администраторы БД мне советовали пользоваться Джоинами, а не несколькими мелкими запросами. Они утверждают, что боязнь Джоинов у не очень опытных программистов от непонятия механизмов, которые работают внутри СУБД.
Замечу, что несколько тысяч записей — это не слишком большой объем БД.
замечу, что я и не говорил, что это большой объем БД.
человек сказал: 40 записей — 300 секунд
я сказал: тысячи записей — доли секунды (практически столько же, как 10 запросов без джоинов)
человек сказал: 40 записей — 300 секунд
я сказал: тысячи записей — доли секунды (практически столько же, как 10 запросов без джоинов)
Ладно, ладно. Я лично писал partitioned-wise joins на оракле, 5-6 джойнах, в одной из таблиц 4 миллиарда записей. Работало in reasonable time! :)
Это смотря какая СУБД. Приведенный случай касался MySQL, у которой, конечно, хороший оптимизатор, но ждать от него гениальности нельзя.
Left join — это ещё ничего, а вот когда налепят восемь inner join-ов — вот это да. Или того хлеще, просто перечислят таблицы во from через запятую.
Left join — это ещё ничего, а вот когда налепят восемь inner join-ов — вот это да
А чем плохо 8 inner join'ов?
Или того хлеще, просто перечислят таблицы во from через запятую.
Сам факт еще ни о чем не говорит. Если в where указаны условия пересечения этих таблиц, то это равносильно inner join, иначе cross join. Поэтому с таким же успехом вы можете негодовать по поводу использования join'ов вообще.
Inner join-ы плохи тем, что это очень процессороёмкая операция на объёмах данных, отличающихся от самых минимальных. Понятно, что это не означает, что от inner join-ов нужно отказываться совсем, но если есть выбор между inner и left при гарантированно одинаковом результате (например, если у нас все данные гарантированно консистентны, а NULL-ов просто не бывает) — то выбирать надо однозначно left.
А cross join крайне требователен к памяти.
А cross join крайне требователен к памяти.
Не могли бы вы немного по-подробнее рассказать почему «inner join более процессороемкий, чем left join»
Что означает — самых минимальных? Выборка в, скажем, 500 000 строк, это минимальный объем данных? Для веб-приложения на бесплатном хостинге под мускулом? А для Data Warehouse на enterprise-level СУБД, на выделенных серверах с отдельным SAN?
Это на какой СУБД такая разница между inner join и left?
1) Inner Join ничуть не сложнее, чем Left Join, даже, наверно, чуть проще, так как результат меньше
2) Перечисление таблиц во From, c точки зрения MySQL, ничем не отличается от inner join
2) Перечисление таблиц во From, c точки зрения MySQL, ничем не отличается от inner join
А просветите, в чем такой явный минус от 8 летф джойнов? Недостаток денормализации? Или вы думаете, он мержит промежуточные resultsets на диске, и возрастает нагрузка на IO? Я не уверен, что согласен с вашим высказыванием (И что я его правильно понял).
А было бы еще лучше для таких целей нанимать БДА :)
Не, те кто просто не знают — это еще нормальные.
Хуже всего те, кто мало того что не знает, так еще и знать не хочет!
Хуже всего те, кто мало того что не знает, так еще и знать не хочет!
И даже не все кандидаты в президенты…
www.youtube.com/watch?v=k4RRi_ntQc8
Barack Obama — Computer Science Question
www.youtube.com/watch?v=k4RRi_ntQc8
Barack Obama — Computer Science Question
Минуты 4, Python:
a=range(50,200,2); bsearch = lambda a,s,i=False,step=False:(not step and bsearch(a,s,len(a)/2,len(a)/4+1)) or (a[i]==s and str(i)) or (s<a[i] and bsearch(a,s,i-step,step/2+step%2)) or (bsearch(a,s,i+step,step/2+step%2)); bsearch(a,178); bsearch(a,54);
вы уверены что это python? :D
Не нужно так писать на питоне :)
Согласен, но я же писал не компонент для использования, а быстрое решение конкретной задачи.
Писать на продакшн так не нужно, согласен =)
Писать на продакшн так не нужно, согласен =)
Чистосердечное признание
После первого написания содержало два бага:
— вместо step сначала проверялась на положительность i — исправил по ходу написания
— вместо строки возвращалось число — зацикливание, если искомый элемент имеет индекс 0.
После первого написания содержало два бага:
— вместо step сначала проверялась на положительность i — исправил по ходу написания
— вместо строки возвращалось число — зацикливание, если искомый элемент имеет индекс 0.
Теперь по повожу распространенных ошибок из спойлера:
— не работает с массивом из 0/1/2 элементов
Работает. При нулевой длине отлично возникает исключение — обрабатывайте.
— не находит первый или последний элемент
Находит
— некорректно работает, если элемента в массиве нет
Это есть. Нужно после проверки на равенство добавить: or (step==1 and '-1')
— некорректно работает, если в массиве есть повторяющиеся элементы
Корректно. Возвратит индекс первого, на который наткнется
— обращение к элементами за пределами массива
Не особо понял, но есть такая замечательная вещь — исключения.
— не работает с массивом из 0/1/2 элементов
Работает. При нулевой длине отлично возникает исключение — обрабатывайте.
— не находит первый или последний элемент
Находит
— некорректно работает, если элемента в массиве нет
Это есть. Нужно после проверки на равенство добавить: or (step==1 and '-1')
— некорректно работает, если в массиве есть повторяющиеся элементы
Корректно. Возвратит индекс первого, на который наткнется
— обращение к элементами за пределами массива
Не особо понял, но есть такая замечательная вещь — исключения.
На любом языке могу писать как на Хаскелле? :)
hpaste.org/fastcgi/hpaste.fcgi/view?id=24986#a24986
Вот кстати мой вариант на Хаскелле, одна ошибка была котороую я поправил, может еще остались, зато наглядно :)
Вот кстати мой вариант на Хаскелле, одна ошибка была котороую я поправил, может еще остались, зато наглядно :)
За это я и люблю питон!
Если мне на собеседовании пишут такой код (были красавцы), обычно именно на этом я и ставлю точку.
Вы на собеседовании требуете написания на листочке красивого кода с комментариями?
На доске, комментариев не надо ;-) И красивого тоже не надо — надо понятного.
Код вполне понятен. Тем более на доске условие в lambda-функции было бы расписано на несколько строк (в каждой по or). Вас смущают названия переменных?
Понимаете, есть такая закономерность — какой у программиста первый позыв в плане стиля, так примерно и будет выглядеть его код, который будет создаваться в моменты стресса, под давлением сроков, production failure — то есть когда нет времени сделать все красиво, надо сделать быстро чтобы работало. Это делается временно и потом остается на века. Поэтому лучше делать сразу все правильно.
Лямбда-функции, замыкания и прочая — это очень хорошо и классно, и если правильно использовать — вполне читаемо и поддерживаемо. Но если инлайн лямбда-функция занимает больше одной строки — это называется spaghetti code, и такого не надо.
Лямбда-функции, замыкания и прочая — это очень хорошо и классно, и если правильно использовать — вполне читаемо и поддерживаемо. Но если инлайн лямбда-функция занимает больше одной строки — это называется spaghetti code, и такого не надо.
В данном случае lambda-функция вполне уместна.
Кстати, можно писать и не в одну строку. Единственная причина, почему у меня написано в одну — это то, что все это набиралось в консоли.
Кстати, можно писать и не в одну строку. Единственная причина, почему у меня написано в одну — это то, что все это набиралось в консоли.
Видимо, в консоли отсутствуют клавиши перевода строки и пробелы :)
У меня там повыше код на Хаскелле и без лямбд, по-моему вполне читабельно, хотя конечно больше занимает.
Можно конечно в одну строчку написать, чтоб непонятно было, сам так люблю делать, но не в production коде :)
А к вам зря придрались, можно писать ясный код на работе и для себя совсем другой, главное чтоб себе было ясно и удобно.
А программист который пишет всегда в одном стиле — это Junior.
Можно конечно в одну строчку написать, чтоб непонятно было, сам так люблю делать, но не в production коде :)
А к вам зря придрались, можно писать ясный код на работе и для себя совсем другой, главное чтоб себе было ясно и удобно.
А программист который пишет всегда в одном стиле — это Junior.
Выглядит, и правда, куда понятнее.
В вашем решении присутствует та же проблема, что и у меня — переполнение стека функций. Хотя, чтобы ее решить придется отказаться от такой приятной вещи, как рекурсия =)
На самом деле меня больше не претензии к коду смутили, а то, что за подобный код на собеседовании можно попрощаться с кандидатом.
В вашем решении присутствует та же проблема, что и у меня — переполнение стека функций. Хотя, чтобы ее решить придется отказаться от такой приятной вещи, как рекурсия =)
На самом деле меня больше не претензии к коду смутили, а то, что за подобный код на собеседовании можно попрощаться с кандидатом.
У меня отлично работает на массивах порядка 100000 элементов (больше не проверял), я думаю хаскель способен соптимизировать тут рекурсию в хвостовую (обычно так и бывает), хотя стоит проверить.
А насчет собеседований, у меня довольно большой опыт по набору, и я бы такого человека спросил во-первых почему он так написал, во-вторых если решение работает это уже плюс, а если он еще сможет переписать по-другому в более традиционной форме это бы для меня был еще больший плюс, так что такой товарищ имел бы однозначное преимущество перед тем кто сразу выдал стереотипное решение.
Те, кто выдает шаблонные решения на собеседованиях обычно потом хуже работают по моему опыту.
А насчет собеседований, у меня довольно большой опыт по набору, и я бы такого человека спросил во-первых почему он так написал, во-вторых если решение работает это уже плюс, а если он еще сможет переписать по-другому в более традиционной форме это бы для меня был еще больший плюс, так что такой товарищ имел бы однозначное преимущество перед тем кто сразу выдал стереотипное решение.
Те, кто выдает шаблонные решения на собеседованиях обычно потом хуже работают по моему опыту.
не «соптимизировать рекурсию в хвостовую», а соптимизировать хвостовую рекурсию в цикл.
Хаскель делает из рекурсии циклы?
любой компилятор Хаскелля обязан выполнять оптимизацию хвостовых вызовов (и не только рекурсивных). Если это хвосторекурсивный вызов, то скорее всего оптимизатор преобразует его именно в цикл
он не обязан. Он просто это сделает, ради повышения производительности.
да нет. он как раз обязан. по стандарту.
ссылочку?
беру слова обратно. похоже что, в отличии от SML и Ocaml, в стандарте хаскелля этого нету. и это печально
в CL кстати тоже это не требуется, но всячески было бы круто иметь. А вот в schema например это чуть ли не must have.
Кстати, а разве есть стандарт на O'Caml?
Кстати, а разве есть стандарт на O'Caml?
Это не печально, из-за ленивости Хаскелю нет нужды оптимизировать хвостовую рекурсию.
не совсем понимаю как это связано с ленивостью. можно подробней?
По ссылке — ответы от русскоязычных гуру:
community.livejournal.com/ru_lambda/104215.html
community.livejournal.com/ru_lambda/104215.html
Совсем нет, есть рекурсия хвостовая, а есть не хвостовая, но которая может быть преобразованна в хвостовую, тут как раз этот случай.
А то что хвостовая рекурсия на самом деле потом превратится в цикл это всем понятно.
А то что хвостовая рекурсия на самом деле потом превратится в цикл это всем понятно.
А можете показать пример не хвостовой рекурсии, в хвостовую?
хвостовая рекурсия же
Знаете, проблема сроков — это проблема менеджмента. И если у вас давление сроков и т.п. — то у вас, наверное, лучше не работать, ибо менеджмент у вас слаб.
Не в менеджменте дело (то есть и в менеджменте, но не всегда в нем). В компании, где я сейчас работаю, проблемы со сроками случаются реже на порядок, чем во всех остальных, в которых я работал до этого — но они случаются, и когда они случаются, надо уметь достойно выходить из таких ситуаций.
Кто называет сроки?
Вы не поверите — иногда они образуются сами, вообще без какого бы то ни было участия с нашей стороны. Если интересно — расскажу об одном из наших проектов, который пришлось завершать в супер-пожарном режиме.
Вот когда «оно само» — это точно просчёт менеджмента.
Не, это не просчет. Это повод уволить его. Если технический специалист говорит что А делать 2 недели, то это проблема менеджера, что он заложив почку, пообещав счастья через 3 дня.
С радостью выслушаю. Но это проблема менеджмента!
> код, который будет создаваться в моменты стресса, под давлением сроков, production failure — то есть когда нет времени сделать все красиво, надо сделать быстро чтобы работало. Это делается временно и потом остается на века. Поэтому лучше делать сразу все правильно.
Какие-то у вас стрессы и сроки «детские» видимо. :-)
Когда реально сроки давят и бизнес-процесс стоит — тогда надо написать «грязно», но чтобы работало. Чтобы падало раз в полчаса, но шелловый скрипт автоматом перезапускал. В общем, чтобы через 2 часа после постановки задачи бизнес процесс пошел. А не так, что код красивый, комменты на месте и внятные, ошибок нет, но готово только послезавтра, когда заказчик уже застрелился.
Какие-то у вас стрессы и сроки «детские» видимо. :-)
Когда реально сроки давят и бизнес-процесс стоит — тогда надо написать «грязно», но чтобы работало. Чтобы падало раз в полчаса, но шелловый скрипт автоматом перезапускал. В общем, чтобы через 2 часа после постановки задачи бизнес процесс пошел. А не так, что код красивый, комменты на месте и внятные, ошибок нет, но готово только послезавтра, когда заказчик уже застрелился.
Добавлю, что после таких «кредитов» в ущерб архитектуре обязательно должен идти этап восстановления и наведения красоты. Только вот этот этап обычно пропускают. Из-за менеджмента, который не видит целесообразности, и из-за программеров, которые исповедут принцип «работает — не трожь». В результате мусор накапливается, работа замедляется, сами себе же роют могилу, вместо исправления багов патчат битые данные в базе.
Сейчас один проект как раз на такой фазе.
И с вашим комментом я согласен, разумный он. И оплату получаю почасовую (так что за причесывание кода отдельно можно деньги получить). И… все равно сомневаюсь — надо ли? Потому что да — работает — не трожь. Тем более, прямо перед самым запуском проекта, после всех долгих тестов.
И с вашим комментом я согласен, разумный он. И оплату получаю почасовую (так что за причесывание кода отдельно можно деньги получить). И… все равно сомневаюсь — надо ли? Потому что да — работает — не трожь. Тем более, прямо перед самым запуском проекта, после всех долгих тестов.
Перед самым запуском не стоит, и времени может не хватить на переделку, и тесты придется прогонять по новой. Риск слишком велик.
Но если потом с этим кодом приходится иметь дело, наверное себе же дешевле будет его переписать. Это как с ремонтом в доме. Пока только протекает кран — можно подставлять кастрюльки. Но поломки, если их не чинить, накапливаются. Перегорает лампочка, забивается труба, перестает работать слив. Неисправление отнимает все больше времени.
Вроде бы, вопрос только в том, насколько быстро все рухнет. И вот здесь реальность меня удивила. Оно никогда не рухнет. Просто превратится в помойку, а удовольствия от жизни на помойке никакого.
Но если потом с этим кодом приходится иметь дело, наверное себе же дешевле будет его переписать. Это как с ремонтом в доме. Пока только протекает кран — можно подставлять кастрюльки. Но поломки, если их не чинить, накапливаются. Перегорает лампочка, забивается труба, перестает работать слив. Неисправление отнимает все больше времени.
Вроде бы, вопрос только в том, насколько быстро все рухнет. И вот здесь реальность меня удивила. Оно никогда не рухнет. Просто превратится в помойку, а удовольствия от жизни на помойке никакого.
А можно узнать маштабы команды?
Да небольшая — 2-3 человека (смотря кого считать человеком :-))
И проект тоже не очень большой, но замудреный — некоторые алгоритмы писались на «интуитивно-анальном понимании принципа работы», поэтому без комментариев там через год уже не разобраться, а лишний if или лишняя вложенность и без того замудреный алгоритм делают совсем непонятным.
И проект тоже не очень большой, но замудреный — некоторые алгоритмы писались на «интуитивно-анальном понимании принципа работы», поэтому без комментариев там через год уже не разобраться, а лишний if или лишняя вложенность и без того замудреный алгоритм делают совсем непонятным.
Хм. Знаете, у вас маленькая команда.
Я говорил про системы несколько большего объема и которые разрабатывают не один десяток человек.
При длине проекта в полгода и размере команды в 3, его можно за полгода повторить, с нуля.
Я говорил про системы несколько большего объема и которые разрабатывают не один десяток человек.
При длине проекта в полгода и размере команды в 3, его можно за полгода повторить, с нуля.
«смотря кого считать человеком» — вижу, накипело :)
да нет, все не так мрачно :-)
просто роли у всех разные и техническая вовлеченность в реализацию — тоже.
просто роли у всех разные и техническая вовлеченность в реализацию — тоже.
а с этого момента я хочу больше деталей!
не очень понимаю любопытство — проект не столь интересен с технической точки зрения. еще один проект на 2-3 человека. совсем не яндекс или mail.ru по интересности реализации. Возможно вы где-то не так меня поняли и представляете какой-то мегапроект.
А что касается «человечности», раз уж спросили, то «человек под вопросом» — это менеджер, который участие в проекте принимает (обсуждает фичи напр), но код не пишет.
А что касается «человечности», раз уж спросили, то «человек под вопросом» — это менеджер, который участие в проекте принимает (обсуждает фичи напр), но код не пишет.
Вот таким способом и получается антипаттерн «многослойный говнокод», который в итоге хрупок и нереюзабелен настолько, что его проще выкинуть в мусор целиком.
Все верно.
Но дилемма в том, чтобы выбрать одно из двух
1) выпустить стабильный продукт (который дествительно стабильный, оч хорошо оттестированный итд)
2) причесать код, и зарелизить нетестированную версию (либо еще месяц тестировать все с нуля)
где-то случайно сделать что-то вроде:
исходный код:
if(a)
b
c
ошибка при причесывании:
if(a){/*comment*/
b /*comment*/
c /*comment*/
}
скомпилируется. работать возможно будет. глючить — тоже. хотя казалось бы, до причесывания код сто тысяч раз проверяли во всех тестах — все работает идеально :-)
у любого действия есть свои плюсы и минусы, и то, что вроде как right way с точки зрения программиста, который любит работать с красивым кодом — не всегда right way с точки зрения успешности проекта.
Но дилемма в том, чтобы выбрать одно из двух
1) выпустить стабильный продукт (который дествительно стабильный, оч хорошо оттестированный итд)
2) причесать код, и зарелизить нетестированную версию (либо еще месяц тестировать все с нуля)
где-то случайно сделать что-то вроде:
исходный код:
if(a)
b
c
ошибка при причесывании:
if(a){/*comment*/
b /*comment*/
c /*comment*/
}
скомпилируется. работать возможно будет. глючить — тоже. хотя казалось бы, до причесывания код сто тысяч раз проверяли во всех тестах — все работает идеально :-)
у любого действия есть свои плюсы и минусы, и то, что вроде как right way с точки зрения программиста, который любит работать с красивым кодом — не всегда right way с точки зрения успешности проекта.
«у любого действия есть свои плюсы и минусы, и то, что вроде как right way с точки зрения программиста, который любит работать с красивым кодом — не всегда right way с точки зрения успешности проекта.»
У кода есть следующие достоинства (в порядке убывания приоритета):
1. Работоспособность (в идеале — корректность).
2. Читабельность.
3. Гибкость.
4. Красота (получается, что в случае чего красотой жертвуют в первую очередь).
Проблема в том, многие менеджеры и разработчики, пожарящие перед релизом забывают простую истину — недоработки при исполнении увеличивают общие трудозатраты.
Надо заранее иметь в виду, что запуск первого релиза за счет недели аврала — это минимум две недели отставания от запуска второго. Если после выхода промежуточного релиза нет готовности безжалостно сносить пожарный говнокод, то отставание может составить месяц и более. Более того: чем больше пожарного кода — тем менее предсказуемы сроки выхода следующих релизов.
У кода есть следующие достоинства (в порядке убывания приоритета):
1. Работоспособность (в идеале — корректность).
2. Читабельность.
3. Гибкость.
4. Красота (получается, что в случае чего красотой жертвуют в первую очередь).
Проблема в том, многие менеджеры и разработчики, пожарящие перед релизом забывают простую истину — недоработки при исполнении увеличивают общие трудозатраты.
Надо заранее иметь в виду, что запуск первого релиза за счет недели аврала — это минимум две недели отставания от запуска второго. Если после выхода промежуточного релиза нет готовности безжалостно сносить пожарный говнокод, то отставание может составить месяц и более. Более того: чем больше пожарного кода — тем менее предсказуемы сроки выхода следующих релизов.
тут немного другая ситуация.
Да, как и везде, «надо — вчера». И чем раньше будет релиз — тем лучше, тем более, что первоначальные оптимистичные сроки уже прошло. НО нет пожара. Пишется «обвязка», мелочи-красивости, не затрагивающие само ядро проекта. А оно и оттестировано уже очень хорошо, и изменения в него практически не вносятся. Именно по этой причине (то что код там не очень читаем, но при этом очень надежен — насколько только можно судить об этом на основании долгих тестов) и не хочется делать с ним ничего, что хоть как-то изменит md5sum исходников :-). Потому что если это сделать — то мы получим не только удобочитаемый код, но и саму программу, которая черт знает как работает — вроде по идее наши правки были только в области «красивостей» и никак не должны влиять на логику программы, но ведь кто знает — так что по хорошему, после месяца тестирования и дописывания комментария /* this function does something */ — чтобы убедиться что все в порядке, надо б еще месяц тесты погонять.
Да, как и везде, «надо — вчера». И чем раньше будет релиз — тем лучше, тем более, что первоначальные оптимистичные сроки уже прошло. НО нет пожара. Пишется «обвязка», мелочи-красивости, не затрагивающие само ядро проекта. А оно и оттестировано уже очень хорошо, и изменения в него практически не вносятся. Именно по этой причине (то что код там не очень читаем, но при этом очень надежен — насколько только можно судить об этом на основании долгих тестов) и не хочется делать с ним ничего, что хоть как-то изменит md5sum исходников :-). Потому что если это сделать — то мы получим не только удобочитаемый код, но и саму программу, которая черт знает как работает — вроде по идее наши правки были только в области «красивостей» и никак не должны влиять на логику программы, но ведь кто знает — так что по хорошему, после месяца тестирования и дописывания комментария /* this function does something */ — чтобы убедиться что все в порядке, надо б еще месяц тесты погонять.
Знаете, после того как вы один раз наступите в в дорожку с таким кодом, вы оттуда не вернетесь. Ваш менеджмент познает, что деля ваши сроки на два, то получается результат.
Вообще есть интересная проблема, что красивый дизайн приложения подразумевает что оно будет жить 100500 лет. Только вот, не факт, что компания доживет пока вы будете делать красивый дизайн.
Вообще есть интересная проблема, что красивый дизайн приложения подразумевает что оно будет жить 100500 лет. Только вот, не факт, что компания доживет пока вы будете делать красивый дизайн.
Обратная ситуация: говнокод, хотели продать проект побыстрее, потом кризис, невыгодная ситуация, да и конкуренты как-то рванули вперед, приходится продолжать свой бизнес. В результате теперь любая новая фича требует нечеловеческих усилий на реализацию, а несколько программистов вычерпывают говна full-time.
Но всем похуй. Менеджмент не способен понять ситуацию (не успеваете? сколько людей добавить?), программеру комфортно и так, лишь бы платили.
Но всем похуй. Менеджмент не способен понять ситуацию (не успеваете? сколько людей добавить?), программеру комфортно и так, лишь бы платили.
Еще есть такое заблуждение, что красивый дизайн садятся, делают, сдают готовый.
Красивый дизайн кристаллизуется в течение 100500 лет, неудачные решения отмирают, удачные остаются. Это работает только в том случае, если находятся люди, способные отличить одно от другого.
Красивый дизайн красив не маникюром и педикюром, а тем, что эффективно решает поставленные задачи.
Красивый дизайн кристаллизуется в течение 100500 лет, неудачные решения отмирают, удачные остаются. Это работает только в том случае, если находятся люди, способные отличить одно от другого.
Красивый дизайн красив не маникюром и педикюром, а тем, что эффективно решает поставленные задачи.
Хе-хе. Только переписать это не получается, ибо всегда есть такой бардак в голове у менеджера, и это становится стилем работы.
Сказать что это плохо? Нет. Это жизнь. Но все-таки это проблема менеджмента.
Сказать что это плохо? Нет. Это жизнь. Но все-таки это проблема менеджмента.
Поддерживаю. А то потом будут такой же production-код лепить.
Зачем на доске? Стиль псевдо-академичности чтоли придать?
Не совсем. Чтобы кандидат объяснял, что он пишет. Если он уткнется в лаптоп, хрен ты из него что выбьешь, а вот у доски он волей-неволей начнет вслух рассуждать и объяснять. А мне именно это и надо.
Не примите близко к сердцу, но что-то странное у вас там, то вам лямбда функции не нравятся, то у доски писать заставляете… Многие люди вообще на доске в жизни код не писали, мне вот например сложнее мыслить с доской, нежели «уткнувшись в лэптоп», так зачем же ставить претендента, у которого и так стресс в виде собеседования, ещё и в дополнительно неудобное положение у доски?
И вообще, зачем кандидат должен объяснять что он пишет в процессе? Вот написал, если не работает, тогда пусть объясняет, а если всё ок, то к чему лишнии слова? Код — куда красноязычнее чем любая вербальная речь.
И вообще, зачем кандидат должен объяснять что он пишет в процессе? Вот написал, если не работает, тогда пусть объясняет, а если всё ок, то к чему лишнии слова? Код — куда красноязычнее чем любая вербальная речь.
хм, спрашивать на собеседование код? Это же моветон. Все передовые рекуртеры просят спарвку из психдиспансера! Настоящий программист без справки не программист!
Ну вот мы как-то так любим чтобы наши программисты умели программировать, да.
программист должен уметь держать в голове много абстракций. Научить его питону или другому языку — это дело пары недель. А вот научить его держать в голове кучу абстракций — нельзя. Это уже состояние психики и оно граничит с шизофренией. Собственно из-за этого и стоит спрашивать справку.
На собеседование можно понять только ширину кругозора. И прикинуть, сможете ли вы заинтересовать такого кадра, или нет.
На собеседование можно понять только ширину кругозора. И прикинуть, сможете ли вы заинтересовать такого кадра, или нет.
А кто говорит про кучу? Я же не требую его вкратце рассказать мне про то, как работает collaborative filtering или чем maximum entropy классификатор отличается от баесовского? (хотя в каких-то случаях буду требовать именно этого, но это очень особые ситуации). Я всего лишь прошу знания основ. Вы же не считаете, что знание, сколько битов в байте, что такое сортировка и что такое двоичный поиск чем-то запредельно сложным и абстрактным?
Ну а если вы знаете это, и вы действительно хороший программист, для вас не составит ни малейшего труда написать код. Да, на доске, да, возможно, с ошибками — но написать, а не рассуждать о своем кругозоре и огромном опыте.
Ну а если вы знаете это, и вы действительно хороший программист, для вас не составит ни малейшего труда написать код. Да, на доске, да, возможно, с ошибками — но написать, а не рассуждать о своем кругозоре и огромном опыте.
НЛО прилетело и опубликовало эту надпись здесь
Вам отказали на собеседовании? Не переживайте. У вас еще будет шанс.
А я не имею права принимать или не принимать — я лишь имею право сказать, понравился мне кандидат или нет. Если кандидат пишет спагетти-код, то он мне сразу перестает нравится.
А я не имею права принимать или не принимать — я лишь имею право сказать, понравился мне кандидат или нет. Если кандидат пишет спагетти-код, то он мне сразу перестает нравится.
вам нужен человек который думает и имеет мозги, или кодогенератор?
Мне нужно чтобы человек не только умел думать, но и умел писать код. К сожалению, сейчас очень мало внимания уделяется умению именно хорошо кодить, слово «кодер» стало чуть ли не ругательным — все менеджеры, лидеры, и прочая, кодеры — быдло. А я кодер. Очень хороший кодер, который умеет кодить эффективный код, который работает быстро и надежно. И на собеседовании я требую от людей того же самого — а именно, умения писать красивый, чистый, хорошо и быстро работающий код. Я что, чего-то странного хочу?
Точно так же считаю. Я в роли лидера начал немного терять связь с реальностью. — «Че? Вот на это ты потратил 2 дня? Да это же шаблончики, тут полчаса максимум». А потом сам сел за эти шаблончики, и за день до ума не довел.
Что есть эффективный код? Где его можно посмотреть?
Хватит троллить. Эффективный код — это код, который работает быстро, надежно, легко поддерживается, и содержит минимальное количество ошибок.
Код либо работает быстро, либо выглядит красиво, либо его легко поддерживать.
А про ошибки, все проще, их более менее const. И этот показатель не зависит не от чего.
А про ошибки, все проще, их более менее const. И этот показатель не зависит не от чего.
Вы какой-то скучный тролль. Просто чтобы поддержать беседу, сообщу, что бывает код, который красиво выглядит и быстро работает. А еще его легко поддерживать, потому что когда программист писал его, он думал, что этот код после написания станет частью проекта, которому жить много-много лет.
Эффективный код — это код, который достигает желаемого эффекта.
Если желаемый эффект — по-быстрому преобразовать набор данных и выкинуть код на помойку — то можно писать в одну строку, с goto и переменными lolcat и loldog.
Если желаемый эффект — производительная, надежная и масштабируемая система — то нужно писать так, как говорит sigizmund.
Если желаемый эффект — по-быстрому преобразовать набор данных и выкинуть код на помойку — то можно писать в одну строку, с goto и переменными lolcat и loldog.
Если желаемый эффект — производительная, надежная и масштабируемая система — то нужно писать так, как говорит sigizmund.
Ага, знаю я одну систему, так ее девелопит команда в 100 человек. Архиекторы и оптимизаторы перфоманса и т.д.
Вы думаете ей от этого легче? Ой нет. Тоже самое сделает 1 человек закрывшись на полгода.
Есть такая штука промышленное программирование, а есть жизнь. Почему-то они ортогональны.
Вы думаете ей от этого легче? Ой нет. Тоже самое сделает 1 человек закрывшись на полгода.
Есть такая штука промышленное программирование, а есть жизнь. Почему-то они ортогональны.
Не, архитекторов и оптимизаторов нафиг. Были, знаем. Нужно чтоб каждый кодер знал свое дело. Команда в 100 человек на один репозиторий — это медленная смерть проекта от ожирения.
Нет, это интересная жизнь. В таких коммандах можно годами получать зп и ничего не делать!
Архитекторов и оптимизаторов нафиг — и кодеры сразу потеряют свою ценность. Потому что они не будет знать, что делать.
Тут могут быть вопросы интерпретации, кого вы называете архитектором и кодером. Если архитектор — это средний чувак с гордым словом «architect» в названии должности и горой UML диаграмм на столе, а код он в глаза видел 5 лет назад, то кодерам без него будет гораздо лучше. Все равно вменяемой архитектуры с таким подходом он в жизнь не родит.
Не сделает. Линус бы тоже не сделал нормальное, полноценное ядро один.
Если выкинуть дрова — то вполне.
Если выкинуть дрова, то он нафиг никому не был бы нужен, кроме самого Линуса (ну, может ещё полдесятка человек).
знаете, я вспоминаю времена, когда фактор использования Linux говорил о том, что у человека есть мозг. И, не сказать, что я был против. Мне они нраивлись… И да. я бы их сохранил!
Да, хорошие были времена.
>И да. я бы их сохранил!
Зачем?
>И да. я бы их сохранил!
Зачем?
Сейчас приходиться делать все тоже самое. Просто сложностей и прослоек стало больше.
ГМ, да ну? 5-6 лет назад, как помню, KDE были совершенно неюзабельным продуктом. Полтора года назад — гораздо, гораздо лучше.
В те времена, о которых вы тут говорите, линукс был совершенно неориентирован на обычного пользователя.
Если есть ностальгия по тем временам, подскажу. Возьмите Solaris/AIX/NetBSD, и вспомните те времена. Если хочется хардкора, возьмите QNX :-D
В те времена, о которых вы тут говорите, линукс был совершенно неориентирован на обычного пользователя.
Если есть ностальгия по тем временам, подскажу. Возьмите Solaris/AIX/NetBSD, и вспомните те времена. Если хочется хардкора, возьмите QNX :-D
Предчувствую возможное негодование и упрек в троллизме. Я просто не согласен, что сейчас стало сложней и хуже. Я считаю, в этом плане линукс )особенно убунту) взял совершенно новую планку для себя за последние 3-4 года.
>5-6 лет назад, как помню, KDE были совершенно неюзабельным продуктом. Полтора года назад — гораздо, гораздо лучше.
Категорически не согласен!
6 лет назад было КДЕ 3.3 (если мне память не изменяет, то в Debian Sarge было как раз 3.3.2), за которым я просидел довольно долго (пока не апгрейднулся до Etch).
1.5 года назад было КДЕ 4.1, за которым я не смог просидеть и дня — валилось на каждый чих, глючило повсеместно.
Категорически не согласен!
6 лет назад было КДЕ 3.3 (если мне память не изменяет, то в Debian Sarge было как раз 3.3.2), за которым я просидел довольно долго (пока не апгрейднулся до Etch).
1.5 года назад было КДЕ 4.1, за которым я не смог просидеть и дня — валилось на каждый чих, глючило повсеместно.
Дык, и ни нужны обычные пользователи, как вы говорите. Я гик — и хочу назад свою игрушку!
Java Effective Programming, Джошуа Блоха, например :) если вы яваист.
Ну или бессмертный Effective C++ Programming ;)
эти книги учат меня как готовить инструменты. Инструмент, язык, это удел подмастерья. Мастеру, творцу, все-равно на чем писать.
Было бы классно, если бы мастер и творец научился писать сперва по-русски.
Ха. Если перефразировать чуть-чуть, то быдлокодеру абсолютно все равно, на каком языке писать быдлокод (на любом языке можно написать программу на фортране). Это я к тому, к чему приводит такой подход — думать, что инструмент не важен.
Понимание общих философских принципов не отменяют необходимость хорошо знать инструмент (если вы все еще программист, а не архитектор/менеджер).
Понимание общих философских принципов не отменяют необходимость хорошо знать инструмент (если вы все еще программист, а не архитектор/менеджер).
Знаете, я программист.
Изучить основы использования новой библиотекой это от дня до недели. Почему? Потому что я знаю много библиотек, и обычно хватает прочесть example или философскую байду.
Да, я не узнаю багов и сокральных знаний. Они преобретуться если я захочу ограничивать свой дизайн этой библиотекой.
Кстати, вы можете называть меня быдлокодером. Я не против.
Изучить основы использования новой библиотекой это от дня до недели. Почему? Потому что я знаю много библиотек, и обычно хватает прочесть example или философскую байду.
Да, я не узнаю багов и сокральных знаний. Они преобретуться если я захочу ограничивать свой дизайн этой библиотекой.
Кстати, вы можете называть меня быдлокодером. Я не против.
Если это библиотека типа Log4J — да. Если это Spring / Hibernate / JBoss / ..- нет. А люди, знания которых по упомянутым монстрам ограничиваются однодневным чтением философской байды, конечно же есть. И они нужны. Называются — менеджеры :-D
А программисты с таким уровнем знаний, извините, на хрен не нужны.
А программисты с таким уровнем знаний, извините, на хрен не нужны.
Скажите мне, а что сложного в hibernate? Нет, ну вот правда? Большой, сложный ORM…
Далее, не понятно, что вы имеете ввиду знание про технологию или библиотеку.
Далее, вы путаете менеджеров и руководителей группы. Менеджер, его больше интересуют бюджеты, сроки и риски, чем библиотеки и прочие средства ограничение.
Далее, не понятно, что вы имеете ввиду знание про технологию или библиотеку.
Далее, вы путаете менеджеров и руководителей группы. Менеджер, его больше интересуют бюджеты, сроки и риски, чем библиотеки и прочие средства ограничение.
Скажите мне, а что сложного в hibernate? Нет, ну вот правда? Большой, сложный ORM…
— Сложного концептуально — сам подход ORM. В нем есть концептуальные сложности и проблемы, преобразования объектной модели в реляционную, ну вы сами отлично знаете.
Но даже если оставить их в стороне, то сам хибернейт, за один день вы не изучите. И за неделю не изучите. Требуется разработать на нем пару крупных проектов, чтобы стать знатоком его. Я бы сказал, требуется стать знатоком БД (ошибочное, уродское заблуждение, что можно писать хороший код на ORM, не понимая хорошо работы СУБД!!!), потом изучить хибернейт и набить шишек в нем, и потом в своем мозгу слить две эти вещи воедино, тогда можно эффективно использовать Hibernate, и достигать производельности И простоты и удобства.
Я знаете ли, видел людей, которые освоили хибейнтейт быстренько, «а че, он же несложный, и с базой не надо работать, он сам все сделает».
Они потом удрученно рассказывали, что у них тормозят все сложные экраны, и они переписывают их на HQL-запросы (!!!), т.е. по сути, отходят от Java-программирования. Граф объектов может выглядить стройно, но не все понимают, что при неправильном использовании хибернейта он раскладывается в обращения к десяткам и десяткам таблиц.
Это к тому, что людям, которые понимают общий подход, а детальные знания о багах, фичах, потенциальных проблемах, наиболее частых ошибках, собираются приобрести потом, в процессе, и за один день, техлидам в сложном и напряженном проекте делать нечего, ИМХО.
Это все разумеется, не в укор Вам, я просто привел пример.
— «Далее, не понятно, что вы имеете ввиду знание про технологию или библиотеку»
— То, что вы называете «инструмент», и хотите быть выше этого.
— Далее, вы путаете менеджеров и руководителей группы. Менеджер, его больше интересуют бюджеты, сроки и риски, чем библиотеки и прочие средства ограничение.
— А руководитель группы — это не менеджер?
Я не путаю, я намеренно упрощаю. Иные менеджеры очень любят лезть в технические мелочи и читать про технические новинки. Если хотите, можем разбить их на тимлидов, техлидов, PM-ов и прочих, в данном случае не суть.
— Сложного концептуально — сам подход ORM. В нем есть концептуальные сложности и проблемы, преобразования объектной модели в реляционную, ну вы сами отлично знаете.
Но даже если оставить их в стороне, то сам хибернейт, за один день вы не изучите. И за неделю не изучите. Требуется разработать на нем пару крупных проектов, чтобы стать знатоком его. Я бы сказал, требуется стать знатоком БД (ошибочное, уродское заблуждение, что можно писать хороший код на ORM, не понимая хорошо работы СУБД!!!), потом изучить хибернейт и набить шишек в нем, и потом в своем мозгу слить две эти вещи воедино, тогда можно эффективно использовать Hibernate, и достигать производельности И простоты и удобства.
Я знаете ли, видел людей, которые освоили хибейнтейт быстренько, «а че, он же несложный, и с базой не надо работать, он сам все сделает».
Они потом удрученно рассказывали, что у них тормозят все сложные экраны, и они переписывают их на HQL-запросы (!!!), т.е. по сути, отходят от Java-программирования. Граф объектов может выглядить стройно, но не все понимают, что при неправильном использовании хибернейта он раскладывается в обращения к десяткам и десяткам таблиц.
Это к тому, что людям, которые понимают общий подход, а детальные знания о багах, фичах, потенциальных проблемах, наиболее частых ошибках, собираются приобрести потом, в процессе, и за один день, техлидам в сложном и напряженном проекте делать нечего, ИМХО.
Это все разумеется, не в укор Вам, я просто привел пример.
— «Далее, не понятно, что вы имеете ввиду знание про технологию или библиотеку»
— То, что вы называете «инструмент», и хотите быть выше этого.
— Далее, вы путаете менеджеров и руководителей группы. Менеджер, его больше интересуют бюджеты, сроки и риски, чем библиотеки и прочие средства ограничение.
— А руководитель группы — это не менеджер?
Я не путаю, я намеренно упрощаю. Иные менеджеры очень любят лезть в технические мелочи и читать про технические новинки. Если хотите, можем разбить их на тимлидов, техлидов, PM-ов и прочих, в данном случае не суть.
Хорошо, я понял вашу позицию. Если коротко — вам не приятна не компетенция в IT. Что же, понимаю. Мне она так же не приятна.
Далее, про hibernate и другие ORM. Странно, но я не понимаю что сложного в моделе ORM, да и зачем вообще нужна ORM. Это лишняя абстракция, хотя она не скрывает, особо сильно, кишки СУБД, зато создает проблемы.
Далее, про hibernate и другие ORM. Странно, но я не понимаю что сложного в моделе ORM, да и зачем вообще нужна ORM. Это лишняя абстракция, хотя она не скрывает, особо сильно, кишки СУБД, зато создает проблемы.
Да я вас и не называл и не собираюсь. Просто заметил, что выше мнение не совпадает с моим.
НЛО прилетело и опубликовало эту надпись здесь
А собственно, зачем вы постите какой-то код на питон (похоже на поиск), в обсуждение оптимизации join-ов?
10 минут python
pastie.org/928420
pastie.org/928420
Писал много раз. Очень сильно его его невзлюбил, когда на первом курсе моя курсовая программулина работала не совсем корректно, долго грешил на поиск, оказалась банальность с поиском не связанная отделяла меня от счастья… Потом снова повторения мать учения на третьем курсе, и вот тут совсем недавно на питоне и то с первого раза не заработал. Кнут прав :)
Action script 3
Писал давно гдето минут 15-20.
Насчет «без тестирования», то не получилось так как написал юнит тест.
package com.kavalok.utils.sorting {
import com.kavalok.collections.ArrayList;
import com.kavalok.interfaces.IComparer;
import com.kavalok.interfaces.ISorter;
import com.kavalok.utils.comparing.ComparingResult;
public class QuickSorter implements ISorter {
public function sort(list: ArrayList, comparer: IComparer): void {
_list = list;
_comparer = comparer;
executeSort(0, list.length);
}
private function executeSort(begin: uint, length: uint): void {
var i: Number = begin;
var j: Number = begin + length — 1;
var currentElement: Object;
var temp: Object;
var centerIndex: uint = uint(begin + length/2);
currentElement = _list.getItemAt(centerIndex);
do {
while (_comparer.compare(_list.getItemAt(i), currentElement) == ComparingResult.SMALLER) i++;
while (_comparer.compare(_list.getItemAt(j), currentElement) == ComparingResult.GREATER) j--;
if (i <= j) {
temp = _list.getItemAt(i);
_list.setItemAt(_list.getItemAt(j), i);
_list.setItemAt(temp, j);
i++; j--;
}
} while ( i<=j );
if ( j > begin ) executeSort(begin, j — begin + 1);
if ( begin + length > i ) executeSort(i, begin + length — i);
}
private var _list: ArrayList;
private var _comparer: IComparer;
}
}
Писал давно гдето минут 15-20.
Насчет «без тестирования», то не получилось так как написал юнит тест.
package com.kavalok.utils.sorting {
import com.kavalok.collections.ArrayList;
import com.kavalok.interfaces.IComparer;
import com.kavalok.interfaces.ISorter;
import com.kavalok.utils.comparing.ComparingResult;
public class QuickSorter implements ISorter {
public function sort(list: ArrayList, comparer: IComparer): void {
_list = list;
_comparer = comparer;
executeSort(0, list.length);
}
private function executeSort(begin: uint, length: uint): void {
var i: Number = begin;
var j: Number = begin + length — 1;
var currentElement: Object;
var temp: Object;
var centerIndex: uint = uint(begin + length/2);
currentElement = _list.getItemAt(centerIndex);
do {
while (_comparer.compare(_list.getItemAt(i), currentElement) == ComparingResult.SMALLER) i++;
while (_comparer.compare(_list.getItemAt(j), currentElement) == ComparingResult.GREATER) j--;
if (i <= j) {
temp = _list.getItemAt(i);
_list.setItemAt(_list.getItemAt(j), i);
_list.setItemAt(temp, j);
i++; j--;
}
} while ( i<=j );
if ( j > begin ) executeSort(begin, j — begin + 1);
if ( begin + length > i ) executeSort(i, begin + length — i);
}
private var _list: ArrayList;
private var _comparer: IComparer;
}
}
… и мой код на питоне перестал казаться мне таким уж жутким.
у меня такое ощущение, что здесь быстрая сортировка, а не бинарный поиск
public int BinarySearch(int[] data, int asked)
{
if(data!=null && data.Length>0)
{
int leftEdge = 0;
int rightEdge = data.Length-1;
int index = 0;
bool work = true;
do
{
index = rightEdge — leftEdge;
if(index/2 > 0)
{
if(data[index]>asked)
{
rightEdge = index;
}
else if(data[index]<asked)
{
leftEdge = index;
}
else if(data[index] == asked)
{
return index;
}
}
else return null;
}while(work);
}
}
//С#
{
if(data!=null && data.Length>0)
{
int leftEdge = 0;
int rightEdge = data.Length-1;
int index = 0;
bool work = true;
do
{
index = rightEdge — leftEdge;
if(index/2 > 0)
{
if(data[index]>asked)
{
rightEdge = index;
}
else if(data[index]<asked)
{
leftEdge = index;
}
else if(data[index] == asked)
{
return index;
}
}
else return null;
}while(work);
}
}
//С#
pastie.org/927590
похапе, 10 минут. не уверен, что без ошибок :) тяжело писать и не тестировать :)
похапе, 10 минут. не уверен, что без ошибок :) тяжело писать и не тестировать :)
Двоичный поиск и без ошибок писал совсем давно. Еще в эпоху паскаля. Но смысл в нем не вижу, есть более оптимальные алгоритмы поиска.
Мой код код
Возможно первое правильное решение здесь.
v2 -> pastie.org/927605
НЛО прилетело и опубликовало эту надпись здесь
В универе писал на ассемблере около часа, не сразу но заработало.
C#
pastie.org/927603
5 минут, алгоритм не реализовывал лет 7.
P.S. массив arr — объявлен переменной класса.
pastie.org/927603
5 минут, алгоритм не реализовывал лет 7.
P.S. массив arr — объявлен переменной класса.
Часто использую разные вариации (под определенный тип исходных данных) бинарного поиска.
Вот вариант на Objective-C — расширение класса NSArray
pastie.org/927604
Минут 10 ушло по памяти написать. Обычно копи-пастом удобнее :).
Вот вариант на Objective-C — расширение класса NSArray
pastie.org/927604
Минут 10 ушло по памяти написать. Обычно копи-пастом удобнее :).
Процент программистов спосбных написать тернарный поиск еще меньше.
а я смотрю, Дональд Кнут — оптимист…
«Только 10% программистов способны написать.» — правильнее?
«Только 10% программистов способны написать.» — правильнее?
int binsearch(int* a, int n, int key) { int lo = 0; int hi = n - 1; while (lo < hi) { int mid = lo + (hi - lo) / 2; if (key > a[mid]) lo = mid + 1; else hi = mid; } return a[hi] == key ? hi : -1; }
BinarySearch proc ;params: array (of integers), length, target
push ebp
mov ebp, esp
mov ebx, [ebp + 8]
mov ecx, [ebp + 12]
xor edx, edx
dec ecx
jmp LoopCond
LoopStart:
mov eax, edx
add eax, ecx
shr eax, 1
push ecx
mov ecx, [ebp + 16]
cmp [eax * 4 + ebx], ecx
pop ecx
je Exit
jl UpperHalf
mov ecx, eax
dec ecx
jmp LoopCond
UpperHalf:
mov edx, eax
inc edx
LoopCond:
cmp ecx, edx
jge LoopStart
mov eax, -1
Exit:
pop ebp
ret
BinarySearch endp
push ebp
mov ebp, esp
mov ebx, [ebp + 8]
mov ecx, [ebp + 12]
xor edx, edx
dec ecx
jmp LoopCond
LoopStart:
mov eax, edx
add eax, ecx
shr eax, 1
push ecx
mov ecx, [ebp + 16]
cmp [eax * 4 + ebx], ecx
pop ecx
je Exit
jl UpperHalf
mov ecx, eax
dec ecx
jmp LoopCond
UpperHalf:
mov edx, eax
inc edx
LoopCond:
cmp ecx, edx
jge LoopStart
mov eax, -1
Exit:
pop ebp
ret
BinarySearch endp
вы невероятно круты :)
Тоже вроде бы при n = 0 не работает:
если [ebp + 12] = 0, тогда после dec ecx получается ecx = -1, edx = 0. После shr eax, 1 получается eax = 0x7fffffff, ну и потом eax*4 + ebx указывает на непонятное место в памяти.
если [ebp + 12] = 0, тогда после dec ecx получается ecx = -1, edx = 0. После shr eax, 1 получается eax = 0x7fffffff, ну и потом eax*4 + ebx указывает на непонятное место в памяти.
Черт, залип. Уже ничего не помню на асме (
грустно
грустно
и вам привет от спектрумистов (Z80 assembler): pastie.org/927781
; Input:
; HL = pointer to sorted array
; BC = array length (must be less than 32767, not tested, but just for case)
; A = search value
;
; Output:
; HL = pointer to value or 0 if not found
; BC = undefined
; DE = undefined
binary_sort:
push hl
add hl,bc
ld b,h: ld c,l
dec bc
pop hl
binary_sort_1:
ld d,h: ld e,l
and a: sbc hl,bc
jp nc,binary_sort_2
ld hl,0
ret
binary_sort_2:
ld h,d: ld l,e
add hl,bc
and a: rr h: rr l
cp (hl)
ret z
jp c,binary_sort_3
ld b,h: ld c,l
dec bc
ex de,hl
jp binary_sort_1
binary_sort_3:
inc hl
jp binary_sort_1
(если убрать двоеточия после меток и поставить убранные парсером табы перед коммандами, то должно компилироваться в ALASM (на самом спеке) либо в sjasmplus (кросскомпилер). естественно, не проверял :))
; Input:
; HL = pointer to sorted array
; BC = array length (must be less than 32767, not tested, but just for case)
; A = search value
;
; Output:
; HL = pointer to value or 0 if not found
; BC = undefined
; DE = undefined
binary_sort:
push hl
add hl,bc
ld b,h: ld c,l
dec bc
pop hl
binary_sort_1:
ld d,h: ld e,l
and a: sbc hl,bc
jp nc,binary_sort_2
ld hl,0
ret
binary_sort_2:
ld h,d: ld l,e
add hl,bc
and a: rr h: rr l
cp (hl)
ret z
jp c,binary_sort_3
ld b,h: ld c,l
dec bc
ex de,hl
jp binary_sort_1
binary_sort_3:
inc hl
jp binary_sort_1
(если убрать двоеточия после меток и поставить убранные парсером табы перед коммандами, то должно компилироваться в ALASM (на самом спеке) либо в sjasmplus (кросскомпилер). естественно, не проверял :))
А еще вот это подозрительное место:
add eax, ecx
shr eax, 1
Наверно, лучше бы было сделать вот так:
shr eax, 1
shr ecx, 1
add eax, ecx
дабы избежать переполнения при больших массивах.
add eax, ecx
shr eax, 1
Наверно, лучше бы было сделать вот так:
shr eax, 1
shr ecx, 1
add eax, ecx
дабы избежать переполнения при больших массивах.
//А че-то лень писать…
0 минут. Не тестировал.
0 минут. Не тестировал.
не компилируется вот эта строчка
return A[first] == val? first: null;
val типа int, а Вы используете вместе с ним null
return A[first] == val? first: null;
val типа int, а Вы используете вместе с ним null
Ну, val тут не причем))
А так?
А так?
int? getIndexOf(int[] A, int val) { int first = 0; int count = A.Length; while(count>1) { count=count/2; int i = first+count-1; if (A[i]== val) return i; if (A[i]<val) first+=count; } if (count==1) return A[first]==val? (int?)first : null; return null; }
pastie.org/927623
7 минут на реализацию и еще 7 на тесты
7 минут на реализацию и еще 7 на тесты
> есть упорядоченный массив, берем число из середины массива, сравниваем с искомым. Если оно оказалось больше, значит искомое число в первой половине массива, если меньше — во второй
Т.е. массив был заранее отсортирован и на это было потрачено время?
И зачем оно такое надо вообще?
Т.е. массив был заранее отсортирован и на это было потрачено время?
И зачем оно такое надо вообще?
function array_search($needle, $haystack) {
if (!is_numeric($needle)) {
trigger_error('Invalid argument needle. Numeric expected.');
return false;
}
if (!is_array($haystack)) {
trigger_error('Invalid argument haystack. Array expected.');
return false;
}
sort($haystack, SORT_NUMERIC); // это тестировал
$length = count($haystack);
$from = 0;
$to = $length - 1;
$result = false;
while ($result === false) {
if ($to > $length - 1 || $from < 0) {
$result = null;
} else {
$index = floor(($from + $to) / 2);
if (!is_numeric($haystack[$index])) {
trigger_error('Invalid value of argument haystack. Only numeric values allowed.');
return false;
}
if ($haystack[$index] > $needle) {
$to = $index - 1;
} elseif ($haystack[$index] < $needle) {
$from = $index + 1;
} else {
$result = $index;
}
}
}
return $result;
}
echo array_search(5, array(3, 76, 8, 4, 2, 2, 1, 5, 2, 3, 1, 2, 5, 7, 2, 3)) . "\n";
Пыхапе. Пол часа. И что-то мне подсказывает что с первого раза не взлетит…
pastie.org/927632
C#, 15 минут, 1 тест. Упал с оверфлоу — ошибку пофиксил и остальные две проверки прошли нормально.
C#, 15 минут, 1 тест. Упал с оверфлоу — ошибку пофиксил и остальные две проверки прошли нормально.
Блин, пока писал тут коментов то понабралось. Сразу вопрос — а почему у всех массив сортированный? Я что не правильно помню алгоритм? Мне казалось, что сортированные данные — это частный случай…
А как вы будете искать в случайном несортированном массиве кроме как полным перебором?
Полным перебором с постоянный разбиением на подсэты — грубо говоря проход по бинарному дереву. Вообщем то это и реализованно в сорсе на пасте.
Просто привычки вчитываться в постановку задачи:
С массивами так: есть упорядоченный массив, берем число из середины массива, сравниваем с искомым.
Мне нравится Ваш подход с рекурсией. Красиво и наглядно. :)
Только медленно)
с современными компьютерами производительность часто оказывается менее важной, чем легкость восприятия кода.
Не должно быть медленнее любой другой реализации на C# для не сортированного массива…
Накладные расходы на вызов метода всегда намного больше, чем на итерацию цикла.
По секрету скажу… Как-то проводил собеседования, никто из проходивших не смог навскидку даже «пузырька» написать. И тоже все серьезные люди.
p.s. Целесообразность таких вопросов на собеседовании — отдельная тема.
p.s. Целесообразность таких вопросов на собеседовании — отдельная тема.
import java.util.*;
public class Main{
public static void main(String[] argv){
int[] a=new int[] {1, 4, 12, 15, 18, 22, 26, 37};
System.out.print(Arrays.binarySearch(a, 18)); //4
}
}
1 минута
public class Main{
public static void main(String[] argv){
int[] a=new int[] {1, 4, 12, 15, 18, 22, 26, 37};
System.out.print(Arrays.binarySearch(a, 18)); //4
}
}
1 минута
Руби
pastie.org/927639
Правда, не совсем без тестов — две строки внизу меня хоть успокоили…
Дальше можно вылизывать
pastie.org/927639
Правда, не совсем без тестов — две строки внизу меня хоть успокоили…
Дальше можно вылизывать
Да будет ссылка:
pastie.org/927639
pastie.org/927639
Да, конечно кусок
должен быть вложен в
Забыл про собственные сниппеты.
arr = [1,2,3,4,5]
(arr+[7]).each{|z| p bis(arr,z)}
должен быть вложен в
begin
end if (__FILE__ == $0)
Забыл про собственные сниппеты.
Выдалось ещё 7 минут — вылизал.
pastie.org/928137
Добавил весьма обнадёживающий бенчмарк:
pastie.org/928137
Добавил весьма обнадёживающий бенчмарк:
user system total real
Built-in Array::index 6.950000 0.020000 6.970000 ( 7.735154)
My own binary search 0.900000 0.030000 0.930000 ( 1.195101)
Неудивительно — index делает перебор, а не бинарный поиск.
В руби конечно стек приличный, но все же не бесконечный. А код симпатичный, читается.
1. Жуткий боян
Было даже на developers.org.ua в 2007-м году: www.developers.org.ua/archives/redron/2007/08/19/binary-merge-search-broken/
Оригинал датируется 2006-м: googleresearch.blogspot.com/2006/06/extra-extra-read-all-about-it-nearly.html
2. Про JDK вспомнили а про .NET забыли
3. В чём мораль? Есть что-то новое, что не было сказано в оригинальных статьях?
Было даже на developers.org.ua в 2007-м году: www.developers.org.ua/archives/redron/2007/08/19/binary-merge-search-broken/
Оригинал датируется 2006-м: googleresearch.blogspot.com/2006/06/extra-extra-read-all-about-it-nearly.html
2. Про JDK вспомнили а про .NET забыли
3. В чём мораль? Есть что-то новое, что не было сказано в оригинальных статьях?
Хорошего программиста пишушего подобные алгоритмы без тестирования я бы прав доступа к репозиторию лишил. Ибо за ошибку, которую он допустит на третью попытку, придётся платить.
Действительно хороший программист должен, во вторую очередь, понять, какие бывают граничные случаи поведения алгоритма, и как их нужно отработать либо задокументировать (это не баг, это фича, ага). То, что в конце топика.
Действительно хороший программист должен, во вторую очередь, понять, какие бывают граничные случаи поведения алгоритма, и как их нужно отработать либо задокументировать (это не баг, это фича, ага). То, что в конце топика.
PHP
pastie.org/927648
Время — 30 минут / финальный вариант достигнут после 3го запуска
с достаточным набором тестов для чисел. Строки не тестил, но теоретически поддерживаются =)
Решение возможно не совсем стандартное т.к. использовал рекурсию (мне так захотелось) и возможность сравнивать строки, а вариант из википедии или другие варианты не смотрел ибо было бы читерством =)
pastie.org/927648
Время — 30 минут / финальный вариант достигнут после 3го запуска
с достаточным набором тестов для чисел. Строки не тестил, но теоретически поддерживаются =)
Решение возможно не совсем стандартное т.к. использовал рекурсию (мне так захотелось) и возможность сравнивать строки, а вариант из википедии или другие варианты не смотрел ибо было бы читерством =)
На многих языках RosettaCode
— binsearch(null, 1)
(хотя, возможно, NullPointerException можно считать тут допустимым)
— про переполнение в строке 26 уже выше было сказано
(хотя, возможно, NullPointerException можно считать тут допустимым)
— про переполнение в строке 26 уже выше было сказано
Это да, но раз уж Сам Блох 10 лет ее не находил, думаю мне простительно :)
Кстати посмотреть как все ломается при переполнении можно, если память есть:
pastie.org/927751
запускал с -Xmx4096m
Кстати посмотреть как все ломается при переполнении можно, если память есть:
pastie.org/927751
запускал с -Xmx4096m
Мне кажется, главное это понимание. Все знать не возможно.
Умный не тот кто все знает, а тот кто знает где найти ответы.
Умный не тот кто все знает, а тот кто знает где найти ответы.
function bins(a,n) {
var res=null, l=0, r=a.length, s;
do {
s=Math.floor((l+r)/2);
if (n<a[s]) {r=s;} else {l=s;}
if (a[l]==n) {res=n;s=r=l;}
if (a[r]==n) {res=n;s=l=r;}
if (r-l==1) l=r;
} while (l<r);
return [res,s];
}
var ar=[1,2,3,6,8,10,13,14,17,18,19,25];
bins(ar,1) // ok
bins(ar,6) // ok
bins(ar,4) // null
* This source code was highlighted with Source Code Highlighter.
20 мин работы.
Предусмотрены случаи:
1) чётн/нечётн/нулевая размерность массива
2) искомое меньше первого или больше последнего элемента
3) на всякий случай вывожу позицию, на которой нашлось число или остановился алгоритм
Мне не очень нравится косяк с двумя проверками на равность, но это — мелочь, наверное.
a = null?
Не знаю что за язык, но должно быть переполнение в вычислении среднего )
Переполнение не смотрел, НО… алгоритм немного не такой как в условии:
например, при поиске первого элемента массива (bins(ar,1)), все необходимые действия не производятся и функция отрабатывает в одну итерацию.
Далее, в любом из вариантов одна из границ остаётся в 7 элементе массива (с индексом 6), например ищем число 9 в вашем примере, и проверяется 7й элемент, а по условию он не должен участвовать вообще, так как в массиве 12 элементов и он должен делится на 0..5 и 6..11 половины.
А в остальном алгоритм хорош… у меня менее изящно получилось, сейчас свой вариант дотестирую и выложу.
например, при поиске первого элемента массива (bins(ar,1)), все необходимые действия не производятся и функция отрабатывает в одну итерацию.
Далее, в любом из вариантов одна из границ остаётся в 7 элементе массива (с индексом 6), например ищем число 9 в вашем примере, и проверяется 7й элемент, а по условию он не должен участвовать вообще, так как в массиве 12 элементов и он должен делится на 0..5 и 6..11 половины.
А в остальном алгоритм хорош… у меня менее изящно получилось, сейчас свой вариант дотестирую и выложу.
видимо все решили попасть в эти 10%
НЛО прилетело и опубликовало эту надпись здесь
Что за бред?..
pastie.org/927725
где — то минут 20
где — то минут 20
сломается вроде на
findPos(new int[0], 0, 0, 0)
не?
findPos(new int[0], 0, 0, 0)
не?
Если new int[0], то NullPointerException, но этим грешат практически все.
findPos(new int[] {0}, 0, 0, 0); выдает ок.
findPos(new int[] {0}, 0, 0, 0); выдает ок.
Мой выше не грешит :)
На самом деле findPos(null, 0, 0, 0) это одно, а пустой массив это другое
П.С. Ну и в вашем случае будет не NPE, а ArrayIndexOutOfBoundsException
На самом деле findPos(null, 0, 0, 0) это одно, а пустой массив это другое
П.С. Ну и в вашем случае будет не NPE, а ArrayIndexOutOfBoundsException
если я не ошибаюсь, то это сродни дихотомии. Когда ищется максимум или миниум функции
после этого топика 99% программистов причислят себя к элитарным 10 процентам что справились с задачей =) Всех поздравляем=)
А как вам это?
pastie.org/927792
pastie.org/927792
(defun dixotomy (obj vector) (let ((len (length vec))) (and (not (zerop len)) (finder obj vec 0 (- len 1)))))
Сорри, начал причесывать имена и нажал ctrl-enter
(defun bin-search (obj vec) (let ((len (length vec))) (and (not (zerop len)) (finder obj vec 0 (- len 1))))) (defun finder (obj vec start end) (let ((range (- end start))) (if (zerop range) (if (eql obj (aref vec start)) obj nil) (let ((mid (+ start (round (/ range 2))))) (let ((obj2 (aref vec mid))) (if (< obj obj2) (finder obj vec start (- mid 1)) (if (> obj obj2) (finder obj vec (+ mid 1) end) obj)))))))
Ну и что? Не каждый может на память прочитать всю таблицу умножения ни разу не сбившись. В чем смысл зазубренного знания? В чем смысл статьи? Что хотел сказать автор? Не вижу.
Дело не в зубрежке, а в способности сходу выдать корректный алгоритм )
В статье предлагается поучаствовать именно тем, кто никогда не писал этот алгоритм. О какой зубрежке может идти речь? Что хотел сказать комментатор? Не вижу.
Комментатор хотел сказать что автор плохо читал оригинальную статью, в которой не было строгого ограничения на «никогда не писал этот алгоритм». После этого появляется резонный вопрос: 10% не реализовывавших алгоритм могут написать его с первого раза без ошибок или 10% программистов вообще?
Разница огромна. 10% программистов и 10% программистов до сих пор никогда не писавших бинарную сортировку это значения даже не разных порядков, это значения с разных сторон шкалы измерений!
Разница огромна. 10% программистов и 10% программистов до сих пор никогда не писавших бинарную сортировку это значения даже не разных порядков, это значения с разных сторон шкалы измерений!
Конечно же я хорошо читал оригинальную статью, и не вижу интереса писать алгоритм, который и так знаешь. Это не перевод, я изложил задачу так, как считаю целесообразным.
Реальная доля программистов здесь тоже не очень интересна. Ну, допустим, 70% могут написать, и что? А если 10%? Главное:
a) считаешь ли ты этот алгоритм простым как дважды два (я считаю)
б) можешь ли ты корректно и элегантно написать его без напрягов (я не могу)
Выводы у каждого свои. Мне задачка позволила немного опуститься на землю.
Реальная доля программистов здесь тоже не очень интересна. Ну, допустим, 70% могут написать, и что? А если 10%? Главное:
a) считаешь ли ты этот алгоритм простым как дважды два (я считаю)
б) можешь ли ты корректно и элегантно написать его без напрягов (я не могу)
Выводы у каждого свои. Мне задачка позволила немного опуститься на землю.
Ну так самое интересное здесь в том, что даже зная алгоритм и реализовав его ни единожды 9 из 10 программистов не смогут его реализовать без ошибок! Разве нет?
Никто не идеален — вот итог вашей статьи. Только какой вывод из этого можно сделать? Какое конструктивное решение это поможет принять? Вот это было бы интересно узнать.
Никто не идеален — вот итог вашей статьи. Только какой вывод из этого можно сделать? Какое конструктивное решение это поможет принять? Вот это было бы интересно узнать.
А, теперь понимаю аргумент. Да, для кого-то вывод будет такой.
Конструктивное решение — сейчас подыщем. Я раньше грешил тем, что выкатывал код на живой без тестирования, потому что «очевидно же работает, всего одна строчка». Несколько подобных уроков научили не доверять себе ни в коем случае. Вообще, незвисимо от сложности изменений. Добавил символ в строку? Тестить.
Умом, что это реально необходимо — не понять. Только на своей шкуре.
Конструктивное решение — сейчас подыщем. Я раньше грешил тем, что выкатывал код на живой без тестирования, потому что «очевидно же работает, всего одна строчка». Несколько подобных уроков научили не доверять себе ни в коем случае. Вообще, незвисимо от сложности изменений. Добавил символ в строку? Тестить.
Умом, что это реально необходимо — не понять. Только на своей шкуре.
Написал статью «Как же все-таки правильно написать двоичный поиск?»
Возможно, она поможет вам «корректно и элегантно написать его без напрягов» столько раз, сколько потребуется.
Возможно, она поможет вам «корректно и элегантно написать его без напрягов» столько раз, сколько потребуется.
pastie.org/927808 как-то так
int binary_find(int pattern,int *arr,int length) {
int step=0,x;
x=length/2;
while(step+x < length) {
if(arr[step+x] < pattern) step+=x;
else if(arr[step+x] == pattern) return step+x;
if(x <= 1) break;
x-=x/2;
}
return -1;
}
int step=0,x;
x=length/2;
while(step+x < length) {
if(arr[step+x] < pattern) step+=x;
else if(arr[step+x] == pattern) return step+x;
if(x <= 1) break;
x-=x/2;
}
return -1;
}
min = 0
max = n-1
While(1)
{
mid = min+max;
If(a[mid]>need)
min = mid;else
If(a[mid]<need)
max =mid;else
Break;
}
Ответ: a[min] ближайший по значению элемент массива
max = n-1
While(1)
{
mid = min+max;
If(a[mid]>need)
min = mid;else
If(a[mid]<need)
max =mid;else
Break;
}
Ответ: a[min] ближайший по значению элемент массива
Топик явно задевает =) Трудно пройти мимо такого, не проверив: «а могу ли я?».
Что касается меня — написать-то написал, но не с первого раза. =)
Тем не менее не ясна мораль данного топика. Тут либо намек на то, что не все программисты хорошо знакомы даже с простейшими алгоритмами, либо на то, что без отладки только hello-world выходит с первого раза (и то не всегда).
Но ни одно из этих двух утверждений и так не вызывает никаких сомнений =)
Что касается меня — написать-то написал, но не с первого раза. =)
Тем не менее не ясна мораль данного топика. Тут либо намек на то, что не все программисты хорошо знакомы даже с простейшими алгоритмами, либо на то, что без отладки только hello-world выходит с первого раза (и то не всегда).
Но ни одно из этих двух утверждений и так не вызывает никаких сомнений =)
Морали никакой нет, а цель есть, опустить гениев на землю. Когда понимаешь, что не можешь написать с первого раза даже такой простой алгоритм — это отрезвляет.
Морали никакой нет, а цель есть, опустить гениев на землю
Видимо меня уже давно опустило =) А гении и не такое с первого раза пишут. Те гении, что за 5 минут сочиняют алгоритм на олимпиаде, еще за 5 пишут и сдают с первой попытки. Хотя там уже скорее автоматизм и привычка правильно писать. И, конечно, огромный опыт и куча изученных алгоритмов.
Видимо меня уже давно опустило =) А гении и не такое с первого раза пишут. Те гении, что за 5 минут сочиняют алгоритм на олимпиаде, еще за 5 пишут и сдают с первой попытки. Хотя там уже скорее автоматизм и привычка правильно писать. И, конечно, огромный опыт и куча изученных алгоритмов.
Насчет олимпиадников и гениев — не согласен )
Олимпиадник никогда не отправит задачу не прогнав тесты+граничные условия, а потому там условия совсем другие ) С первого раза писать невыгодно, надо писать быстро и быстро исправлять ошибки :-)
Олимпиадник никогда не отправит задачу не прогнав тесты+граничные условия, а потому там условия совсем другие ) С первого раза писать невыгодно, надо писать быстро и быстро исправлять ошибки :-)
Ну такую задачу олимпиадник напишет мизинцами ног, по пьяни, в проруби, смской.
Я имел в виду обычных программистов, которые считают себя если не гениями, то уж лучшими в своей команде наверняка. То, что таким себя мнит каждый первый — феномен заслуживающий отдельной статьи.
Я имел в виду обычных программистов, которые считают себя если не гениями, то уж лучшими в своей команде наверняка. То, что таким себя мнит каждый первый — феномен заслуживающий отдельной статьи.
До этого ни разу не писал бинарный поиск — использовал библиотечные реализации языков.
10 мин — первый вариант
потом 5 минут мысленного тестирования — обнаружил один баг — добавил + 1 для правой ветки поиска.
И вот:
pastie.org/927876
Касательно типичных ошибок.
Если использовать указатели, а не индексирование массива, то практически не используется ни одна конструкция приводящая к этим ошибкам.
Мне например никогда бы не пришло в голову находить средний указатель путем (a+b)/2 поскольку операция сложения для указателей бессмысленна. А вот вычитание и сложение с числом — типичный шаблон применения указателей: a + (b — a)/2
Много упрощения в коде дает обозначение конца интервала не последним его элементом, а следующим за ним. Т.е. длина интервала end — begin, а не end — begin + 1.
10 мин — первый вариант
потом 5 минут мысленного тестирования — обнаружил один баг — добавил + 1 для правой ветки поиска.
И вот:
pastie.org/927876
Касательно типичных ошибок.
Если использовать указатели, а не индексирование массива, то практически не используется ни одна конструкция приводящая к этим ошибкам.
Мне например никогда бы не пришло в голову находить средний указатель путем (a+b)/2 поскольку операция сложения для указателей бессмысленна. А вот вычитание и сложение с числом — типичный шаблон применения указателей: a + (b — a)/2
Много упрощения в коде дает обозначение конца интервала не последним его элементом, а следующим за ним. Т.е. длина интервала end — begin, а не end — begin + 1.
Все верно говорите :) Я бы еще писал сразу return pos вместо break, и return null в конце для надежности (а то можно протерять зануление pos в конце итерации)
Я просто не хотел привлекать внимание фанатов единой точки выхода :))
А так — да. Когда писал, не сразу вписал pos = NULL. Но опыт не пропьешь :) Краем глаза заметил что чего-то не хватает и добавил.
Впрочем с return тоже не все ветки можно обработать, т.ч. тут скорее личные предпочтения и опыт играют роль, а не потенциальная проблемность техники.
А так — да. Когда писал, не сразу вписал pos = NULL. Но опыт не пропьешь :) Краем глаза заметил что чего-то не хватает и добавил.
Впрочем с return тоже не все ветки можно обработать, т.ч. тут скорее личные предпочтения и опыт играют роль, а не потенциальная проблемность техники.
pastie.org/927964
Python, 10 минут
Python, 10 минут
pastie.org/927971
На Java за 40 минут. Изучаю джаву два месяца на досуге, такая вот проба вскрыла отсутствие знаний по многим статьям.)
На Java за 40 минут. Изучаю джаву два месяца на досуге, такая вот проба вскрыла отсутствие знаний по многим статьям.)
Про 10% раньше не слышал, но феномен известный. Лично я показывал этот феномен своим студентам на примере алгоритма КВУР (квадратное уравнение). Ситуация аналогичная. Алгоритм простой, но редко кто может обработать все исключительные случаи за один проход.
НЛО прилетело и опубликовало эту надпись здесь
Есть. Но цель не в том, чтобы написать ей замену, а в том, чтобы проверить себя, сможешь ли написать простой алгоритм без ошибок. Если нет — что уже тогда говорить о сложных алгоритмах. Не все же функции есть в библиотеке, иногда приходится и самому мозгами пораскинуть.
Если middle будет округляться в большую сторону, то там будет выход за пределы массива при отсутствии искомого элемента. Если в меньшую — будет бесконечный цикл.
Рассмотри массив из двух элементов, каждый из которых меньше или больit искомого.
Рассмотри массив из двух элементов, каждый из которых меньше или больit искомого.
pastebin.com/p7pVxhVM тесты вроде проходит.
НЛО прилетело и опубликовало эту надпись здесь
Потратил пол-часа, чтобы убедиться, что статья — развод :)
Вот, что вышло pastie.org/928188
Язык — Python
Вот, что вышло pastie.org/928188
Язык — Python
Да почему развод, почитайте комменты выше. Если пишете этот алгоритм в первый раз, и он сразу запустился — поздравляю, вы в 10%
Такие, и многие другие задачи можно найти и порешать на dl.gsu.unibel.by :-)
Опс, dl.gsu.by
Ищем число 1 в массиве [2]
l = 0, r = 1 ( в этом ошибка, должно быть arr.size — 1)
в конце первой итерации получаем l = 1, r = 0, и пошло плясать.
Правильно? Или уже гоню под конец дня.
l = 0, r = 1 ( в этом ошибка, должно быть arr.size — 1)
в конце первой итерации получаем l = 1, r = 0, и пошло плясать.
Правильно? Или уже гоню под конец дня.
Да, гоню конечно же
Но зато ошибка в другом: r = arr.size — 1
Все, я не из 10%
Все, я не из 10%
Лезем по индексу -1 если массив пустой
Мда, поспешные выводы дают о себе знать.
Тогда думаю в начале
Тогда думаю в начале
return nil if arr.nil? or arr.empty?
[][-1] как раз вернёт nil и не является проблемой.
За алгоритм через цикл — одновременно респект (так как не требует погружения в стек, мой рекурсивный подход правильно в этом упрекнули) и дизреспект, так как это менее идиоматично.
И да,
За алгоритм через цикл — одновременно респект (так как не требует погружения в стек, мой рекурсивный подход правильно в этом упрекнули) и дизреспект, так как это менее идиоматично.
И да,
>> find([],5)
NoMethodError: undefined method `<' for nil:NilClass
Так, опять меня подводит незнание ruby
Python выдаст exception — и это, ИМХО, правильно.
Я бы предложил
заменить на
Заодно убрать последний else из цикла и поставить по завершении цикла
Python выдаст exception — и это, ИМХО, правильно.
Я бы предложил
return nil if l == r and arr[l] != value
заменить на
return nil if l >= r and arr[l] != value
Заодно убрать последний else из цикла и поставить по завершении цикла
return m
А мне наоборот, очевидно, что массив должен вести себя так же как хэш. И вернуть nil при запросе к элементу, не входящему в список ключей.:)
Но это, согласитесь вкусовщина.
Зато есть оператор <=>, который возвращает -1,0 или 1, в зависимости от. И он заметно упрощает восприятие кода в подобных случаях. Плюс — меньше разадресации массива, то есть более быстрый код.
Но это, согласитесь вкусовщина.
Зато есть оператор <=>, который возвращает -1,0 или 1, в зависимости от. И он заметно упрощает восприятие кода в подобных случаях. Плюс — меньше разадресации массива, то есть более быстрый код.
pastie.org/928260
C++. не больше 10 минут
C++. не больше 10 минут
Не получилось с первого раза, без отладки. Написал вот что.
size_t lt = 0;
size_t rt = N;
while (lt<rt)
{
size_t m = (lt+rt)>>1;
if (a[m]==aItemToFind) return m;
if (a[m]<aItemToFind) lt = m;
else rt=m+1;
}
return NOT_FOUND;
Надо было:
if (a[m]<aItemToFind) lt = m+1;
else rt=m;
size_t lt = 0;
size_t rt = N;
while (lt<rt)
{
size_t m = (lt+rt)>>1;
if (a[m]==aItemToFind) return m;
if (a[m]<aItemToFind) lt = m;
else rt=m+1;
}
return NOT_FOUND;
Надо было:
if (a[m]<aItemToFind) lt = m+1;
else rt=m;
ну, можно ещё немного улучшить…
size_t m = (static_cast(lt) + static_cast(rt)) >> 1;
или size_t m = lt + ((rt-lt)>>1);
А так вроде правильно.
size_t m = (static_cast(lt) + static_cast(rt)) >> 1;
или size_t m = lt + ((rt-lt)>>1);
А так вроде правильно.
perl
pastie.org/928287
10 минут, тест для проверки что обрезав массив до двух элементов, виснет. после чего еще минута.
pastie.org/928287
10 минут, тест для проверки что обрезав массив до двух элементов, виснет. после чего еще минута.
«10% программистов могут решить эту задачу»
Давайте разделять, решить, или решить с первого раза не запуская (т.е написать код и чтоб сразу работало) это немного разные вещи…
Со времён 40-60 годов многое изменилось, и скорость компов в том числе. На сегодняшний день работа программиста отличается от тех времён. Появилось не мало хороших инструментов позволяющих не выбивать дырки на перфокартах по откомпилированному в голове коду (потому что вторая попытка займёт весь рабочий день) а «писать-запускать-править-писать дальше» и всё это за считанные секунды.
Давайте разделять, решить, или решить с первого раза не запуская (т.е написать код и чтоб сразу работало) это немного разные вещи…
Со времён 40-60 годов многое изменилось, и скорость компов в том числе. На сегодняшний день работа программиста отличается от тех времён. Появилось не мало хороших инструментов позволяющих не выбивать дырки на перфокартах по откомпилированному в голове коду (потому что вторая попытка займёт весь рабочий день) а «писать-запускать-править-писать дальше» и всё это за считанные секунды.
НЛО прилетело и опубликовало эту надпись здесь
Это так, согласен. Но это не значит, что от решения таких задач нет толку. Смотрите, если все простые задачи уже решены за нас в стандартной библиотеке, значит нам остались только более сложные задачи, которых там нет. Как мы будем решать эти более сложные задачи, если мы не умеем решить даже простую задачу из стандартной библиотеки?
Я вам скажу как, опыта на этот счет достаточно. Очень хреново. Я делал проверку кода, когда работал в команде. Многие программисты не могли родить простейший код даже с 20 попытки! Они привыкли сидеть на готовом, они не способны написать что-то сложнее простой композиции foo(bar())
Я вам скажу как, опыта на этот счет достаточно. Очень хреново. Я делал проверку кода, когда работал в команде. Многие программисты не могли родить простейший код даже с 20 попытки! Они привыкли сидеть на готовом, они не способны написать что-то сложнее простой композиции foo(bar())
НЛО прилетело и опубликовало эту надпись здесь
На C# 20 минут потратил на реализацию и 25 мин. на прогонку различных вариаций, в результате, которой заметил, что не правильно резал пополам, т.е. пока 1-у ошибку допустил, не считая бага на переполнение
pastie.org/928396
pastie.org/928396
Я в школе на паскале такое фигачил :)
Исходя из этой статьи…
НЛО сьело длинную ссылку на картинку
Классно, спасибо. Выходит, не все так уныло в нашем царстве.
Может, цифры проставить? Было бы ещё нагляднее.
И Ruby с AS3 слились.
И Ruby с AS3 слились.
Цвета были сгенерированы одной строчкой случайнные, поэтому такие проблемы.
Оффтоп: кто-нибудь знает хорошие средства для работы с google char api? 10 минут гугленья ничего удобоваримого не выдали, а каждый раз руками URL формировать как-то невесело.
А, виноват, вообще не разобравшись ответил, совсем не в ту степь.
Вас, видимо интересует что-то вроде
www.maxb.net/scripts/jgcharts/include/demo/
или
pygooglechart.slowchop.com/
Ну а я люблю Руби, для него есть gchartrb.rubyforge.org/
www.maxb.net/scripts/jgcharts/include/demo/
или
pygooglechart.slowchop.com/
Ну а я люблю Руби, для него есть gchartrb.rubyforge.org/
def bin(xs, x): if not(xs and len(xs)): return None start, end = 0, len(xs) - 1 while(start != end): newend = mid = (start + end) // 2 newstart = newend if newend != start else end start, end = (newstart, end) if (xs[mid] < x) else (start, newend) return start if (xs[start] == x) else None
python. 6минут на хвосторекурсивную, минута на прогон тестов, минута на конвертацию в цикл
еще чуть подумал, и решил что можно красивее внутренность цикла сделать :)
def bin(xs, x): if not(xs and len(xs)): return None start, end = 0, len(xs) - 1 while(start != end): mid = (start + end) // 2 start, end = (mid + 1, end) if (xs[mid] < x) else (start, mid) return start if (xs[start] == x) else None
Если вместо start != end поставить start >= end
То можно (в предположении что нам передали массив, пустой или нет) избавиться от первого if'а.
То можно (в предположении что нам передали массив, пустой или нет) избавиться от первого if'а.
ну как ты да :) только смысл. могут ведь передать и None
Смысл — меньше действий и короче (=>яснее) код.
ну. в 1) короче наверно не станет. потому что нужно будет return внутрь цикла вносить и проверять там на == (возможно и нет, но надо думать, а мне лень :) )
в 2) возможно кому-то и яснее, но не мне :) мне более понятно когда явно отметаются крайние случаи (None и []), чем думать о том что там в условии. да и (start != end) мне больше понятно чем (start >= end). я просто читаю код как «пока начало не совпало с концом» и не думаю о том что там есть порядок.
но опять же. это мой код, потому мне понятней. вам, наверно, другой код понятней.
в 2) возможно кому-то и яснее, но не мне :) мне более понятно когда явно отметаются крайние случаи (None и []), чем думать о том что там в условии. да и (start != end) мне больше понятно чем (start >= end). я просто читаю код как «пока начало не совпало с концом» и не думаю о том что там есть порядок.
но опять же. это мой код, потому мне понятней. вам, наверно, другой код понятней.
Добавлю свой вклад с Perl:
Ссылка на крутую реализацию алгоритма двоичного поиска
Кстати, если отбросить всю тестовую дребедень, я думаю один из самых компактных алгоритмов получился.
Ссылка на крутую реализацию алгоритма двоичного поиска
Кстати, если отбросить всю тестовую дребедень, я думаю один из самых компактных алгоритмов получился.
НЛО прилетело и опубликовало эту надпись здесь
Захотелось как то поизвращаться, поэтому получился вот такой вариант — C#, более получаса, 2 строчки:
- public static int Dichotomy(int[] data, int subject)
- {
- if(data!=null)
- for (int step = (data.Length - 1) / 2, stop = (int)Math.Sqrt(data.Length), lim = data.Length;
- stop > -1 && step >= 0 && step < lim;
- step = step + (data[step] > subject ? -1 : 1) * ((step + 1) / 2), stop--)
- if (data[step] == subject)
- return step;
- return - 1;
- }
* This source code was highlighted with Source Code Highlighter.
Оно точно корректно работает?
Массив 0,1,...,10
Ищем число 7.
step принимает значения 4, 6, 9, 4,…
Какой смысл несет переменная stop?
Массив 0,1,...,10
Ищем число 7.
step принимает значения 4, 6, 9, 4,…
Какой смысл несет переменная stop?
Ну конечно не работает! Я ещё подумал, зачем я ввёл индекс… Ща верну :)
Ну а стоп — это стоп, чтоб корректно работало с 0 и не уходило в бесконечный цикл ((0+1)/2 =0)…
Ну а стоп — это стоп, чтоб корректно работало с 0 и не уходило в бесконечный цикл ((0+1)/2 =0)…
Тогда надо не sqrt, а Log2, иначе алгоритм будет работать за O(sqrt(n)), а не O(log(n))
И все равно некрасиво это как-то, ИМХО...)
И все равно некрасиво это как-то, ИМХО...)
В очередной раз убеждаюсь в том, что если автор проверяет те случаи, которые он учёл в коде — ну или это обратная зависимость, но результат тот же. Как то так:
Шаг постоянно падает, поэтому нет смысла проверять, что он в пределах массива. Получается, что и индекс в пределах массива, так как скачок ограничен шагом. Стоп — обратный отсчёт максимального количества шагов, для корректной остановки при шаге в 0. Ну а знак ± указывает в какую сторону шагать. Вроде всё.
public static int Dichotomy(int[] data, int subject)
{
if (data != null)
for (int step = (data.Length - 1) / 2, index = step, stop = (int)Math.Sqrt(data.Length);
stop > -1 ; step = ((step + 1) / 2), index += (data[index] > subject ? -1 : 1) * step, stop--)
if (data[index] == subject)
return index;
return -1;
}
* This source code was highlighted with Source Code Highlighter.
Шаг постоянно падает, поэтому нет смысла проверять, что он в пределах массива. Получается, что и индекс в пределах массива, так как скачок ограничен шагом. Стоп — обратный отсчёт максимального количества шагов, для корректной остановки при шаге в 0. Ну а знак ± указывает в какую сторону шагать. Вроде всё.
Нет, индекс надо проверять иначе без костыля никак…
Немного оптимизации (и да, мне есть чем заняться на работе):
public static int Dichotomy(int[] data, int subject)
{
if (data != null)
for (int len=data.Length, step=(len - 1)/2, index=step, stop=(int)Math.Log(len, 2), sign;
stop-- > -1 && index > -1 && index < len; step=++step/2, index +=sign * step)
if (0 == (sign = subject.CompareTo(data[index])))
return index;
return -1;
}
* This source code was highlighted with Source Code Highlighter.
Вот мое решение поставленной задачи на Python'е: pastie.org/929570
зы: на самом деле я не думал над решением 26 часов =) просто только что узнал о этом топике из Твиттера @ilysenkov'a ;) а решение ~10 минут
зы: на самом деле я не думал над решением 26 часов =) просто только что узнал о этом топике из Твиттера @ilysenkov'a ;) а решение ~10 минут
Массив портить нехорошо:) Но вариант красивый.
Нравится ход мыслей, но на практике портить массив нельзя, потому что он еще может понадобиться. И копировать нельзя, может в память не поместиться. print mas[i] — это считаем что опечатка.
На самом деле нет. Сразу не сообразил, но для вычисления индекса нужно еще запоминать, сколько мы вырезали из начала.
Согласен, в коде накосячил (невнимательно задание прочел)
Нашел число, а не индекс и массив урезал =)
Вот версия #2 все на том же Python'е: pastie.org/931548
Нашел число, а не индекс и массив урезал =)
Вот версия #2 все на том же Python'е: pastie.org/931548
Mathematica), 7 минут:
pastie.org/930135
pastie.org/930135
arr[[m]] < elem, left = m,
arr[[m]] > elem, right = m
При left = 0 и right = 1 quotient будет 0. И если arr[0] не является искомым числом, цикл пойдет по кругу до бесконечности.
arr[[m]] > elem, right = m
При left = 0 и right = 1 quotient будет 0. И если arr[0] не является искомым числом, цикл пойдет по кругу до бесконечности.
Не заметил сначала, что в этом языке индексация массивов с единицы, но это вроде бы ничего не меняет.
Не могли бы вы привести контр пример, учитывая, что индексация всё-таки с 1.
Да, разумеется. Перевел алгоритм в Javascript, чтоб проверить, попробуйте те же данные в Mathematica.
pastie.org/931837
pastie.org/931837
pastebin.org/169249
15 минут писал, протом прогнал тесты, получил зацикливание, выделил отдельно обработку массива из одного-двух элементов, в итоге где-то 30 минут
15 минут писал, протом прогнал тесты, получил зацикливание, выделил отдельно обработку массива из одного-двух элементов, в итоге где-то 30 минут
PHP, 10 минут, pastie.org/931216
Так долго потому что под Beatles и всякие рюшечки приделал.
Так долго потому что под Beatles и всякие рюшечки приделал.
PHP, рекурсия. Уже оттестировано — первая набросанная на коленке версия лишние проверки делала.
pastie.org/4125051
pastie.org/4125051
Если у меня сейчас попросят нарисовать эпюру сложного напряженного состояния — я скорее всего уже не смогу. А если и смогу — то сделаю кучу ошибок. Хотя всего несколько лет назад я с легкостью их рисовал.
Неиспользуемые знания довольно быстро забываются. Я сейчас полез в википедию, чтобы посмотреть, а что такое вообще бинарный поиск. К стыду своему, я никогда им не пользовался (хотя, может быть, он есть в тех фреймворках, что я использую).
Можно ли на основании этого утверждать, что я плохой программист? Можно, вероятно. Но чтобы утверждать, что я плохой программист, не нужно вообще ничего — в том числе и никакого знания обо мне. Если ваша оценка хорошего программиста как человека, что может написать бинарный поиск, соответствует тем задачам, что он будет решать — честь вам и хвала, вы нашли свою silver bullet.
Неиспользуемые знания довольно быстро забываются. Я сейчас полез в википедию, чтобы посмотреть, а что такое вообще бинарный поиск. К стыду своему, я никогда им не пользовался (хотя, может быть, он есть в тех фреймворках, что я использую).
Можно ли на основании этого утверждать, что я плохой программист? Можно, вероятно. Но чтобы утверждать, что я плохой программист, не нужно вообще ничего — в том числе и никакого знания обо мне. Если ваша оценка хорошего программиста как человека, что может написать бинарный поиск, соответствует тем задачам, что он будет решать — честь вам и хвала, вы нашли свою silver bullet.
Кстати, судя по числу комментариев, примерно 9 из 10%, которые могут написать бинарный поиск, собрались в комментариях к этой статье. Теперь вы можете посмотреть друг на друга и понять, наконец, как выглядят те страшно элитные 10%, в которые вы все входите.
Я лучше войду в оставшиеся 90% — там люди посимпатичнее.
Я лучше войду в оставшиеся 90% — там люди посимпатичнее.
Дело не в знании, а в отсутствие желания учиться. Тут многие почему-то думают, что если кто-то не может писать двоичный поиск, то он не программист. Это не так. Если человек не знает, но при этом пробовал написать и изучил правильную версию — респект таким людям. Если может написать — тоже респект. А вот те, кто недоумевают, мол, зачем мне оно надо, если уже есть куча готовых версий — таким не место в программировании. Каким образом они будут решать сложные задачи, если с простыми справиться не способны? Будут писать кривые неоптимальные алгоритмы. Понятное дело, что умение писать двоичный поиск — это не гарант успеха, но у таких намного больше шансов решить сложную задачу.
Никто же не спрашивал, зачем в школе изучать математику. «Математику уже затем учить надо, что она ум в порядок приводит» © Ломоносов. Здесь то же самое.
Никто же не спрашивал, зачем в школе изучать математику. «Математику уже затем учить надо, что она ум в порядок приводит» © Ломоносов. Здесь то же самое.
Про неиспользуемые знания правильно, но не относится к теме. Задача не переизобрести алгоритм, а просто перести из слов в код.
Если программист не знает/не может написать двоичный поиск, A*, BFS, то возникает вопрос что он тогда вообще программировал в жизни. Сайты-визитки? Датинги? Я конечно встречал таких senior программистов, но без боли на их творения смотреть нельзя. Это те сумрачные гении, которые, чтобы округлить число до ближайней степени десятки проходятся по строковому представлению этого числа десятью регулярками, заменяющими каждую цифру на 0, а потом дописывают спереди единичку. Те гении, которые за 10 лет не могут научиться экранировать данные перед вставкой в базу (а зачем, это все равно в админке). Их может интересовать кто выиграл в матче/на евровидении/на выставке сраных собак, но что такое BTREE в результате выполнения `SHOW index IN users` они не слышали и не интересовались.
Насчет собравшихся в треде, ну скажем любой программист в Google напишет двоичный поиск. Наверное тоже несимпатичные люди недостойные вашего общества.
Если программист не знает/не может написать двоичный поиск, A*, BFS, то возникает вопрос что он тогда вообще программировал в жизни. Сайты-визитки? Датинги? Я конечно встречал таких senior программистов, но без боли на их творения смотреть нельзя. Это те сумрачные гении, которые, чтобы округлить число до ближайней степени десятки проходятся по строковому представлению этого числа десятью регулярками, заменяющими каждую цифру на 0, а потом дописывают спереди единичку. Те гении, которые за 10 лет не могут научиться экранировать данные перед вставкой в базу (а зачем, это все равно в админке). Их может интересовать кто выиграл в матче/на евровидении/на выставке сраных собак, но что такое BTREE в результате выполнения `SHOW index IN users` они не слышали и не интересовались.
Насчет собравшихся в треде, ну скажем любой программист в Google напишет двоичный поиск. Наверное тоже несимпатичные люди недостойные вашего общества.
Язык: перл. Пол часа с перепроверкой, готовая маленькая программа, включающая генерацию массива, сначала поиск всех элементов массива, потом поиск случайных значений. Сделал перепроверку простую — что бы визуально убедиться в правильности поиска. Вроде как все работает. После этого прочитал спойлеры. Действительно, переполнение и неопределенный элемент в массиве сделают прогу нерабочей. Но этого и не было в техзадании: массив то по условию упорядоченный, а как можно упорядочить неопределенные значения?.. :)
Да и еще: зачем искать одним сравнением одно значение по середине, когда можно сравнивать краевые элементы текущего интервала массива? Сравнение — функция не ресурсоемкая, потому не логично ли сделать два сравнения в цикле а не одно? Так можно получить результат за меньшее кол-во циклов (статистически, ессно).
pastie.org/4166519
Да и еще: зачем искать одним сравнением одно значение по середине, когда можно сравнивать краевые элементы текущего интервала массива? Сравнение — функция не ресурсоемкая, потому не логично ли сделать два сравнения в цикле а не одно? Так можно получить результат за меньшее кол-во циклов (статистически, ессно).
pastie.org/4166519
function BinarySearch(value: integer; arr: PIntegerArray; size: integer): integer;
var
mask: cardinal;
index: cardinal;
begin
mask := $80000000;
while mask > size do
mask := mask shr 1;
index := 0;
while mask > 0 do
begin
index := index or mask;
if (index >= size) then
index := index and (not mask)
else if arr[index] > value then
index := index and (not mask)
else if arr[index] = value then
break;
mask := mask shr 1;
end;
if (index < size) and (arr[index] = value) then
Result := index
else
Result := -1;
end;
Решил попробовать использовать не деление массива на 2 части, а постепенный спуск по маске. Скорее всего, это работает медленнее, чем уже приведенные решения.
Написано не сходу. Первые 2-3 прогона вычислял глюки (не искало нулевой элемент). Дальше еще несколько прогонов улучшал читаемость.
Даже близко не приблизился к 10%, которые могут сходу без тестовых прогонов и отладки написать решение.
В качестве развлечения и развеивания скуки на работе отлично подошло.
function BinarySearch(value: integer; arr: PIntegerArray; size: integer): integer;
var
mask: cardinal;
index: cardinal;
begin
mask := $80000000;
while mask > size do
mask := mask shr 1;
index := 0;
while mask > 0 do
begin
index := index or mask;
if (index >= size) or (arr[index] > value) then
index := index and not mask;
if arr[index] = value then
Exit(index);
mask := mask shr 1;
end;
Result := -1;
end;
Заодно проверил время выполнения. В несколько раз больше времени выполнения классического алгоритма. Понял, что я полный нуб и мне еще учиться и учиться. :)
А вот и мои пять копеек:
Дикое извращение на JavaScript… Изначально думал, что убью на алгоритм минут 10-15, но не тут то было — 50 минут. Видимо, зря в рекурсию полез… Проще надо было быть.
Написание подобных алгоритмов — хорошая самопроверка на адекватность, после бессонной ночи кодинга. :-)
function binarySearch( inputArray , searchValue ){
var RESULT = false;
var halfLenghtIndex = Math.ceil( ( inputArray.length-1 ) / 2 );
if ( inputArray[ halfLenghtIndex ] === searchValue ){
RESULT = halfLenghtIndex;
} else if ( inputArray[ halfLenghtIndex ] > searchValue ) {
RESULT = binarySearch( inputArray.splice( 0 , halfLenghtIndex ) , searchValue );
} else if ( inputArray[ halfLenghtIndex ] < searchValue && inputArray[ inputArray.length-1 ] >= searchValue ) {
RESULT = halfLenghtIndex + binarySearch( inputArray.splice( halfLenghtIndex , inputArray.length - halfLenghtIndex ) , searchValue );
}
return RESULT;
}
Дикое извращение на JavaScript… Изначально думал, что убью на алгоритм минут 10-15, но не тут то было — 50 минут. Видимо, зря в рекурсию полез… Проще надо было быть.
Написание подобных алгоритмов — хорошая самопроверка на адекватность, после бессонной ночи кодинга. :-)
Только 10% программистов способны написать двоичный поиск