Scheme homework help - scheme

Okay so I have started a new language in class. We are learning Scheme and i'm not sure on how to do it. When I say learning a new language, I mean thrown a homework and told to figure it out. A couple of them have got me stumped.
My first problem is:
Write a Scheme function that returns true (the Boolean constant #t) ifthe parameter is a list containing n a's followed by n b's. and false otherwise.
Here's what I have right now:
(define aequalb
(lambda (list)
(let ((head (car list)) (tail (cdr list)))
(if (= 'a head)
((let ((count (count + 1)))
(let ((newTail (aequalb tail))))
#f
(if (= 'b head)
((let ((count (count - 1)))
(let ((newTail (aequalb tail))))
#f
(if (null? tail)
(if (= count 0)
#t
#f)))))))))))
I know this is completely wrong, but I've been trying so please take it easy on me. Any help would be much appreciated.

A trick I picked up from Essentials of Programming Languages is to always write recursive list functions by handling the two important cases first: null (end of list) and not null.
So, the basic structure of a list function looks something like this:
(define some-list-function
(lambda (list)
(if (null? list)
#f
(do-some-work-here (head list)
(some-list-function (tail list))))))
Usually you (1) check for null (2) do some work on the head and (3) recur on the tail.
The first thing you need to do is decide what the answer is for a null list. It's either #t or #f, but which? Does a null list have the same number of a as b?
Next, you need to do something about the recursive case. Your basic approach is pretty good (although your example code is wrong): keep a count that goes up when you see a and down when you see b. The problem is how to keep track of the count. Scheme doesn't have loops* so you have to do everything with recursion. That means you'll need to pass along an extra counter variable.
(define some-list-function
(lambda (list counter)
(if (null? list)
; skip null's code for a second
Now you have to decide whether the head is 'a or not and increment count if so (decrement otherwise). But there's no count variable, just passing between functions. So how to do it?
Well, you have to update it in-line, like so:
(some-list-function (tail list) (+ 1 count))
By the way, don't use = for anything but numbers. The newer, cooler Lisps allow it, but Scheme requires you to use eq? for symbols and = for numbers. So for your 'a vs 'b test, you'll need
(if (eq? 'a (head tail)) ...)
; not
(if (= 'a (head tail)) ...)
I hope this helps. I think I gave you all the pieces, although there are a few things I skipped over. You need to change the null case now to check count. If it's not = 0 at the end, the answer is false.
You should also maintain a separate flag variable to make sure that once you switched to 'b, you return #f if you see another 'a. That way a list like '(a a a b b a b b) won't pass by mistake. Add the flag the same way I added counter above, by adding another function parameter and passing along the value at each recursive call.
Finally, if your teacher really isn't giving you any help, and won't, then you might want to read a basic book on Scheme. I haven't used any of these myself, but I've heard they're good: The Scheme Programming Language, How to Design Programs or err umm I thought there was a third book online for free, but I can't find it now. I guess if you have lots of extra time and want to blow your mind, you can read Structure and Interpretation of Computer Programs. It teaches a little Scheme and lot about programming languages.
*It does have some of these things, but it's better to ignore them for now.

Isn't list a keyword? I always used to use "alist" as my variable name to get around it.
You could use counters like you are, but I might go for a recursive function that has the following conditions:
params: alist
returns true if the list is nil,
false if the first element is not a,
false if the last element is not b,
(aequalb (reverse (cdr (reverse (cdr alist))))) ;; pick off the front and back, and recurse
in this case, you may need to write a reverse function... can't remember if it was there already.
Also, from a syntax perspective, you don't need to introduce a lambda expression...
(define (foo arg) (+ 1 arg))
is a function called foo, takes a number, and adds one to it. You would call it (foo 1)

I'd take a look at andmap, take and drop, which (between them) make this pretty trivial. Oh and at least for now, I'd probably try to forget that let even exists. Not that there's anything particularly wrong with it, but I'd guess most of the problems you're going to get (at least for a while) don't/won't require it.

Here's a first-cut that may help you. It handles the basic problem, although you need to test to make sure there are no edge cases.
Anyway, the function checks several conditions:
It first checks a base case (recursive functions need to have this, to avoid the possibility of infinite recursion). If the input list is empty then return true (assumption is that all items have been removed, so at this point we are done).
Then the code checks to see if the first items is an a and the last is a b. If so, it strips these chars off and recurses.
Otherwise something is wrong, so the function returns false
(define (aeqb items)
(cond
((equal? '() items) #t)
((and (equal? "a" (car items))
(equal? "b" (car (reverse items))))
(aeqb (cdr (reverse (cdr (reverse items))))))
(else #f)))
(aeqb '("a" "a" "b" "b"))

Related

Filtering a list with indexes MIT-scheme

Is there a good way to filter a list using each element and its index in scheme? This is how I'm doing it now, but it seems overly complex
(map cdr
(filter (lambda (index-and-element)
(filter-proc (car index-and-element)
(cdr index-and-element)))
(map cons (iota (length l))
l)))
Looks perfectly fine to me. Except, perhaps you meant map cdr...
Personally I like very short variable names whenever possible, so instead of index-and-element I'd just use ie -- they are unimportant, it's just some wiring, so make them as invisible as possible.
Another possibility is to use (map list ...) initially, not (map cons ...), and then inside the lambda to use (apply filter-proc ie). this way filter-proc is called with two arguments, so it can be defined (define (filter-proc idx elt) ...).
And after all that, since it is indeed complex and error-prone to type all this anew each time, we'd just define a higher-order function for this so it is easier to use, like
(define (indexed-filter ipred lst)
(filter (lambda (ie)
(apply ipred ie))
(map list (iota (length lst))
lst)))
;; (define (ipred idx elt) ....) ; returns Bool
and use it whenever the need arises.
I've intentionally left out the (map cadr ...) post-processing step, since you could sometimes want to get the indices of the matching elements instead of the elements themselves. So that would be part of the calling "protocol" so to speak -- whether you're interested in indices, elements, or both, you'd just tweak the call to this general procedure.

How to use symbols and lists in scheme to process data?

I am a newbie in scheme, and I am in the process of writing a function that checks pairwise disjointess of rules (for the time being is incomplete), I used symbols and lists in order to represent the rues of the grammar. Uppercase symbol is a non-terminal in the grammar, and lowercase is a terminal. I am trying to check if a rule passes the pairwise disjointness test.
I will basically check if a rule has only one unique terminal in it. if it is the case, that rule passes the pairwise disjointness test. In scheme, I am thinking to realize that by representing the terminal symbol in lower case. An example of that rule would be:
'(A <= (a b c))
I will then check the case of a rule that contains an or. like:
'(A <= (a (OR (a b) (a c))))
Finally, I will check recursively for non terminals. A rule for that case would be
'(A <= (B b c))
However, What is keeping me stuck is how to use those symbols as data in order to be processed and recurse upon it. I thought about converting the symbols to strings, but that did not in case of having a list like that for example '(a b c) How can I do it?
Here is what I reached so far:
#lang racket
(define grammar
'(A <= (a A b))
)
(define (pairwise-disjoint lst)
(print(symbol->string (car lst)))
(print( cddr lst))
)
Pairwise Disjoint
As far as I know, the only way to check if a set is pairwise disjoint is to enumerate every possible pair and check for matches. Note that this does not follow the racket syntax, but the meaning should still be pretty clear.
(define (contains-match? x lst)
(cond ((null? x) #f) ; Nothing to do
((null? lst) #f) ; Finished walking full list
((eq? x (car lst)) #t) ; Found a match, no need to go further
(else
(contains-match? x (cdr lst))))) ; recursive call to keep walking
(define (pairwise-disjoint? lst)
(if (null? lst) #f
(let ((x (car lst)) ; let inner vars just for readability
(tail (cdr lst)))
(not
;; for each element, check against all later elements in the list
(or (contains-match? x tail)
(contains-match? (car tail) (cdr tail)))))))
It's not clear to me what else you're trying to do, but this is the going to be the general method. Depending on your data, you may need to use a different (or even custom-made) check for equality, but this works as is for normal symbols:
]=> (pairwise-disjoint? '(a b c d e))
;Value: #t
]=> (pairwise-disjoint? '(a b c d e a))
;Value: #f
Symbols & Data
This section is based on what I perceive to be a pretty fundamental misunderstanding of scheme basics by OP, and some speculation about what their actual goal is. Please clarify the question if this next bit doesn't help you!
However, What is keeping me stuck is how to use those symbols as data...
In scheme, you can associate a symbol with whatever you want. In fact, the define keyword really just tells the interpreter "Whenever I say contains-match? (which is a symbol) I'm actually referring to this big set of instructions over there, so remember that." The interpreter remembers this by storing the symbol and the thing it refers to in a big table so that it can be found later.
Whenever the interpreter runs into a symbol, it will look in its table to see if it knows what it actually means and substitute the real value, in this case a function.
]=> pairwise-disjoint?
;Value 2: #[compound-procedure 2 pairwise-disjoint?]
We tell the interpreter to keep the symbol in place rather than substituting by using the quote operator, ' or (quote ...):
]=> 'pairwise-disjoint?
;Value: pairwise-disjoint?
All that said, using define for your purposes is probably a really poor decision for all of the same reasons that global variables are generally bad.
To hold the definitions of all your particular symbols important to the grammar, you're probably looking for something like a hash table where each symbol you know about is a key and its particulars are the associated value.
And, if you want to pass around symbols, you really need to understand the quote and quasiquote.
Once you have your definitions somewhere that you can find them, the only work that's left to you is writing something like I did above that is maybe a little more tailored to your particular situation.
Data Types
If you have Terminals and Non-Terminals, why not make data-types for each? In #lang racket the way to introduce new data type is with struct.
;; A Terminal is just has a name.
(struct Terminal (name))
;; A Non-terminal has a name and a list of terms
;; The list of terms may contain Terminals, Non-Terminals, or both.
(struct Non-terminal (name terms))
Processing Non-terminals
Now we can find the Terminals in a Non-Terminal's list of terms using the predicate Terminal? which is provided automatically when we define the Terminal as a struct.
(define (find-terminals non-terminal)
(filter Terminal? (Non-terminal-terms non-terminal)))
Pairwise Disjoint Terminals
Once we have filtered the list of terms we can determine properties:
;; List(Terminal) -> Boolean
define (pairwise-disjoint? terminals)
(define (roundtrip terms)
(set->list (list->set terms)))
(= (length (roundtrip terminals)
(length terminals))))
The round trip list->set->list isn't necessarily optimized for speed, of course and profiling actual working implementations may justify refactoring, but at least it's been black-boxed.
Notes
Defining data types with struct provides all sorts of options for validating data as the type is instantiated. If you look at the Racket code base, you will see struct used frequently in the more recent portions.
Since grammar has a list within a list, I think you'll have to either test via list? before calling symbol->string (since, as you discovered, symbol->string won't work on a list), or else you could do something like this:
(map symbol->string (flatten grammar))
> '("A" "<=" "a" "A" "b")
Edit: For what you're doing, i guess the flatten route might not be that helpful. so ya, test via list? each time when parsing and handle accordingly.

Scheme program to turn every element of a list into atoms

I need a program that takes a list as input and turns every element found in the list into atoms. Here's what i have so far but i keep running into errors.
(define make-lat
(lambda (l)
(cond
((null? l) (quote ()))
(else
(cond
((list? (car l))
(cons (caar l)
make-lat (cdr l)))
(else
((atom? (car l))
(cons (car l)
(make-lat(cdr l)
)))))))))
Can someone help me out?
Your code looks a little disorganized to me, and I think you might want to think about following the steps in the How To Design Programs Design Recipe:
Step one: can you write a purpose statement for your program? It should say what the function does.
Step two: can you write a contract? It should say what kind of data the program takes in, and
what it produces. You've got to be specific, here, and any kind of data that you specify must either be built-in or have an explicit "data definition".
Step three: write some test cases! Provide a sample input, and the output that you expect.
For more design recipe goodness, check out How To Design Programs.
Your question looks like homework.
Here's a couple of things you could do to try and debug.
Use the Repl to try out parts of the function. E.g if in a cond, you are checking for null, you could do it on the REPL too.
(null? '(1 2 3)) or (null? '())
Check individual S-Exps. Are you sure that every function that you call has an opening and closing parens.
As a tip, simplify your cond's. You don't need to nest conds. You can put all conditions one by one.

Removing all duplicate members from a list in scheme

I am trying to remove duplicates in a list, using recursion. This is what I have. It only removes the first duplicate, not all of them.
My idea is to look at the first member, check if its a member of the rest of the list, if so, call the function again. If not, create a list with the first member and the result from calling the function again. I don't understand why it doesn't remove all the duplicates.
(define (removeDupes L)
(cond ((null? L) ())
((list? (member (car L) (cdr L))) removeDupes (cdr L))
(#T (cons ((car L) (removeDupes (cdr L)))))))
This is what I modified it to, and it works!! And I understand what was wrong with the cons. It needs two parameters and I only gave it one. I still have no Idea why the third line did not work....
(define (removeDupes L)
(cond ((null? L) ())
((list? (member (car L) (cdr L)))(removeDupes(cdr L)))
(#T (cons (car L) (removeDupes (cdr L))))))
There are multiple errors in your code, but the one that's probably causing the problem you've reported here is that your parentheses are wrong in the third line. You're trying to call removeDupes but your code doesn't actually do so; instead the value in that case ends up being (cdr L). Can you see why?
When you fix this, you'll find that your code starts producing errors. For the one you're likely to encounter first: take a careful look at how you're invoking cons on the last line. For the one you're likely to encounter next: remember that () is not self-evaluating in Scheme.
(I think this sort of thing is much harder to miss if you take care with the spacing and layout of your code. Put spaces between the elements of every list, for instance. Until you get so familiar with this stuff that these mistakes stop happening, you might want to make a habit of checking the parentheses any time you run across a mysterious error: have you missed a ( at the start of an expression, or put an extra ( before the arguments of a function, or forgotten the extra level of parens round a cond clause, or etc. etc. etc. Don't worry: after a while it'll stop happening...)

Scheme early "short circuit return"?

I'm trying to find out how I can do an "early return" in a scheme procedure without using a top-level if or cond like construct.
(define (win b)
(let* ((test (first (first b)))
(result (every (lambda (i) (= (list-ref (list-ref b i) i) test))
(enumerate (length b)))))
(when (and (not (= test 0)) result) test))
0)
For example, in the code above, I want win to return test if the when condition is met, otherwise return 0. However, what happens is that the procedure will always return 0, regardless of the result of the when condition.
The reason I am structuring my code this way is because in this procedure I need to do numerous complex checks (multiple blocks similar to the let* in the example) and putting everything in a big cond would be very unwieldy.
Here is how to use call/cc to build return yourself.
(define (example x)
(call/cc (lambda (return)
(when (< x 0) (return #f))
; more code, including possible more calls to return
0)))
Some Schemes define a macro called let/cc that lets you drop some of the noise of the lambda:
(define (example x)
(let/cc return
(when (< x 0) (return #f))
0))
Of course if your Scheme doesn't, let/cc is trivial to write.
This works because call/cc saves the point at which it was called as a continuation. It passes that continuation to its function argument. When the function calls that continuation, Scheme abandons whatever call stack it had built up so far and continues from the end of the call/cc call. Of course if the function never calls the continuation, then it just returns normally.
Continuations don't get truly mind-bending until you start returning them from that function, or maybe storing them in a global data structure and calling them later. Otherwise, they're just like any other language's structured-goto statements (while/for/break/return/continue/exceptions/conditions).
I don't know what your complete code looks like, but it might be better to go with the cond and to factor out the complex checks into separate functions. Needing return and let* is usually a symptom of overly imperative code. However, the call/cc method should get your code working for now.
One way would be to use recursion instead of looping, then an early exit is achieved by not recursing further.
You can use the "call with current continuation" support to simulate a return. There's an example on wikipedia. The function is called call-with-current-continuation, although there's often an alias called call/cc which is exactly the same thing. There's also a slightly cleaner example here
Note: This is quite an advanced Scheme programming technique and can be a bit mind bending at first...!!!!
In this case you don't want a when, you want an if, albeit not top-level.
(define (win b)
(let* ((test (first (first b)))
(result (every (lambda (i) (= (list-ref (list-ref b i) i) test))
(enumerate (length b)))))
(if (and (not (= test 0)) result)
test
0)))
The reason it was always returning zero is that whether or not the body of the when got executed, its result would be dropped on the floor. You see, the lambda implicit in the function define form creates an implicit begin block too, so
(define foo
(lambda (b)
(begin
(let ...)
0)))
and the way begin works is that it returns the result of the last form inside, while dropping all the intermediate results on the floor. Those intermediate results are intended to have side effects. You're not using any of that, which is great(!), but you have to be careful to only have one form (whose result you really want) inside the function definition.
Grem

Resources