I need to write a function in Scheme that acts as a zipper - meaning it takes two lists and creates a 'zipper' out of the two lists such that
(zip '(a b c) '(1 2 3)) => ((a 1) (b 2) (c 3))
Furthermore it takes each element in the nth position and pairs them together.
I'm fairly new to Scheme, so any help would be much appreciated!
Thanks!
From my Standard Prelude: (define (zip . xss) (apply map list xss))
Related
I am trying to write a function that returns the cartesian product of 2 sets (lists) with the help of the 'map' function and I want each pair of elements in the returned list to be a vector.
(cartesian-product '(1 2 3) '(a b))
'(#(3 a) #(3 b) #(2 a) #(2 b) #(1 a) #(1 b))
My initial idea was to make a separate procedure that makes a vector out element c (constant) in set 2 and element n in set 1 where element n changes for each iteration and then proceed to map this separate function with set 2. So for example, if I use the above lists (in the code sample) I would get 3 different vectors from this separate function:
#'(a 1) #'(a 2) #'(a 3)
And when using map on this I would get the result:
'(#'(a 1) #'(a 2) #'(a 3) #'(b 1) #'(b 2) #'(b 3))
But I realized that I would instead get a result that looks something like this:
'((#'(a 1) #'(a 2) #'(a 3)) (#'(b 1) #'(b 2) #'(b 3)))
because the separate function has to be recursive and it would have to return a list when finished.
Now I am back to square one and I am out of ideas. Help please...
Should mention that this is a school assignment and I am not allowed to use any predefined functions except for simple ones like:
cdr,car,cons,map etc
Try to keep it as basic as possible. I have only been using Scheme for like a month so go easy on me :)
We can nest two maps and flatten the result at the end, making sure to create a vector in the right place:
(define (cartesian-product lst1 lst2)
(apply append
(map (lambda (x)
(map (lambda (y)
(vector x y))
lst2))
lst1)))
It works as expected:
(cartesian-product '(1 2 3) '(a b))
=> '(#(1 a) #(1 b) #(2 a) #(2 b) #(3 a) #(3 b))
i am trying to make a function in Scheme which returns how many times a character repeats in a list.
For example if i have (list 2 6 'a 'b 'a 'a 2)
the result must be ((2 . 2) (6 . 1) (a . 3) (b . 1))
it didnt need to be written in the most efficient way,just want to be easy and simple for understanding.
Thanks in advance for helping me :)
Since this appears to be homework, you posted no code whatsoever, and we know nothing about your constraints and your current knowledge of Scheme, it's hard to answer.
Basically, you can do this efficiently with a hash map, or less efficiently with 2 nested loops. I'll explain the latter for you to get started.
I'll assume you know how to loop through the list.
So basically you need to
1) loop over your list
2) for each element of the list (let's call it e)
3) loop over the list once more, counting how many of (e) you find
4) assemble (e) and the result of your counting loop
The results of step 4) need to be assembled in a result list.
If you do this, the result will be something like
'((2 . 2) (6 . 1) (a . 3) (b . 1) (a . 3) (a . 3) (2 . 2))
which is close... but not correct because you counted some elements a few times.
So in addition to the above you need a way of keeping track of every element you already encountered, and steps 3) and 4) need to be done only if you encounter a new element. Keeping track could be through another list, or simply by checking your current result list, depending on your code.
If you have any code to show, please update your question and we can help more.
EDIT
OK, since GoZoner has posted code, I have 2 alternative versions for you. I hope you study all of these and make up your own mind, instead of simply copying one.
First, the version I described; as opposed to GoZoner's version, it does not use mutable lists but is slower than the mutable version:
(define (how-many lst)
(let loop ((lst2 lst) (res '()))
(if (empty? lst2)
(reverse res)
(let ((c (car lst2)))
(loop (cdr lst2)
(if (assoc c res)
res
(cons (cons c (count (lambda (e) (eq? e c)) lst)) res)))))))
=> '((2 . 2) (6 . 1) (a . 3) (b . 1))
If you want to use a mutable structure (and I would, too), I recommend mutable hash tables. The following example is in Racket but is trivial to adapt to R6RS Scheme hash tables if required:
(define (how-many lst)
(let ((res (make-hash)))
(for-each (lambda (e) (hash-update! res e add1 0)) lst)
(hash->list res)))
=> '((6 . 1) (a . 3) (b . 1) (2 . 2))
Just note that hash tables do not respect order, so you'll get the same result but the pairs will probably in a different order (and even vary from one call to the next).
Something like this:
(define (character-count list)
(assert (list? list))
(let looking ((list list) (rslt '()))
(cond ((null? list) rslt)
((assoc (car list) rslt) =>
(lambda (pair)
(set-cdr! pair (+ 1 (cdr pair)))
(looking (cdr list) rslt)))
(else (looking (cdr list)
(cons (cons (car list) 1) rslt))))))
> (character-count '(2 a 2 a b c 2))
((c . 1) (b . 1) (a . 2) (2 . 3))
I get an 'A'?!
I am learning how to use higher-order functions in scheme. I get the idea of using higher-order functions, however I am having trouble using them. For this learning exercise, I would prefer to only use some combination of filter, fold, and/or map.
For example, I want to construct the set difference between two lists call them A and B. I am defining set difference as x such that x is an element of A but x is not an element of B. I only want to use the functions map, filter and fold. For example:
Let A = (1 8 6 2)
Let B = (5 7 9 1 6)
The set difference of A and B would be (8 2)
The idea is to construct a new list by iterating over the elements of A and seeing if an element of A equals an element of B, if so don't add a to the new list; otherwise add a to the new list.
My algorithm idea goes something like this:
Let neq be "not equal to"
For each a in A and b in B evaluate the expression: (neq? a b)
For a = 1 we have:
(and (neq? 1 5) (neq? 1 7) (neq? 1 9) (neq? 1 1) (neq ? 1 6))
If this expression is true then a goes in the new list; otherwise don't add a to the new list. In our example (neq? 1 1) evaluates to false and so we do not add 1 to the new list.
Pretty much my entire procedure relies on 1, and this is where I have a trouble.
How do I do step 1?
I see that in step 1 I need some combination of the map and fold functions, but how do I get the and a neq b distributed?
EDIT This is the closest sample I have:
(fold-right (trace-lambda buggy (a b c) (and (neq? a b))) #t A B)
|(buggy 3 5 #t)
|#t
|(buggy 2 4 #t)
|#t
|(buggy 1 1 #t)
|#f
#f
The above shows a trace of my anonymous function attempting to perform the (and (neq? a b)) chain. However, it only performs this on elements in A and B at the same position/index.
All help is greatly appreciated!
A simplified version of member is easy to implement using fold, of course:
(define (member x lst)
(fold (lambda (e r)
(or r (equal? e x)))
#f lst))
Now, with that, the rest is trivial:
(define (difference a b)
(filter (lambda (x)
(not (member x b)))
a))
If you want to amalgamate all that into one function (using your neq?), you can do:
(define (difference a b)
(filter (lambda (x)
(fold (lambda (e r)
(and r (neq? e x)))
#t b))
a))
In Haskell, fold is capable of short-circuiting evaluation because of lazy evaluation.
But in Scheme it is impossible. That's why in Racket e.g., there's a special function supplied for that, ormap, which is capable of short-circuiting evaluation. IOW it is a special kind of fold which must be defined explicitly and separately in Scheme, because Scheme is not lazy. So according to your conditions I contend it is OK to use it as a special kind of fold.
Using it, we get
(define (diff xs ys)
(filter
(lambda (y)
(not (ormap (lambda (x) (equal? x y)) ; Racket's "ormap"
xs)))
ys))
If your elements can be ordered, it is better to maintain the sets as ordered (ascending) lists; then diff can be implemented more efficiently, comparing head elements from both lists and advancing accordingly, working in linear time.
Using Racket:
(define A '(1 8 6 2))
(define B '(5 7 9 1 6))
(filter-not (lambda (x) (member x B)) A)
==> '(8 2)
Of course, it is possible in Scheme to implement member on top of fold that short-circuits on the first match:
(define (member x lst)
(call-with-current-continuation
(lambda (return)
(fold (lambda (e r)
(if (equal? e x)
(return #t)
r))
#f lst))))
the first strange thing about map in clojure is in following snippet:
(apply map list '((1 a) (2 b) (3 c)))
The result is surprising for me:
((1 2 3) (a b c))
Anyone could explain how it works?
(apply f x '(y z)) is equivalent to (f x y z), so your code is equivalent to (map list '(1 a) '(2 b) '(3 c)).
When called with multiple lists, map iterates the lists in parallel and calls the given function with one element from each list for each element (i.e. the first element of the result list is the result of calling the function with the first element of each list as its arguments, the second is the result for the second elements etc.).
So (map list '(1 a) '(2 b) '(3 c)) first calls list with the first elements of the lists (i.e. the numbers) as arguments and then with the second elements (the letters). So you get ((list 1 2 3) (list 'a 'b 'c)).
I'm looking for a function in Scheme to replace a element in an equation by a value.
Exemple : '(+ a b c a) with (1 2 3) should give me '(+ 1 2 3 1). (I don't want to resolve the equation, it was just an exemple)
Basically, I want to say that a=1, b=2, c=3
To proceed, I extract the variables of my first list in another list.
Then, I received the expected values in another list.
Now, I want to assign values to variables.
Any hints on how I proceed?
Thanks a lot.
You can use an "association list" of mappings that looks like ((a 1) (b 2) (c 3)).
assq can retrieve the matching pair. So, for everything in your original list, you can look it up using assq and then replace it.
So:
(lambda (ls a-list)
(map (lambda (x)
(let ((lookup (assq x a-list)))
(if lookup
(cadr lookup)
x)))
ls)))
Would take a list and an association list and replace everything in the original list with its replacement (if there is one).
Ain't this what let do?
> (let ((a 1) (b 2) (c 3))
(+ a b c b))
=> 8
If you don't want to evaluate the expression:
> (let ((a 1) (b 2) (c 3))
`(+ ,a ,b ,c ,a))
=> (+ 1 2 3 1)