Буквально на днях случайно наткнулся на Хабре на статью о лямбда-выражениях из нового (будущего) стандарта C++. Статья хорошая и даёт понять преимущества лямбда-выражений, однако, мне показалось, что статья недостаточно полная, поэтому я решил попробовать более детально изложить материал.
Matvei Kotov @mkot
Пользователь
Дискретные структуры: матан для айтишников
4 min
224K
Посмотришь на любую программу обучения по IT-специальности, и тут же увидишь дисциплину «Дискретная математика» (возможно, под другим названием), обычно для перво- или второкурсников. И её наличие вполне разумно, поскольку дискретная математика и непрерывная математика (представленная на первом курсе институтов с незапамятных времён математическим анализом) — две грани единой Математики, — красивой, могучей науки.
Хотя раньше такого понятия, как «дискретная математика» вовсе не было, это не значит, что не возникало дискретных задач: Абель, Дирихле, Фибоначчи, Эйлер, чьи имена возникают по ходу изучения дискретной математики, — отнюдь не наши современники! Но просто в те времена для выделения самостоятельной ветви математики ещё не сложилось критической массы задач и приёмов, не было видно взаимосвязей между ними. А большое количество плодотворных взаимосвязей между, на первый взгляд, различными понятиями, — то, что математики в своей науке очень ценят.
Ну хорошо, математикам всё математическое интересно. А зачем дискретная математика программисту?
+55
Что каждый программист должен знать про оптимизации компилятора
17 min
81KTranslation
Высокоуровневые языки программирования содержат в себе много абстрактных программистских конструкций, таких как функции, условные операторы и циклы — они делают нас удивительно продуктивными. Однако одним из недостатков написания кода на высокоуровневом языке является потенциальное значительное снижение скорости работы программы. Поэтому компиляторы стараются автоматически оптимизировать код и увеличить скорость работы. В наши дни логика оптимизации стала очень сложной: компиляторы преобразуют циклы, условные выражения и рекурсивные функции; удаляют целые блоки кода. Они оптимизируют код под процессорную архитектуру, чтобы сделать его действительно быстрым и компактным. И это очень здорово, ведь лучше фокусироваться на написании читабельного кода, чем заниматься ручными оптимизациями, которые будет сложно понимать и поддерживать. Кроме того, ручные оптимизации могут помешать компилятору выполнить дополнительные и более эффективные автоматические оптимизации. Вместо того чтобы писать оптимизации руками, лучше бы сосредоточиться на дизайне архитектуры и на эффективных алгоритмах, включая параллелизм и использование особенностей библиотек.
Данная статья посвящена оптимизациям компилятора Visual C++. Я собираюсь обсудить наиболее важные техники оптимизаций и решения, которые приходится применить компилятору, чтобы правильно их применить. Моя цель не в том, чтобы рассказать вам как вручную оптимизировать код, а в том, чтобы показать, почему стоит доверять компилятору оптимизировать ваш код самостоятельно.
Данная статья посвящена оптимизациям компилятора Visual C++. Я собираюсь обсудить наиболее важные техники оптимизаций и решения, которые приходится применить компилятору, чтобы правильно их применить. Моя цель не в том, чтобы рассказать вам как вручную оптимизировать код, а в том, чтобы показать, почему стоит доверять компилятору оптимизировать ваш код самостоятельно.
+38
Чтобы распознавать картинки, не нужно распознавать картинки
18 min
237KПосмотрите на это фото.

Это совершенно обычная фотография, найденная в Гугле по запросу «железная дорога». И сама дорога тоже ничем особенным не отличается.
Что будет, если убрать это фото и попросить вас нарисовать железную дорогу по памяти?
Если вы ребенок лет семи, и никогда раньше не учились рисовать, то очень может быть, что у вас получится что-то такое:

Это совершенно обычная фотография, найденная в Гугле по запросу «железная дорога». И сама дорога тоже ничем особенным не отличается.
Что будет, если убрать это фото и попросить вас нарисовать железную дорогу по памяти?
Если вы ребенок лет семи, и никогда раньше не учились рисовать, то очень может быть, что у вас получится что-то такое:
+253
Необъяснимые особенности нашего мозга
1 min
2.4KДорогие хабравчани, вашему вниманию небольшая задачка, которая докажет всем ещё раз то, что загадка человеческого мозга ещё далеко не разгадана.
В своём распоряжении вы имеете 10 секунд, иначе это не сработает.
Всё что вам надо сделать, так это сосчитать количество букв «F» в нижеследующем тексте.
Помните, не больше 10 секунд!
+++++++++++++++++++++++++++
FINISHED FILES ARE THE RE-
SULT OF YEARS OF SCIENTIF-
IC STUDY COMBINED WITH THE
EXPERIENCE OF YEARS
+++++++++++++++++++++++++++
Объяснения под катом
В своём распоряжении вы имеете 10 секунд, иначе это не сработает.
Всё что вам надо сделать, так это сосчитать количество букв «F» в нижеследующем тексте.
Помните, не больше 10 секунд!
+++++++++++++++++++++++++++
FINISHED FILES ARE THE RE-
SULT OF YEARS OF SCIENTIF-
IC STUDY COMBINED WITH THE
EXPERIENCE OF YEARS
+++++++++++++++++++++++++++
Объяснения под катом
+100
3D Life — в поисках планеров
5 min
19K
Многим известна игра «Жизнь», изобретенная Дж.Конвеем еще в 1970 г. Еще шире известен один из объектов этой игры – планер (или глайдер) – движуееся образование из 5 клеток:

В 1987 г. Были найдены первые планеры в трехмерных версиях «жизни» ( www.complex-systems.com/pdf/16-4-7.pdf ). К сожалению, из случайных конфигураций они возникают очень редко (в отличие от двумерной версии). Я решил поискать правила игры, в которых планеров было бы побольше.
+61
Применение нейросетей в распознавании изображений
10 min
244KПро нейронные сети, как один из инструментов решения трудноформализуемых задач уже было сказано достаточно много. И здесь, на хабре, было показано, как эти сети применять для распознавания изображений, применительно к задаче взлома капчи. Однако, типов нейросетей существует довольно много. И так ли хороша классическая полносвязная нейронная сеть (ПНС) для задачи распознавания (классификации) изображений?
+128
Поиграем в жизнь
4 min
30KПредставьте себе листок бумаги в клетку. Подозреваю, что уже на этом этапе некоторые хабралюди догадались, о чем пойдет речь. Что ж, моё почтение им. Остальные же продолжают представлять себе листок бумаги в клетку. Во всех подробностях. В мельчайших деталях.
А теперь представьте, что на этом простом листочке мы создадим простой, но оттого не менее впечатляющий симулятор жизни. Ни больше, ни меньше. Конечно, он будет очень упрощенный, но ведь чтобы понять что-то сложное надо начать с простого, не так ли? Этот симулятор можно применить ко множеству наук и с каждой из них он будет иметь множество достаточно интересных точек соприкосновения. От социологии до астрономии, от биологии до электротехники.
Ладно, хватит завлекалок. Пора удариться в математику.

А теперь представьте, что на этом простом листочке мы создадим простой, но оттого не менее впечатляющий симулятор жизни. Ни больше, ни меньше. Конечно, он будет очень упрощенный, но ведь чтобы понять что-то сложное надо начать с простого, не так ли? Этот симулятор можно применить ко множеству наук и с каждой из них он будет иметь множество достаточно интересных точек соприкосновения. От социологии до астрономии, от биологии до электротехники.
Ладно, хватит завлекалок. Пора удариться в математику.

+116
Отладка C++ программ в ОС GNU/Linux
2 min
29KTutorial
Так уж случилось, что по долгу работы очень много времени провожу с операционными системами семейства GNU/Linux. Основным видом моей деятельности является разработка программного обеспечения на С++.
Так вот, основной проблемой при использовании отладчика – это отображение сложных контейнеров, например, stl-контейнеров.
Решение, которое я предлагаю, актуально для gdb. Этот отладчик поддерживает скрипты, написанные на языке python, а механизмы отображения сложных объектов, называются pretty printers. Т.е. чтобы отладчик отображал нам все правильно, необходимо указать ему где находятся скрипты с этими самыми pretty printers. Для указания отладчику дополнительных команд необходим файл .gdbinit.
Итак, попробую оформить все, как инструкцию, так и читать удобней, и сам не забуду.
Так вот, основной проблемой при использовании отладчика – это отображение сложных контейнеров, например, stl-контейнеров.
Решение, которое я предлагаю, актуально для gdb. Этот отладчик поддерживает скрипты, написанные на языке python, а механизмы отображения сложных объектов, называются pretty printers. Т.е. чтобы отладчик отображал нам все правильно, необходимо указать ему где находятся скрипты с этими самыми pretty printers. Для указания отладчику дополнительных команд необходим файл .gdbinit.
Итак, попробую оформить все, как инструкцию, так и читать удобней, и сам не забуду.
+16
Распознавание цифр с помощью простейшей статистики и анализа топологии
2 min
25KДело было на третьем курсе, появился у нас предмет ИИС (интеллектуальные информационные системы). Так как я давно интересовался распознаванием образов, удалось выпросить тему «распознавание рукописных цифр». Я решил не возиться с нейронными сетями и придумать что-то свое, простое, но достаточно эффективное.
+65
Распознавание рукописных математических выражений
7 min
24KЗдравствуй, Хабр!
В этой статье я хочу поделиться опытом распознавания рукописных математических выражений. Хотя уже и существуют такие средства распознавания рукописных формул как «Панель математического ввода» mip.exe в Windows7, разнообразие подходов к решению данной проблемы не может не впечатлять. Об одном из таких подходов я и собираюсь рассказать.

В этой статье я хочу поделиться опытом распознавания рукописных математических выражений. Хотя уже и существуют такие средства распознавания рукописных формул как «Панель математического ввода» mip.exe в Windows7, разнообразие подходов к решению данной проблемы не может не впечатлять. Об одном из таких подходов я и собираюсь рассказать.
+226
Я не знаю Си
4 min
51KЦель этой статьи — заставить всех, особенно программистов на Си, сказать «я не знаю Си».
Хочется показать, что тёмные углы в Си значительно ближе, чем кажется и даже тривиальные строки кода несут в себе undefined behavior.
Хочется показать, что тёмные углы в Си значительно ближе, чем кажется и даже тривиальные строки кода несут в себе undefined behavior.
+251
Теорема Клини о неподвижной точке: квайны
6 min
23KЗдравствуйте, хабралюди. В последнее время было много разговоров о квайнах, и даже некоторый теоретический спин-офф.
Повторю за автором только что упомянутого топика: если вы знакомы с CS, то далее читать нет смысла — все это
вы и так хорошо знаете. А статья будет ответом на вопрос — всегда ли можно написать квайн? Точнее, на любом ли языке?
Физики скажут, что на всех: раз можно написать и на компилируемом C, и на брейнфаке, а кто-то и на SQL пишет — опыт говорит, что ответ на вопрос да. Математика тоже говорит, что да.
Повторю за автором только что упомянутого топика: если вы знакомы с CS, то далее читать нет смысла — все это
вы и так хорошо знаете. А статья будет ответом на вопрос — всегда ли можно написать квайн? Точнее, на любом ли языке?
Физики скажут, что на всех: раз можно написать и на компилируемом C, и на брейнфаке, а кто-то и на SQL пишет — опыт говорит, что ответ на вопрос да. Математика тоже говорит, что да.
Теорема 2
На любом алгоритмически полном языке программирования можно написать программу, печатающую свой код.+51
Фракталы в простых числах
3 min
156K
Я обнаружил этот фрактал, когда разглядывал интерференцию волн на поверхности речки. Волна движется к берегу, отражается и накладывается сама на себя. Есть ли порядок в тех узорах, которые создаются волнами? Попробуем найти его. Рассмотрим не всю волну, а только вектор ее движения. «Берега» сделаем гладкими, для простоты эксперимента.
Эксперимент можно провести на обычном листке в клеточку из школьной тетради.
+176
Компьютер из 10000 костей домино
1 min
42KМэтт Паркер, отметившийся в проектах Numberphile и Standup Maths, в компании с командой Domino Computer Builders построили, наверное, самый медленный компьютер в мире из костей домино.
Немного деталей под катом.
Немного деталей под катом.
+93
Жизнь на плоскости Лобачевского
10 min
88K
Как возникла плоскость Лобачевского, достаточно известно. В позапрошлом веке господа Гаусс, Лобачевский и Бойяи, проживавшие примерно в одно время в разных странах тогдашней Европы, задумались, что будет, если отменить пятый постулат Евклида и заменить его на противоположную аксиому. Оказалось, что не случится ничего плохого, и никаких противоречий не возникнет. Заметная часть последующего изучения неевклидовой геометрии была посвящена выяснению того, кто из них у кого украл идею этой самой геометрии.
Менее известно, что несмотря на «отрицательный» способ определения неевклидовой геометрии (вместо того, чтобы сказать, что через точку проходит ровно одна прямая, не пересекающая данную, мы говорим, что таких прямых может быть сколько угодно), мы, тем не менее, получаем систему теорем и формул, не менее стройную, чем та, что есть в евклидовой геометрии. И одновременно, у нас есть гораздо большее разнообразие геометрических фигур, в том числе, разбиений плоскости на правильные многоугольники.
+251
Снова «Морской бой». Считаем число возможных расположений кораблей
6 min
35KРаз уж неделя «Морского боя» на Хабре продолжается, добавлю и я свои два цента.
При попытке найти оптимальную стратегию для игры за компьютер довольно быстро приходим к такому приближению:
Допустим, что состояние некоторых клеток нам уже известно, и мы хотим сделать ход, максимально приближающий нас к победе. В таком случае имеет смысл выбирать клетку, которая занята кораблём противника в наибольшем числе возможных размещений кораблей, не противоречащих имеющейся информации
В самом деле. Если возможная конфигурация только одна, то мы заканчиваем игру за один ход, расстреливая его корабли по очереди (ведь конфигурация нам известна!) Если же конфигураций больше, то нам нужно уменьшить их число как можно сильнее, тем самым увеличив имеющееся у нас количество информации. Если мы попадём в корабль, то ничего не потеряем (ведь ход остаётся у нас!), а если промахнёмся — то число оставшихся комбинаций будет минимальным из возможных после этого хода.

Понятно, что это только приближение к отпимальной стратегии. Если противник будет знать о нашем плане, он постарается разместить корабли так, чтобы они не попадали в те клетки, куда мы будем стрелять в начале игры. Правда, ему это поможет мало — мы всё равно в конце концом зажмём его в угол — но возможно, что определённая гибкость нам не помешала бы. Кроме того, не исключено, что продуманная серия ходов, первый из которых не является оптимальным, привела бы к лучшему результату. Но не будем пока усложнять и без того сложную задачу, а попытаемся просчитать все конфигурации и построить карту вероятности заполнения поля.
На первый взгляд, задача кажется неподъёмной. Число конфигураций представляется порядка 1020 (на самом деле их несколько меньше — ближе к 1015), так что на полный перебор времени уйдёт слишком много. Перебирать раскраски поля и оставлять только допустимые — не лучше: всё равно нам каждую комбинацию придётся просмотреть.
Что же ещё попробовать? Любой олимпиадник тут же ответит — динамическое программирование. Но как его организовать?
При попытке найти оптимальную стратегию для игры за компьютер довольно быстро приходим к такому приближению:
Допустим, что состояние некоторых клеток нам уже известно, и мы хотим сделать ход, максимально приближающий нас к победе. В таком случае имеет смысл выбирать клетку, которая занята кораблём противника в наибольшем числе возможных размещений кораблей, не противоречащих имеющейся информации
В самом деле. Если возможная конфигурация только одна, то мы заканчиваем игру за один ход, расстреливая его корабли по очереди (ведь конфигурация нам известна!) Если же конфигураций больше, то нам нужно уменьшить их число как можно сильнее, тем самым увеличив имеющееся у нас количество информации. Если мы попадём в корабль, то ничего не потеряем (ведь ход остаётся у нас!), а если промахнёмся — то число оставшихся комбинаций будет минимальным из возможных после этого хода.

Понятно, что это только приближение к отпимальной стратегии. Если противник будет знать о нашем плане, он постарается разместить корабли так, чтобы они не попадали в те клетки, куда мы будем стрелять в начале игры. Правда, ему это поможет мало — мы всё равно в конце концом зажмём его в угол — но возможно, что определённая гибкость нам не помешала бы. Кроме того, не исключено, что продуманная серия ходов, первый из которых не является оптимальным, привела бы к лучшему результату. Но не будем пока усложнять и без того сложную задачу, а попытаемся просчитать все конфигурации и построить карту вероятности заполнения поля.
На первый взгляд, задача кажется неподъёмной. Число конфигураций представляется порядка 1020 (на самом деле их несколько меньше — ближе к 1015), так что на полный перебор времени уйдёт слишком много. Перебирать раскраски поля и оставлять только допустимые — не лучше: всё равно нам каждую комбинацию придётся просмотреть.
Что же ещё попробовать? Любой олимпиадник тут же ответит — динамическое программирование. Но как его организовать?
+54
Быстрая, экономная, устойчивая…
10 min
61K
Если вам понадобится алгоритм сортировки массива, который:
- Работал бы гарантированно за O(N*log(N)) операций (обменов и сравнений);
- Требовал бы O(1) дополнительной памяти;
- Был бы устойчивым (то есть, не менял порядок элементов с одинаковыми ключами)
то вам, скорее всего, предложат ограничиться любыми двумя из этих трёх пунктов. И, в зависимости от вашего выбора, вы получите, например, либо сортировку слиянием (требует O(N) дополнительной памяти), либо пирамидальную сортировку (неустойчив), либо сортировку пузырьком (работает за O(N2)). Если вы ослабите требование на память до O(log(N)) («на рекурсию»), то для вас найдётся алгоритм со сложностью O(N*(log(N)2) — довольно малоизвестный, хотя именно его версия используется в реализации метода std::stable_sort().
На вопрос, можно ли добиться выполнения одновременно всех трёх условий, большинство скажет «вряд ли». Википедия о таких алгоритмах не знает. Среди программистов ходят слухи, что вроде бы, что-то такое существует. Некоторые говорят, что есть «устойчивая быстрая сортировка» — но у той реализации, которую я видел, сложность была всё те же O(N*(log(N)2) (по таймеру). И только в одном обсуждении на StackOverflow дали ссылку на статью B-C. Huang и M. A. Langston, Fast Stable Merging and Sorting in Constant Extra Space (1989-1992), в которой описан алгоритм со всеми тремя свойствами.
+145
Интерпретация во время компиляции, или Альтернативное понимание лямбд в C++11
22 min
33K
> С каждым новым релизом количество способов нетривиально вывихнуть себе мозг при помощи С++ продолжает увеличиваться)
> > Особенно, если не менять подход к реализации игрового поля и продолжать пытаться все вычисления выполнять не над константами, а над типами.
А так ли сложно будет написать универсальный вычислитель на типах, более удобный для программирования, чем клеточный автомат? Как оказалось, несложно; я в 30 раз больше времени потратил на эту статью, чем на написание и отладку собственно кода вычислителя.
Чуть раньше AveNat опубликовала введение в лямбда-исчисление в двух частях, так что вдохновение пришло мгновенно. Хотелось, чтобы можно было (образно) писать так:
#include <iostream>
#include <LC/kernel.h>
#include <LC/church_numerals.h>
int main()
{
// Представление натуральных чисел в виде лямбда-абстракций
typedef ChurchEncode<2> Two; // 2 = λfx.f (f x)
typedef ChurchEncode<3> Three; // 3 = λfx.f (f (f x))
// * = λab.λf.a (b f)
typedef Lambda<'a', Lambda<'b', Lambda<'f',
Apply<Var<'a'>, Apply<Var<'b'>, Var<'f'> > >
> > > Multiply;
// Вычисление (* 2 3)
typedef Eval<Apply<Apply<Multiply, Two>, Three>> Output;
// Переход обратно от лямбда-абстракций к натуральным числам
typedef ChurchDecode<Output> Result;
std::cout << Result::value;
}
А на выходе получать такое:
ilammy@ferocity ~ $ gcc cpp.cpp
ilammy@ferocity ~ $ ./a.out
6
Статья получилась несколько великоватой, так как мне хотелось рассказать обо всех интересных штуках, которые здесь используются. И ещё она требует базового набора знаний о лямбда-исчислении. Приведённых выше обзоров, среднего знания C++ (с шаблонами), и здравого смысла должно быть достаточно для понимания содержимого.
Под катом находится очередное прокомментированное конструктивное доказательство Тьюринг-полноты шаблонов C++ в виде compile-time интерпретатора бестипового лямбда-исчисления (плюс печеньки в виде макросов и рекурсии).
+94
Производящие функции — туда и обратно
9 min
108K«Производящая функция является устройством, отчасти напоминающим мешок. Вместо того чтобы нести отдельно много предметов, что могло бы оказаться затруднительным, мы собираем их вместе, и тогда нам нужно нести лишь один предмет — мешок».
Д. Пойа
Математика делится на два мира — дискретный и непрерывный. В реальном мире есть место и для того и для другого, и часто к изучению одного явления можно подойти с разных сторон. В этой статье мы рассмотрим метод решения задач с помощью производящих функций — мостика ведущего из дискретного мира в непрерывный, и наоборот.
Идея производящих функций достаточно проста: сопоставим некоторой последовательности <g0, g1, g2, ..., gn> — дискретному объекту, степенной ряд g0 + g1z + g2z2 +… + gnzn +… — объект непрерывный, тем самым мы подключаем к решению задачи целый арсенал средств математического анализа. Обычно говорят, последовательность генерируется, порождается производящей функцией. Важно понимать, что это символьная конструкция, то есть вместо символа z может быть любой объект, для которого определены операции сложения и умножения.
Д. Пойа
Введение
Математика делится на два мира — дискретный и непрерывный. В реальном мире есть место и для того и для другого, и часто к изучению одного явления можно подойти с разных сторон. В этой статье мы рассмотрим метод решения задач с помощью производящих функций — мостика ведущего из дискретного мира в непрерывный, и наоборот.
Идея производящих функций достаточно проста: сопоставим некоторой последовательности <g0, g1, g2, ..., gn> — дискретному объекту, степенной ряд g0 + g1z + g2z2 +… + gnzn +… — объект непрерывный, тем самым мы подключаем к решению задачи целый арсенал средств математического анализа. Обычно говорят, последовательность генерируется, порождается производящей функцией. Важно понимать, что это символьная конструкция, то есть вместо символа z может быть любой объект, для которого определены операции сложения и умножения.
+67
Information
- Rating
- Does not participate
- Location
- Hoboken, New Jersey, США
- Registered
- Activity