чем заменить цикл for
Вам не нужны циклы в JavaScript
Дата публикации: 2020-01-20
От автора: узнайте, как заменить циклы и использовать функции высшего порядка, такие как map, Reduce и Filter.
Почему мы заменяем циклы?
Использование функций высшего порядка сделает ваш код:
JavaScript. Быстрый старт
Изучите основы JavaScript на практическом примере по созданию веб-приложения
1. Перебрать все элементы и получить новый модифицированный массив
Примечание: если вы используете map, вы не можете ввести break или continue или return во время цикла. Для этого случая вы должны использовать every или some.
2. Перебрать все элементы и выполнить действие
3. Фильтрация массива
Используя стандартный цикл for:
JavaScript. Быстрый старт
Изучите основы JavaScript на практическом примере по созданию веб-приложения
4. Создание вывода с элементами массива
Приведенный выше код может быть еще более упрощенным:
5. Проверка, содержит ли массив значение
%c в операторе console применяет стиль к тексту консоли.
6. Проверить, соответствует ли каждый элемент в массиве условию
Используя цикл for:
Спасибо за прочтение. Надеюсь, вам это нравится.
Редакция: Команда webformyself.
JavaScript. Быстрый старт
Изучите основы JavaScript на практическом примере по созданию веб-приложения
JavaScript. Быстрый старт
Изучите основы JavaScript на практическом примере по созданию веб-приложения
Однострочный for на Python: списковое включение и генераторные выражения
Oct 31 · 4 min read
При создании коллекций элементов на Python циклы for заменяются однострочными выражениями. Python поддерживает четыре типа особенных генераторов, называемых также включениями:
Списковое включение
Синтаксис генератора списков устроен следующим образом:
Часть с условием if указывается опционально.
Пример
Давайте создадим список чисел, исключив из него все отрицательные значения — для начала решим задачу с помощью обычного цикла for :
Генератор словарей
Для быстрого, лаконичного и наглядного создания словарей язык программирования Python предлагает воспользоваться специальным сокращением для циклического перебора элементов, известным как “ генератор словарей”.
Синтаксис генератора словарей устроен следующим образом:
Пример
Давайте возведем в квадрат все числовые значения словаря при помощи словарного включения:
Генератор множеств
Генера т ор множества одновременно похож на словарное включение и на списковое включение: фигурные скобки, как у словарей, остальной синтаксис выражения — как у списков. Основное отличие генератора множеств от словарного включения заключается в том, что для генерации словаря указываются ключ и значение через двоеточие, а для генерации множества — одно только значение.
Синтаксис генератора множеств устроен следующим образом:
Пример
Давайте создадим список произвольных чисел и множество парных чисел на его основе:
При помощи генератора множеств подобная программа пишется в одну строчку:
Генераторные выражения
Синтаксис генераторных выражений следующий:
Пример
Давайте возведем в квадрат все четные числа списка и отброс им все нечетные.
Для начала решим задачу с помощью обычного цикла for :
С помощью выражения-генератора можно вообще забыть о потребности в функции square_even() и сделать то же самое с помощью одной строки кода:
Генератор кортежей
При взгляде на синтаксис генераторных выражений, сразу же в голову приходит мысль: как написать кортежное включение?
Генераторное выражение можно передавать в качестве параметра любой функции-конструктору стандартных типов данных Python:
Когда включения не подходят?
Только что вы узнали о четырех типах генераторов последовательностей в Python.
Теперь важно научиться избегать соблазна заменить все циклы for в ваших проектах на включения: давайте обсудим, в каких случаях генераторы последовательностей не подходят.
Короче говоря, не используйте включения, когда они снижают качество вашего кода!
Давайте рассмотрим матрицу; она часто представляется в Python как список из списков. Если вы хотите отобразить матрицу в одном измерении, то можете применить двойное списковое включение:
Код лаконичен, но, возможно, не так интуитивно понятно, что он делает: если вместо включения написать вложенный цикл for, то программа сразу станет более понятным:
Питонистический подход к циклам for: range() и enumerate()
Автор заметки, перевод которой мы сегодня публикуем, хочет рассказать о некоторых особенностях использования циклов for в Python.
Цикл for — это один из краеугольных камней программирования. С этими циклами будущие программисты знакомятся в самом начале учёбы и, после первого знакомства, пользуются ими постоянно.
Если вы занялись разработкой на Python, имея опыт работы с другим популярным языком программирования, вроде PHP или JavaScript, то вам знакома методика применения переменной-счётчика, хранящей, например, индекс текущего элемента массива, обрабатываемого в цикле. Вот пример работы с циклом, написанный на JavaScript:
Работая с циклами for очень важно понимать то, что эти циклы не перебирают массивы. Они лишь дают программисту механизм для работы с переменной-счётчиком, которая используется для обращения к элементам обрабатываемых массивов.
Старый (неудачный) способ работы с массивами
В результате вы можете обнаружить функцию range() и написать на Python нечто подобное следующему:
Проблема этого цикла заключается в том, что он не очень хорошо соответствует идеологии Python. В нём мы не перебираем список, а, вместо этого, используем вспомогательную переменную i для обращения к элементам списка.
Использование функции enumerate()
Эта функция принимает два аргумента: итерируемый объект и необязательное начальное значение счётчика.
Такой код получился гораздо чище кода из предыдущего примера. Мы ушли от работы со списком индексов, мы перебираем сами значения, получая к ним прямой доступ в цикле for, и видим значения, с которыми работаем, в объявлении цикла.
Итоги
Надеюсь, этот небольшой рассказ о циклах for в Python позволил вам узнать что-то новое об этом языке.
Превращаем рекурсию в цикл
Максим написал рекурсивный алгоритм, и столкнулся со Stack Overflow exception.
Зачем Максим это сделал?
Потому что он любит короткие и элегантные на его взгляд решения.
Он не наслаждается, когда пишет так:
Он хочет писать вот так:
Но когда он запускает подобные этому рекурсивные алгоритмы, бывает так, что он видит это:
Почему «элегантный» алгоритм не сработал?
Потому что в Javascript есть ограничение на глубину стека вызовов. Каждый вложеный вызов функции factorial кладёт в стек запись о вызове функции. Когда размера стека не хватает — возникает эта ошибка. В случае на картинке — ошибка вылетела при 10700+ вложенных вызовах.
Что делать Максиму?
Зависит от правильности алгоритма, размера задачи или стойкости его принципов.
Сначала он должен проверить, может быть, он ошибся. Подобные ошибки могут появляться когда алгоритм написан не правильно. Необходимо проверить, приходит ли каждый вызов функции к базе рекурсии или нет.
Если это не так, то нужно оценить размер задачи. Эта функция, может быть, никогда не будет вызвана на больших входных данных. В таких случаях пусть оставит рекурсивный алгоритм. Возможно, пометит границы применимости в комментарии к коду и достаточно.
Если же Максим не ошибся в алгоритме и данных достаточно много, то Максиму нужно заменить рекурсивный алгоритм итеративным.
Варианты замены рекурсивного алгоритма
Обычно рекурсивный алгоритм может быть заменён циклом и, если необходимо, вспомогательной структурой данных, чаще всего стеком.
В случае расчёта факториала алгоритм лучше заменить на циклический, описанный выше. Но существуют более сложные рекурсивные алгоритмы, где нужно использовать дополнительную структуру данных.
Метод «TODO-списка»
Я использую такую вспомогательную аналогию для того, чтобы представить рекурсивный алгоритм в форме цикла. Я представляю выполнение алгоритма как череду выполнения задач с одновременным планированием того, что необходимо сделать далее.
Например расчёт факториала можно реализовать так:
Сначала написали короткую документацию к этой функции.
Теперь решим эту задачу для не «тривиальных» случаев.
Для этого определим стек команд и переменную для результата.
Теперь нам необходимо запланировать несколько задач, которые наш алгоритм должен выполнить.
Теперь напишем реализацию этих команд в цикле, который исчерпывает стек задач.
Реальный пример более сложной рекурсии
Сергей решил занятся самообучением алгоритмам и решил написать нечто из раздела парсеров. Он решил, что парсером будет функция, которая принимает некоторый текст, и возвращает итератор по возможным результатам парсинга. Результатом парсинга является спарсеное значение и остаток строки, который не был использован при парсинге.
Так вот он хочет написать такую функцию many1 :
Она должна применить этот парсер один или более раз и вернуть все возможные варианты последовательных применений этого парсера.
Рекурсия
Решим с помощью рекурсии.
Со списком задач
Задача парсинга текста действительно может вызывать большую глубину рекурсии. Поэтому Сергею необходимо переписать этот алгоритм через цикл.
Вот как он это сделал:
Схема точно такая как для факториала: стек задач, и цикл, который их исчерпывает.
Здесь используется стек для хранения двух видов задач:
Послесловие
Я поделился своими аналогиями, которые могли бы применить абстрактные «Максим» или «Сергей» для того чтобы превратить рекурсию в цикл.
Расскажите, как вы превращаете рекурсию в циклы. Возможно, у вас есть свои аналогии? Или может вам они не нужны? Возможно вы бы решили задачу Сергея по-другому, расскажите как? Попадались ли вам рекурсивные алгоритмы в ваших проектах? Были ли случаи, где встречали Stack Overflow Error?
Очень интересно узнать ваш опыт и ваше мнение, особенно по задаче парсинга. Можно ли её решить без рекурсии, но более просто?
Как научить преодолевать трудности, а заодно и писать циклы
Несмотря на то, что речь пойдет об одной из базовых тем, данная статья написана для опытных специалистов. Цель — показать какие заблуждения бывают у новичков в программировании. Для практикующих разработчиков эти проблемы уже давно решены, позабыты или вообще не замечены. Статья может пригодиться, если вдруг вам придется помогать с этой темой кому-нибудь. В статье проводятся параллели с материалом из различных книг по программированию авторства Шилдта, Страуструпа, Окулова.
Тема про циклы выбрана потому, что на ней отсеивается довольно много людей при освоении программирования.
Данная методика рассчитана на слабых студентов. Как правило, сильные на этой теме не застревают и особенных методик для них придумывать не нужно. Второстепенная цель статьи — перевести эту методику из класса «работает на всех студентах, но только у одного преподавателя» в класс «работает у всех студентов, всех преподавателей». На абсолютную оригинальность не претендую. Если вы уже применяете похожую методику для обучения этой теме, напишите, пожалуйста, чем ваш вариант отличается. Если решите применить, расскажите по итогам, как все прошло. Если похожая методика описана в какой-нибудь книжке, напишите, пожалуйста, название.
Данную методику я отрабатывал 4 года, занимаясь индивидуально со студентами разного уровня подготовки. Всего около полусотни студентов и двух тысяч часов занятий. Поначалу на этой теме студенты навечно застревали и уходили. После каждого студента методика и материалы корректировались. Последний год студенты уже не застревают на этой теме, так что я решил поделиться наработками.
Зачем столько букв? Циклы это же элементарно!
Как я уже писал выше, для практикующих разработчиков и для сильных студентов, сложность концепции циклов может быть недооценена. Например можно устроить долгую лекцию, увидеть кивающие головы и умные глаза. Но при попытке решить какую-нибудь задачу, начинается ступор и необъяснимые проблемы. После лекции у студентов наверняка сложилось лишь частичное понимание. Ситуация усугубляется тем, что студенты не могут сами озвучить, в чем именно их заблуждение.
Однажды я осознал, что студенты воспринимают мои примеры как иероглифы. То есть как неделимые куски текста, в которых нужно дописать какую-то «магическую» букву и оно заработает.
Иногда я замечал, что студенты думают, что для решения конкретной задачи нужна какая-то еще конструкция, которую я просто еще не рассказал. Хотя для решения требовалось лишь немного модифицировать пример.
Поэтому я пришел к идее о том, что основное внимание нужно обращать не на синтаксис выражений, а на идею о рефакторинге повторяющегося кода с помощью циклов. Как только ученики осваивают эту идею, то любой синтаксис подтягивается путем небольших упражнений.
Кому и зачем я преподаю
Поскольку вступительных экзаменов нет, то на занятиях могут быть как сильные, так и очень слабые студенты. Более подробно о моих студентах можно почитать в статье Портрет слушателей вечерних курсов
Я стремился к тому, чтобы программирование осваивали все, кто этого хочет.
Мои занятия проходят индивидуально и студент платит свои деньги за каждое. Казалось бы, студенты будут оптимизировать затраты и требовать минимум. Однако люди ходят на очные занятия с живым преподавателем не за самими знаниями, а за уверенностью в том что они успели усвоить, за ощущением прогресса и за одобрением от эксперта (преподавателя). Если студенты не будут чувствовать прогресса в своем обучении, они будут уходить. В целом можно построить занятия так, чтобы студенты ощущали прогресс в увеличении количества знакомых конструкций. То есть сначала подробно изучаем while, потом изучаем for, потом do while и вот у нас готов курс на тысячу и одну ночь, в котором два месяца изучаются одни только циклы, а на выходе — студент, который под диктовку написал стандартную библиотеку. Однако для того, чтобы решать практические задачи, нужно не только знание материала, но и самостоятельность в его применении и в поиске новой информации. Поэтому для очных курсов считаю правильным принцип — научить минимуму и поощрять самостоятельное изучение нюансов и смежных тем. В теме про циклы, минимумом я считаю конструкцию while. На ней можно понять принцип. Зная принцип можно освоить и for и do-while самостоятельно.
Чтобы добиться освоения материала слабыми студентами, описать синтаксис недостаточно. Нужно давать побольше простых, но разнообразных заданий и расписывать примеры более подробно. В конечном итоге скорость освоения ограничивается способностью студента к преобразованию выражений и поиску закономерностей. Для сообразительных студентов, большинство заданий будут скучными. При занятиях с ними, можно не настаивать на решении 100% задач. Мой материал можно посмотреть на моем гитхабе. Правда репозиторий больше похож на гримуар чернокнижника — никто, кроме меня, не поймет что где находится, а если провалить проверку, то можно сойти с ума
Методика ориентирована на практику
Теория объясняется на примере решения задачи. На занятиях по основам программирования, где изучаются ветвления и циклы, просто не получится устроить полезную лекцию по одной теме на целый час. 15-20 минут хватает, чтобы объяснить концепцию. Основные сложности появляются при выполнении практических заданий.
Начинающие преподаватели могут вывалить операторы, ветвления, циклы и массивы за одну лекцию. Вот только студенты у них столкнутся с проблемой усвоения этой информации.
Нужно ведь не только рассказать материал, но и убедиться, что слушатели его поняли.
Факт усвоения темы определяется по тому, как студент справляется с самостоятельной работой.
Если студенту удалось решить задачу по теме без помощи преподавателя, значит тема усвоена. Чтобы обеспечить самостоятельную проверку, у каждой задачи описывается таблица с тестовыми сценариями. У задач есть ярко выраженный порядок. Пропускать задачи не рекомендуется. Если текущая задача слишком сложная, то к следующей переходить бесполезно. Она ещё сложнее. Чтобы студент мог осилить текущую сложную задачу, ему объясняется несколько приемов на примере первой задачи. Собственно, все содержание темы сводится к приемам преодоления трудностей. Циклы это, скорее, побочный эффект.
Первая задача всегда пример. Вторая отличается незначительно и выполняется «самостоятельно» сразу же после первой под присмотром преподавателя. Все последующие задачи направлены на то, чтобы обратить внимание на разные мелочи, которые могут вызывать заблуждения.
Объяснение примера представляет собой диалог, в котором у студента нужно вызывать back propagation и кросс-валидацию чтобы убедиться в усвоении порции материала.
Буду банален и заявлю, что первый пример по теме — очень важен. При наличии материала для обширной самостоятельной работы, упущения первого примера можно поправить. Если кроме примера больше ничего нет, то студент скорее всего не освоит тему.
While или for?
Один из спорных вопросов — выбор конструкции для примера: while или for. Однажды мой знакомый практикующий разработчик без опыта преподавания целый час убеждал меня, что цикл for — самый простой для понимания. Аргументы сводились к «в нем все понятно и по местам разложено». Однако первопричина затруднений настоящих новичков в самой идее цикла, а не в его написании. Если человек не поймет эту идею, то у него будут затруднения с синтаксисом. Как только идея осознана, то проблемы оформления кода исчезают сами.
В моих материалах тема циклов следует за темой про ветвления. Внешнее сходство if и while позволяет провести прямую аналогию: «когда условие в заголовке истинно, то выполняется тело». Особенность цикла лишь в том, что тело выполняется много раз.
Второй мой аргумент в том, что while требует меньше оформления, чем for. Меньше оформления — меньше глупых ошибок с пропущенными запятыми и скобочками. У новичков еще не настолько развита внимательность и дотошность, чтобы автоматически избегать синтаксических ошибок.
Третий аргумент — во многих хороших книгах while объясняется первым.
Если студенту удается легко преобразовывать выражения, то можно рассказать о for мимоходом. Студент дальше сам выберет что ему больше нравится. Если же преобразования вызывают затруднения, то лучше не рассеивать внимание. Пускай сначала студент решит все с помощью while. Когда тема циклов освоена, можно переписать решения, чтобы отработать преобразование while в for.
Циклы с постусловием — довольно редкий зверь. На него я время не трачу вообще. Если студент освоил идеи выявления закономерностей и преобразования выражений, то сможет разобраться без моей помощи.
При демонстрации первого примера сильным студентам, обращаю внимание на то, что в первом примере важно зафиксировать не только решение, но и всю цепочку действий, которые привели к результату. Ленивые студенты могут пренебречь писаниной и перенести себе только конечный алгоритм. Их нужно убедить в том, что однажды и для них попадется сложная задача. Для ее решения, понадобится идти по шагам как в этом примере. Именно поэтому важно зафиксировать все этапы. В следующих задачах можно будет оставить только финальный вариант решения.
Основная идея автоматизации в том, что мы поручаем компьютеру выполнять рутинную работу за человека. Один из базовых приемов — написание циклов. Он применяется когда в программе подряд пишется несколько одинаковых повторяющихся действий.
Явное лучше неявного
Ура, работает!
Ура, работает!
Ура, работает!
Ура, работает!
Ура, работает!
Ура, работает!
Ура, работает!
Ура, работает!
Такой вариант плох тем, что в выводе не видно значения счетчика. Это проблема для начинающих. Не стоит ее недооценивать. Поначалу эта задача была первой, а задача про вывод ряда чисел по возрастанию — второй. Приходилось вводить дополнительные термины «цикл N раз» и «цикл от A до B», которые по сути одно и то же. Чтобы не плодить лишних сущностей, я решил показывать только пример с выводом ряда чисел. Немногим удается без подготовки научиться держать в голове счетчик и моделировать поведение программы в голове. Некоторые студенты впервые сталкиваются с моделированием «в уме» именно на теме про циклы.
После некоторой практики, задачу на повторение одинакового текста я даю на самостоятельное решение. Если давать сначала видимый счетчик, а потом невидимый, то у студентов возникает меньше проблем. Иногда достаточно подсказки «не пиши счетчик на экран».
Как объясняется у других?
В большинстве учебных материалов в интернете, синтаксис цикла дается в составе «лекции». Например на developer.mozilla.org (в настоящий момент) вместе с циклом while описываются еще несколько конструкций. При этом даются исключительно сами конструкции в виде шаблонов. Результат их запуска описывается словами, а иллюстрация отсутствует. На мой взгляд, такая подача темы умножает на ноль полезность таких материалов. Ученик может переписать код и запустить его сам, но эталон для сравнения все равно нужен. Как понять, что пример переписан правильно, если не с чем сравнить результат?
Когда дается только шаблон, без примера, студенту становится еще сложнее. Как понять, что фрагменты кода расставлены в шаблоне правильно? Можно попробовать написать как-нибудь, а потом запустить. Но если нет эталона для сравнения результата, то запуск тоже не поможет.
В курсе по C++ на интуите синтаксис цикла закопан в третьей странице лекции 4 по теме «операторы». При объяснении синтаксиса циклов делают особый упор на термин «оператор». Термин подается в виде набора фактов вроде «символ; это оператор», «<> это составной оператор», «тело цикла должно быть оператором». Мне такой подход не нравится тем, что он как бы прячет важные взаимосвязи за одним термином. Разбор исходного кода программы на термы на таком уровне нужен разработчикам компиляторов для реализации спецификации языка, но никак не студентам в первом приближении. Новички в программировании редко обладают достаточной дотошностью, чтобы настолько внимательно относиться к терминам. Редкий человек запоминает и понимает новые слова с первого раза. Практически никто не может правильно применить термин, который только что узнал. Поэтому у студентов возникает куча ошибок вроде «написал while(a такт 10
такт 9
такт 8
такт 7
такт 6
такт 5
такт 4
такт 3
такт 2
такт 1
Подход с описанием шаблона, примера программы и результата работы этой программы используется также в книге «Javascript для детей» и в курсе js на w3schools.com. Формат веб-страницы даже позволяет сделать этот пример интерактивным.
В книге Страуструпа «Принципы и практика с использованием C++» 2016 г. автор пошел еще дальше. Первым делом объясняется какой результат должен получиться, а уже после этого — показывают текст программы. Причем в качестве примера берут не просто случайную программу, а дают экскурс в историю. Это помогает обратить внимание на нее «Смотри, это не просто какой то бесполезный текст. Ты видишь что то значимое».
В качестве примера итерации рассмотрим первую программу, выполненную на машине с хранимой программой (EDSAC). Она была написана Дэвидом Уилером (David Wheeler) в компьютерной лаборатории Кэмбриджского университета (Cambridge University, England) 6 мая 1949 года. Эта программа вычисляет и распечатывает простой список квадратов.
0 0
1 1
2 4
3 9
4 16
.
98 9604
99 9801
Здесь в каждой строке содержится число, за которым следуют знак табуляции (‘\t’) и квадрат этого числа. Версия этой программы на языке C++ выглядит так:
Любопытно, что шаблон синтаксиса в этой книге не описывается. Страуструп в руководстве инструктора (перевод) делает упор на то, что уважает интеллект своих студентов. Возможно умение выявить шаблон в нескольких примерах и считается проявлением такого интеллекта.
Как объясняю я сам
На этой задаче мы знакомимся с приемами решения сложных задач. Первоначальное решение нужно сделать примитивно и просто. Ну а затем можно подумать, как улучшить это решение.
Введение
Глава 1
Глава 2
Глава 3
Глава 4
Глава 5
Глава 6
Глава 7
Заключение
По моим наблюдениям, подход «шаблон-пример-результат» в разных комбинациях все равно приводит к тому, что студенты воспринимают цикл как иероглиф. Это проявлялось в том, что они не понимали зачем там писать условие, как выбирать между i++ и i— и прочие вроде бы очевидные вещи. Для избежания этих заблуждений, подход к рассказу о циклах должен подчёркивать смысл повторения одинаковых действий и только потом — оформление их с помощью конструкции. Поэтому прежде чем давать синтаксис цикла, нужно решить задачу «в лоб». Примитивное решение задачи про оглавление выглядит так:
Как его можно улучшить?
Заменить однообразные действия на цикл.
Какие действия тут повторяются подряд без изменений?
В этом фрагменте таких нет. Впрочем команды по выводу слова «Глава» с номером очень похожи друг на друга.
Поэтому следующий этап — поиск разницы между фрагментами. Это только в этой задаче все очевидно, потом повторяться будут не одиночные команды, а блоки кода по 5 строк и более. Искать придется не просто в списке команд, а конструкциях ветвления или цикла.
В примере разница между командами в числе после слова «Глава».
Как только разница найдена, нужно понять закономерность изменения. Отличающийся фрагмент это число? Оно постоянно увеличивается или уменьшается? Как меняется значение числа между двумя командами рядом?
В примере число после слова «Глава» увеличивается с шагом 1. Разница найдена, закономерность выявлена. Теперь можно заменить различающийся фрагмент на переменную.
Объявлять такую переменную нужно перед первым из повторяющихся фрагментов. Такую переменную обычно называют I или j или как-то более развернуто. Её начальное значение должно быть равно первому выводимому на экран значению. В примере первое значение это 1.
Какое начальное значение нужно взять для вывода ряда чисел «100, 101, 102, 103, 104, 105»?
В этом ряду первое число 100.
После каждой команды вывода нужно увеличить значение этой переменной на 1. Эта единица — шаг изменения.
Какой шаг будет в ряду чисел «100, 102, 104, 106»?
В этом ряду шаг 2.
После замены различающегося фрагмента на переменную, код будет выглядеть так:
После применения приема «выразить закономерность переменной» в коде получается несколько групп одинаковых действий, которые идут подряд. Теперь повторяющиеся действия можно заменить на цикл.
Далее вводится новые термины, чтобы студент не оказался в ситуации «все понимаю, но сказать не могу»:
— счётчик — всегда переменная, которая нужна для отслеживания количества шагов цикла. Обычно целое число, которое сравнивается с ограничением.
— шаг счётчика — описание закономерности изменения счётчика.
— ограничение — число или переменная, с которой сравнивается счётчик, чтобы алгоритм был конечным. Значение счётчика меняется так, чтобы приближаться к ограничению.
— тело цикла — набор команд, которые будут повторяться. Когда говорится «команда написана внутри цикла», то имеют в виду именно тело.
— итерация цикла — однократное выполнение тела цикла.
— условие цикла — логическое выражение, от которого зависит, будет ли выполняться ещё одна итерация. (Тут возможна путаница с конструкциями ветвления)
Нужно быть готовым к тому, что первое время студенты будут применять термины не по назначению. Это относится как к сильным, так и к слабым. Налаживание общего языка это целое искусство. Сейчас напишу кратко: нужно ставить задачу «выдели фрагмент кода с » и самому правильно использовать эти термины в разговоре.
После преобразования с циклом получается фрагмент:
Главное заблуждение
Одно популярное заблуждение студентов в том, что они помещают внутри конструкции цикла такие действия, которые нужно делать всего один раз. Например вот так:
Ученики постоянно натыкаются на эту проблему, как в начале, так и в более сложных задачах.
Коронная подсказка в этом случае:
Сколько раз нужно повторять написание команды: один раз или много?
Команды вывода слов «Введение» и «Заключение», а также объявление и инициализация переменной i не похожи на другие повторяющиеся действия. Они выполняются всего по одному разу, значит их нужно писать за пределами тела цикла.
В коде должны остаться все три этапа решения, чтобы потом ссылаться на них в случае затруднений. Первые два варианта достаточно закомментировать, чтобы они не мешали.
Внимание студента нужно обратить на следующие факты:
— В условии цикла обычно сравнивается счётчик и ограничение. Счётчик может меняться в теле цикла, а ограничение — нет. Чтобы нарушить это правило, нужно сформулировать веские причины.
— Команды для вывода слов «Введение» и «Заключение» находятся за пределами тела цикла. Нам их нужно выполнить 1 раз. «Введение» — до повторения действий, «Заключение» — после.
В процессе закрепления этой темы, освоения следующих, а также разбирательств с затруднениями даже сильным студентам полезно задавать вопрос: «А вот это действие сколько раз нужно выполнять? Один или много?».
Развитие дополнительных навыков
Чтобы понять, насколько быстро можно двигаться, нужно дать прочитать условия этих задач и спросить: «чем они отличаются от примера?», «Что нужно изменить в примере, чтобы решить их?». Если студент осмысленно отвечает, тогда пусть решит хотя бы одну на занятии, а остальные — дома самостоятельно. Если решение будет успешно, то можно начать объяснение про условия внутри циклов.
Если с самостоятельным решением затруднения, то нужно все отрабатывать на занятии. Чтобы решение задачи не напоминало рисование совы, я рекомендую сначала решить задачу не универсально. То есть так, чтобы решение проходило первый тест и не использовало конструкцию цикла. Ну а потом уже применять преобразования, чтобы добиться универсальности решения.
Циклы и ветвления
На мой взгляд, полезно дать тему «циклы внутри ветвлений» отдельно. Так, чтобы потом было видно разницу между многократной проверкой условия и однократной.
Задачи для закрепления будут про вывод чисел от А до В, которые вводятся пользователем:
— всегда по возрастанию.
— по возрастанию или по убыванию в зависимости от значений А и В.
К теме «ветвления внутри циклов» нужно переходить только после того, как студент освоил приемы: «замена закономерности на переменную» и » замена повторяющихся действий на цикл».
Главная причина применения ветвлений внутри циклов — аномалии в закономерности. В середине она нарушается в зависимости от исходных данных.
Тем студентам, которые способны искать решение путем комбинирования простых приемов, достаточно сказать «ветвления можно писать внутри циклов» и дать задачу «для примера» полностью на самостоятельное решение.
Задача для примера:
Пользователь вводит число Х. Вывести в столбик числа от 0 до 9 и поставить знак ‘+’ напротив того числа, которое равно Х.