I am trying to finish a finite state machine in Scheme. The problem is, that I am not sure how to tell it what characters it should test. If I want to test a String "abc112" then how do I do that?
Here is the code:
#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))]))]))
And here is the launch code which I am trying to test:
(fsmtrlst (list 'start (lambda (abc112) (char=? abc112 ))))
EDIT:
ok,.. the overall product is okey, but my tutor is not happy with it,.. he wants me to make a finite state machine with transition function -> something like a global definition which would say: when in state X comes character Y go to Z ... and then i will test a list of characters to see if it is false or true ... So the only difference is that the code shouldn't be specific to use only numbers and letters but any character... is it somehow possible? thank you for your answer
EDIT 2: now I have the basic info how it should look like:
That is, the machine looks like
A ---------> B ----------> C ----------> D ----------> (E)
letter number number letter
(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)
but i am not sure how to write the definition of fsmstart.
Thank you for answers.
This accepts sequences of exactly four characters which are letter, number, number, letter, and nothing else.
EDIT 3: I am using tutorials online and a book that my mentor teacher provided. I figured out the fsm I wanted to make. Thank you for your help.
Just out of curiosity:
How would differ to have rather specific fsm?
Example:
START ----"b"-----> STATE A -----"a" ----> STATE B -----"c"-----> FINAL STATE
That the fsm would be true only when the list of characters is "bac" and nothing else.
Is it possible?
Thank you for your feedback.
EDIT 4:
Ok, I managed to do write but once again, I am not sure how to make the input of characters. This is the code:
There are 3 states but it will be true only when going from state A to state 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?
Thank you for your answer!!!
I am curious: I take it you did not write this fsm? Is this for a homework assignment or are you trying to teach yourself? The code for the FSM looks fine (quite fine, in fact). However, your launch line:
(fsmtrlst (list 'start (lambda (abc112) (char=? abc112 ))))
Makes no sense. Here is why: fsmtrlst is the finite state machine transition list. It was defined in the first big block of code. It is not a function to be called. I believe the function you want to call is run-fsm. That takes a start symbol, a transition list, a list of final states, and an input. The input is not actually a string, but a list. As a consequence, you can launch it with the following line:
(run-fsm 'start fsmtrlst fsmfinal (string->list "abc112"))
That will call run-fsm with the defined transition list fsmtrlst, the defined list of final states, and the input-ready form of the string "abc112".
Incidentally, everything except 'start is defined to be a final (accepting) state. Not all inputs are accepting inputs, though. For example, replacing "abc122" with "abc(122" is not accepted.
Is this what you want?
Update:
Your edit has clarified things. Your definition of fsmstart is fine. You did miss a question mark (?) on one of your char-alphabetic? usages in fsmtrlst. Is your confusion that you don't know how to use your new definitions? First, you should remove the old definitions of fsmtrlst and fsmfinal. Otherwise, you will likely get a duplicate definition error. From your new definition, your line to execute should look like:
(run-fsm fsmstart fsmtrlst fsmfinal (string->list "w00t"))
This will return #t, because "w00t" is a character followed by two numbers, followed by a character.
I speculate that you are still having difficulty with the syntax rules of scheme, and not just problems with the logic of your particular program. You might want to try a simpler exercise.
UPDATE 2: Shouldn't you consider formulating a new question?
Your most recent update has broken the code. The transition portion of the fsm worked because transitions were defined as a list:
(from-state test-function to-state)
You have attempted to create a transition:
(from-state string-literal to-state)
You could change (A, "a", B) to (A (lambda (x) (string=? x "a") B).
When you tried to invoke your function, you took a function that expected a list of characters and gave it a list of list of strings. These are not the same thing. Also, did you notice that you put commas in your lists, but they existed nowhere else in the code? These mistakes are why I suggest you begin a scheme tutorial. These are basic scheme problems, unrelated to your particular exercise. I suggest you rewind your edits to what you had yesterday.
Unfortunately, I can no longer update this answer. I wanted to update my answer so that if someone came along your question with similar concerns, they would see a complete answer. However, you have provided a moving target. Please consider halting your edits and submit a new question when you have one.
Related
This is a homework question
The function takes in a list as the parameter, which may contain as many layers as sublists as needed For example, '(a (1 b 3)) or '((a 3 5) (b (3 1) 4)). The output has the same list structure of the input (meaning that sublists are maintained), but the car of each list is the sum of all numbers in the list. And all other non-numeric values are discarded. As an example output, consider '((a 3 5) (b (3 1) 4)), the output should be '(16 (8) (8 (4))). Also, only use basic scheme instructions/operations such as + - * /, car, cdr, cons, append, null?, number?, if/else, cond, etc.. Cannot Use a helper method.
So far this is the code I have, which sometimes partially does the job. But I'm having a really hard time figuring out how to get the sum from the sublists to add up at one spot at the car of the outmost list.
(define partialsums*
(lambda (lis)
(cond
[(null? lis) '(0)]
[(list? (car lis)) (cons (partialsums* (car lis)) (if (not (null? (cdr lis))) (partialsums* (cdr lis)) '()))]
[(number? (car lis)) (cons (+ (car lis) (car (partialsums* (cdr lis)))) '())]
[else (cons (+ 0 (car (partialsums* (cdr lis)))) '())])))
I've already spent several hours on this but couldn't quite grasp how to correctly approach the problem, probably because this is my first week using scheme :(. Any help is appreciated.
Also, I cannot use a helper method. Everything needs to be done inside one function in a recursive style. letrec is not allowed either.
To make life easy, you should model the data. Since there are no types, we can do this informally.
What is the structure of the input?
We can model it like "Data Definitions" from How to Design Programs. Read the "Intertwined Data" section because our data definition is similar to that of an S-expression.
; A NestedElem is one of:
; - Atom
; - NestedList
; An Atom is one of:
; - Number
; - Symbol
; A NestedList is one of
; - '()
; - (cons NestedElem NestedList)
We can define an atom? predicate to help us differentiate between clauses of the kinds of data in our program.
; Any -> Boolean
; is `a` an atom?
(define atom?
(lambda (a)
(or (number? a)
(symbol? a))))
The structure of the program should match the structure of the Data.
So we define a "template" on our data. It distinguished and destructs each data into clauses. It further de-structures the rhs of a clause.
; NestedElem -> ...
(define nested-elem-template
(lambda (ne)
(cond
[(atom? ne) ...]
[else ...])))
; Atom -> ...
(define atom-template
(lambda (atom)
(cond [(number? atom) ...]
[(symbol? atom) ...])))
; NestedList -> ...
(define nested-list-template
(lambda (nl)
(cond [(null? nl) ...]
[else (... (car nl)... (cdr nl))])))
We definitely know more about the data. (car nl) in the nested-list-template is of type NestedElem. Therefore we can fill up some ...s with calls to templates that deal with that kind of data. In the same vein, we can wrap recursive calls around expressions of a datatype we know of.
; NestedElem -> ...
(define nested-elem-template
(lambda (ne)
(cond
[(atom? ne) (atom-template ne)]
[else (nested-list-template ne)])))
; Atom -> ...
(define atom-template
(lambda (atom)
(cond [(number? atom) ...]
[(symbol? atom) ...])))
; NestedList -> ...
(define nested-list-template
(lambda (nl)
(cond [(null? nl) ...]
[else (... (nested-elem-template (car nl))
... (nested-list-template (cdr nl)))])))
Now we can "fill in the blanks".
We can "filter", "map", and "fold" over this data structure. All those can be defined using the template as a scaffold.
Note 1: Your HW asks you to do multiple tasks:
remove the symbols
sum up the numbers
cons the sum onto every list
Don't try to do everything in a single function. Delegate into multiple helper functions/traversals.
Note 2: I did not model the output type. It's the same as input type except that Symbol is no longer an atom.
I am trying to learn typed scheme/racket(?). Down below I have an example from my code:
#lang typed/racket
(: add (Real Real -> Real))
(define (add x y)
(+ x y))
I would like to implement a procedure "check" which checks if two datatypes are allowed with an operator. For example,
(check '(+ int int))
Should result in
int
But
(check '(* int (+ real int)))
Should result in something like this:
The operator '+' must have two operands of the same (numerical) type.
That is, check should take a list.
Questions:
How do I implement "check"? Firstly I though "ok, I have a list, so let's use car and cdr" to get the operator and the operands but it didn't work and I don't even know why it doesn't work. I also though about making if statements like (if (and (= x y) (or (= x int) (= y int)) and so on to make the checks but... don't think this is the right way to go.
Should I make a procedure "add" or not? Is there any other way to do this? Int the examples it looks like they are only using "+", "-" and so on. Lastly; How do I check that the input "int" is an int and then gives int as output.
I am pretty lost right now and I am sorry for my pretty vaugue questions but I would be really happy if someone could help me out to understand this.
Note: the procedure add takes real numbers and output a real number so it doesn't follow along with the example too well. But I hope you grasp the idea. Thanks :)
You're asking a fascinating question, and it doesn't have a simple answer.
The program that you're trying to write is essentially a type-checker. That is, it takes an expression, and checks to see whether the given function's domain includes the arguments it's being called with. We can write one of those, but I suspect you're going to be unsatisfied. Here, let me go write one now....
#lang typed/racket
(require typed/rackunit)
;; a type is either
;; - 'number, or
;; - (list 'fn list-of-types type)
;; examples of types
'number
'(fn (number number) number)
(define-type FnTy (List 'fn (Listof Ty) Ty))
(define-type Ty (U 'number FnTy))
;; given an expression, returns a type
;; or signals an error
(: check (Any -> Ty))
(define (check input)
(cond [(and (list? input)
(pair? input)
(symbol? (car input)))
(define fn-ty (lookup-fn-type (car input)))
(define arg-types (map check (rest input)))
(cond [(equal? (cadr fn-ty) arg-types)
(caddr fn-ty)]
[else (error 'check
"expression didn't type-check: ~v\n"
input)])]
[(number? input)
'number]
[else (raise-argument-error
'check
"well-formed expression"
0 input)]))
(: lookup-fn-type (Symbol -> FnTy))
(define (lookup-fn-type fn-name)
(match fn-name
['+ '(fn (number number) number)]
[other (raise-argument-error 'lookup-fn-type
"known function name"
0 fn-name)]))
(define TEST-INPUT '(+ 3 43))
(check-equal? (check TEST-INPUT)
'number)
(check-equal? (check '(+ (+ 3 4) 129837))
'number)
Does this answer any part of your question?
I am trying to write a function that can check whether or not some input is a quotation for a syntax checker.
I have the following code:
(define is-quote-expression?
(lambda (v)
(equal? (car v) 'quote)
(is-quotation? (cdr v)))))
(define is-quotation?
(lambda (v)
(or (number? v)
(boolean? v)
(char? v)
(string? v)
(symbol? v)
(null? v)
(and (pair? v)
(is-quotation? (car v))
(is-quotation? (cdr v)))))
When I try to evaluate, I get the following:
(is-quote-expression? '1)
#f
(is-quote-expression? (cons 'quote 1))
#t
I think my TA told me that the Scheme environment replaced all "'" with "'quote", however, this does not seem to be the case. We are running Petite Chez Scheme.
What am I not seeing?
Thanks in advance.
There are a couple of problems with your code, for starters the (lambda (pair? v) part in is-quote-expression? is almost certainly a mistake (you're defining a lambda with two parameters called pair? and v).
Also, I believe you intended to call is-quotation? from is-quote-expression? only if v isn't a pair, so it doesn't make sense to ask again if (pair? v) in is-quotation?. And who said that a pair is a quotation only if both its car and cdr are quotations?
Here, I believe this is what you intended:
(define is-quote-expression?
(lambda (v)
(if (pair? v)
(equal? (car v) 'quote)
(is-quotation? v))))
(define is-quotation?
(lambda (v)
(or (number? v)
(boolean? v)
(char? v)
(string? v)
(symbol? v)
(null? v))))
I agree with Óscar's post, though, is-quote-expression? accepts a list rather than a pair and returns whether it was a quotation.
(define is-quote-expression?
(lambda (v)
(and (proper-list-of-given-length? v 2)
(equal? (car v) 'quote)
(is-quotation? (cadr v)))))
Also, your original question shows some confusion as to what quote actually does. This is what really should happen:
> (is-quote-expression? '1)
#f
> (is-quote-expression? (cons 'quote 1))
#f
> (is-quote-expression? (quote 42))
#f
> (is-quote-expression? (quote (quote 42)))
#t
Note how the built-in quote procedure simply returns what it is passed. In the case of (quote 42) it simply returns 42. But (quote (quote 42)) returns (quote 42), which is what you wish to pass to is-quote-expression?.
The behavior of quote is specified in R6RS, appendix A.3. For '1, the relevant rule is 6sqv:
(store (sf1 ...) S1[ 'sqv1 ]) → (store (sf1 ...) S1[ sqv1 ])
Time to break this down.
The "S → T" notation defines one step in evaluating a term, where "S" evaluates to "T".
Since store and the sf1 non-terminals appear the same on both the left and right sides, you don't need to understand them to understand how '1 evaluates. If you need something, think of store as "storage environment" and the sfn as pairs of names and values; (store ((x 1) (y 2)) S) means the identifier x is associated with the value 1 and y with 2 when evaluating the term S.
If you're not familiar with the S[e] notation, it refers to a term with one "hole" (an term with a [] in it) filled with e. There are two related syntax elements: terms with holes (S[]) and terms with a hole filled by a value (S[e]). Holes are a little (but only a little) like unnamed variables. One important difference is that a term is allowed only one hole. Holes are perhaps best explained by example. All of the following are S[]:
(+ [] 1 2)
(list [] 'a "foo")
(cond ((= x 0) [])
((> x 0) 1)
(else -1))
Note that a hole can only appear where a sub-term is syntactically valid; [] 2) is not a term-with-hole. S[0] would be a term with 0 substituted into the hole:
(+ 0 1 2)
(list 0 'a "foo")
(cond ((= x 0) 0)
((> x 0) 1)
(else -1))
When a value is given for a hole, the term S[] is also called a "context". This comes from one of the primary uses for terms-with-holes: to match any term containing the given value. S[e] is any term that contains e as a valid sub-term, so S[] is the context that e appears in. In short, S1['sqv1] is a stand-in for any term that contains a quote.
(+ 'foo 1 2)
(list 'bar 'a "foo")
(cond ((= x 0) 'baz)
((> x 0) 1)
(else -1))
Note the second term provides two different contexts for quote-terms: (list [] 'a "foo"), (list 'bar [] "foo"). This suggests that you shouldn't think of holes too much as just being unnamed variables.
If you're wonder why context terms and holes are used, they're an alternative to recursive definitions. Without contexts, → would have to be defined recursively over the structure of terms (Scheme's grammar defines the structure). Substitution in lambda calculus is an example of structural recursion, as are any tree-processing functions you might define in Scheme (though Scheme syntax is quite different than the syntax used to define → and lambda calculus substitution).
(define (tree-depth tree)
(if (pair? tree)
(max (tree-depth (car tree))
(tree-depth (cdr tree)))
1
) )
Next, let's examine the meaning of sqv, which is short for "self-quoting values". This is a non-terminal from the Scheme grammar, given in appendix A.2.
sqv ::= n | #t | #f
n ::= [numbers]
sqv is simply a number or boolean.
All together, the 6sqv evaluation rule means that a quoted number or boolean evaluates to the number or boolean; the quote is simply discarded.
What this signifies for your homework is that you can't tell the difference between 1 and '1 with a normal function, since sub-terms are evaluated before the function is called. You'll need a macro.
Why go through all this just to say that "'1 evaluates to 1"? Firstly, answering "why" takes more than answering "what". Also, it will hopefully help you go beyond the question, learning a little bit how to read Scheme's formal semantics, give you a taste of computational theory concepts and lead to many more questions.
In Exercise 30.1.1 of HtDP, I started off using local and then modified it to use lambda in order to answer the question.
(define (add-to-each2 accu a-list)
(cond
[(empty? a-list) empty]
[else (local ((define s (+ accu (first a-list))))
(cons s (add-to-each2 s (rest a-list))))]))
and
(define (add-to-each5 accu a-list)
(cond
[(empty? a-list) empty]
[else (cons ((lambda (x y)
(first (map + (list (first y))
(list x)))) accu a-list)
(add-to-each5 (+ accu (first a-list))(rest a-list)))]))
In this particular instance, to me, the local version is easier to read. Are there situations where the lambda version would be preferred? Thank you.
First off, I think you might be getting relative-2-absolute confused with add-to-each, since add-to-each just adds the same number to each element of the list, rather than incrementing an accumulator. The rest of this post assumes that's the case, and just takes out that incrementing.
I think let would be my first choice for the local binding. Your lambda example uses a common pattern that simulates let using lambda and application:
(let ([x e]) body)
Is equivalent to:
((lambda (x) body) e)
If you use this transformation from lambda to let in your example, you get:
(define (add-to-each5 n a-list)
(cond
[(empty? a-list) empty]
[else (cons (let ([x n] [y a-list])
(first (map + (list (first y))
(list x))))
(add-to-each5 n (rest a-list)))]))
A good compiler will likely generate the same code for this as for your two examples, so it mostly comes down to style. The "left-left lambda" pattern can be more difficult to read, as you note, so I prefer let.
However, Exercise 30.1.1 is trying to make you use map as a replacement for the explicit recursion that occurs in each of your examples. You are using map in your example but only for a single addition at a time, which makes map kind of painful: why bother wrapping up (list (first y)) and (list x) when you just want (+ (first y) x)?
Let's look at a simple definition of map to see how it might be helpful, rather than painful, for this problem:
(define (map f ls)
(cond
[(empty? ls) empty]
[else (cons (f (first ls)) (map f (rest ls)))]))
Right away, you should notice some similarities to add-to-each: the first line of the cond checks for empty, and the second line conses something to do with the first element onto a recursive call to map on the rest. The key, then, is to pass map an f that does what you want to do to each element.
In the case of add-to-each, you want to add a particular number to each element. Here's an example of adding 2:
> (map (lambda (n) (+ 2 n)) (list 1 2 3 4 5))
(3 4 5 6 7)
Notice that map and lambda are both here as 30.1.1 requests, and they act on an entire list without the explicit recursion of the original add-to-each: the recursion is all abstracted away in map.
This should be enough to get you to a solution; I don't want to give away the final answer, though :)
How to write a program in scheme that takes an arbitrary
sexpression consisting of integers and which returns an sexpression that is identical to
the original but with all the integers doubled?
We want a procedure that takes an S-expression as input, and outputs an S-expression with the same structure, but where each integer is doubled; generally, a procedure to map S-expressions:
(define (double x)
(if (number? x)
(* x 2)
x)))
(define (sexp-map op sexp)
...)
(sexp-map double some-sexpression)
The S-expression we get (SEXP) is going to be either an atom, in which case the result is (OP SEXP), or a list of S-expressions. We might think to map OP across SEXP in this case, but S-expressions nest arbitrarily deep. What we should actually do is map a procedure that will transform each element in the smaller S-expression with OP. Well would you look at that, that's just another way to describe of the goal of the procedure we're currently trying to write. So we can map SEXP-MAP across SEXP.
Well, no we can't actually, because SEXP-MAP needs to be called with two arguments, and MAP will only give it the one. To get around that, we use a helper procedure F of one argument:
(define (sexp-map op sexp)
(define (f x)
(if (list? x)
(map f x)
(op x)))
(f sexp))
F winds up doing all the real work. SEXP-MAP is reduced to being a facade that's easier to use for the programmer.
It sounds like what you want is to find each integer in the s-expression, then double it, while keeping the rest of it the same.
If you're not aware, s-expressions are just lists that may happen to contain other lists, and it makes sense to deal with them in levels. For instance, here's a way to print all the values on level one of an s-expression:
(define (print-level-one sexp)
(display (car sexp))
(print-level-one (cdr sexp)))
This will end up calling display on the car of every part of the s-expression.
You could do something similar. You'll need the functions integer? and pair? to check whether something is an integer, which should be doubled, or another list, which should be treated just like the top-level list.
(Note: I'm being deliberately vague because of the comment about homework above. If you just want the answer, rather than help figuring out the answer, say so and I'll change this.)
An Sexp of numbers is one of
-- Number
-- ListOfSexp
A ListOfSexp is one of
-- empty
-- (cons Sexp ListOfSexp)
So, you'll need one function to handle both of those data definitions. Since the data definitions cross-reference each other, the functions will do the same. Each individual function is pretty straight forward.
(define (double E)
(cond ((null? E) '())
((list? (car E)) (cons (double (car E)) (double (cdr E))))
((number? E) (list E))
(else (cons (* 2 (car E)) (double (cdr E))))
))
(map (lambda (x) (* x 2)) '(1 2 3 4 5)) => '(2 4 6 8 10)
What does it do? (lambda (x) (* x 2)) takes a number and doubles it, and map applies that function to every element of a list.
Edit: Oh, but it won't go into trees.
(define double
(lambda (x)
(cond ((null? x) (list))
((list? (car x)) (cons (double (car x)) (double (cdr x))))
(else (cons (* 2 (car x)) (double (cdr x)))))))
EDIT
Fixed this. Thanks to Nathan Sanders for pointing out my initial oversight concerning nested lists.