Интересная задачка по программированию

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

Задача

Перебрать все целые числа на заданном отрезке с заданным шагом, не используя операторы ветвления (if, if-else, switch-case…), операторы цикла (for, while, do-while…) и операторы безусловного перехода (goto, break…). Также нельзя генерировать и выполнять код во время выполнения программы, то есть в JavaScript, например, вам нельзя использовать функцию eval.

Язык программирования можете взять любой. Я выбрал JavaScript.

Примеры такого перебора. В данном случае это просто вывод всех перебираемых чисел на консоль. (Реализация функции iterate, естественно, пропущена):

// от 0 до 5 с шагом 1
iterate(0, 5, 1, console.log); // 0, 1, 2, 3, 4, 5
 
// от 0 до 10 с шагом три
iterate(0, 10, 3, console.log); // 0, 3, 6, 9
 
// от 5 до -5 с шагом -2
iterate(5, -5, -2, console.log); // 5, 3, 1, -1, -3, -5
 
// от 3 до 3 с шагом 2
iterate(3, 3, 2, console.log); // 3
 
// от 3 до 0 с шагом 2
iterate(3, 0, 2, console.log); // не выведет ничего

Подсказки

Смотреть по порядку!

Решение

Рассмотрим сначала, как вычисляется значение переменной hasNext, значение которой показывает, нужна ли следующая итерация или нет. Нас интересуют два случая:

  • Когда число, с которого начинается перебор, меньше чем число, которым он заканчивается, и шаг перебора больше нуля.
  • Когда число, с которого начинается перебор, больше чем число, которым он заканчивается, и шаг перебора меньше нуля.

В остальных случаях перебор даже не должен начаться.

Осталось только для случаев 1 и 2 проверить не вышел ли текущий элемент за границы перебора.

Теперь, когда известно, нужна ли следующая итерация или нет, сымитируем поведение условного оператора (см подсказку 2): код после операнда hasNext не выполнится, если значение hasNext будет равно false, так как в этом случае значении всего выражения заведомо известно, и так же равно false

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

Жду ваших решений

Если вы придумали своё решение и хотите им поделится, то милости прошу. Только не спойлерите – другим, возможно, тоже захочется подумать. Воспользуйтесь для размещения кода какими-нибудь сервисами, например, gist или pastie, и приведите в комментарии только ссылку.

Успехов вам. Разминайте мозги!