Конечный автомат в схеме

#scheme #racket

#схема #ракетка

Вопрос:

Я пытаюсь завершить конечный автомат в схеме. Проблема в том, что я не уверен, как сообщить ему, какие символы он должен тестировать. Если я хочу протестировать строку «abc112», то как мне это сделать?

Вот код:

 #lang racket    
(define (chartest ch)
  (lambda (x) (char=? x ch)))
;; A transition is (list state char!boolean state)
(define fsmtrlst 
  (list
   (list 'start char-alphabetic? 'name)
   (list 'start char-numeric? 'number)
   (list 'start (chartest #() 'lparen)
   (list 'start (chartest #)) 'rparen)
   (list 'name char-alphabetic? 'name)
   (list 'name char-numeric? 'name)
   (list 'number char-numeric? 'number)))

(define (find-next-state state ch trl)
  (cond
    [(empty? trl) false]
    [(and (symbol=? state (first (first trl)))
          ((second (first trl)) ch))
     (third (first trl))]
    [else (find-next-state state ch (rest trl))]))

(define fsmfinal '(name number lparen rparen))

(define (run-fsm start trl final input)
  (cond
    [(empty? input)
     (cond
       [(member start final) true]
       [else false])]
    [else
     (local ((define next (find-next-state start (first input) trl)))
       (cond
         [(boolean? next) false]
         [else (run-fsm next trl final (rest input))]))]))
  

И вот код запуска, который я пытаюсь протестировать:

 (fsmtrlst (list 'start (lambda (abc112) (char=? abc112 ))))
  

Редактировать:

хорошо, .. в целом продукт в порядке, но мой преподаватель им недоволен,.. он хочет, чтобы я создал конечный автомат с функцией перехода -> что-то вроде глобального определения, которое гласило бы: когда в состоянии X появляется символ Y, перейдите к Z … и затем я протестирую список символов, чтобы увидеть, является ли это false или true … Таким образом, единственное отличие заключается в том, что код не должен быть специфичным для использования только цифр и букв, но и любого символа… возможно ли это каким-то образом? спасибо за ваш ответ

ПРАВКА 2: теперь у меня есть основная информация о том, как это должно выглядеть:

То есть машина выглядит как

A ———> B ———-> C ———-> D ———-> ( E) буква номер, цифра, буква

 (define fsmtrlst
 (list
   (list 'A char-alphabetic? 'B)
   (list 'B char-numeric? 'C)
   (list 'C char-numeric? 'D)
   (list 'D char-alphabetic 'E)))

(define fsmfinal '(E))

(define fsmstart 'A)
  

но я не уверен, как написать определение fsmstart.

Спасибо за ответы.

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

ПРАВКА 3: Я использую онлайн-руководства и книгу, предоставленную моим наставником. Я разобрался с fsm, который хотел создать. Спасибо за вашу помощь.

Просто из любопытства:

Чем бы отличался довольно специфичный fsm?

Пример:

НАЧАЛО —-«b»——> СОСТОЯНИЕ A ——«a» —-> СОСТОЯНИЕ B ——«c»——> КОНЕЧНОЕ СОСТОЯНИЕ

Что fsm будет истинным только тогда, когда в списке символов есть «bac» и ничего больше. Возможно ли это?

Спасибо за ваш отзыв.

ПРАВКА 4:

Хорошо, мне удалось выполнить write, но еще раз, я не уверен, как производить ввод символов. Это код:

Существует 3 состояния, но это будет верно только при переходе из состояния A в состояние C.

     (define (chartest ch)
    (lambda (x) (char=? x ch)))

    (define fsm-trans
       '((A, "a", B), (A, "b", A), (B, "c", C)))

    (define (find-next-state state ch trl)
      (cond
        [(empty? trl) false] 
        [(and (symbol=? state (first (first trl)))
              ((second (first trl)) ch)) <- And also this line returns an error
         (third (first trl))]
        [else (find-next-state state ch (rest trl))]))


    (define fsm-final '(C))

    (define start-state 'A)

    (define (run-fsm start trl final input)
      (cond
        [(empty? input)
         (cond
           [(member start final) true]
           [else false])]
        [else 
         (local ((define next (find-next-state start (first input) trl)))
           (cond
             [(boolean? next) false]
             [else (run-fsm next trl final (rest input))]))]))


    (run-fsm start-state fsm-trans fsm-final (list '("a", "c")))  <- I know this is the last problem with the code, the definition of the input. How can I tell Scheme what characters I want to test?
  

Спасибо за ваш ответ!!!

Комментарии:

1. Пожалуйста, сделайте отступ в своем коде, чтобы сделать его читабельным. Кроме того, что должен делать конечный автомат?

2. @Heatsink: Я импортировал код в dr-scheme и сошел с ума от клавиши tab

3. В Emacs вы могли бы просто выполнить C-A-. Просто говорю.

4. Я обновил свой ответ, но я беспокоюсь, что вы зацикливаетесь на небольших проблемах, которые можно было бы лучше решить, попробовав более простое упражнение. Используете ли вы учебное пособие по scheme или книгу в дополнение к своему обучению?

Ответ №1:

Мне любопытно: я так понимаю, вы не писали этот fsm? Это для домашнего задания или вы пытаетесь научить себя? Код для FSM выглядит нормально (на самом деле, довольно хорошо). Однако ваша строка запуска:

 (fsmtrlst (list 'start (lambda (abc112) (char=? abc112 ))))
  

Не имеет смысла. Вот почему: fsmtrlst это список переходов конечного автомата. Он был определен в первом большом блоке кода. Это не функция, которую нужно вызывать. Я полагаю, что функция, которую вы хотите вызвать, является run-fsm . Для этого требуется начальный символ, список переходов, список конечных состояний и входные данные. Входные данные на самом деле представляют собой не строку, а список. Как следствие, вы можете запустить его с помощью следующей строки:

 (run-fsm 'start fsmtrlst fsmfinal (string->list "abc112"))
  

Это вызовет run-fsm с определенным списком переходов fsmtrlst , определенным списком конечных состояний и готовой к вводу формой строки «abc112».

Между прочим, все, кроме 'start , определено как конечное (принимающее) состояние. Однако не все входные данные принимают входные данные. Например, замена «abc122» на «abc(122» не принимается.

Это то, чего вы хотите?

Обновить:

Ваша правка прояснила ситуацию. Ваше определение fsmstart прекрасно. Вы пропустили знак вопроса (?) в одном из ваших char-alphabetic? использований в fsmtrlst . Вас смущает то, что вы не знаете, как использовать ваши новые определения? Во-первых, вы должны удалить старые определения fsmtrlst и fsmfinal . В противном случае вы, скорее всего, получите ошибку дублирования определения. Из вашего нового определения ваша строка для выполнения должна выглядеть следующим образом:

 (run-fsm fsmstart fsmtrlst fsmfinal (string->list "w00t"))
  

Это вернет #t , потому что «w00t» — это символ, за которым следуют два числа, за которыми следует символ.

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

ОБНОВЛЕНИЕ 2: Не следует ли вам подумать о формулировании нового вопроса?

Ваше последнее обновление привело к нарушению кода. Переходная часть fsm работала, потому что переходы были определены в виде списка:

 (from-state test-function to-state)
  

Вы попытались создать переход:

 (from-state string-literal to-state)
  

Вы могли бы изменить (A, "a", B) на (A (lambda (x) (string=? x "a") B) .

Когда вы попытались вызвать свою функцию, вы взяли функцию, которая ожидала получить список символов, и передали ей список строк. Это не одно и то же. Кроме того, вы заметили, что вы ставили запятые в своих списках, но они больше нигде не существовали в коде? Именно из-за этих ошибок я предлагаю вам начать с руководства по scheme. Это основные проблемы схемы, не связанные с вашим конкретным упражнением. Я предлагаю вам перемотать ваши правки к тому, что у вас было вчера.

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

Комментарии:

1. Я отредактировал (несколько раз) свой вопрос. Я сталкиваюсь с последними проблемами перед завершением fsm.