Transforming this into an expression - scheme

Hi guys i'm wanted to know if i have the correct expression for this picture, if not why please
(a((f(b c))(g h))e)

You're close, but not quite right. It'll be more clear if we build the list structure explicitly using cons; this is more like it:
(cons 'a
(cons (cons (cons 'f
(cons 'b 'c))
(cons 'g
(cons 'h '())))
(cons 'e '())))
=> '(a ((f b . c) g h) e)
Notice that in this part: (f b . c) we have an improper list, because the sublist doesn't end in null.

You answer is incorrect as it doesn't properly express the improper list (f b . c). Also the parentheses around g h are an error.
With dotted pairs the full expression would be:
'(a ((f b . c) g h) e)
Note that '(f b . c) is not the same as '(f (b c)).
See that '(f (b c)) is:
(cons 'f (cons (cons 'b (cons 'c '())) '()))
Rather than what '(f b . c) is:
(cons 'f (cons (cons 'b 'c) '()))
Note the improper list.

Related

cons* in scheme - how to implement

I tried to implement the cons* (https://scheme.com/tspl4/objects.html#./objects:s44).
Examples:
(cons* '()) -> ()
(cons* '(a b)) -> (a b)
(cons* 'a 'b 'c) -> (a b . c)
(cons* 'a 'b '(c d)) -> (a b c d)
this is what I did do far but I don't know how to replace the ?? to make the third example (the dot notion) work
(define cons*
(lambda x
(if
(null? x)
x
(if (list? (car (reverse x)))
(fold-right cons (car (reverse x)) (reverse (cdr (reverse x))))
???
)
)
)
)
Here's a lo-fi way using lambda -
(define cons*
(lambda l
(cond ((null? l) null)
((null? (cdr l)) (car l))
(else (cons (car l) (apply cons* (cdr l)))))))
Here's a way you can do it using match (Racket)
(define (cons* . l)
(match l
((list) null) ; empty list
((list a) a) ; singleton list
((list a b ...) (cons a (apply cons* b))))) ; two or elements
Often times patterns and order can be rearranged and still produce correct programs. It all depends on how you're thinking about the problem -
(define (cons* . l)
(match l
((list a) a) ; one element
((list a b) (cons a b)) ; two elements
((list a b ...) (cons a (apply cons* b))))) ; more
Or sugar it up with define/match -
(define/match (cons* . l)
[((list)) null]
[((list a)) a]
[((list a b ...)) (cons a (apply cons* b))])
All four variants produce the expected output -
(cons* '())
(cons* '(a b))
(cons* 'a 'b 'c)
(cons* 'a 'b '(c d))
'()
'(a b)
'(a b . c)
'(a b c d)
Personally, I'd use a macro instead of a function to transform a cons* into a series of cons calls:
(define-syntax cons*
(syntax-rules ()
((_ arg) arg)
((_ arg1 rest ...) (cons arg1 (cons* rest ...)))))
(define (writeln x)
(write x)
(newline))
(writeln (cons* '())) ;; -> '()
(writeln (cons* '(a b))) ;; -> '(a b)
(writeln (cons* 'a 'b 'c)) ;; -> (cons 'a (cons 'b 'c)) -> '(a b . c)
(writeln (cons* 'a 'b '(c d))) ;; -> (cons 'a (cons 'b '(c d))) -> '(a b c d)
A Simple Procedure
I think that you are making this more complicated than it needs to be. It seems best not to use lambda x here, since that would allow calls like (cons*) with no arguments. Instead, I would use (x . xs), and I would even just use the define syntax:
(define (cons* x . xs)
(if (null? xs)
x
(cons x (apply cons*
(car xs)
(cdr xs)))))
If there is only one argument to cons*, then xs is empty, i.e., (null? xs) is true, and that single argument x should be returned. Otherwise you should cons the first argument to the result of calling cons* again, with the first element of xs as the first argument, followed by the remaining arguments from xs. The trick here is that (cdr xs) returns a list, which will itself be put into a list thanks to the (x . xs) syntax. This is the reason for using apply, which will apply cons* to the arguments in the list.
This works for all of the test cases:
> (cons* '())
()
> (cons* '(a b))
(a b)
> (cons* 'a 'b 'c)
(a b . c)
> (cons* 'a 'b '(c d))
(a b c d)
Using Mutation
Taking a closer look at what a proper list really is suggests another approach to solving the problem. Consider a list like (a b c d). This is really a chain of cons cells that look like this:
(a . (b . (c . (d . ()))))
We would like to transform this list to an improper, or dotted, list:
(a . (b . (c . (d . ())))) --> (a . (b . (c . d)))
This transformed list is equivalent to (abc.d), which is what we would like the call to (cons* 'a 'b 'c 'd) to return.
We could mutate the proper list to an improper list by setting the cdr of the next-to-last pair to the car of the last pair; that is, by setting the cdr of (c . (d .()) to d. We can use the list-tail procedure to get at the next-to-last pair, list-ref to get at the car of the last pair, and set-cdr! to set the cdr of the next-to-last pair to the new value. After this, the list is no longer terminated by an empty list (unless the car of the final pair is itself an empty list!).
Here is a procedure proper->improper! that mutates a proper list to an improper list. Note that the input must be a proper list to avoid an error. If the input list contains only a single element, then that element is simply returned and no mutation takes place.
(define (proper->improper! xs)
(cond ((null? (cdr xs))
(car xs))
(else
(set-cdr! (list-tail xs (- (length xs) 2))
(list-ref xs (- (length xs) 1)))
xs)))
Now cons* can be defined simply in terms of proper->improper!:
(define (cons* . xs)
(proper->improper! xs))
Here, the arguments to cons* are packed up into a fresh list and passed to proper->improper! which effectively removes the terminal empty list from its input, returning a chain of pairs whose last cdr is the last argument to cons*; or if only one argument is provided, that argument is returned. This works just like the other solution:
> (cons* '())
()
> (cons* 'a)
a
> (cons* 'a 'b 'c 'd)
(a b c . d)
> (cons* 'a 'b '(c d))
(a b c d)
Real Life
In real life, at least in Chez Scheme, cons* is not implemented like any of these solutions, or even in Scheme at all. Instead Chez opted to make cons* a primitive procedure, implemented in C (I believe).

Trying to replace all instances of an element in a list with a new element [Racket]

As the title said, I'm trying to write a function that takes a list, a variable, and an element, then replaces all instances of the variable in the list with that element.
For example:
(substitute '(C or (D or D)) 'D #f) would return
'(C or (#f or #f))
Right now what I've got is:
(define (substitute lst rep new)
(cond ((or (null? lst))
lst)
((eq? (car lst) rep)
(cons new (substitute (cdr lst) rep new)))
(else
(cons (car lst) (substitute (cdr lst) rep new)))))
Which doesn't check nested lists like my example, though it works fine when they aren't a part of the input.
And I'm having trouble with where to place recursion in order to do so - or would it be easier to flatten it all and then rebuild it after everything's been replaced in some way?
Here's another solution using pattern matching via match -
(define (sub l rep new)
(match l
((list (list a ...) b ...) ; nested list
(cons (sub a rep new)
(sub b rep new)))
((list a b ...) ; flat list
(cons (if (eq? a rep) new a)
(sub b rep new)))
(_ ; otherwise
null)))
It works like this -
(sub '(a b c a b c a b c) 'a 'z)
;; '(z b c z b c z b c)
(sub '(a b c (a b c (a b c))) 'a 'z)
;; '(z b c (z b c (z b c)))
(sub '() 'a 'z)
; '()
At first sight, your question looks similar to How to replace an item by another in a list in DrScheme when given paramters are two items and a list?. From my understanding, your question is slightly different because you also want to replace occurrences within nested lists.
In order to deal with nested lists, you must add a clause to check for the existence of a nested list, and replace all occurrences in that nested list by recursing down the nested list:
(define (subst l rep new)
(cond ((null? l)
'())
((list? (car l)) ; Check if it is a nested list.
(cons (subst (car l) rep new) ; Replace occurrences in the nested list.
(subst (cdr l) rep new))) ; Replace occurrences in the rest of the list.
((eq? (car l) rep)
(cons new
(subst (cdr l) rep new)))
(else
(cons (car l)
(subst (cdr l) rep new)))))
Example use (borrowed from the answer given by user633183):
(subst '(a b c a b c a b c) 'a 'z)
;; '(z b c z b c z b c)
(subst '(a b c (a b c (a b c))) 'a 'z)
;; '(z b c (z b c (z b c)))
(subst '() 'a 'z)
; '()
This can be done using map and recursion:
(define (subst lst rep new)
(map (lambda (x)
(if (list? x)
(subst x rep new)
(if (eq? rep x) new x))) lst))
the output:
(subst '(a b c (a b c (a b c))) 'a 'z)
; '(z b c (z b c (z b c)))

How to compute the number of times pattern in one list appears in other list in Scheme

I am stuck up in a Scheme program for about 5 hours. The program that I am working on should take two lists as input and then compute the number of times the pattern within the first list appears on the second list.
For example : > (patt '(b c) '(a b c d e b c)) ==> answer = 2
(patt '(a b c) '(a b c a b c d e a b c c c)) ==> answer = 3
(patt '((a b) c) '(a b (a b) c d e b c)) ==> answer = 1
Below is the code that I have till now.
(define (patt lis1 lis2)
(cond
((null? lis1) 0)
((null? lis2) 0)
[(and (> (length lis1) 1) (eq? (car lis1) (car lis2))) (patt (cdr lis1) (cdr lis2))]
((eq? (car lis1) (car lis2)) (+ 1 (patt lis1 (cdr lis2))))
(else (patt lis1 (cdr lis2)))
))
Can someone please help me solve this. Thanks!
Consider the subproblem of testing if a list starts with another list.
Then do this for every suffix of the list. Sum up the count of matches.
If you want non overlapping occurrences, you can have the prefix match, return the suffix of the list so that you can skip over the matching part.
Also use equals? for structural equality, not eq? which is for identity.
You need to divide the problem into parts:
(define (prefix? needle haystack)
...)
(prefix? '() '(a b c)) ; ==> #t
(prefix? '(a) '(a b c)) ; ==> #t
(prefix? '(a b c) '(a b c)) ; ==> #t
(prefix? '(a b c d) '(a b c)) ; ==> #f
(prefix? '(b) '(a b c)) ; ==> #t
(define (count-occurences needle haystack)
...)
So with this you can imagine searching for the pattern (count-occurences '(a a) '(a a a a)). When it is found from the first element you need to search again on the next. Thus so that the result is 3 for the (a a a a) since the matches overlap. Every sublist except when it's the empty list involves using prefix?
Good luck!
(define (patt list1 list2)
(let ([patt_length (length list1)])
(let loop ([loop_list list2]
[sum 0])
(if (>= (length loop_list) patt_length)
(if (equal? list1 (take loop_list patt_length))
(loop (cdr loop_list) (add1 sum))
(loop (cdr loop_list) sum))
sum))))
After giving this homework problem a little time to marinate, I don't see the harm in posting additional answers -
(define (count pat xs)
(cond ((empty? xs)
0)
((match pat xs)
(+ 1 (count pat (cdr xs))))
(else
(count pat (cdr xs)))))
(define (match pat xs)
(cond ((empty? pat)
#t)
((empty? xs)
#f)
((and (list? pat)
(list? xs))
(and (match (car pat) (car xs))
(match (cdr pat) (cdr xs))))
(else
(eq? pat xs))))
(count '(a b c) '(a b c a b c d e a b c c c)) ;; 3
(count '((a b) c) '(a b (a b) c d e b c)) ;; 1
(count '(a a) '(a a a a)) ;; 3

Scheme procedure to substitute the element in a pair

I'm trying to write a procedure: when a pair starts with a, it would return b; when a pair starts with b, it would return c; and when a pair starts with c, it would return a.
(define e '((a b) (b c) (c a)))
(define (make-encoder e)
(cond ((eq? 'a (car (assq 'a e)))
(cadr (assq 'a e)))
((eq? 'b (car (assq 'b e)))
(cadr (assq 'b e)))
((eq? 'c (car (assq 'c e)))
(cadr (assq 'c e)))))
What is returned is only 'b', so I'm wondering where my brackets are wrong in cutting off the remaining code? I have played around for so long and wondering if that's my problem, or if it something else.
I don't think it's an issue of wrong parens; I can't really see a way to tweak your code to get the desired behavior. Here's how I would do it:
(define (make-encoder assoc-list)
(lambda (lst)
(define (-> elem)
(cadr (assq elem assoc-list)))
(map -> lst)))
As you can see, when you call this procedure with an association list such as e, it will return a new function that takes a list and maps -> over it, where -> looks up the element in the association list and returns result. Hence:
> ((make-encoder e) '(a b a c a b))
'(b c b a b c)
You have looking up the value of a key in a association list with (cadr (assq k a)) but what you are missing is how to apply that to every item in a list. That is where map comes in. So:
> (map (lambda (v) (cadr (assq v '((a b) (b c) (c a))))) '(a b a c a b))
'(b c b a b c)
This can be turned into a function by placing it within lambdas or a definition and replacing the values with bound names.

Scheme Cons (with #f as a second statement) output

I was wondering, If
(cons (quote (a b c)) #f)
gives an output
(( a b c ))
Then what output does this give:
(cons (quote (a b c)) #t)
?
Thank you
The first expression will not evaluate to ((a b c)) in most interpreters, it seems that your interpreter is evaluating #f as an empty list:
(cons (quote (a b c)) '())
=> '((a b c))
Having said that, you just substituted a #f with a #t, the standard results will look like this:
(cons (quote (a b c)) #f)
=> '((a b c) . #f)
(cons (quote (a b c)) #t)
=> '((a b c) . #t)
Why don't you try it online? in here for instance.
CommonLisp:
* (if '() 'true 'false)
FALSE
Scheme:
> (if '() 'true 'false)
true
And back in CommonLisp:
* (cons (quote (a b c)) nil)
((A B C))

Resources