DrRacket 2 list inputs and reversing only one - scheme

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.

Related

Alternating Sum Using Foldr/Foldl (Racket)

Back again with another Racket question. New to higher order functions in general, so give me some leeway.
Currently trying to find the alternating sum using the foldr/foldl functions and not recursion.
e.g. (altsum '(1 3 5 7)) should equal 1 - 3 + 5 - 7, which totals to -4.
I've thought about a few possible ways to tackle this problem:
Get the numbers to add in one list and the numbers to subtract in another list and fold them together.
Somehow use the list length to determine whether to subtract or add.
Maybe generate some sort of '(1 -1 1 -1) mask, multiply respectively, then fold add everything.
However, I have no clue where to start with foldl/foldr when every operation is not the same for every item in the list, so I'm having trouble implementing any of my ideas. Additionally, whenever I try to add more than 2 variables in my foldl's anonymous class, I have no idea what variables afterward refer to what variables in the anonymous class either.
Any help or pointers would be greatly appreciated.
We can leverage two higher-order procedures here: foldr for processing the list and build-list for generating a list of alternating operations to perform. Notice that foldr can accept more than one input list, in this case we take a list of numbers and a list of operations and iterate over them element-wise, accumulating the result:
(define (altsum lst)
(foldr (lambda (ele op acc) (op acc ele))
0
lst
(build-list (length lst)
(lambda (i) (if (even? i) + -)))))
It works as expected:
(altsum '(1 3 5 7))
=> -4
Your idea is OK. You can use range to make a list of number 0 to length-1 and use the oddness of each to determine + or -:
(define (alt-sum lst)
(foldl (lambda (index e acc)
(define op (if (even? index) + -))
(op acc e))
0
(range (length lst))
lst))
As an alternative one can use SRFI-1 List Library that has fold that allows different length lists as well as infinite lists and together with circular-list you can have it alterate between + and - for the duration of lst.
(require srfi/1) ; For R6RS you import (srfi :1)
(define (alt-sum lst)
(fold (lambda (op n result)
(op result n))
0
(circular-list + -)
lst))
(alt-sum '(1 3 5 7))
; ==> -4

Scheme - Adding a list to a list of lists?

I am trying to answer a scheme question, for a part of this question I have to make a list of lists:
(define (join a b (result '()))
(cons (list a b) result))
So I am taking in two characters, and placing them in a list, then I need to place each sublist into a list of lists, this function is being called recursively with two characters each time, so it is supposed to work like this:
join 1 4
=> ((1 4))
join 2 5
=> ((1 4) (2 5))
join 3 6
=> ((1 4) (2 5) (3 6))
However, I am getting ((3 6) (2 5) (1 4)), so the elements need to be reversed, I tried reversing my cons function to (cons result (list a b)) but then I get (((() 1 4) 2 5) 3 6), how can I get the list the right way around, or is there an easier way to do what I'm doing?
If you need to add elements at the end of a list use append; cons is for adding elements at the head. Try this:
(define (join a b (result '()))
(append result (list (list a b))))
Notice that append combines two lists, that's why we have to surround the new element inside its own list. Also, it's not a good idea to add elements at the end, using append is more expensive than using cons - if possible, rethink your algorithm to add elements at the head, and reverse the result at the end.
This can easily be done like this:
(define (group-by-2 lst)
(let loop ((lst lst) (rlst '()))
(if (or (null? lst) (null? (cdr lst)))
(rcons->cons rlst)
(loop (cdr lst)
(rcons (list (car lst)
(cadr lst))
rlst)))))
(group-by-2 '(1 2 3 4 5 6 7 8))
; ==> ((1 2) (2 3) (3 4) (4 5) (5 6) (6 7) (7 8))
Now rcons is like cons but it makes a reverse list. (rcons 1 (rcons 2 (rcons 3))) ; ==> {3 2 1} however it is not a list so you have to convert it to a list (rcons->list (rcons 1 (rcons 2 (rcons 3))) ; ==> (3 2 1)
The magic functions are really not that magical:
(define rcons cons)
(define rcons->cons reverse)
So in fact I didn't really have to make that abstraction, but hopefully I made my point. It doesn't matter how you organize the intermediate data structure in your programs so why not make the best for the job you are doing. For lists it's always best to iterate from beginning to end and make from end to beginning. Every insert O(1) per element and you do a O(n) reverse in the end. It beats doing append n times that would make it O(n²)

Possible position of element in list using recursion?

Can anybody tell how to insert an element in the list in different positions and return a list of those possible combination as lists using only recursion?
For example, list is (2 3) and element to insert is 1.
Output:
list(
list (1 2 3)
list (2 1 3)
list (2 3 1)
)
The first step is to determine what the output should look like, and in this case it should be a list of lists.
The second step is usually to break the problem down into cases of the input list.
The case of the empty list is pretty simple - the result is a list that contains one singleton list
(define (insert i ls)
(if (null? ls)
(list (list i))
(...)))
For the case of the non-empty list, it's helpful to examine the structure of the expected result.
(insert 1 '(2 3))
-->
((1 2 3) (2 1 3) (2 3 1))
Note that only the first element of the result has 1 as its first element, and we can easily create this with (cons 1 '(2 3)).
The other elements all have the first element of the input list as their first element, and if you look at their tails, (1 3) and (3 1), you'll see that they are the results of the recursion (insert 1 '(3)).
What's missing is that you need to cons the 2 onto each one of them afterwards.
Now we have all the necessary parts - in summary
(define (insert i ls)
(if (null? ls)
(list (list i))
(cons (cons i ls) (<...something...> (insert i (cdr ls))))))
Where I've left a "<...something...>" part for you to figure out.

Scheme create list of pairs using foldr without explicit recursion

I am learning a course of Scheme and have to do the following task. I have to write a function that gets two lists A and B in the same length and returns one list that every item inside is a list of two items - one from A and second from B.
For example the function gets '( 1 2 3) and '(4 5 6) and returns '((1 4)(2 5)(3 6)).
I can do that using map like this:
(define (func lst1 lst2) (map (lambda(x y) (list x y)) lst1 lst2))
But the the question is to do that by foldr and without explicit recursion.
Can anyone please help me? I have no idea how to do that....
Thanks!
The trick is knowing what to pass as a function parameter, here's how:
(define (func l1 l2)
(foldr (lambda (e1 e2 acc)
(cons (list e1 e2) acc))
'()
l1 l2))
Notice that we're passing two lists at the end of foldr, so the lambda expects three parameters: the current element from the first list (e1), the current element from the second list (e2) and the accumulated output (acc), which starts with value '(). The rest is easy, just build the output along using cons and list. It works as expected:
(func '(1 2 3) '(4 5 6))
=> '((1 4) (2 5) (3 6))

What is the output from this short string of cdr/car commands?

I am trying to understand how multiple calls of car and cdr work together. For example, the following example seems simple enough:
(car (cdr '(car (cdr (1 2 3))))
My DrRacket compiler outputs '(cdr (1 2 3)) when it is run, but I don't see how. Shouldn't cdr of (1 2 3) be taken first? What about the first two car and cdr?
No, the quote operator will quote all forms and sub forms that follow it. Only the first car and cdr of the list are executed; first (cdr '(car (cdr (1 2 3))) -> '((cdr (1 2 3)), and then (car '((cdr (1 2 3))) -> '(cdr (1 2 3)).
The problem here is that "quote" is much more powerful than you think it is. In particular, the quote is an instruction to the "reader"--the very first piece of code to examine your program--to rewrite your program from
(car (cdr '(car (cdr (1 2 3))))
...into
(car (cdr (list (quote car) (list (quote cdr) (list 1 2 3))))
That is, quote trickles down and changes every left paren into a new list creation, and every identifier into a quoted symbol.
Applying quote to things other than identifiers (e.g., 'abc) is a fairly slippery concept, and usually makes more sense after you have lots of experience with lists, and are looking for a nice way to abbreviate them.

Resources