Перевод римских чисел в арабские. Пример автоматного распознавателя

Задача

 

Можно использовать вложенные операторы case. Это удобно, например, при реализацииавтоматных распознавателей, которые дают способ наглядной записи алгоритмов распознавания текстов.

Представленная таблица предназначена для перевода римских чисел, составленных из цифр X, V, I.

 

Решение

Алгоритм решения задачи: 

  X V I
1 n := 10; state := 2 n := 5; state := 3 n := 1; state := 6
2 n := n + 10; state := 2 n := n + 5; state := 3 n := n + 1; state := 6
3 ok := false ok := false n := n + 1; state := 4
4 ok := false ok := false n := n + 1; state := 5
5 ok := false ok := false n := n + 1; state := 7
6 n := n + 8; state := 7 n := n + 3; state := 7 n := n + 1; state := 5
7 ok := false ok := false ok := false

Первый столбец (цифры от 1 до 7) – это состояния (state).

Для расшифровки XIV начинаем с состояния 1. Первый символ – ‘X’, поэтому смотрим столбец ‘X’ и находим n := 10; state := 2. Итак, полагаем n равным 10 и сдвигаем стрелку на вторую строку. Теперь смотрим столбец, определяемый вторым символом, т.е. ‘I’, и находим n := n + 1; state := 6. Значение n, таким образом, становится 10 + 1 = 11. Сдвигаем стрелку к строке 6. Теперь в столбце ‘V’ находим n := n + 3; state := 7. Значение n становится равным 11 + 3 = 14. Сдвигаем стрелку на строку 7 и замечаем, что любая следующая цифра ‘X’, ‘V’ или ‘I’ будет теперь ошибкой (чисел XIVX, XIVV, XIVI не может быть).

Эта таблица позволяет декодировать римскую запись чисел, содержащих любое количество цифр X (в начале) и цифры V, I, записанные по обычным правилам:
I, II, III, IV, V, VI, VII, VIII, IX, X, XI и т.д.

Вместе с тем такое число как IIII будет воспринято как ошибочное и переменная ok примет значение false. Для работы с цифрами M, D, C и L таблицу можно расширить.

Программа на языке Паскаль: 

var
    n, state: integer;
    symbol: char;
    ok: boolean;
 
begin
    state := 1;
    ok := true;
    n := 0;
 
    while not eoln do begin
        read(symbol);
        if ((symbol = 'X') or (symbol = 'V') or (symbol = 'I')) then
            case state of
            1: case symbol of
                'X': begin n := 10; state := 2 end;
                'V': begin n := 5; state := 3 end;
                'I': begin n := 1; state := 6 end
               end;
            2: case symbol of
                'X': begin n := 10; state := 2 end;
                'V': begin n := n + 5; state := 3 end;
                'I': begin n := n + 1; state := 6 end
               end;
            3: case symbol of
                'X', 'V': ok := false;
                'I': begin n := n + 1; state := 4 end
               end;
            4: case symbol of
                'X', 'V': ok := false;
                'I': begin n := n + 1; state := 5 end
               end;
            5: case symbol of
                'X', 'V': ok := false;
                'I': begin n := n + 1; state := 7 end
               end;
            6: case symbol of
                'X': begin n := n + 8; state := 7 end;
                'V': begin n := n + 3; state := 7 end;
                'I': begin n := n + 1; state := 5 end
               end;
            7: ok := false;
            end
            else begin
                if ok then
                    writeln(n:2)
                else
                    writeln('error');
                state := 1;
                ok := true
            end;
        end;
readln
end.

Примечания: 

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

Тема

Циклы

Уровень

Сложные задачи

Теги

Комментарии

Вот так работает. Я там ещё кое-что подредактировала под себя:

program p1;
uses crt;
label gb;
var
    i,n,state:integer;
    symbol:char;
    str:string;
    ok:boolean;
 
begin
clrscr;
    state := 1;
    ok:=true;
    n := 0;
    gb:
    readln(str);
    for i:=1 to length(str) do
    begin
    symbol:=str[i];
        if ((symbol = 'X') or (symbol = 'V') or (symbol = 'I')) then
        begin
            case state of
            1: case symbol of
                'X': begin n := 10; state := 2; continue; end;
                'V': begin n := 5; state := 3; continue; end;
                'I': begin n := 1; state := 4; continue; end;
                end;
            2: case symbol of
                'X': begin n :=n+10; if i>3 then begin ok:=false; break; end else continue; end;
                'V': begin n := n + 5; state := 3; continue; end;
                'I': begin n := n + 1; state := 4; continue; end
               end;
            3: case symbol of
                'X', 'V': begin ok := false; break; end;
                'I': begin n := n + 1; state:=4; continue; end
               end;
            4: case symbol of
                'X':begin n:=n+8; break; end;
                'V': begin n:=n+3; break; end;
                'I': begin n := n + 1; state := 5; continue; end
               end;
            5: case symbol of
                'X', 'V': begin ok := false; break; end;
                'I': begin n := n + 1; state := 6; continue; end
               end;
            6: begin ok:=false; break; end;
            end;
            end
            else
            begin
                    writeln('Error, try typing in capital letters. '); goto gb;
            end;
            end;
            if not ok then begin write('The number was incorrect. Try again. '); goto gb; end else write(n);
end.

var
    n,i, state: integer;
    symbol: char;
    ok: boolean;
    s:string[4];
 
begin
    state := 1;
    ok := true;
    n := 0;
 symbol := 'X';i:=0;
s:='XIV'; 
{ s[1]:='X';
  s[2]:='V';
  s[3]:='I';
  s[4]:='I';}
    for i:=1 to 4
      do begin symbol := s[i];writeln('-----',symbol);
        if ((symbol = 'X') or (symbol = 'V') or (symbol = 'I')) then
            case state of
            1: case symbol of
                'X': begin n := 10; state := 2 end;
                'V': begin n := 5; state := 3 end;
                'I': begin n := 1; state := 6 end
               end;
            2: case symbol of
                'X': begin n :=n+ 10; state := 2 end;
                'V': begin n := n + 5; state := 3 end;
                'I': begin n := n + 1; state := 6 end
               end;
            3: case symbol of
                'X', 'V': ok := false;
                'I': begin n := n + 1; state := 4 end
               end;
            4: case symbol of
                'X', 'V': ok := false;
                'I': begin n := n + 1; state := 5 end
               end;
            5: case symbol of
                'X', 'V': ok := false;
                'I': begin n := n + 1; state := 7 end
               end;
            6: case symbol of
                'X': begin n := n + 8; state := 7 end;
                'V': begin n := n + 3; state := 7 end;
                'I': begin n := n + 1; state := 5 end
               end;
            7: ok := false;
            end
            else begin
                if ok then
                    writeln(n:2)
                else
                    writeln('error');
                state := 1;
                ok := true
            end; writeln(n:2)
        end; 
end.

Добавить комментарий