Any way to map functions with more than one argument in Scheme/Racket? - scheme

I'm currently doing an introductory course in Racket/Scheme, and am currently studying map, apply, and fold. For the most part, I've been assuming that map can only work on lambdas that accept a single argument. However, for certain problems I would find it incredibly useful to get around this somewhat - say, having a function that can be mapped to a list whilst also carrying an accumulator that updates independently for each recursive function call. While I can't get much more specific than that for fear of violating Honor Code, is there any way to get around being unable to give each recursive call an accumulator if you plan to use map?

map takes as many lists as you want:
(map + '(1 2 3) '(3 2 1) '(3 3 3)) ; ==> (7 7 7)
fold has an accumulator:
(foldl (lambda (a b c acc) (+ a b c acc)) 1 '(1 2 3) '(3 2 1) '(3 3 3)) ; ==> 22

Related

Return a predecessor for a given value and given list

I'm familiar with recursion procedures, but somehow I cannot solve this problem: I want to return a predecessor value for a given list.
(define (pred value lst)
...)
(pred 3 (list 8 3 7 3)) should return 8
(pred 2 (list 1 2 2 2 2)) should return 1
Note that I only want to return the "first" occurrence of a predecessor, therefore in this first example the number 7 does not have to be returned.
I'm currently stuck because I "loose information" about the predecessor value, once I call a recursion by (pred value (rest lst)) ... I don't know to "store" this information in e.g. a list.
Thanks for any help! I'm already trying for hours...
So here is how to fix this. You make a helper that takes additional arguments. One of those can be the previous element. eg.
(define (iterate-pred value last lst)
...)
(pred 3 '(1 2 3 4)) ; ==>
(iterate-pred 3 1 '(2 3 4)) ; ==>
(iterate-pred 3 2 '(3 4)) ; ==>
; ==> 2
So to update the variables you just call the same procedure again with the new values. It is just as easy as iterating the list to begin with, which uses the same strategy.
You can implement these as internal procedure either with define/letrec or you can use named let. Then you can omit value in the helper since you have access to it through the scope.
Good luck!

DrRacket 2 list inputs and reversing only one

I'll preface this by saying this is for an assignment, but I am not sure how to approach this after going through other stackoverflow questions for an hour or two.
I'm attempting to create a reverse function that accepts 2 lists as input and returns the first list reverse appended with the second list.
Example: (reverse '(1 2) '(3 4)) --> (2 1 3 4)
My code is below, I have tried conditional statements such as when the first list is NOT null then do the main logic, then when it is only return l2 (which still returned (3 4 2 1) instead of (2 1 3 4).
The problem I'm having is that no matter what I do the second list is always at the beginning of the first reversed list.
(define (myreverse l1 l2)
(if (null? l) l2)
(append (myreverse(cdr l1) l2) (list(car l1))))
Consider the following:
(reverse '(1 2 3 4))
=> '(4 3 2 1)
(append (reverse '(1 2)) '(3 4))
=> '(2 1 3 4)
Think about how you can implement reverse, and how you can use it in your myreverse procedure.
With racket/scheme it is very helpful to think of these kinds of problems from the bottom up.
For example, what do you do when the first list is null?? Well, you're done! so just return the second list. What do you do when it has just one element? Well, we tack that element onto the second list and we're done. But a moment's thought tells us that all the cases are now covered.
(define (rev-first left right)
(if (null? left)
right
(rev-first (??? left) (???? right))))
Actually this kind of recursion is captured with foldl and foldr more generally. But I don't know if it's instructive for you at this point.

Scheme skip or continue during lambda map

I am building a function that takes a set of integers, and returns a subset of the odd integers. I am running into the problem that I need to skip over the even integers in my map, but right now my function returns #<void> instead.
(define (oddSubset set)
(map
(lambda (x)
(cond
((odd? x) x)))
s))
In use:
> (oddSubset '(1 2 3))
'(1 #<void> 3)
Is there logic I can use like "else, continue onto next element"?
Note: I am trying to rewrite the built in filter function
map does not have the possibility to skip, but you can use filter instead:
(filter odd? '(1 2 3 4 5 6)) ; ==> (1 3 5)
Or you can use fold-right
(fold-right (lambda (e acc)
(if (odd? e)
(cons e acc)
acc))
'()
'(1 2 3 4 5 6)) ; ==> (1 3 5)
I assume #!r6rs. Both fold-right and filter are in the library (rnrs lists (6)). There is also SRFI-1 which gives both of these procedures for a R5RS language.
In the none standard language #!racket uses the name foldr in place of fold-right.
map looks like a weird choice for this. By definition it maps a function onto each element in a list and returns the list of the results, so trying to "skip" elements seems unnatural.
filter is what you're looking for.
(filter odd? '(1 2 3))
'(1 3)
map applies a function on all elements. Each invocation of the function is supposed to be independant from the others. Even if you introduce a state with a closure, you can't avoid map to build a list of same size as your input.
You want to (re-)implement the filter function. If you want to do it by yourself, you should try to use foldl and foldr instead.
(cond
((odd? x) x))
map check each element in the list: if it is odd, then return that element. But you did not tell your program what to do when the element is not odd, so map return void.
To solve your problem: use filter instead, since map will return something for each element in the list.
If you want to know how to implement filter, try reading the second chapter of SICP

Nested for-loop in LispWorks (4x4 queens)

I have just started using LispWorks and I am working on the 4x4 Queen problem. What I am trying to do is with the help of 4 for-loops state all the possible Queen-combinations, and then checking whether they are possible solutions or not. A possible state (1 3 4 2) for example means that in row 1 queen is in column 1, in row 2 queen is in column 3 and so on.
I think I am doing something wrong though because the compiler don't like my loops. The error I'm getting is something like: Loop keyword expected in...
Here is the code:
(loop for i in '(1 2 3 4)
nconc (loop for j in '(1 2 3 4)
nconc (loop for k in '(1 2 3 4)
nconc (loop for l in '(1 2 3 4)
(defvar first 0)
(defvar second 0)
(defvar third 0)
(defvar fourth 0)
(setq first (abs (- 1 i)))
(setq second (abs (- 2 j)))
(setq third (abs (- 3 k)))
(setq fourth (abs (- 4 l)))
(if (and (not (eq first second)) (not (eq first third)) (not (eq first fourth)) (not (eq second third))
(not (eq second fourth)) (not (eq first second)) (not (eq third fourth)))
(if (and (or (eq i j) (eq i k) (eq i l) (eq j k) (eq j l)) (or (eq k l)))
(print i j k l)))))))
Please help me out with the nested loops and feel free to comment on my code and possibly suggest better ways of solving this problem. Please keep it fairly basic, I am a complete beginner to LispWorks and I have only done some ADA 95 and Java before.
Thank you in advance
The reason you get the error message is that your code is lacking the keyword do after '(1 2 3 4) in the inner loop. As you are not collecting results from the loops, just printing the final result, you should use do instead of nconc in the outer loops as well.
Fixing this, another error shows up: print only print one object, so in order to print all four numbers you can use e.g. (print (list i j k l))
The program then prints
(1 1 1 1)
(1 3 1 1)
(2 2 1 1)
(4 2 2 2)
(4 4 3 3)
(4 4 4 4)
so something is wrong with the logic as well.
However, there are also lots of improvements that can be done to the code:
Do not use defvar to introduce new variables inside the loop. defvar creates dynamic ("global") variables. Instead, use let, or introduce them as loop variables, like you have done with i , j etc.
Instead of first creating the variables, and then updating them once using setq, give them the correct value when they are created (using let or a loop keyvword).
As you are comparing pairs of numbers: Instead of using eq (which is for symbols) or eql (which is the correct one for comparing two numbers of the same type), use = or /= which can compare many numbers to check if they are all equal/different.
Together with a small fix of the logic, this results in the following code (which for illustration introduces some variables using loop keywords, and some using let):
(loop for i in '(1 2 3 4)
for first = (abs (- 1 i))
do (loop for j in '(1 2 3 4)
for second = (abs (- 2 j))
do (loop for k in '(1 2 3 4)
do (loop for l in '(1 2 3 4)
do (let ((third (abs (- 3 k)))
(fourth (abs (- 4 l))))
(if (and (/= first second third fourth)
(/= i j k l))
(print (list i j k l))))))))
Which result in
(2 4 3 1)
(3 2 4 1)
(4 1 3 2)
(4 2 1 3)
meaning that there are still logic errors present.
Hopefully the simplified code makes it easy to spot the error, which probably has something to do with not comparing (+ i 1), (+ j 2) etc.
Finally: If you want to extend the code to handle more queens, creating a recursive solution will be better than a solution using even more nested loops.

Map, Filter, Foldr in DrRacket/Scheme

Programming language: Scheme/DrRacket
We're currently going over map, filter, and foldr in my comp sci class. I understand that all three can be used to create abstract functions, but I am honestly a little confused about the difference between the three and when I'd use each one.
Anyone care to explain what each is used for and how they are different? Unfortunately my book is not very clear.
The basic idea is that all three are ways of applying some function to all the elements of a list.
Map is perhaps the simplest--you just apply the function to each element of the list. This is basically the same as a for-each loop in other languages:
(map (lambda (x) (+ x 1)) '(1 2 3))
=> (2 3 4)
Basically, map is like this: (map f '(1 2 3)) is the same as (list (f 1) (f 2) (f 3)).
Filter is also simple: the function acts like an arbiter, deciding whether to keep each number. Imagine a really picky eater going through a menu and whining about the things he won't eat ;)
(filter (lambda (x) (equal? x 1)) '(1 2 3))
=> (1)
Fold is the hardest to understand, I think. A more intuitive name would be "accumulate". The idea is that you're "combining" the list as you go along. There are some functions in ever day use that are actually folds--sum is a perfect example.
(foldr + 0 '(1 2 3))
=> 6
You can think of the fold as taking the function and putting it between each element in the list: (foldr + 0 '(1 2 3)) is the same as 1 + 2 + 3 + 0.
Fold is special because, unlike the other two, it usually returns a scalar value--something that was the element of the list rather than the list itself. (This isn't always true, but think of it this way for now anyway.)
Note that I may not have gotten every detail of the code perfect--I've only ever used a different, older implementation of Scheme so I might have missed some Racket details.
I can recommend these finger exercises (and the text that comes before):
http://htdp.org/2003-09-26/Book/curriculum-Z-H-27.html#node_idx_1464

Resources