#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.