Внимание! Контрольная работа по МиК переносится на следующую неделю! Продолжать отработку заданий, опубликованных в группах. 

Существенность переменных БФ

Определения и теория вопроса изложены здесь.

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

Как обычно, прошу ограничиться не более чем одной задачей в сутки (не лишайте остальных шанса улучшить рейтинг!).

Задача1. Описать функцию function susch(bf: String; k: Byte):Boolean , которая проверяет на существенность k-ю переменную БФ bf.

Задача2. Описать процедуру procedure ficList(bf: String; var ficL: String) , которая создаёт список ficL номеров фиктивных переменных БФ bf (будем считать, что переменных не более 9-ти).

Задача3. Описать процедуру procedure delFic(var bf: String; k: Byte) , которая устраняет из bf фиктивную переменную c номером k.

Задача4. Описать процедуру procedure delAllFic(var bf: String) , которая устраняет из bf все фиктивные переменные.

Задача5. Описать процедуру procedure vec2tbl(var bf: String) , которая выводит заданную в векторной форме БФ в виде таблицы истинности.

Существенность перем.БФ

В форумах новая серия задач по этой теме.

Задача 1

Добрый вечер, Валерий Шахамболетович!

  1. function susch(bf: String; k: Byte):Boolean;
  2. var p,d,n,i:byte;
  3.     s1,s2:string;
  4. begin
  5. s1:='';
  6. s2:='';
  7. n:=1;
  8. if (length(bf)>=2)  then begin//если длина формулы больше 2
  9.    i:=i shr 1;//сдвигаем вправо на 1
  10.    n:=n+1;// n -количество переменных
  11. end;
  12. d:=1 shl (n-k+1);//длина отрезка (2^n-k+1)
  13. d:=d div 2;//получаем половины
  14. s1:=copy(bf,1,d);//первая половина
  15. s2:=copy(bf,d+1,d);//вторая половина, далее нужно сравнить
  16. if s1=s2 then susch:=False
  17. else susch:=True

Задача 1.

  1. function susch(bf: String; k: Byte):Boolean;
  2. var L,n:byte;
  3.     s1,s2:string;
  4. begin
  5. s1:='';
  6. s2:='';
  7. Readln(n);//вводим (n)
  8. if (length(bf)>=2)  then begin//если длина формулы больше 2
  9.   L:=Exp((n-k+1)*Ln(2));//длина отрезка (2^n-k+1)
  10.   s1:=copy(bf,1,L);//первая половина
  11.   s2:=copy(bf,d+1,L);//вторая половина
  12.     if s1=s2 then susch:=False
  13.         else susch:=True;
  14. end;
  15. else susch:=True;

Богдан,

Не понятно, откуда взялась переменная d.
Количество end'ов не соответствует числу begin'ов.
Строку 13 в конце вставили, видимо, случайно.
Вы пробовали запустить этот код?

Богдан

Что значит 7-я строка!?!?
В строке 9, удобней использовать логический сдвиг
что за переменная d в строке 11, может это все таки L
В строке 14 после end перед else ';' не ставится !!!

15-я строка лишняя

еще в 9 строке типу byte

еще в 9 строке типу byte нельзя присваивать тип real, а тип real будет, так как там есть экспонента

"Несчастья" кода Богдана

"Несчастья" кода Богдана произросли, очевидно, и из ошибок кода Виктории в том числе - некоторые кусочки просто перекочевали из одного описания в другое, приклеившись в новом месте где попало. Ни она, ни он не удосужились хотя бы попытаться скомпилировать свои творения. Ошибки на уровне грубого синтаксиса.
Слишком уж их много, чтобы что-то предметно обсуждать.

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

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

Виктория

Виктория, ошибка твоя в том, что 1)ты объявляешь кучу переменных, из которых многие у тебя не используются, 2) ты сдвигаешь переменные i и d, но перед этим сдвигом им ничего не присваиваешь, поэтому в Паскале они считаются неопределёнными и выполнять подобные операции над ними нельзя!

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

посмотрите здесь задачу про "треугольную" запись в файл

Задача 2.

  1. procedure ficList(bf: String; var ficL: String);
  2. var i: integer;
  3.     zap: char;
  4. begin
  5.    ficl:='';
  6.    zap:=',';
  7.    for i:=1 to 9 do begin //так как по условию переменных не более 9
  8.      If ((function susch(bf:string; i:integer):boolean) = false) then //если переменная фиктивна то
  9.         ficl:=ficl + i + zap; //добавить в список её номер и отделить запятой
  10.         end;
  11.    ficl(length(ficl)):='';
  12. end;

Богдан

Что за странное выражение в строке 8 !?!?!?

  1. ...
  2.   If ((function susch(bf:string; i:integer):boolean) = false) then //если переменная фиктивна то
  3. ...

Можно было так :

  1. ...
  2.  if susch(bf,i)=false then begin  // если i-я переменная фиктивна, то ...
  3. ...

и ещё
выражение в 9-й строке явно вызовет ошибку при запуске программы

  1. ficl:=ficl + i + zap;// i:integer; ficl:string !!!!!

Можно было так:

  1. ... //переменная c описана как String;
  2.  str(i,c); // переводим  i в стринг  c
  3.  ficL:=ficL+c+zap;  // добавляем в список

Исправленный вариант задачи 1

Условие:"Описать функцию function susch(bf: String; k: Byte):Boolean , которая проверяет на существенность k-ю переменную БФ bf."

  1. function susch(bf: String; k: Byte):Boolean;
  2. var d,n,i:byte;
  3.      s1,s2:string;
  4. begin
  5. n:=1;
  6. i:=length(bf);
  7. while (i>2)do  begin
  8.    i:=i shr 1;
  9.    n:=n+1;
  10. end;
  11. d:=1 shl (n-k+1);//длина отрезка(2^n-k+1)
  12. d:=d div 2;
  13. s1:=copy(bf,1,d);
  14. s2:=copy(bf,d+1,d);
  15. if s1=s2 then susch:=False
  16. else susch:=True
  17. end;

задача 2(исправленная)

  1. procedure ficList(bf: String; var ficL: String);
  2. var i: integer;
  3.     zap: char;
  4. begin
  5.    ficl:='';
  6.    zap:=',';
  7.    for i:=1 to 9 do begin //так как по условию переменных не более 9
  8.     if susch(bf,i)=false then begin  // если i-я переменная фиктивна, то ...
  9.         str(i,c); // переводим  i в стринг  c
  10.         ficL:=ficL+c+zap;  // добавляем в список
  11.         end;
  12.    ficl(length(ficl)):='';
  13. end;

задача 3.

  1. procedure delFic(var bf: String; k: Byte);
  2. begin
  3. if susch(bf,k)=false then
  4. bf:=bf - bf[k];
  5. end;

Богдан

В "задача 2(исправленная)" ещё есть ошибка в 12 строке:
Вместо твоего варианта :

  1. ...
  2. ficl(length(ficl)):='';
  3. ...

Нужно написать так :

  1. ...
  2. ficl[length(ficl)]:='';// последнему эл-ту(т.е. запятой) присвоить ''
  3. ...

Ещё можно было сделать так:

  1. ...
  2. delete(ficl,length(ficl),1);// из ficl с последней позиции удалить подстроку длины 1
  3. ...

И ещё, насчет задачи 3

bf:=bf - bf[k]; - нет такой операции над стринговыми типами

Никита

А как же тогда в "задаче 3" удалить элемент из стринга? Подскажи...

Богдан, для этого есть

Богдан, для этого есть стандартная процедура Delete (S, poz, n) удаляет из строки S, начиная с позиции poz, подстроку из n символов.

По задачам 1-3 о существенности

Уже и на том спасибо, Вика, что в конце модуля появился END, переменная i прежде чем использоваться получает теперь начальное значение и в код внесён хоть какой-то цикл (сказать справедливости ради, действительно вычисляющий число переменных ф-ции). Но при этом, критерий существенности не отрабатывается - перечитайте его! И последуйте сами своему алгоритму хотя бы при k=2 !

Богдан - сплошное блуждание в потёмках (единственный плюс - хотя бы пытаетесь что-то делать). Бесмысленно браться за задачи 2, 3 когда не решена задача 1.

Комментарии Никиты (да и Вики по поводу Богдана) поддерживаю.

P.S. Вместо susch(bf,i)=false лучше писать not susch(bf,i).

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

Валерий Шахамболетович, проверяла при разных наборах,ответ программа выдавала правильный

В очередной раз повторюсь

В очередной раз повторюсь - правильный ответ на отдельных тестах не доказывает правильность программы!

Призываю подобрать для

Призываю подобрать для Виктории контрпример.

Контрпример для Виктории

Её программа неверно работает к примеру при '1111'

  1. program u;
  2. var k,n: longint;
  3.     bf: string;
  4. function susch(bf: String; k: longint):Boolean;
  5. var d,n,i:longint;
  6.      s1,s2:string;
  7. begin
  8. n:=1;
  9. i:=length(bf);
  10. while (i>2)do  begin
  11.    i:=i shr 1;
  12.    n:=n+1;
  13. end;
  14. d:=1 shl (n-k+1);
  15. d:=d div 2;
  16. s1:=copy(bf,1,d);
  17. s2:=copy(bf,d+1,d);
  18. if s1=s2 then susch:=False
  19. else susch:=True
  20. end;
  21. begin
  22. readln(bf);
  23. readln(K);
  24. Writeln(susch(bf, k));
  25. end.

Программа выдает что первая переменная не фиктивна, что ошибочно.

Богдан

В наборе '1111' все (2) переменные фиктивны:
'1111' -> '11'='11'(две половины равны) упрощаем вектор (первая переменная фиктивна) -> '11' -> (две половины равны) '1'='1' -> '1'

'1111' -> '1'

Так что на этом примере программа сработает ( результат будет False при к=1 и к=2)

Не путайтесь!

Вывод FALSE
процедуры:
Writeln(susch('1111', k));
означает НЕТ, не верно что k-я переменная существенна, т.е. она ФИКТИВНА.
Так что прав Никита, на этом-то примере, где обе переменные (k=1,2) фиктивны, всё пройдёт гладко.

Так никто и не придумал ... А

Так никто и не придумал ...
А ведь это очень просто, ну хотя бы импликация: 1101

при k=1 получим отрезки длины

при k=1 получим отрезки длины 2^2-1+1=4, здесь первая переменная будет существенной, т.к. первая половина отрезка не совпадет со второй, а вот при k=2 рассматриваемые отрезки будут длины 2, т.е. будет смотреть на половину 11 и на половину01.Получается, вторая переменная тоже будет существенной?

Вика

при к=1
отрезки длины 4 (таких отрезков 1 !) делим пополам '11' и '01' -> '11' не равны '01' -> 1-я переменная существенна

при к=2
отрезки длины 2 ( таких отрезков 2 !) , т е '11' и '01' сравниваем в каждом отрезке верхнюю и нижнюю половины:
'11' -> '1' равно '1' -> 2-я переменная фиктивна
дальше нет смысла рассматривать второй отрезок

Никита, я так и предполагала

Никита, я так и предполагала про вторую переменную, и следуя алгоритму программы тоже получается что она фиктивна, но все-таки я остаюсь в смятении, что не так?

Вика

думаю дело в этих двух строках:

  1. ...
  2. s1:=copy(bf,1,d);
  3. s2:=copy(bf,d+1,d);
  4. ...

нет,Никита, я считаю, что они

нет,Никита, я считаю, что они верны. Тут скорее всего дело в другом

Вика,Никита.

Ребятки! А не хотите ли вы внимательней просмотреть теоретический материал на который я сослался в начале этой страницы? Ну, хотя бы критерий несущественности ... И не кажется ли вам странным, что в обычной импликации есть, оказывается, фиктивная переменная?

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

Валерий Шахамболетович, получается, следуя алгоритму программы, в примере 1101 при переменной k=2, программа рассмотрит и сравнит только половину 11, поэтому и выдаст ответ false,хотя это неверно. Подскажите пожалуйста, с помощью какого цикла можно исправить эту ошибку, у меня не получается справиться...

Цикл по всем отрезкам длины l

Цикл по всем отрезкам длины l (Вы рассмотрели только самый первый). Выдайте false только в том случае, если в них во всех верхняя половина совпала с нижней.

function susch

  1.  
  2. function susch (bf: String; k: Byte):Boolean;
  3.   var
  4.     i,g,h,n : integer;
  5.   begin
  6.     n:=kol(length(bf));//находит количество переменных
  7.     g:=step(2,n-k);// возводит 2 в степень n-k
  8.     susch:=false;
  9.     h:=1;
  10.     while (h<length(bf)) do begin
  11.       if(copy(bf ,h,g) <> (copy(bf,h+g,g))) then begin
  12.         susch:=true;
  13.         break;
  14.       end;
  15.       h:=h+2*g;
  16.     end;
  17.   end;

я думаю, здесь вместо

я думаю, здесь вместо создания новой функции step, которая возводит в степень,удобнее использовать метод сдвига 1 shl (n-k+1);

можно но моя функция

можно но моя функция расчитанна на возведение в степень при любом основании

В развитие коммента Вики...

Вариант 6, 7 строк кода Сурена:

  1. ...
  2. n:=round(ln(bf)/ln(2));
  3. g:=2 shl (n-k);
  4. ...

Поддерживаю Вику. В данной задаче, безусловно, следует использовать сдвиг.

Задача 2

Описать процедуру procedure ficList(bf: String; var ficL: String) , которая создаёт список ficL номеров фиктивных переменных БФ bf (будем считать, что переменных не более 9-ти).

  1. procedure ficList(bf: String; var ficL: String);
  2.  var i:byte;
  3.    c:string[1];
  4. begin
  5.  ficL:='';
  6.  for i:=1 to 9 do begin  //по всем переменным
  7.   if susch(bf,i)=false then begin  // если i-я переменная фиктивна, то
  8.    str(i,c); // переводим её в строку
  9.    ficL:=ficL+c;  // добавляем в список
  10.   end; //if
  11.  end; //for
  12. end; //ficList

Задача №2

Задача, которая выводит номер только одной введенной переменной, если она фиктивная

  1. program Peremennie;
  2.  var k,n: longint;
  3.      bf: string;
  4.      i:byte;
  5.  function susch(bf: String; k: Byte):Boolean;
  6.   var l:integer;
  7.       i:byte;
  8.       s:string;
  9.  begin
  10.   l:=round(power(2,n-k+1));
  11.   susch:=false;
  12.   while bf<>'' do begin
  13.    s:=copy(bf,1,l);
  14.    if copy(s,1,l div 2)<>copy(s,l div 2+1,l div 2)
  15.    then begin
  16.    susch:=true;
  17.    break;
  18.    end;
  19.    delete(bf,1,l)
  20.   end;
  21.  end;
  22.  function ficList(bf: String; k: Byte):String;
  23.    var l:byte;
  24.        i:byte;
  25.        FicL:string;
  26.  begin
  27.   FicL:='';
  28.     if Susch(bf,k)=false then FicL:=FicL+chr(k)+',' else writeln('net');
  29.     FicList:=Ficl;
  30.  end;
  31. begin
  32.  writeln('vvedite bf');
  33.  readln(bf);
  34.  writeln('vvedite kolichestvo peremennih');
  35.  readln(n);
  36.  writeln('vvedite proveryaemyu peremennyu');
  37.  readln(k);
  38.  Writeln(ficList(bf,k));
  39. end.

подскажите ошибки и объясните,если проверять 9 переменных,то обязательно нужен массив?

Никита, опередил))

Никита, опередил))

Простите,сразу программу

Простите,сразу программу выдала

Ксюша

В 28 - й строке:

  1. ...
  2.  If Susch(bf,k)=false then FicL:=FicL+chr(k)+',' else writeln('net');
  3. ...

чтобы перевести переменную к в знак 'к' необходимо воспользоваться следующей формулой c=chr(ord('0')+k);
И тогда уже так:
  1. ...
  2.  If Susch(bf,k)=false then FicL:=FicL+chr(ord('0')+k);+',' else writeln('net');
  3. ...

Никит,спасибо) с этим

Никит,спасибо) с этим мучалась, не выводил нормальные цифры,грешила на АВС уже

Ксюша

Но можно ещё воспользоваться стандартной процедурой str(i,c);, которая переводит i ( вещественного или целочисленного типа) в строку с

а для 9 всё же массив нужен?

а для 9 всё же массив нужен? просто изначально делала как у тебя.но выводило кучу номеров(точнее квадратиков,т.к. 28 строка не верна),вместо одного

запомню)

запомню)

Думаю что не нужен

Мы циклом for перебираем переменные от 1 до 9

да,ну и ввод номеров

да,ну и ввод номеров переменных тоже в цикле for?

Ксюш

Ты имеешь в виду создание списка FicL ?