Редактирование и вычитка книги

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

Модераторы: Oleg_D, Модераторы

Re: "Песни о Паскале" - для школьников и начинающих

Сообщение Paster Fob » 08.04.2012 22:43:00

Oleg_D писал(а):Не понял вопроса. Все так и должно быть: в строке должно быть не точно 8 символов, а не менее 8.

Что не понятного?В условии цикла сказано пока (длина строки меньше 8 ) или (n1<2) или (n2>2) или (n3>2)Должно выполниться 1-ое условие или 2-ое или 3-е или 4-е.Если первыми выпадут 2 нуля то n1 будет равен 2.Значит цикл должен прекратиться,но он не прекращается,а наоборот продолжается,как будто между условиями стоит не or ,а and.в приведённом мной примере с repeat...until,между скобками я поставил and,если поставить or то программа печатает букв меньше 8,минимум 2.Почему в цикле while условия наоборот написаны?
Аватара пользователя
Paster Fob
постоялец
 
Сообщения: 188
Зарегистрирован: 22.02.2011 21:53:36
Откуда: Новосибирск.

Re: "Песни о Паскале" - для школьников и начинающих

Сообщение Oleg_D » 08.04.2012 22:51:16

Paster Fob писал(а):В условии цикла сказано пока (длина строки меньше 8 ) или (n1<2) или (n2>2) или (n3>2)

Поправлю, у меня так записано:
Код: Выделить всё
while (Length(S)<8) or (n1<2) or (n2<2) or (n3<2) do

Paster Fob писал(а):Почему в цикле while условия наоборот написаны?

Потому, что так полагается по правилам языка:
- цикл WHILE выполняется, пока условие истино (true)
- цикл REPEAT выполняется, пока условие ложно (false)
Oleg_D
постоялец
 
Сообщения: 391
Зарегистрирован: 09.05.2011 11:28:36

Re: "Песни о Паскале" - для школьников и начинающих

Сообщение Paster Fob » 10.04.2012 14:07:30

Ну не могу я сделать это задание.Как написать чтобы символы одного регистра не соседствовали?Сделал такой вариант,но программа всё равно работает не правильно.
Код: Выделить всё
type tset=set of byte;

var m,n,n1,n2,n3:byte;ch:tset;
    s:string;

procedure readinset(var aset:tset;var arg:string );
{var ch:char;}
begin
  if n in aset then begin
    {ch:=arg[length(arg)];
      if ((ord(ch)>=48) and (ord(ch)<=57)) and ((n>=48) and (n<=57)) or
      ((ord(ch)>=65) and (ord(ch)<=90)) and ((n>=65) and (n<=90)) or
      ((ord(ch)>=97) and (ord(ch)<=122)) and ((n>=97) and (n<=122)) then
        begin

        end;}
    arg:=arg+char(n);
    aset:=aset-[n];
  end;
end;

var k:byte;
begin
  randomize;
  ch:=[48..57,65..90,97..122];
  s:='';n1:=0;n2:=0;n3:=0;k:=3;
  while (length(s)<8) or (n1<2) or (n2<2) or (n3<2) do begin
    m:=random(3);
      if (k=2) and (m=2) then m:=m-1;
      if (k=1) and (m=1) then m:=m+1;
      if (k=0) and (m=0) then m:=m+1;
    case m of
      0 : begin
            n:=random(10)+48;
            inc(n1);
            readinset(ch,s);
          end;
      1 : begin
            n:=random(26)+65;
            inc(n2);
            readinset(ch,s);
          end;
      2 : begin
            n:=random(26)+97;
            inc(n3);
            readinset(ch,s);
          end;
    end;
    k:=m;
  end;
  writeln(s);
  readln
end.

Аватара пользователя
Paster Fob
постоялец
 
Сообщения: 188
Зарегистрирован: 22.02.2011 21:53:36
Откуда: Новосибирск.

Re: "Песни о Паскале" - для школьников и начинающих

Сообщение Oleg_D » 10.04.2012 15:20:07

Еще раз повторю уточненное задание:
-----
Г) Напишите программу для генерации пароля не менее чем из восьми цифр и латинских букв. Он должен включать не менее двух больших букв, не менее двух маленьких букв и не менее двух цифр. Например: «7UpJ7rsT», «PasCal701». Сделайте четыре варианта так, чтобы соблюдались следующие условия:
• символы пароля могут повторяться;
• все символы пароля уникальны (примените множество);
• буквы одного регистра и цифры не соседствуют, например: «Pa7sCaL5», уникальность символов не требуется;
• символы не соседствуют и уникальны.
-----
Вот решение для 3-го случая, здесь счетчики не нужны:
Код: Выделить всё
function PassWord: string;
var S: string;  { результат }
    v: integer; { вариант очередного символа }
    C: char;    { очередной символ }
begin
  S:='';
  v:= Random(3);
  while Length(S)<8 do begin
    case v of
      0: C:= Char(Random(10)+Ord('0'));
      1: C:= Char(Random(26)+Ord('a'));
      2: C:= Char(Random(26)+Ord('A'));
    end;
    S:= S+C;
    v:= (v+1) mod 3;
  end;
  PassWord:=S;
end;

begin
  Randomize;
  Writeln(PassWord);
  Writeln(PassWord);
  Writeln(PassWord);
  Writeln(PassWord);
  Writeln(PassWord);
  Writeln(PassWord);
  Readln;
end.


Добавлено спустя 45 минут 42 секунды:
Попытайтесь теперь решить 4-й вариант: "символы не соседствуют и уникальны".
Тогда выложу и это решение.
Oleg_D
постоялец
 
Сообщения: 391
Зарегистрирован: 09.05.2011 11:28:36

Re: "Песни о Паскале" - для школьников и начинающих

Сообщение tema » 12.04.2012 01:40:32

Не очень понял лицензию, поэтому просто спрошу:
Можно ли напечатать Вашу книгу в нескольких экземплярах и раздать своим ученикам?
Ваше авторство, само собой, будет указано на первой странице, как у Вас и написано:
© Деревенец Олег Виленович, 2010-2012,
все права защищены
http://oleg-derevenets.narod.ru
tema
постоялец
 
Сообщения: 375
Зарегистрирован: 24.03.2011 20:19:27

Re: "Песни о Паскале" - для школьников и начинающих

Сообщение Oleg_D » 12.04.2012 10:05:27

tema писал(а):Можно ли напечатать Вашу книгу в нескольких экземплярах и раздать своим ученикам?

Да, можно.
Но лучше немного подождать. Сейчас работаю над 11-й редакцией, надеюсь скоро выложить её, а также предложить для издания по принципу "печать по требованию". Если получится, обязательно сообщу на форуме.
Oleg_D
постоялец
 
Сообщения: 391
Зарегистрирован: 09.05.2011 11:28:36

Re: "Песни о Паскале" - для школьников и начинающих

Сообщение tema » 12.04.2012 13:08:03

Спасибо. А когда приблизительно ждать?
ЗЫ
посмотрел в типографиях... что-то дороговато выходит. Пожалуй, дети пусть купят новый картридж и бумагу и сами распечатаем :-)

Добавлено спустя 26 минут 10 секунд:
Увидел задачку выше.
Эту строчку:
Код: Выделить всё
v:= (v+1) mod 3;

Я считаю даже не неточностью, а ошибкой, ибо это уже не полностью случайная генерация пароля. Случайной тут будет являться генерация первого символа, остальные зависимы.
Вот сразу с четвёртым пунктом:
Код: Выделить всё
function PassWord: string;
var S: string;
    v,vnew: integer;
    C: char;
    isp:set of char;
begin
  S:='';
  isp:=[];
  v:= Random(3);
  while Length(S)<8 do begin
    repeat
      case v of
        0: C:= Char(Random(10)+Ord('0'));
        1: C:= Char(Random(26)+Ord('a'));
        2: C:= Char(Random(26)+Ord('A'));
      end;
    until not (c in isp);
    isp:=isp+[c];
    S:= S+C;
    repeat
      vnew:=Random(3);
    until vnew<>v;
    v:=vnew;
  end;
  PassWord:=S;
end;

begin
  Randomize;
  Writeln(PassWord);
  Writeln(PassWord);
  Writeln(PassWord);
  Writeln(PassWord);
  Writeln(PassWord);
  Writeln(PassWord);
  Readln;
end.
tema
постоялец
 
Сообщения: 375
Зарегистрирован: 24.03.2011 20:19:27

Re: "Песни о Паскале" - для школьников и начинающих

Сообщение Oleg_D » 12.04.2012 13:35:50

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

Добавлено спустя 8 минут 53 секунды:
tema писал(а):Я считаю даже не неточностью, а ошибкой, ибо это уже не полностью случайная генерация пароля. Случайной тут будет являться генерация первого символа, остальные зависимы.

Согласен, но с маленькой поправкой: пароль таки случайным будет, но сорт символа, действительно будет циклически повторяться. Впрочем, в условии сказано: "символы одного сорта не соседствуют", и это требование выполняется для обоих вариантов. Но Ваш вариант, разумеется лучше, хитрее. :)
Oleg_D
постоялец
 
Сообщения: 391
Зарегистрирован: 09.05.2011 11:28:36

Re: "Песни о Паскале" - для школьников и начинающих

Сообщение Valeriy » 17.04.2012 16:03:58

Уважаемый Oleg, если можно, объясните пожайлуста.

Программа P_40_2 на стр 290.
Для чего в программе применена инструкция - if EoLn(aFile) then Readln(aFile);
Что означает { пропуск конца строки }, это дополнительный перевод каретки?
В главе 29 этого нет.
Я пробовал убрать её из программы, программа работает. Если её не будет какие проблемы могут быть в работе программы?
Извините за вопрос, просто не хочется оставлять белых пятен.
Заранее спасибо!
Valeriy
новенький
 
Сообщения: 14
Зарегистрирован: 02.09.2011 06:13:57

Re: "Песни о Паскале" - для школьников и начинающих

Сообщение Oleg_D » 17.04.2012 16:44:03

Valeriy писал(а):Для чего в программе применена инструкция - if EoLn(aFile) then Readln(aFile);

Точно не помню, но на Free Pascal, кажется, наблюдал такой глючок: когда последняя строка файла заканчивается не признаком EOLN, а признаком EOF, то последнее число как-то не так читалось. А после вставки Readln(aFile) все работало. То есть, это перестраховка, хуже от этого не будет. Попробуйте за последней строкой не поставить перевод каретки и исследовать оба варианта.
Valeriy писал(а):Извините за вопрос

Не извиняйтесь, - на то и форум, чтобы спрашивать :D Это ж всем на пользу.

Добавлено спустя 43 минуты 28 секунд:
По поводу задачи 38-Г. Думаю еще раз поправить в ней условие вот так.
Код: Выделить всё
Г) Генерация пароля длиной не менее восьми символов. В пароль входят символы трёх сортов: цифры, маленькие и большие латинские буквы, например: «7UpJ7rsT», «PasCal701». Сделайте четыре варианта так, чтобы соблюдались следующие условия:
- символ каждого сорта входит в пароль не менее двух раз, некоторые символы могут повторяться;
- все символы пароля уникальны (примените множество);
- символы одного сорта не соседствуют, например: «Pa7sCaL5», уникальность символов не требуется;
- символы одного сорта не соседствуют и все символы уникальны.

То есть, требование символ каждого сорта входит в пароль не менее двух раз относится только к первому случаю. Иначе решения получаются немного громоздкими для новичка.
И тогда годится то, что предложено tema
Код: Выделить всё
repeat
     vnew:=Random(3);
until vnew<>v;
v:=vnew;

А иначе выделенное жирным шрифтом условие не выполняется. Кстати, этот кусок можно заменить одним оператором:
Код: Выделить всё
v:= (v+1+Random(2)) mod 3;
Oleg_D
постоялец
 
Сообщения: 391
Зарегистрирован: 09.05.2011 11:28:36

Re: "Песни о Паскале" - для школьников и начинающих

Сообщение tema » 17.04.2012 21:03:15

Oleg_D писал(а):Кстати, этот кусок можно заменить одним оператором:
Код: Выделить всё
v:= (v+1+Random(2)) mod 3;

Угу, я потом тоже так подумал и даже у себя в тестовой программке написал именно так, но сюда не стал уже писать. Там-то я не думая я в лоб написал :-)

Добавлено спустя 7 минут 46 секунд:
Кстати, я бы добавил пятое задание собирательное: выполнить предыдущие 3 задания (2-4) с условием, что сначала вводится алфавит для использования в генерации. Символов в алфавите >8
Например:
вводим с клавиатуры первый сорт: 123, второй сорт: qwe, третий сорт: RTY, четвёртый сорт: !@#
И выполнить предыдущие (2-4) задания для заданного алфавита.
Последний раз редактировалось tema 17.04.2012 23:30:41, всего редактировалось 2 раз(а).
tema
постоялец
 
Сообщения: 375
Зарегистрирован: 24.03.2011 20:19:27

Re: "Песни о Паскале" - для школьников и начинающих

Сообщение Paster Fob » 17.04.2012 21:41:41

4-ый вариант я вот так решил:
Код: Выделить всё
type tset=set of byte;

procedure readset(var arg:string;ach:byte;var aset:tset);
begin
  if ach in aset then begin
    aset:=aset-[ach];
    arg:=arg+char(ach);
  end;
end;

var  s:string;sen:tset;
     k,ch,n:byte;

begin
  randomize;
  k:=0;
  repeat
    sen:=[48..57,65..90,97..122];
    s:='';
    n:=random(3);
    while length(s)<>8 do begin
      case n of
        0 : begin
              ch:=random(10)+48;
              readset(s,ch,sen);
            end;
        1 : begin
              ch:=random(26)+65;
              readset(s,ch,sen);
            end;
        2 : begin
              ch:=random(26)+97;
              readset(s,ch,sen);
            end;
      end;
      n:=(n+1) mod 3;
    end;
    writeln(s);
    inc(k);
  until k=10;
  readln
end.
Аватара пользователя
Paster Fob
постоялец
 
Сообщения: 188
Зарегистрирован: 22.02.2011 21:53:36
Откуда: Новосибирск.

Re: "Песни о Паскале" - для школьников и начинающих

Сообщение tema » 17.04.2012 23:22:06

Ну чтож и я внесу лепту :-)
Я бы решил так:
Код: Выделить всё
function PassWord: string;
var
S: string;
a:array[1..3] of string;
n,v:integer;
begin
  S:='';
  a[1]:='0123456789';
  a[2]:='qwertyuiopasdfghjklzxcvbnm';
  a[3]:='QWERTYUIOPASDFGHJKLZXCVBNM';
  v:=Random(3)+1;
  while Length(S)<8 do begin
    n:=Random(length(a[v]))+1;
    s:=s+(a[v,n]);
    delete(a[v],n,1);
    v:= ((v+Random(2)) mod 3)+1;
    end;
  PassWord:=S;
end;

begin
  Randomize;
  Writeln(PassWord);
  Writeln(PassWord);
  Writeln(PassWord);
  Writeln(PassWord);
  Writeln(PassWord);
  Readln;
end.

Без уникальности (третье задание) просто убрать эту строчку:
Код: Выделить всё
delete(a[v],n,1);
и можно будет свернуть две предыдущие в одну:
Код: Выделить всё
s:=s+(a[v,Random(length(a[v]))+1]);
tema
постоялец
 
Сообщения: 375
Зарегистрирован: 24.03.2011 20:19:27

Re: "Песни о Паскале" - для школьников и начинающих

Сообщение Oleg_D » 18.04.2012 10:24:45

Valeriy писал(а):Для чего в программе применена инструкция - if EoLn(aFile) then Readln(aFile);

Еще раз благодарю "Valeriy" за этот вопрос и хочу вернуться к нему. Я вспомнил, в чем там дело было. Когда последняя строка НЕ завершается возвратом каретки, то количество чисел считается правильно, а иначе считается на 1 больше и считывается еще одно несуществующее число как ноль. Дело в том, что EOLN=TRUE и в конце файла тоже. Вот тестовая программка.
Код: Выделить всё
function ReadNumbers(var aFile: text): integer;
var cnt,n: integer;
begin
  cnt:=0;
  while not Eof(aFile) do begin
    { Пропуск пустых строк }
    (*
    while Eoln(aFile) do
      if Eof(aFile) then Break else Readln(aFile);
    if Eof(aFile) then Break;
    *)
    Read(aFile, n);
    Inc(cnt);
  end;
  ReadNumbers:= cnt;
end;

var F: Text;

begin
  Assign(F, 'Test.txt'); Reset(F);
  Writeln(ReadNumbers(F));
  Close(F);
  Readln;
end.
А вот тестовый файл
Код: Выделить всё
20 30 40
Если убрать звездный комментарий, то получится 3, а если примитивно, то 4. Книжные примеры я упрощал, конечно, но в боевых программах надо учитывать такие вещи, как пустые строки и прочие несуразности. Программку в книге я подправлю, конечно.
Paster Fob писал(а):4-ый вариант я вот так решил:

Немножко не дотягивает до правильного. Сделайте пароль длиннее
Код: Выделить всё
while length(s)<40 do begin
и увидите, что некоторые соседи не на месте. Тут в каждой ветке надо цикл подбора символа закрутить.
tema писал(а):Я бы решил так:
Пара замечаний.
1. Решение уместно после 44-й главы, где уже рассмотрены массивы и операции со строками.
2. В строке
Код: Выделить всё
v:= ((v+Random(2)) mod 3)+1;
маленькая ошибка, надо
Код: Выделить всё
v:= ((v+1+Random(2)) mod 3)+1;
Кстати, в других задачах можно применить обобщение этой формулы для случайного выбора из N ветвей:
Код: Выделить всё
v:= ((v+1+Random(N-1)) mod N)+1;
Благодарю всех за активное обсуждение!
Oleg_D
постоялец
 
Сообщения: 391
Зарегистрирован: 09.05.2011 11:28:36

Re: "Песни о Паскале" - для школьников и начинающих

Сообщение tema » 18.04.2012 12:55:14

Oleg_D писал(а):
tema писал(а):Я бы решил так:
Пара замечаний.
1. Решение уместно после 44-й главы, где уже рассмотрены массивы и операции со строками.

Я ещё до туда не дочитал :D поэтому не знаю что этим пользоваться нельзя. Но так убирается куча лишних случайных операций и вообще код получается довольно компактный.
Oleg_D писал(а):2. В строке
Код: Выделить всё
v:= ((v+Random(2)) mod 3)+1;
маленькая ошибка, надо
Код: Выделить всё
v:= ((v+1+Random(2)) mod 3)+1;
Кстати, в других задачах можно применить обобщение этой формулы для случайного выбора из N ветвей:
Код: Выделить всё
v:= ((v+1+Random(N-1)) mod N)+1;
Благодарю всех за активное обсуждение!

у меня нет ошибки :D
Код: Выделить всё
v:= ((v+Random(2)) mod 3)+1; {ПРАВИЛЬНО}

это правильно. Я понимаю, почему Вы решили, что ошибка: у Вас в коде о 0 до 2 и Вы использовали:
Код: Выделить всё
v:= ((v+1+Random(2)) mod 3);

Но у меня от 1 до 3, поэтому "+1" надо вынести за все скобки, а в Вашей поправке получается двойной "+1" и возможны варианты повторения числа.
Например: v=3; random(2)=1 получается у Вас v=((3+1+1) mod 3)+1=3, т.е. v опять равно 3, а у меня v=((3+1) mod 3) +1=2
Обобщённая так:
Код: Выделить всё
v:= ((v+Random(N-1)) mod N)+1;


Oleg_D писал(а):
Paster Fob писал(а):4-ый вариант я вот так решил:

Немножко не дотягивает до правильного. Сделайте пароль длиннее
Код: Выделить всё
while length(s)<40 do begin
и увидите, что некоторые соседи не на месте. Тут в каждой ветке надо цикл подбора символа закрутить.

Можно не закручивать лишних три цикла. Можно сделать readset вместо процедуры функцией и возвращать true при удачном выполнении. И считать новую n тут n:=(n+1) mod 3;, только когда true.

Добавлено спустя 17 минут 2 секунды:
Хотя..... Наверное
while not readset(s,ch,sen);

будет выглядеть всё-таки компактнее :-)
Последний раз редактировалось tema 18.04.2012 14:09:18, всего редактировалось 1 раз.
tema
постоялец
 
Сообщения: 375
Зарегистрирован: 24.03.2011 20:19:27

Пред.След.

Вернуться в Книга "Песни о Паскале"

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 0

Рейтинг@Mail.ru