Начала Паскаля: линейные программы, целые и вещественные типы

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

Дааа... Косяк :(

Спасибо, что заметили

Я пока отвлёкся, Вы всё уже

Я пока отвлёкся, Вы всё уже правильно разрешили. Вопрс с правильностью открыт.

Евгений всегда

Евгений всегда пожалуйста!
Попробую снова вернуться к вашей подсказке Валерий Шахамболетович,меня терзает смутное сомнение,но помоему надо еще что-то увидеть...

Завтра попробую дорешать если успею

Родители гонят из-за комьютера

.

Извините, но не понимаю почему тип именно word, а не int? Если вводятся в условии нат. числа.

Натуральные числа-это числа

Натуральные числа-это числа вида 0,1,2,3,...,n
Поэтому тип word,в диапазон integer входят целые числа,т.е натуральные,ноль,и числа,противоположные по знаку натуральным

Баланко Валерий

Ты не прав.
Во-первых натуральные числа это 1,2,3,4,...,n,... (0 не входит)
Во-вторых множество натуральных чисел содержится в множестве целых чисел.
Разница лишь в том, что с типом word программа будет работать с натуральными числами n<=65535, а с типом integer с числами n<=32767.

Про натуральные действительно

Про натуральные действительно ошибся(
Я не выделил взятие типа integer как страшную ошибку,просто если по заданию числа натуральные,то думаю лучше брать подходящий тип

word, а не int

Word, а не int, потому что натуральные - это целые, положительные, а не просто целые (которые могут быть и отрицательными). Integer ЛОГИЧЕСКИ шире, чем Word и создаёт ненужную (и даже вредную) избыточность множества значений, которые должны бы рассматриваться по условию данной задачи.

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

Валерий зря сдался

Так что, Валерий зря сдался - он был ближе к истине, чем Евгений, Роман и Дмитрий (единственная неточность - 0 действпительно не натурален)

Вариант решения задачи 2-1

Задача 2-1. Определить, представляют ли цифры заданного в десятичной записи 3-х значного натурального числа возрастающую последовательность. Вывести 1, если да и вывести 0, если нет. Например, на числах 527, 224, 543 программа ответит - 0, а на числе 478 - 1.
Предполагается линейное (т.е. не содержащее условных и циклических операторов) решение на Паскале.

Решение.

  1. a:= x div 100;   b:= (x mod 100)  div 10;  c:= x mod 10;  //выделение цифр числа
  2. Inc(a);   Inc(b);   Inc(c);  //увеличение значений цифр на 1, чтобы не было нулей
  3. x:=  (a div b) + (b div c);  //0, если ДА (т.е. число “хорошее”), не 0, если НЕТ
  4. // главное теперь, сделать так, чтобы было  1, если НЕТ.
  5. // Исходим из того, что cейчас  x <= 11, т.е. занимает не более 4-х битов памяти (почему?)
  6. y:= (x mod 2) + (x div 2) mod 2;   //сумма последних двух битов x.
  7. x:= x div 4;  //отрезаем два уже учтённых в сумме бита
  8. y:= y+ (x mod 2) + (x div 2) mod 2;   //плюс сумма первых двух битов x.
  9. // Полученное  y <=4, т.е. занимает не более 3-х битов, которые так же сложим:
  10. x:= (y mod 2) +(y mod 4) div 2 + y div 8;
  11. // Полученное  x <=3, т.е. занимает не более 2-х битов, которые так же сложим:
  12. y:= ( x mod 2) + (x div 2);   // y = 0, 1 или 2, т.е. содержит одну или ноль единиц
  13. x:= (y mod 2) + (y div 2); // это и есть ответ 0 или 1, с “точностью до наоборот”.
  14. Writeln(1-x);   // вывод окончательного ответа

Важно понять, что выше приведённые манипуляции со сложением двоичных разрядов в конце концов приведут к 1 тогда и только тогда, когда обработанное число x (c начальным значением, сформированным в строке 4) отлично от нуля.
Жду вопросов и комментариев.

Решение отнюдь не простое

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

Как насчет

Как насчет моего варианта решения? Оно вообще решаемо?

Цепочка равносильных утверждений

По сути первая часть решения аналогична, но тут строится функция 1 div x + 1 div y, зависящая от двух натуральных ( т.е. вида 1,2,3,... ) аргументов. Она принимает значение 2 тогда и только тогда, когда оба аргумента равны 1. Иначе получаем либо 0, либо 1.
(1 div x + 1 div y) mod 2 = 1 тогда и только тогда, когда x=y=1. Если

(1) a < b <=> a+1 < b+1 <=> x=1 <=> 1 div x = 1
(2) b < c <=> b+1 < c+1 <=> y=1 <=> 1 div y = 1
(1) and (2) <=> 1 div x + 1 div y = 2 <=> (1 div x + 1 div y) div 2 = 1

  1.   ...
  2.   a:=n div 100; b:=(n div 10) mod 10; c:=n mod 10;
  3.   inc(a); inc(b); inc(c); // Увеличиваем все три значения на 1,
  4.                           // чтоб исключить ошибку при целочисленном делении.
  5.   x:=a div b + 1;         // x=1, если a<b. Иначе x>1.
  6.   y:=b div c + 1;         // y=1, если b<c. Иначе y>1.
  7.  
  8.   write( (1 div x+1 div y) div 2 );    // выводим 1 тогда и только тогда, когда оба аргумента равны 1.
  9.                           // То есть, верны оба неравества a<b и b<c). Иначе 0.
  10.   ...

Может быть кто-то и придумает проще ...

В моём решении (см. выше) основную трудность представляет следующая частная подзадача:
Дано неотрицательное целое N <= C, где С - некоторая, так же заданная натуральная константа. Написать линейную программу, печатающую 0, если N=0, и 1, если N>0

Идея моего метода решения этой подзадачи состоит в следующем утверждении (попробуйте его доказать или опровергнуть!):
Если N > 0 и представлено в некоторой системе счисления p-разрядным числом (p>1), то сложив цифры представляющие N, получим число N1 такое, что: 0< N1 < N. Применив такое же преобразование к N1 и продолжая этот процесс, мы будем получать всё меньшие и меньшие положительные числа, требующие для своего представления всё меньшего и меньшего числа разрядов, пока не дойдём до 1-разрядного числа Nk > 0.

Поясню это на примере. Пусть N=25403 (пятизначное положительное десятичное число). Сложим его цифры, получим N1=14.
Ещё сложим, получим N2 = 5 ( 5 - однозначное положительное десятичное число).
Этот приём позволяет вопрос о положительности p-разрядного числа свести к вопросу о положительности 1-разрядного числа (что может быть проще).
А при выборе двоичной системы счисления (что в решении я и делаю!), выше указанный процесс будет завершаться получением одного двоичного разряда (со значением 0 или 1), который непосредственно может интерпретироваться как ответ.

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

Добивается ли Ваш вариант решения...

Женя, давайте рассмотрим часть Вашего кода. Вы задаёте переменным a,b,c значения цифр трехзначного числа, а далее пишите:

  1. x:=(a+1) div (b+1);
  2. y:=(b+1) div (a+1);
  3. a:=x*y;

Что может оказаться в переменной x?. Хорошо бы, если она характеризовала истинность неравенства a. К счастью, так и есть.
При а < b , имеем x=0. При a >= b, имеем x>=1.
Теперь можно поиграть со значением x, но вы находите значение переменной y (она тоже характеризует только отношение значений a и b, но не b и с).
При а > b, имеем y=0. При a <= b, имеем y>=1.
И тут вы вычисляете a := x * y, которое, кстати позволяет выяснить, есть ли среди цифр a,b,c две равные, но ничего не проясняет о том, какое из них больше, а какое меньше остальных.
a=0 <=> x*y=0 <=> x=0 или y=0 <=> a>b или a x≠0 и y≠0 <=> a<=b и a>=b <=> a=b.

yura!

В режиме "изменить", после отправки коммента, в пункте АДМИНИСТРИРОВАНИЕ (вверху) включайте статус "опубликовано". Я посмотрю, почему для Вас не работает это по умолчанию.

Верны ли мои рассуждения?

  1. x:=(a+1) div (b+1);
  2. y:=(b+1) div (a+1);
  3. a:=x*y;
  4. x:=(b+1) div (c+1);
  5. y:=(c+1) div (b+1);
  6. b:=x*y;

Данные строчки предназначены для проверки, есть ли в числе повторяющиеся цифры. Если они есть, то ответ будет равен нулю, иначе единице.
  1. x:=(a+1) div (b+1);
  2. y:=(b+1) div (a+1);

Без этих строчек возрастающее значение после проверки на равные числа превращалось бы в 0
  1. n:=((c+1) div (b+1))*((b+1) div (a+1))

Данная строчка позволяет исключить убывающую последовательность.

Однако при вводе числа 169 например получаеться не 1 а другое число, большее 1.

to Фирсов Евгений

В принципе, да. Рассуждения верны.
Итак, несколькими проверками Вы исключаете числа с одинаковыми цифрами. Затем исключаете числа с убывающим порядком цифр.
Таким образом, Ваша переменная n = 0, если и только если порядок цифр в введенном числе не является возрастающим (как и требуется). И n>0 для любого числа с возрастающим порядком цифр.
Значит, Вы свели задачу к той, частной подзадаче, о который выше писал Валерий Шахамболетович.

karpenko_yura! ПОВТОРНО!

Ваши комменты не публикуются без моей помощи.
Посмотрите настройки меню Администрированиние в режиме комментов "Изменить". После любой отправки коммента, переключайте там на "Опубликовано".

to Юрий Александрович

Но ведь нам надо выводить 1 если числа представляют собой возрастающую последовательность, а 1 будет выводиться только в последовательностях типа 123 234 789. в остальных возврастающих n>1.
Можно ли как-то исправить этот недочет?

Евгений, гораздо понятней

1. Евгений, гораздо понятней комментарии вносить прямо в код, как у меня.
Тем более, что у Вас одни и те же переменные и даже одни и те же операторы используются в коде многократно. Стоит дополнительных усилий понять какое именно ВХОЖДЕНИЕ оператора (переменной) Вы имеете ввиду в тот или иной момент.
Читать Ваши комменты (типа последних) можно только открыв два окна - окно кода и окно, собствено, комментария к этому коду, пытаясь при этом установить что чему соответстует. Многие ли захотят проходить через эти испытания - думаю нет ...
Вы ведь заинтересованы в ЧИТАТЕЛЯХ Ваших комментов?

2. В Вашем последнем варианте кода (от Пт, 15/10/2010 - 22:55) Валерий Баланко указал ошибку. Нового варианта кода ещё не представлено. Если честно, я потрял нить. Какую программу мы обсуждаем? Ту, уже заведомо неправильную?

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

А что касается решений этой

А что касается решений этой здачи, то самое простое представлено Ю.А. (в его комменте от Сб, 16/10/2010 - 18:02). Так что, главный бонус уходит к нему!

Хорошо

Что касаеться коментариев в коде, то я все понял, исправлюсь. Насколько я понял, мое решение задачи не приводит к точному правильному варианту.

P.S. Кстате, Влерий Шахамболетович, хочу заметить, что во всех коментариях, в которых вы ссылаетесь на другой коментарий, возникла какая-то ошибка со временем. Например в последнем вашем коментарии, в котором вы ссылаетесь на решение Юрия Александровича, написано: от Сб, 16/10/2010 - 18:02), а при просмотре страницы с коментариями (лично у меня), коментарий Юрия Александровича стоит от Сб, 16/10/2010 - 19:02, т.е. с часом разницы, что затрудняет поиск коментариев.

В.Ш., мне кажется в комменте

В.Ш., мне кажется в комменте за Сб, 16/10/2010 - 12:32 в строке 9 Вы забыли прибавить к сумме первых 2-х битов числа сумму 2-х последних битов, т.е.:

  1. y:= y + (x mod 2) + (x div 2) mod 2;

После этого y <=4 и занимает не более 3-х битов.
4 - это 100 в двоичном представлении
3 - это 11
2 - это 10
Следовательно в комментарии в строке 12 правильнее было бы написать, что x <= 2, но это не столь важно.

Решение с помощью операции

Решение с помощью операции сдвига:

  1. var
  2.   a, b, c: Word;
  3.   x: Integer;
  4. begin
  5.   Readln(x);
  6.   a := x div 100;
  7.   b := (x mod 100) div 10;
  8.   c := x mod 10;
  9.   Inc(a); Inc(b); Inc(c);
  10.   x := (a div b) + (b div c);
  11.   Dec(x); //Если x был равен 0, то теперь x = -1
  12.           //и старший бит в его 2-ичном представлении равен 1
  13.           //Если x был больше 0, то теперь x >= 0
  14.           //и старший бит в его 2-ичном представлении равен 0
  15.   x := x shr 31; //Сдвигаем вправо на 31, т.к. переменная типа
  16.                  //Integer занимает в памяти 32 бита
  17.   Writeln(x);
  18. end.

Более подробно об операциях сдвига можно почитать здесь и здесь.

Кроме Натальи

Кроме Натальи, похоже, внимательно коды никто не читает. Спасибо, Наташа. Действительно, упустил у. Уже исправил.

И с точной оценкой x <= 2, в принципе согласен.
Но более грубую оценку я привёл сознательно. Мне показалось, будет понятней сказать, что x <=3, т.к. x получено в результате суммирования трёх слагаемых, каждое из которых может равняться 1.
А то, что все эти слагаемые одновременно не будут единицами, я не стал уточнять, т.к., Вы и сами заметили, данный факт не влияет на дальнейшее решение.

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

Спасибо, Евгений, что

Спасибо, Евгений, что заметили сдвиг по времени. Постараюсь исправить.

У меня время на час отстает

У меня время на час отстает

Валерий Шахамболетович

Будут ли еще задачи? И если будут, то выкладывайте, если можно, несколько задач, как вы сделали это в начале темы, чтобы не было проблем с тем, что некоторые не успевают решить ту или иную задачу.

Думаю следующие задачи будут

Думаю следующие задачи будут уже на другую тему. Имеется предположение что на циклы.