Практика 4.2 — Счётчики, накопители, минимум и максимум


Задачи на for и таблицы трассировки с разбором

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

Упражнение 4.2.1 — Буквы в пароле

При регистрации на школьном сайте требуется пароль длины N. Не менее половины его символов должны быть латинскими буквами.

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

Учитывайте и заглавные буквы от 'A' до 'Z', и строчные от 'a' до 'z'.

Пример ввода:

6
D
6
v
7
U
2

Пример вывода:

Количество букв в пароле: 3
Пароль подходит

Проверьте также пароль нечётной длины. Например, при N = 5 двух букв недостаточно: как минимум половина означает не менее трёх букв. Подумайте, как проверить это без потери дробной части при целочисленном делении.

Упражнение 4.2.2 — Учёт собак

На ежегодной вакцинации в районе Шарон для каждой собаки вводят первую букву её имени, возраст в годах и обозначение категории:

  • R — породистая собака с документами;
  • L — породистая собака без документов;
  • M — собака смешанной породы.

Напишите программу, которая считывает данные 50 собак. Для каждой собаки выведите введённые данные, включая обозначение категории.

В конце выведите количество собак каждой категории и сообщите, какая категория встречалась чаще всего. Продумайте случай, когда несколько категорий имеют одинаковое наибольшее количество.

Упражнение 4.2.3 — Суммы цифр

Напишите программу, которая считывает 100 положительных четырёхзначных чисел. Для каждого числа выведите true, если сумма крайних цифр — тысяч и единиц — равна сумме средних цифр — сотен и десятков. Иначе выведите false.

Упражнение 4.2.4 — Загрязнение воздуха

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

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

Программа должна:

  • каждый день сообщать, превышает ли дневной показатель допустимый уровень;
  • вывести номер дня с наибольшим дневным показателем;
  • вывести номер дня с наименьшим дневным показателем.

Нумеруйте дни с 1. При равных крайних значениях укажите первый подходящий день.

Упражнение 4.2.5 — Метание копья

В соревновании участвовали семь человек. Для каждого участника известна дальность его броска.

Напишите программу, которая считывает семь расстояний и выводит:

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

Нумеруйте участников с 1. Если одинаковую крайнюю дальность показали несколько участников, укажите первого из них.

Упражнение 4.2.6 — Сбор на переработку

68 учеников двух десятых классов собирают пластиковые бутылки и батарейки для переработки. За каждый предмет класс получает баллы:

  • пластиковая бутылка — 3 балла;
  • батарейка — 7 баллов.

Для каждого ученика вводятся номер класса (1 или 2), количество собранных бутылок и количество батареек. Если предметов этого вида нет, вводится 0.

Напишите программу, которая выведет общий результат каждого класса, затем номер победившего класса либо сообщение «Ничья».

Упражнение 4.2.7 — Трассировка вложенных условий

Проследите выполнение программы для следующего ввода слева направо. Первое число задаёт количество последующих чисел:

5, 13, 10, 20, 18, 25
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int s = 0, n, a;
Console.WriteLine("Введите положительное целое число");
n = int.Parse(Console.ReadLine());

for (int i = 0; i < n; i++)
{
    Console.WriteLine("Введите положительное целое число");
    a = int.Parse(Console.ReadLine());
    if (a > 10)
        if (a >= 20)
            Console.WriteLine("boom");
        else
            s = s + a;
}

Console.WriteLine(s); // (**)
  1. Составьте таблицу с колонками для всех переменных, каждого условия и вывода.
  2. Приведите пример ввода, при котором команда, отмеченная (**), выведет 0.
Проверка трассировки

После первого ввода n = 5, а s = 0. Перед каждой итерацией выводится приглашение ввести число. В таблице ниже колонка «Вывод тела» показывает дополнительный вывод после этого приглашения.

i n i < n a a > 10 a >= 20 s после тела Вывод тела
0 5 true 13 true false 13
1 5 true 10 false Не проверяется 13
2 5 true 20 true true 13 boom
3 5 true 18 true false 31
4 5 true 25 true true 31 boom
5 5 false 25 Не проверяется Не проверяется 31

После цикла выводится 31. Обратите внимание: else относится к ближайшему if (a >= 20), поэтому в сумму входят только числа строго больше 10 и строго меньше 20.

Пример для итогового вывода 0: 3, 10, 20, 25. Здесь n = 3, и ни одно из следующих чисел не попадает в диапазон от 11 до 19.

Упражнение 4.2.8 — Полный квадрат и ошибочная проверка

Полный квадрат — неотрицательное целое число, которое можно получить возведением целого числа в квадрат. Например, 16 — полный квадрат, потому что 4 * 4 = 16.

Часть 1. Объясните ошибку

Следующий код не подходит для определения всех полных квадратов:

1
2
3
4
5
6
7
8
9
10
11
12
int s = 0, num;
for (int i = 1; i <= 5; i++)
{
    num = int.Parse(Console.ReadLine());

    if (num == Math.Pow(i, 2))
    {
        s += num;
        Console.WriteLine(num);
    }
}
Console.WriteLine(s);

Объясните, в чём ошибка. Составьте таблицу трассировки для вводов 3, 4, 5, 16, 6, именно в этом порядке. Включите введённое число, i, Math.Pow(i, 2), результат сравнения и s после итерации.

Решение: подробная и сокращённая таблицы

Подробная таблица

Пустая ячейка означает, что на этом шаге значение не изменилось или команда не выполнялась.

Строка кода i num num == Math.Pow(i, 2) s Вывод
1       0  
2–4 1 3      
6     false    
2–4 2 4      
6     true    
8–9       4 4
2–4 3 5      
6     false    
2–4 4 16      
6     true    
8–9       20 16
2–4 5 6      
6     false    
2: последняя проверка i <= 5 6        
12         20

Сокращённая таблица

Можно объединить действия одной итерации в строку, если при этом видно, что изменилось и почему:

Ввод num i Math.Pow(i, 2) Результат сравнения s после тела Вывод тела
3 1 1 false 0
4 2 4 true 4 4
5 3 9 false 4
16 4 16 true 20 16
6 5 25 false 20

После цикла выводится итоговая сумма 20.

Почему алгоритм неверен

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

Например, если первым ввести 9, то при i = 1 сравнение с Math.Pow(1, 2) даст false, хотя 9 = 3 * 3 — полный квадрат. Правильная проверка не должна зависеть от номера ввода.

Часть 2. Исправьте проверку

Напишите программу, которая генерирует десять целых чисел от 1 до 20 включительно и для каждого сообщает, является ли оно полным квадратом.

Создайте один объект Random перед циклом и используйте его для всех десяти чисел. Верхняя граница Next не включается, поэтому для диапазона от 1 до 20 нужна запись rnd.Next(1, 21).

Пример решения
Random rnd = new Random();

for (int i = 0; i < 10; i++)
{
    int num = rnd.Next(1, 21);
    int root = (int)Math.Sqrt(num);

    if (root * root == num)
        Console.WriteLine($"{num} — полный квадрат");
    else
        Console.WriteLine($"{num} — не полный квадрат");
}

Math.Sqrt возвращает квадратный корень. Приведение к int оставляет целую часть положительного результата. Проверка root * root == num определяет, восстанавливает ли эта целая часть исходное число. Для указанного небольшого диапазона это удобный способ проверки.

Дальше