С++ от человека из Яндекса

Категория: Курсы Автор: Александр Никитин Опубликовано: 16-04-2012

Метки:

Добрый день! После пятничного вебинара у многих возникли вопросы о продвинутом курсе по С++ от экс-сотрудника Яндекса Семена Давыдова. Сразу хотим сказать: вы почти опоздали. Сегодня есть последний шанс попасть в учебную группу.

Пару слов о курсе. Будет очень маленькая группа и индивидуальная работа с каждым участником. Благодаря Семену мы очень много переняли из модели обучения в закрытой школе Яндекса и построили процесс по этим методикам так, чтобы у каждого из студентов был максимальный эффект.

Посмотрите видео о курсе ↓↓↓



Подробная программа курса

Оплатить участие в курсе:
Очно: http://prog-school.ru/shop/s/order/live_cpp2_live.html
Онлайн: http://prog-school.ru/shop/s/order/live_cpp2_online.html

P.S. Добираем два-три человека и закрываем набор! Кто успеет оплатить, тот будет учиться.

Точка, точка, запятая…

Категория: ABC, Культура кода Автор: Алексей Захаренков Опубликовано: 15-04-2012

Метки: , ,

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

Точкой с запятой в С++ должны завершаться многие команды. Среди них:

  1. объявления переменных:
    int a, b, arr[10], *p;
  2. определение типа структуры/класса/объединения/перечисления. Например:
    struct Point { int x; int y; };

    В общем случае такое определение может выглядеть приблизительно так:

    struct Point { int x; int y; } p1, p2, points[15], *pPointer;

    Здесь, кроме того что вводится новый тип данных Point, ещё определяются четыре переменные: две переменные типа Point, один массив элементов типа Point и один указатель на Point. Сравните это объявление с примером из пункта 1. Теперь вы должны увидеть, что пункт 2 – это усложнённый вариант объявления переменных. Т.е., на самом деле, последняя точка с запятой в определении типа структуры (или класса) завершает не определение типа структуры, а список переменных этого типа, который, как частный случай, может оказаться пустым. Правда, на практике такой «частный случай» чаще всего и реализуется, поэтому многие программисты давно забыли, откуда происходит необходимость ставить точку с запятой в конце определения класса.

  3. Объявление элементов данных структуры/класса. Это две точки с запятой в определении структуры Point из пункта 2, стоящие после определения полей x и y этой структуры.
  4. Читать полностью »

Онлайн-семинар «Новый стандарт С++11″

Категория: Курсы, События, Школа Программирования Автор: Александр Никитин Опубликовано: 11-04-2012

Метки:

Курс C++В эту пятницу 13 апреля в 21.00 по мск состоится вебинар «Новый стандарт C++11″

Вход бесплатный!

Семинар проведет Семен Давыдов, автор курса C++. Управление памятью.

Семен расскажет про некоторые новые интересные возможности, которые недавно появились в языке. Будет окно редактора, на котором он будет писать и запускать код real-time с этими новыми возможностями.
Параллельно Семен будет отвечать на вопросы по С++ и курсу C++. Управление памятью в целом.

Желающие смогут писать и запускать код параллельно. Для этого понадобится или Visual Studio 2010 или gcc версии не старее 4.6.
Чтобы попасть на вебинар, оставьте свои контакты в этой форме ↓

Ваш e-mail: *
Ваше имя: *
Контактный телефон:

Разбор задач марафона С++

Категория: Школа Программирования Автор: Семён Давыдов Опубликовано: 09-04-2012

Метки:

День 1.

1. Забыл, как умножать.

Для целых чисел подойдет такой код:

int mult7(int x)
{
    return (x << 3) - x;
}

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

Складывает любые объекты, для которых определена операция ‘+’. (числа, строки, списки)

int product(a, b)
{
    int result = 0;
 
    while(b)
    {
        if (b & 1) // b % 2 == 1
            result += a;
 
        b >>= 1;
        result += result;
    }
 
    return result;
}

Отмечу решение Максима (он прислал несколько):

return a / (1.0 / b); // Ловко. Никто ведь не запрещал делить.

2. Когда деревья были большими.

Компилятор borland C++ 3.1 располагает переменные в памяти подряд и вызов a[10] = 0 обнуляет i. Цикл начинается заново.

3. Угадайка.

Здесь надо было использовать двоичный поиск, который каждый раз сокращает область поиска вдвое. Тогда отдагать число можно за log(1000) < 10 вопросов.

День 2.

1. Карусель.

Решение на python:

   if len(a) == len(b) and a in b*2:
       print "YES"
   else:
       print "NO

Удвоеная строка содержит все свои циклические перестановки. Достаточно сравнить длины и проверить вхождение первой строки в удвоенную вторую.

2. Дело об исчезающем прямоугольнике.

Поля в списке инициализации инициализируются в том порядке, в каком они перечислены в определении класса.
Поле _area идет раньше всех и будет обработана первой. Но _width и _height еще не инициализированы, поэтому площадь получается неверной.

3. Калькулятор.

Ясно, что в лоб посчитать не получится, поскольку 15^9783 не влезет ни в какую память.
Но можно заметить, что последняя цифра произведения зависит только от последней цифры исходного числа. Причем, эта последняя цифра повторяется.
Надо выяснить период и выписать цифры. Это можно сделать даже в уме.
Теперь составим табличку:

table int[10][4] = {{0, 0, 0 ,0}, {1 1 1 1}, {2 4 8 6}, {3 9 7 1}, {4, 6, 4, 6}, {5, 5, 5, 5}, {6, 6, 6, 6}, {7, 9, 3, 1}, {8, 4, 2, 6}, {9, 1, 9, 1}};
int result = (p == 0) ? 1 : result[e % 10][p % 4];

Степенная функция определена для e > 0. Люди, которые знали, чему равно 0^0 давно покинули эту землю.

День 3.

1. Лифт.

return 3 - x;

Это решение не использует ветвления и требует только 1 машинную команду.

2. Горе от копирования.

Здесь возникает бесконечная рекурсия от того, что конструктор копирования явно вызывает operator =, а operator = неявно вызывает конструктор копирования, когда возвращает результат по значению.
Проблемы бы не возникло, если operator = возвращал бы ссылку.

Общая рекомендация: никогда не реализовывать конструктор копирования через operator =. Конструктор копирования должен работать сам по себе, а operator = иметь следущий канонический вид.

T& operator = (const T& other)
{
    T tmp(other);
    this->swap(tmp); // класс должен содержать метод swap, не генерирующий исключений.
    return *this;
}

3. Выскочка.

В задаче явно не указано, что массив нельзя менять. Те, кто предложил решение, не меняющее массив, получили дополнительные баллы.

Сперва решение, меняющее массив. Если бы не было ограничения на дополнительную память, то мы просто завели бы второй массив и отмечали в нем те числа, которые уже прошли.
Но у нас нет памяти. Значит будем отмечать на месте.
Числа имеют значения от 1 до N-1. Поэтому, если мы уже видели число, то будем менять его знак. Если встретилось отрицательное число, значит мы его уже видели:

int find_duplicate(int* array, size_t n)
{
    for (size_t i = 0; i != n; ++i)
    {
        int marked = abs(array[i]);
        if (array[i] < 0)
            return marked;
        else
            array[marked] = -array[marked];
    }
}

Потом можно пройти массив еще раз и поменять все отрицательные значения обратно на положительные, создав иллюзию, что массив не менялся.

Правильное решение данной задачи – алгоритм поиска циклов Флойда (зайца и черепахи). Будем рассматривать число в ячейке, как индекс следующей ячейки.
Т.е. наш массив – это описание графа. В нашем графе точно есть цикл, это задано условием.

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

int find_duplicate(int* array)
{
    int start = 0;
 
    int turtle = array[start];
    int bunny  = array[array[start]];	
 
    while (turtle != bunny)
    {
	turtle = array[turtle];
	bunny  = array[array[bunny]];
    }
 
    int turtle2 = start;
 
    while (turtle2 != turtle)
    {
	turtle = array[turtle];
	turtle2 = array[turtle2];
    }
 
    return turtle;
}


P.S. Продвинутый курс по С++ стартует уже в эту субботу: http://proglive.ru/courses/cpp2

Марафон C++ завершен.

Категория: Школа Программирования Автор: Семён Давыдов Опубликовано: 09-04-2012

Метки:

«…Я невозмутимо пошел дальше. Но, боясь, что пешком по гористой дороге идти будет тяжело, я заставил дорогу сделаться все более пологой и вдали наконец спуститься в равнину. Камни исчезли по моей воле, ветер затих и потерялся в вечере. Я шел хорошим шагом, и так как я шел с горы, я поднял голову, подобрался и скрестил руки на затылке. Поскольку я люблю сосновые боры, я шел через сосновые боры, а поскольку мне нравится молча смотреть на звездное небо, звезды всходили для меня на широко распростершемся небе медленно и спокойно, как то вообще им свойственно. Я видел лишь отдельные вытянутые облака, которые гнал ветер, дувший только на их высоте. Довольно далеко против моей дороги я поставил, вероятно, отделенную от меня рекой гору, вершина которой поросла кустарником и граничила с небом…»

Франц Кафка. «Описание одной борьбы»

Пока мы что-то делаем – мы меняем мир.

Я хочу поблагодарить всех участников марафона. Это очень интересно – смотреть за работой другого человека. И вдвойне интересно, когда у людей получается. Уверен, каждый из них вынес для себя что-то полезное и самим фактом участия продвинул себя немного вперед.

А победителя у нас два. Разрыв настолько же ничтожный, насколько субъективный, и я не могу отдать предпочтение. Эти двое – Юра Пермяков и Максим Новик.

Каждый из победителей получает скидку 50% на очный, либо онлайн-курс С++. Управление памятью, который стартует уже в эту субботу!

Юрий и Максим, для получения своего заслуженного подарка напишите письмо на support@prog-school.ru, либо позвоните +7 (495) 987-19-69

Разбор задач будет позднее. Хотя, про лифт расскажу сразу:

int switch(int value) { return 3 - value};