Search
Write a publication
Pull to refresh
35.17
CodeAbbey
Веб-сайт с задачами по программированию

Нужен ли код в книге Занимательных Задач по программированию?

Reading time11 min
Views1.5K

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

А как же наш любимый программизьм? :) Мне известно не так много примеров. Зачем вообще программисту задачи? Для начинающего актуально, конечно, на них "нарабатывать практику" (или когда уже не новичок но осваивает новый для себя язык программирования) - но не только это. Задачки кроме того дают идеи. Программисты же народ творческий и хотя бы подсознательно постоянно в поиске идей.

Когда на сайте у меня количество задач перевалило за 400, пришло на ум что можно их собрать под одной обложкой - для любителей поразмышлять в отрыве от компьютера. Идея эта однако встала на паузу - но недавно мне о ней напомнили. Коллега с Хабра предположил возможность издания подобной книжки на русском языке.

Один из вопросов по которому мы не нашли пока консенсуса - размещение в подобной книжке "решений". Поэтому обращаюсь за помощью к общественности, к коллегам-айтишникам в первую очередь - ниже будет немного подробностей и примеров задач, по разделам - и опрос, насчет того в каком виде нужны (или не нужны) эти самые решения.

Общие замечания

Сайт и задачи о которых речь НЕ относятся в большинстве своём к "олимпиадному" или "спортивному" программированию. Наоборот они в большинстве своём достаточно простые, нацеленные больше "на широту, чем на глубину" - чтобы дать практику, м.б. развлечение - и по возможности познакомить с какими-то не очень известными вещами из нашей отрасли.

Они условно разделены на такие разделы:

  1. Простые задачи - то что подходит для новичков, школьников - или когда только-только знакомишься с новым языком.

  2. Задачи на реализацию - тоже несложные, но более объёмистые, чтобы можно было минимально хотя бы задуматься над композицией и декомпозицией кода и т.п.

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

  4. Головоломки - тут собрались задачи в которых решение быть может неочевидно или очевидное решение оказывается ошибочным, а может неэффективным. Иногда нужно вспомнить подходящий алгоритм - но часто просто додуматься с какой стороны подойти. Здесь немало задач присланных пользователями.

  5. Специальные - сюда попали задачи на Брейнфак и SQL, на машину Тьюринга и Ассемблер для intel-4004, игры с сервером по HTTP и всякое такое.

Почему решения в виде кода кажутся нежелательными:

  • сейчас много популярных языков - и книжка с примерами на Python или C++ вызовет легкое разочарование у тех кто использует Go или Java например

  • решения задач кроме простейших могут быть довольно объёмны - и раздувать книжку за счет листингов программ - выглядит нехорошо по отношению к читателю

  • не всем нам нравятся объяснения решений в виде кода - программисты не так уж любят вчитываться чужой код (хотя и приходится заниматься этим постоянно)

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

Итак, посмотрим на сами примеры - каким из них "решения" вообще актуальны.

Раздел "Простые Задачи"

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

СУММА "А+B" (#1)

Подобная "задача" это что-то вроде традиции, не будем нарушать её и мы. Она позволит проверить что мы хотя бы понимаем как собрать и запустить программу, как ввести числа с консоли (а не вбивать, "хардкодить" их прямо в тексте).

Пример:
входные данные:
355 113
ответ:
468

СУММЫ В ЦИКЛЕ (#3)

Теперь у нас несколько пар чисел - и мы хотим вывести сумму каждой пары. Нужно просто "обернуть" предыдущую программу в цикл. В первой строке указано количество пар, а сами они идут дальше, по паре на строку.

Пример:
входные данные:
3
100 8
15 245
1945 54
ответ:
108 260 1999

СУММА В ЦИКЛЕ (#2)

Небольшая модификация предыдущей задачи - теперь мы хотим найти общую сумму всех чисел поданных на вход. По хорошему нужно завести дополнительную переменную для накопления результата. В то же время, даже если вы уже знаете что такое массив, имейте в виду что он здесь не нужен (хотя в языке вроде Python трудновато от него избавиться). В первой строке указано количество чисел для суммирования, во второй сами числа.

Пример:
входные данные:
8
10 20 30 40 5 6 7 8
ответ:
126

ОКРУГЛЕНИЕ (#6)

В некоторых задачах нам нужно будет округлять ответ до целого. Оказывается, существует несколько способов сделать это - и нам нужно выбрать какой-то один, чтобы не запутаться. Будем использовать тот, которому учат в школе:
- если дробная часть абсолютной величины числа меньше 0.5, то округляем "в сторону нуля" (фактически, отбрасывая дробную часть)
- в противном случае округляем "от нуля" - к ближайшему целому бОльшему по модулю.
Заметим что в некоторых языках (в частности, в Python) встроенная функция округления работает немного иначе (так называемое "банковское" округление), поэтому возможно удобнее окажется встроенную функцию не использовать.

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

Пример:
входные данные:
3
12 8
11 -3
400 5
ответ:
2 -4 80

РЕШЕТКА ИЗ ШЕСТИУГОЛЬНИКОВ (#73)

Во многих играх вроде пошаговых стратегий заметно что персонажи двигаются по "гексагональной" решетке (например в режиме битвы в классических Heroes of Might and Magic) - она улучшает "изотропность" игрового поля - и вообще красивее выглядит - но немного сложнее для программирования. В этой задаче мы попрактикуемся с ней!

Представьте что персонаж стоит в ячейке обозначенной X. Ему доступны шаги в 6 направлениях. Направление A означает шаг непосредственно вправо, а остальные (B, C, D, E, F) - против часовой стрелки от него. Вам будет задана последовательность ходов, обозначенных соответствующими буквами - и требуется в качестве ответа указать расстояние между начальной и конечной точкой (по прямой, то есть в "Евклидовом" смысле), считая расстояние между центрами соседних ячеек (то есть величину шага) за единицу.

Входные данные содержат количество "тесткейсов" в первой строке. Остальные строки содержат сами "тесткейсы" - каждый в виде строчки ходов, для которой нужно посчитать указанное расстоние по прямой. Ответ достаточно представить с точностью до 1e-7.

Пример:
входные данные:
3
AABF
FEDCBA
BCB
ответ:
3.0 0.0 2.64575131

Задачи на реализацию

Как упоминалось, здесь задачи тоже несложны, но более объёмны - поэтому и условия могут содержать довольно длинные объяснения. Конечно, если вы знаете, например, правила описываемой игры, при первом прочтении необязательно скрупулёзно их перечитывать.

КРЕСТИКИ-НОЛИКИ (#46)

На этот раз мы ещё не собираемся писать компьютерного “оппонента” для известной игры, но сделаем важный шаг на пути к этому – научимся определять, завершается ли игра очередным ходом, или нет. Как вы вероятно знаете, игра происходит на поле 3x3 клетки. Предположим что они пронумерованы следующим образом:

    1 | 2 | 3
   ---+---+---
    4 | 5 | 6
   ---+---+---
    7 | 8 | 9

Игроки по очереди ставят свои отметки (крестики “X” или нолики “О”) в ещё не занятые клетки. Тот кто очередным ходом “достраивает” линию из трёх своих отметок (по горизонтали, вертикали или диагонали – всего 8 возможных линий) – тот и выиграл. Например если игроки ходят по очереди в клетки с такими номерами:

7 (x), 5 (o), 4 (x), 1 (o), 9 (x), 2 (o), 8 (x)

То на поле получится такая позиция:

    O | O | 
   ---+---+---
    X | O |
   ---+---+---
    X | X | X

Очевидно, первый игрок (крестики) выиграл последним ходом (в клетку 8).

Входные данные содержат несколько строк, описывающих несколько игр, в виде последовательностей ходов. Общее число игр (N) указано в самой первой строке. Ответ должен содержать N чисел, указывающих, на каком ходу была выиграна каждая из игр (0 означает что игра закончилась вничью).

Пример:
входные данные:
3
7 5 4 1 9 2 8 3 6
5 1 3 7 6 4 2 9 8
5 1 2 8 6 4 7 3 9
ответ:
7 6 0

ФРОДО И ЧЁРНЫЕ ВСАДНИКИ (#182)

Идея этой задачи возникла из предложения пользователя Laurent Petit на форуме.

В первой части книги “Властелин Колец” есть леденящая кровь сцена когда хоббит Фродо со своими спутниками прячутся от Чёрных Всадников из Мордора, которые догнали их по дороге из Хоббитона в Брыль.

Представим себе, что всё это происходит на квадратном пространстве, размером 100 на 100 ярдов. В нём присутствуют несколько Чёрных Всадников, пытающихся отыскать несчастных хоббитов. Каждый из Чёрных Всадников имеет ограниченное поле зрения – такую, как показано на картинке.

Предположим, Всадник стоит в точке (0, 0) и смотрит вдоль оси X. Конечно дальше всего он видит по направлению “вперед” – однако он может ограниченно чувствовать и присутствие теплокровных существ позади. В общем, граница где хоббит будет обнаружен, определяется простым уравнением в полярных координатах:

R = 20 + 15 * cos(theta)

Здесь theta – угол между направлением на заданную точку (в частности, хоббита) – и направлением взгляда Всадника. Например, если Всадник смотрит вдоль оси Y, а хоббит прячется в точке (30,30) – тогда он в безопасности (theta = pi/4), но если он ближе, в точке (10,10), то Всадник легко обнаружит беднягу...

Ваша задача – приблизительно оценить процент “безопасной территории” в квадрате, при заданном размещении всадников.

Входные данные содержат количество Всадников в первой строке (N=4..6) – а следующие строки содержат тройки чисел – координаты и угол в радианах (направление в котором ориентирован всадник).

Ответ должен содержать N+1 чисел. Сперва – процент площади которую не просматривает ни один Всадник. Далее процент площади которую контролирует только один Всадник, затем площадь под контролем какой либо пары Всадников и так далее. Значения округлить до целых чисел.

Пример:
входные данные:
4
20 81 0.6
39 35 0.5
90 16 -1.5
85 20 -1
ответ:
63 31 7 0 0

ИГРА "ЗМЕЙКА" (#96)

Эта игра, также называемая “червяк”, известна ещё с 1970-х годов: змейка ползает по прямоугольному полю, собирая “еду” и стараясь избежать столкновений с границами поля или с самой собой.

В этой задаче нужно написать программу эмулирующую такую игру. На поле “разбросаны” фрукты, и задана последовательность движений “змеи”. Требуется выполнить эти движения и определить, на каком ходу змея “врежется” в себя.

Начальное состояние поля подаётся на вход программы в виде прямоугольника 21 на 13 ячеек, например:

   X X X - - - - - $ - - - - - $ - - $ $ - -
   $ - - - - - - - - $ - - $ $ - - $ - $ - -
   $ - - $ - $ $ - - - - - - - $ - - - - - -
   - $ - - $ - - $ - - - - - $ $ $ $ $ - $ $
   $ - - - $ $ - - - - - - - - - - - $ - - -
   - $ $ - - - - - - - - - - - - $ - - - - $
   $ - - - - - - - - $ - - - - - $ $ - - - -
   $ - - - $ - - $ $ - - - $ - $ $ - - - - -
   - - - - $ $ - - - - - - $ $ - - - - - - $
   - $ - - - $ - - - - - - - $ - - - - $ - $
   - - - - - $ - $ - - - - - $ $ - - - - - -
   - - - - - $ - - $ - - $ - - - - - - - - $
   - - $ - - $ - - - - - - $ - - - $ - - $ -

Змея изначально всегда находится в левом верхнем углу и имеет длину 3 и направлена вправо. Последовательность движений подаётся на вход в таком виде:

12 D 4 L 10 U 1 R 6 D 7 R 9 U 9 L 16

Это следует читать так: сделать 12 шагов, сменить направление (D – вниз), сделать ещё 4 шага, сменить направление (L – влево), сделать ещё 10 шагов, сменить направление (U – вверх), сделать 1 шаг, сменить направление (R – вправо) и так далее. Заметим, что смена направления не считается отдельным ходом.

Каждый ход заключается в том что “голова” змеи сдвигается на 1 клетку в текущем направлении (лучше сказать “наращивается”). В то же время “хвост” укорачивается на 1
клетку. Если при данном ходе “голова” попала на место где лежал фрукт (они обозначены символом $), то фрукт считается съеденным, а длина змеи увеличивается на единицу (клетка в хвосте не стирается на этом ходу).

Ответ должен содержать координаты клетки где произошло столкновение и номер хода, на котором оно случилось. Координата верхнего левого угла (0, 0).

Пример:
входные данные:
X X X - $ - - $ $ - $ $ $ - - - - - - - $

- - - $ - - - - - - - $ - - - - - $ $ $ -
$ $ $ - - - - - $ - - - - $ $ - - - - $ $
- $ - - - - - - $ $ - - - $ - - $ - - - -
- $ $ - - - - $ - - - $ - - - - - - - - -
$ - - $ - - $ - - $ - $ - - - - - - - - -
- - - - - $ - - - - - - $ - - - - $ - - $
- - - - - $ $ - $ - - $ - - - - $ $ - - -
- $ - - - - - $ - $ - $ - - - - - - $ - -
- $ $ - $ - - - - - - - $ - - - $ - $ - $
- - - - - - - - - - - - - - $ $ $ - - - -
- - - $ - - - - - - - - - $ - - - $ - - $
- - - - - - - - - $ - - - - - - $ $ $ - -
5 D 1 L 1 U 1 L 3
ответ:
6 0 8

Популярные Алгоритмы

ПЬЕР ФЕРМА ВЗЛАМЫВАЕТ ШИФР RSA (#153)

Если после решения задачи на реализацию ассиметричного шифрования RSA (#152) у вас осталось не очень чёткое представление о надёжности этого алгоритма, давайте рассмотрим следующу возможную "атаку" на него.

Вновь нужно расшифровать сообщение, но теперь мы не знаем p и q, а только их произведение n - именно в такой ситуации находится потенциальный взломщик. Шифрование всё равно можно осуществить используя e=65537 но к сожалению мы не знаем показатель степени d необходимый для расшифровки!

Мы заподозрили что человек, выбиравший ключи, был новичок в своём деле, и для удобства взял достаточно близкие значения p и q так что, вероятно, можно их найти попытавшись разбить n на множители.

Ферма не зря упомянут в названии задачи - скорее всего его алгоритм факторизации чисел понадобится вам как вспомогательная часть в решении данной проблемы. Его вы легко найдёте в интернете.

Преобразование чисел в данные осуществляется тем же способом как и в предыдущем упражнении. Входные данные содержат n в первой строке, во второй будет шифр, сгенерированный как a ^ 65537 % n, где a есть исходное сообщение, преобразованное в длинное целое. Ответ должен содержать расшифрованное сообщение.

Пример:
входные данные (длинное число разбито на несколько строк):
input data:
2005386240811006492510206908835874977464399827995998174235015291258
133373258958037573585627258926557618335589879504876460462075566
410747651590614428022205934562315249635550863811428
ответ:
EGG EAT SKI SHY ARM EON HIP FUN LOW

Головоломки

В этом разделе собрано больше 100 задач - все они требуют сначала немного подумать. Некоторые задачи могут быть решены неэффективным путём (полный перебор и пр) - что мы абсолютно не запрещаем вам попробовать (даже если ваш код будет работать несколько часов - невольно начинаешь уважать компьютер!) - но при этом всегда приветствуется если вы вернётесь к такой "неэффективно решённой" задаче в будущем, и сообразите как сделать лучше. Иногда для этого требуется какой-нибудь полезный алгоритм - но чаще просто смекалка.

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

ПАCХАЛЬНЫЕ КРОЛИКИ (#259)

Эту задачу предложил пользователь Mathias Kern

Вы познакомились с семейством Пасхальных Кроликов - все они забавные одномерные создания - и занимаются тем что особым образом размещают Пасхальные Яйца в одномерном массиве с ячейками, пронумерованными индексами 1, 2, 3, ...

Каждый из Кроликов характеризуется собственной длинной прыжка и оставляет в каждой посещённой ячейке массива яйцо, если его там не было. В противном случае он наоборот ворует яйцо из ячейки. Вот жадина!

У первого Крлика длина прыжка равна 2, и он оставляет яйца в ячейках 2, 4, 6, 8, 10, 12...

Второй кролик с длинной прыжка 3 оставляет яйцо в ячейке 3, ворует яйцо из ячейки 6, оставляет яйцо в ячейке 9, ворует из ячейки 12 и так далее.

Третий кролик, прыгая в каждую 4 ячейку, ворует из ячеек 4 и 8, оставляет яйцо в ячейке 12 и так далее.

Задача в том, чтобы для массива размера N определить сколько яиц в нём останется после того как по нему проскачут все кролики с длиннами прыжков от 2 до N. Значение N не более нескольких миллиардов.

Входные данные содержат несколько чисел N - разные размеры массивов для которых нужно решить задачу (просто разбейте строчку по пробелам). Ответ должен содержать столько же чисел - количество яиц оставшихся в каждом из массивов после посещения кроликами.

Пример:
входные данные:
3 8 15 97
ответ:
2 6 12 88

Специальные задачи

В этом разделе собраны задачи которые нужно решить на указанном языке (например, упражнения по SQL или головоломки на Brainfuck), игры в которых нужно написать код "сражающийся" против сервера и т.п.

САМОПЕЧАТАЮЩАЯСЯ ПРОГРАММА (#286)

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

ПОСЛЕДОВАТЕЛЬНОСТЬ КВАДРАТОВ НА БФ (#126)

Упражнение на языке Brainfuck - напишите программу, которая получает на вход число X - и печатает квадраты чисел от 1 до X.

В этой задаче можно использовать дополнительные "фичи" версии BF используемой на сайте:
: - эта команда печатает число из текущей ячейки на стандартный вывод
; - эта наоборот считывает число в текущую ячейку со стандартного ввода
# - копирует число из текущей ячейки на верхушку встроенного стека
$ - выталкивает число из стека в текущую ячейку

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

Пример:
входные данные:
5
ответ:
1 4 9 16 25

ВЕБ-СКРЕЙПЕР ДЛЯ СОЦСЕТИ (#160)

За идею этой задачи благодарю мою коллегу Жанну Хаймеддинову

В современном интернете очень много информации. И неудивительно что информация предназначенная для людей часто извлекается и обрабатывается также и роботами.

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

Начните со страницы пользователя по имени John Doe:
http://codeabbey.github.io/social-network/

Вы увидите что на каждой странице есть данные о дате рождения человека и его состоянии. Также видно, что можно перейти на страницы связанных с ним людей по ссылками. Например от John Doe можно перейти к Dan Wagner (через "Друзей") а отсюда к Dave Johnson (через "сообщения на стене").

Задача заключается в том чтобы посчитат суммарное состояние (в долларах) всех людей с заданной фамилией (например, Johnson), которых можно "достать" с исходной через любое количество ссылок.

Общий путь решения может быть таким:

  • напишите функцию скачивающую страницу по ссылке

  • напишите функцию извлекающую другие ссылки из скачанной страницы

  • также напишите код для извлечения фамилии и данных о состоянии

  • теперь сделайте цикл который обходит "социальный граф" (ориентируйтесь на подходящие задачи из раздела по алгоритмам)

  • останется только сложить значения для людей с заданной фамилией

Пример:
входные данные:
doe
ответ:
130000

Заключение

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

Only registered users can participate in poll. Log in, please.
В каком виде нужны решения, если нужны
22.58% Обязательно код на Python к каждой задаче7
19.35% Обязательно код на C++ к каждой задаче6
38.71% Обязательно псевдокод к каждой задаче12
25.81% Код скорее всего не нужен нигде. Секции с текстовыми подсказками будет достаточно.8
19.35% Псевдокод тоже не особо нужен. Я не люблю псевдокод.6
3.23% Код, быть может, и пригодился бы, но я не пишу на Python или C++1
0% Да и сами эти задачи никому не нужны :) Бросьте вы эту затею0
51.61% Идея книжки мне нравится16
31 users voted. 4 users abstained.
Tags:
Hubs:
Total votes 1: ↑1 and ↓0+2
Comments3

Articles

Information

Website
www.codeabbey.com
Registered
Founded
Employees
1 employee (me only)
Representative
Родион Горковенко