Форум » Обработка числовых последовательностей » C4 задача 38 » Ответить

C4 задача 38

oval: в операторе [quote] if X > Xprev then L := L + X – Xprev; { изменяем высоту подъема } if L > LMax then LMax := L; end else L := 0; [/quote] не хватает begin [quote]while True do begin readln(X); { читаем число } if X = 0 then break; ................ end; [/quote] такой выход из цикла разве не является "Грязным хаком"? на мой взгляд плохо продумана логика алгоритма Вот другой вариант решения [quote] var X, Xtn, Xt, N, LMax: integer; {X - очередное число, Xtn - предыдущее число, Xt - первое число в подъеме} begin N := 0; LMax := 0; Xt := 0; Xtn := 0; repeat readln(X); if Xt = 0 then Xt := X; {выполнится один раз для первого числа, возможно, оно будет первым в подъеме} N:= N + 1; if X < Xtn then {если X < Xtn, то Xtn последнее число в подъеме} begin if Xtn - Xt > LMax then LMax := Xtn - Xt; Xt :=X; end ; Xtn:=X; until x = 0; writeLn('Получено ', N-1, ' чисел'); { 0 не входит в последовательность} writeLn('Наибольшая высота подъема ', LMax); end. [/quote]

Ответов - 4

Поляков: oval пишет: не хватает begin Спасибо, конечно так. такой выход из цикла разве не является "Грязным хаком"? :-) Это предмет споров. Обычно "грязный хак" - это использование недокументированных возможностей. Здесь такого нет. Я обсуждал этот вопрос со многими специалистами, неизменно приходили к таким выводам: 1) да, "высокая теория" не рекомендует так делать рад "чистоты" кода (из цикла должен быть только один выход) 2) в то же время в промышленном программировании такой прием применяется постоянно. Почему же так происходит? Дело в том, что это цикл, в котором необходимость продолжения действия определяется в середине тела цикла (после того, как отработал оператор read), не в начале, и не в конце. Поэтому, строго говоря, использование while и repeat тут не очень удобно. Можно, конечно, но получается обычно менее прозрачно, чем с break. Итак, прочитали 0. Нужно сразу закончить цикл, что и делает break. Естественно, можно поставить ветвление if (X>0) ..., но это фактически то же самое, что и break. Если не делать ни того, ни другого, и использовать repeat-until, нужно обязательно проверять, как это нулевое значение "протащится" через оставшуюся часть тела цикла, не будет ли побочных эффектов. А зачем, собственно? Чтобы соблюсти "чистоту"? Можно поставить выход через break, и логика программы станет понятной. Так что, я всегда выберу удобство и понятность вместо слепого следования "правилам".на мой взгляд плохо продумана логика алгоритма Пожалуйста, изложите конкретные претензии. Для меня эта логика естественна. За что тут могут снизить балл на ЕГЭ, я не знаю. Вот другой вариант решения Тоже вариант. Но я достаточно долго соображал, как будет проходить завершающий 0 через остаток цикла.

oval: Поляков пишет: За что тут могут снизить балл на ЕГЭ, я не знаю. на ЕГЭ балл не снизят, но своим детям я такое решение не зачту в крайнем случае выход через булевскую переменную while not(end_posl) do begin readln(X); { читаем число } end_posl:=X=0; ................ end; хотя, действительно, это вопрос только "чистоты" кода как будет проходить завершающий 0 через остаток цикла 0 конец ввода, и соответственно, конец последнего подъема, проверяем его высоту

Поляков: oval пишет: действительно, это вопрос только "чистоты" кода То есть, чисто религиозный. :-) Мне наоборот кажется, что решение с логической переменной "кривое", хотя соответствует формальным признакам "кошерности". Я так никогда не напишу, если в языке есть break. Тут выбор между следованием "идее" и понятностью кода. "Каждый выбирает для себя..." (Ю. Левитанский) Возможно, это недостаток моей логики и стиля мышления.


Поляков: Продолжение банкета - тут.



полная версия страницы