Лабораторная работа по ММИПиУ Задание. 1. Перевести свой студенческий шифр в двоичную систему счисления. 2. Построить таблицу значений функции, соответствующей полученному двоичному коду, найти минимальную ДНФ этой функции и выполнить проверку. 3. Построить дешифратор для двоичного кода, полученного в пункте 1 задания. 4. Создать программу, реализующую работу полученного дешифратора. Пример выполнения лабораторной работы. 1. Перевести число из десятичной записи в двоичную можно, например, воспользовавшись математическим пакетом Derive (Сетевые приложения, папка Математика). Для этого в окне Derive нужно: 1) установить вывод в двоичной системе счисления: Options Mode Settings Output Radix Binary 2) набрать десятичное число (в нашем примере – 186071) в строке ввода и нажать Enter – в рабочей области отобразится двоичный эквивалент введенного десятичного числа: 101101011011010111. 2. Т.к. полученный двоичный код содержит 18 значений, ему в соответствие можно поставить булеву функцию, зависящую от 5-ти переменных. При этом у такой функции последние 14 значений (из 32-х возможных) не будут определены, т.е. такая функция будет не полностью определенной (частичной). Найдем минимальную ДНФ частичной функции f(x,y,z,t,w)=(1011 0101 1011 0101 11- - - - - - - - - - - - - - ). При отыскании минимальной ДНФ будем использовать двухслойные карты Карно (верхний слой – при x=0, нижний – при x=1). При построении покрытий максимального размера при необходимости будем в клетках с прочерками доопределять функцию единичными значениями. Строим таблицу f(x,y,z,t,w): tw 00 01 10 11 xyz 000 1 0 1 1 001 0 1 0 1 010 1 0 1 1 011 0 1 0 1 100 101 110 111 1 - 1 - - - Строим Карты Карно: 1-е двухслойное покрытие: 2-е двухслойное покрытие: tw tw tw 00 01 11 10 00 01 11 10 00 01 11 10 xyz xyz xyz 1 1 000 000 000 1 0 1 1 1 0 1 1 0 1 1 001 001 001 0 1 1 0 0 1 0 0 1 1 0 011 011 011 0 1 1 0 0 1 1 0 0 1 1 0 1 1 010 010 010 1 0 1 1 1 0 1 1 0 1 100 101 111 110 1 - 1 - - - 100 101 111 110 1 - 1 -1 -1 - -1 -1 - zw 3-е двухслойное покрытие: tw 00 01 11 10 xyz 1 000 1 0 1 001 0 1 1 0 011 0 1 1 0 1 010 0 1 1 100 101 111 110 1 -1 1 -1 -1 - -1 -1 -1 -1 -1 -1 Однослойное покрытие: tw 00 01 11 10 xyz 000 1 0 1 1 001 0 1 1 0 011 0 1 1 0 010 1 0 1 1 100 101 111 110 1 -1 -1 -1 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 - 1 -1 1 -1 -1 - -1 -1 - -1 -1 z w Окончательно получаем: tw 00 01 11 10 xyz 1 000 1 0 1 1 001 0 1 0 011 0 1 1 0 010 1 0 1 1 100 101 111 110 100 101 111 110 1 -1 -1 -1 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 Проверка: x t wy z false false 00 false x y false z false false false false false 000 1 false false false 001 0 false false true false false true 011 0 false false true false 010false true 1 false true false 100true false true 101true false false 111true false true 110true false false true true false true false false false 1 false false true true true true false false t false 01 false true 0 true 1 false false 1 true true 0 false false 1 true true false false true true false false w f(x,y,z,t,w) false true 11 10 true false false 1 1 true true true 1 0 false false true true 1 0 false false true1 true 1 false true true- false false true true- true false- false true true false- false true true false true true true tw x Минимальная ДНФ: f(x,y,z,t,w) = z w z w t w x. Проверим, что все слагаемые в ДНФ найдены правильно и задают все единичные значения функции. Для этого в Derive построим таблицу значений функции по найденной ДНФ. Для построения таблицы значений логической функции используется встроенная функция TRUTH_TABLE(x1,…,xn, f(x1,…xn)). Изменить порядок строк в полученной таблице на противоположный можно функцией REVERSE(). Введем в строку ввода: REVERSE(TRUTH_TABLE(x, y, z, t, w, (z ∧ w) ∨ (¬ z ∧ ¬ w) ∨ (t ∧ w) ∨ x)) и Ctrl+Enter. 3. Построим дешифратор для двоичного кода 101101011011010111. Дешифратором называется конечный автомат, выходным алфавитом которого является множество {0,1}, причем на вход подается бесконечная последовательность символов некоторого алфавита. Символ 1 печатается в том и лишь в том случае, если в данный момент считывающее устройство автомата обозревает последний символ уже считанного слова , фиксированного для данного автомата, а на ленте записана последовательность символов, в которую входит . Слово называется кодовой комбинацией этого автомата. Дешифратор должен уметь распознавать все вхождения своей кодовой комбинации в заданную последовательность символов. Составим таблицу состояний дешифратора, содержащего 18 внутренних состояний (по числу символов заданной кодовой комбинации 101101011011010111). Вспомогательная таблица: Если дешифратор находится в значит, прочитано состоянии qi+1, начало кода длины i: q1 101101011011010111 q2 101101011011010111 q3 101101011011010111 q4 101101011011010111 q5 101101011011010111 q6 101101011011010111 q7 101101011011010111 q8 101101011011010111 q9 101101011011010111 q10 101101011011010111 q11 101101011011010111 q12 101101011011010111 q13 101101011011010111 q14 101101011011010111 q15 101101011011010111 q16 101101011011010111 q17 101101011011010111 q18 101101011011010111 Промежуточная таблица: A Окончательная Выделяем наибольший отрезок, совпадающий с таблица: началом кода и A Q 0 1 Q 0 1 q1 q2 q3 q4 q5 q6 q7 q8 q9 q10 q11 q12 q13 q14 q15 q16 q17 q18 q1,0 q3,0 q2 ,0 q2 ,0 q6,0 q3,0 q8,0 q4,0 q2 ,0 q11,0 q2 ,0 q1 ,0 q14,0 q8 ,0 q16,0 q2 ,0 q4 ,0 q2 ,0 q2,0 q2,0 q4,0 q5,0 q2 ,0 q7,0 q2,0 q9,0 q10,0 q2,0 q12,0 q13,0 q2 ,0 q15,0 q2 ,0 q17,0 q18,0 q19,1 q1 q2 q3 q4 q5 q6 q7 q8 q9 q10 q11 q12 q13 q14 q15 q16 q17 q18 q1,0 q3,0 q1,0 q3,0 q6,0 q1,0 q8,0 q1,0 q3,0 q11,0 q1,0 q8,0 q14,0 q1,0 q16,0 q1,0 q3,0 q11,0 q2,0 q2,0 q4,0 q5,0 q2,0 q7,0 q5,0 q9,0 q10,0 q2,0 q12,0 q13,0 q2,0 q15,0 q5,0 q17,0 q18,0 q2,1 содержащий идущие подряд символы последовательности, включая последний: 11 100 1010 10111 101100 1011011 10110100 101101010 1011010111 10110101100 101101011010 1011010110111 10110101101100 101101011011011 1011010110110100 10110101101101010 101101011011010110 101101011011010111 Пояснения к построению таблицы дешифратора. 1) Строим вспомогательную таблицу. Дешифратор начинает свою работу в состоянии q1 и будет переходить в каждое последующее qi+1-е состояние только при считывании очередного i-го символа кодовой комбинации. Другими словами, если дешифратор находится в состоянии qi+1, это равносильно тому, что он распознал первые i символов кодовой комбинации. Здесь i=1,…,17. 2) Строим промежуточную таблицу, в которой указываем переходы дешифратора из состояния в состояние при последовательном чтении символов заданной кодовой комбинации. При этом выходной символ будет равен 1 в одном единственном случае – когда дешифратор находится в последнем состоянии (в нашем случае в q18) и входным символом является последний символ заданной кодовой комбинации (в нашем случае 1). 3) Строим окончательную таблицу, добавляя недостающие переходы в промежуточную таблицу. При этом состояние, в которое перейдет дешифратор, определяем по получаемой последовательности символов. Выделяем в ней наиболее длинный отрезок, который может служить началом заданной кодовой комбинации. По вспомогательной таблице определяем, какому из состояний соответствует выделенный отрезок (начало кодовой комбинации), и это состояние указываем как состояние перехода. Рассмотрим, как строится каждая из таблиц, на примере первых четырех строк: 0 1 0 1 q1 q1 q1,0 q2,0 q1 q1,0 q2,0 101101011011010111 q2 q2 q3,0 q2,0 q2 q3,0 q2,0 11 101101011011010111 q3 q3 q2 ,0 q4,0 q3 q1,0 q4,0 100 101101011011010111 q4 q4 q2 ,0 q5,0 q4 q3,0 q5,0 1010 101101011011010111 Вспомогательная таблица. Если дешифратор находится в состоянии q1, то ни один символ кодовой комбинации еще не распознан; если дешифратор находится в состоянии q2, то распознан первый символ кодовой комбинации, если в состоянии q3, то распознаны первые 2 символа кодовой комбинации и т.д. Окончательная таблица. 1-я строка. Если дешифратор находится в состоянии q1 и на вход поступает символ 0, то дешифратор остается в этом же состоянии, т.к. 0 не является началом кодовой комбинации; если в состоянии q1 на вход поступает 1, то дешифратор переходит в q2 – распознан 1-й символ кодовой комбинации. 2-я строка. Если дешифратор находится в q2 (т.е. считан символ 1), и на вход поступает 0, то переходим в q3, т.к. распознаны первые 2 символа кодовой комбинации – 10. Если дешифратор находится в q2 и на вход поступает 1, то переходим в q2, т.к. в полученной последовательности 11 только последний символ может служить началом кодовой комбинации (он обведен в рамку). А такое распознанное начало кодовой комбинации равносильно тому, что дешифратор находится в состоянии q2. 3-я строка. Если дешифратор в состоянии q3 (распознано 10), и на вход поступает 0, то в последовательности 100 никакой целый фрагмент, включающий последний символ, не может служить началом кодовой комбинации, поэтому переходим в q1 (ничего не распознано). Если же в q3 на вход поступила 1, то распознано 101, переходим в q4. 4-я строка. Если в q4 (распознано 101) на вход поступил 0, то в 1010 все символы, включая последний, не могут служить началом кодовой комбинации, и символы 010 (начиная со второго) также не являются началом кодовой комбинации, а 10 (начиная с третьего) – начало заданной кодовой комбинации. То, что 10 распознано, равносильно тому, что дешифратор находится в состоянии q3, и т.д. 4. Программа, реализующая работу дешифратора, может иметь следующий вид: program Deshifrator; const q0: array [1..18] of byte = (1,3,1,3,6,1,8,1,3,11,1,8,14,1,16,1,3,11); q1: array [1..18] of byte = (2,2,4,5,2,7,5,9,10,2,12,13,2,15,5,17,18,2); var fi:text; ch:char; CurrentState: byte; begin assign(fi,'input.txt'); reset(fi); CurrentState := 1; while not eof(fi) do begin read(fi,ch); if (ch = '0') then begin CurrentState := q0[CurrentState]; end else if (ch = '1') then begin if (CurrentState = 18) then writeln('The code was found.'); CurrentState := q1[CurrentState]; end; end; writeln('End of file. Press Enter.'); readln; end. Пусть файл input.txt, который обрабатывает программа, содержит следующую последовательность символов: 000101101011011010111011010110110101111101101011011010110110101111 Заданная кодовая комбинация 101101011011010111 в данной последовательности встречается 3 раза. Первое и последнее еѐ вхождение обведены в рамки, а второе закрашено: 000101101011011010111011010110110101111101101011011010110110101111 Сразу после считывания последнего символа кодовой комбинации (при каждом ее обнаружении) программа выдаст сообщение: 'The code was found.'. Таких сообщений в нашем примере будет 3.