I need to write a function in Scheme (Racket) that takes two not necessarily equal
length lists and return a list which each element is the sum of the elements of the same
index from the two lists. if the lists' length is not equal the shorter one should append to itself until it reaches the size of the longer one. for example:
=> (addLists '(1 2 3 4) '(1 2))
(2 4 4 6)
=> (addLists '(1 2 3 4) '(1 2 3 4 5))
(2 4 6 8 6)
Until now I was able to write a function that completes this for equal length lists, but the problem lies with how do I increase the length of the shorter list within this function (or with a helper function that gets a list and a size and extends it properly).
(define (sumListPairs lst1 lst2)
(if (null? lst1) null
(cons (+ (car lst1) (car lst2))
(sumListPairs (cdr lst1) (cdr lst2)))))
Will appreciate any help, Thank you.
This can be done, but since I have the impression that this is a homework exercise, I'll only give a hint. First, introduce a named-let to do the actual recursion. Then, expand the number of cases in the recursion from two to four.
(define (sumListPairs lst1 lst2)
(let loop ((l1 lst1) (l2 lst2))
(cond ((and (null? l1) (null? l2)) null)
((null? l1) ...)
((null? l2) ...)
(else (cons (+ (car lst1) (car lst2))
(loop (cdr l1) (cdr l2)))))))
Now, fill in the ... parts. Note that you have access to all of l1, l2, lst1 and lst2. (You might want to refactor a bit after you're done, since the cases will be quite similar.)
Related
I am quite new with Scheme and with StackOverflow as well!
So, for the first contact I would like to do something simple and easy in Scheme.
I want to define a function that substracts the elements of the introduced list.
For example, the inputs should be: (sub '(4 12 6) '(0 6 3))
And the output should be: (4 6 3)
Thanks!!
What you'll need is to have a base case where you check if either list is empty and evaluate it to the empty list or you make a pair with the calculation of the first element of each list and the recursion for the rest of both lists. Basically you end up with:
(cons (- 4 0) (cons (- 12 6) (cons (- 6 3) '()))) ; ==> (4 6 3)
As an example of a recursive list processing function here is one that negates all elements:
(define (negate-list lst)
(if (null? lst)
'()
(cons (- (car lst))
(negate-list (cdr lst)))))
(negate-list '(1 2 3 4)) ; ==> (-1 -2 -3 -4)
Now there are even more fancy ways to do this. Eg,. you can use tail recursion:
(define (negate-list lst)
(let loop ((lst lst) (acc '()))
(if (null? lst)
(reverse acc)
(loop (cdr lst)
(cons (- (car lst)) acc)))))
You can use map:
(define (negate-list lst)
(map - lst))
So there you go. you're half way there.
I'm supposed to create a function called ( merge-list lst1 lst2) that alternately picks elements from one of the two input lists and creates a new list. For example the output of
(merge-list ‘(2 4) ‘(b c)) is '(2 b 4 c). Here's what I have so far, but when I compile I am receiving the "application:not a procedure" error
(define (merge-list lst1 lst2)
(cond ((null? lst1) lst2)
((null? lst2) lst1))
(append( append(list(car lst1) list(car lst2)))list-shuffle((cdr lst1)(cdr lst2))))
The solution is simpler than you think, we don't even have to use append - in fact, you should avoid using append, whenever possible use cons for building an output list: this is because append does more work and can potentially lead to O(n^2) solutions. Try this instead:
(define (merge-list lst1 lst2)
(cond ((null? lst1) lst2) ; if the first list is empty, return the second
((null? lst2) lst1) ; if the second list is empty, return the first
(else (cons (car lst1) ; otherwise `cons` the first element of the first list
(merge-list lst2 (cdr lst1)))))) ; and interleave the lists
It works as expected for lists of the same length:
(merge-list '(2 4) '(b c))
=> '(2 b 4 c)
(merge-list '(2 4 6) '(b c d))
=> '(2 b 4 c 6 d)
The original code I try to implement.. the output should be (1.4) (2.5) from my code.. I think you all know what I try to do....this is also tail recursion practice
my code
(define (myFunc lst1 lst2)
(if (or (null? lst1) (null? lst2))
'()
(list (cons (car lst1) (car lst2))
(myFunc (cdr lst1) (cdr lst2)))
))
after several of you gave me good advice about cons-pair.. so now it get's the dotted symbol in the middle.. then problem is that the improper list with empty list in the end..
when 2 input lists are like this ..... '(1 2 3 4) '(4 5 6))
my output is like this ; ((1 . 4) ((2 . 5) ((3 . 6) ())))
the empty list in the end of output shouldn't be there... so I couldn't understand about improper list , proper list....? is there are any document, I can look at?
Consider the difference between cons and list:
That is, (cons a b) creates a cell whose car is a and cdr is b.
(list a b) creates a cell whose car is a, but the cdr is a list, and the car of that list is b, while its cdr is nil.
If b is a list, the one on the left will be a list which has b as its tail, and with a added at the front of b.
The one on the right will also be a list, but one which has b as its second element, not as its tail like you want.
To fix your program, you only need to replace your list with a cons.
But your function is not tail-recursive, because it does things with the result of the recursive call.
To make it tail-recursive, a good way is usually to make a helper function which has an accumulator parameter.
I would probably write it something like this:
(define (zip-cars l1 l2)
(cons (car l1) (car l2)))
(define (zip-help l1 l2 result)
(if (or (null? l1) (null? l2))
result
(zip-help (cdr l1) (cdr l2) (cons (zip-cars l1 l2) result))))
(define (zip l1 l2)
(zip-help l1 l2 '()))
Just replace list with cons. Then your code will evaluate to `(cons (cons (cons .... (cons ... '())) and your list will be properly terminated.
(define (zip lst1 lst2)
(if (or (null? lst1) (null? lst2))
'()
(cons (cons (car lst1) (car lst2))
(zip (cdr lst1) (cdr lst2)))))
then
(zip '(1 2 3 4) '(4 5 6))
=> '((1 . 4) (2 . 5) (3 . 6))
This is not tail-recursive, though, since after returning from zip the consing still has to be done.
EDIT
An example of a tail-recursive version:
(define (zip lst1 lst2)
(let loop ((lst1 lst1) (lst2 lst2) (res '()))
(if (or (null? lst1) (null? lst2))
(reverse res)
(loop (cdr lst1)
(cdr lst2)
(cons (cons (car lst1) (car lst2)) res)))))
I am trying to write a function that takes two lists (must be of equal length) and then goes through each list comparing individual items.
For example: (1 2 3) and (2 4 5) would return true because each element of list 2 is greater than the corresponding element in list 1. (1 2 3) and (0 4 1) would return false as would (1 2 3) and (1 2 3 4) since they are of different size. Using Dr Racket
(define (each-bigger? a-lon another-lon)
(cond
(if
[(= (length a-lon) (length another-lon))true]
(then
[(> (first a-lon) (first another-lon))true]
(then
[(> (rest a-lon) (rest another-lon))true]
[else false])))))
this didn't work.
Unfortunately you've got both your syntax and your logic wrong. I believe your intention was to write something like this:
(define (each-bigger? lst1 lst2)
(cond
((and (null? lst1) (null? lst2)) #t) ; both lists are empty => true
((or (null? lst1) (null? lst2)) #f) ; only one is empty => not the same length => false
((>= (car lst1) (car lst2)) #f) ; first element of lst1 >= first element of lst2 => false
(else (each-bigger? (cdr lst1) (cdr lst2))))) ; recur on the rest of the list
which can be shortened to
(define (each-bigger? lst1 lst2)
(or (and (null? lst1) (null? lst2)) ; EITHER both lists are empty
(and (not (or (null? lst1) (null? lst2))) ; OR 1) none of them is empty
(< (car lst1) (car lst2)) ; 2) AND first element of lst1 < first element of lst2
(each-bigger? (cdr lst1) (cdr lst2))))) ; 3) AND each-bigger? is true for the rest of both lists
Hope this helps!
Clearly you want to implement a solution from scratch, and #uselpa's advice is spot-on. But in a non-academic context you should use existing procedures for solving this kind of problem, in particular andmap is your best friend here:
(define (each-bigger? lst1 lst2)
(and (= (length lst1) (length lst2))
(andmap < lst1 lst2)))
The trick is that andmap applies a predicate on elements of both lists, passing as parameters the first element of lst1 and the first element of lst2, then the second element of lst1 and the second element of lst2, and so on (BTW, andmap accepts one or more lists as parameters, as long as the predicate receives the same number of parameters).
If all the applications of the predicate return #t then #t is returned, if a single predicate returns #f then evaluation stops and #f is returned. In the above example, the predicate is just <, applied pair-wise between the two lists. It works as expected:
(each-bigger? '(1 2 3) '(2 4 5))
=> #t
(each-bigger? '(1 2 3) '(0 4 1))
=> #f
(each-bigger? '(1 2 3) '(2 4 5 6))
=> #f
I'm making a program that takes a list and a sum. If some of the numbers in the list add up to the sum, it returns true. Else, return false. It seems to be working for some cases but not for others. For example,
if I input this:
(numlist-sum '(5 9) 9)
It should return true because one of the numbers (9) equals the sum (9). But, for some reason, its returning false.
I can't figure out what the problem is. Help please?
(define (numlist-sum? ls sum)
(if (null? ls) #t
(if (and (null? (cdr ls)) (equal? (car ls) sum)) #t
(if (equal? (car ls) sum) #t
(if (equal? (cdr ls) sum) #t
(if (equal? (apply + (car ls) (cdr ls)) sum) #t
#f))))))
I'll give you some hints for solving this problem (looks like homework). First write a procedure that generates all the possible subsets of the list (e.g., the power set of the list). For example:
(powerset '(1 2 3))
=> '(() (1) (2) (3) (1 2) (1 3) (2 3) (1 2 3))
With the above procedure in hand (and it's easy to find the algorithm, Google is your best friend), simply iterate over each of the sublists and sum its values:
(apply + '(2 3))
=> 5
If one of the sublists' sum equals the expected value, return #t. If none of the sums satisfy the expected value, return #f.
EDIT:
I forgot to mention, this is a well-known problem - it's the subset sum problem, which can be efficiently solved (at least, more efficiently than generating the power set) using dynamic programming. But I don't think that's the goal of this homework in particular.
Here is a solution that checks each element one by one and then recurses down the list if the first element isn't the sum.
(define (numlist-sum list sum)
(and (not (null? list))
(let ((head (car list)))
(cond ((number? head)
(or (= sum head)
(numlist-sum (cdr list) sum)))
((list? head)
(or (= sum (apply + head))
(numlist-sum (cdr list) sum)))
(else 'ill-formed-list)))))
Also, note that your code can be rewritten as:
(define (numlist-sum? ls sum)
(or (null? ls)
(if (and (null? (cdr ls)) (equal? (car ls) sum))
(equal? (car ls) sum)
(equal? (cdr ls) sum)
(equal? (apply + (car ls) (cdr ls)) sum)))
I'd say the use of '(if pred #t else ...) is a bit awkward and hides the true logic of the code.