I'm stuck 5 days with this task in Racket, does anybody know how can I approach it?
Given a function of arity 2 and a list of n elements, return the evaluation of the string function of all the elements, for example:
>(reduce + '(1 2 3 4 5 6 7 8 9 10))
55
> (reduce zip '((1 2 3) (4 5 6) (7 8 9)))
'((1 (4 7)) (2 (5 8)) (3 (6 9)))
Here you go.
(define (reduce func list)
(assert (not (null? list)))
(if (null? (cdr list))
(car list)
(func (car list) (reduce func (cdr list)))))
Tests:
> (reduce + '(1 2 3 4 5 6 7 8 9 10))
55
> (reduce zip '((1 2 3) (4 5 6) (7 8 9)))
((1 (4 7)) (2 (5 8)) (3 (6 9)))
For completeness, an implementation for zip (one that assumes two lists and that your lists are all the same length) is:
(define (zip l1 l2) (map list l1 l2))
You can express it in terms of foldl:
(define (reduce f xs)
(and (not (empty? xs)) (foldl f (first xs) (rest xs))))
(define reduce
(λ (f init ls)
(if (empty? ls)
init
(reduce f (f init (first ls)) (rest ls)))))
Related
I'm trying to create a function in Racket that will read two lists and create a union of the elements in the two sets. This is the code I created to try and emulate this function:
(define (union set1 set2)
(define unilst '())
(letrec ([build (lambda (build1 build2 lst)
(define a '())
(define b '())
(cond[(equal? build1 '()) 0]
[(equal? build2 '()) 0]
[else (set! a (first build1)) (set! b (first build2))
(cond
[(= a b) (set! lst (cons lst a))]
[else (set! lst (cons b lst))
(set! lst (cons a lst))])
(set! lst (cons (build (rest build1) (rest build2) lst) lst))])
lst)])+
(set! unilst (build set1 set2 '()))
unilst))
But the output I receive is:
((((3 4 2 3 1 2) 3 4 2 3 1 2) 2 3 1 2) 1 2)
Should I handle my recursion differently? Or is there something I'm missing?
Any help would be appreciated.
This looks like you've tried to write code in a different language but with Scheme syntax.
There is almost never any point in using set!.
The union of the sets s1 and s2 is
if s1 is empty, then s2
if s2 is empty, then s1
if (first s1) is a member of s2, then the union of (rest s1) and s2
otherwise, add (first s1) to the union of (rest s1) and s2
(define (union s1 s2)
(cond [(empty? s1) s2]
[(empty? s2) s1]
[(member (first s1) s2) (union (rest s1) s2)]
[else (cons (first s1) (union (rest s1) s2))]))
Test:
> (union '() '())
'()
> (union '() '(1 2 3))
'(1 2 3)
> (union '(1 2 3) '())
'(1 2 3)
> (union '(1 2 3) '(1 2 3))
'(1 2 3)
> (union '(1 2 3) '(4 5 3))
'(1 2 4 5 3)
> (union '(3 2 1) '(4 5 3))
'(2 1 4 5 3)
Of course, if the output is supposed to be a set, the inputs must also be sets (i.e. no repeated values).
For my homework problem, I have to remove the duplicates in a list if part of the list is inside another. The expected outcome is supposed to be this:
(remove-redundant '((R (1 2 3 8 e 4 7 6 5))
(U (e 2 3 1 8 4 7 6 5))
(D (1 2 3 7 8 4 e 6 5)))
'((D (1 2 3 e 8 4 7 6 5))
(L (e 2 3 1 8 4 7 6 5))
(U (2 e 3 1 8 4 7 6 5))
(U (2 8 3 1 e 4 7 6 5))))
Returns:
((R (1 2 3 8 e 4 7 6 5)) (D (1 2 3 7 8 4 e 6 5)))
It is supposed to check to see if the list inside each list, for the 1st parameter appears anywhere in the 2nd. If it does appear, then remove that from the 1st list. Basically, if (1 2 3 e 8 4 7 6 5) matches something in the 1st list, remove it from the 1st list. I need to do this recursively, it is supposed to be a functional program.
I have already tried recursing through the list, but it doesn't reset (i.e. it will check the second list for the beginning of the first list but then will return.
(defun same-state (l1 l2)
(if (equal (cadr l1) (cadr l2)) t nil))
(defun remove-redundant (l1 l2)
(cond
((null l2) l1)
((null l1) nil)
((same-state (car l1) (car l2)) (remove-redundant (cdr l1) (cdr l2))
(T (remove-redundant l1 (cdr l2)))))
You're close, but there should be some accumulation of the cells you want to keep in the t case of your cond form,
eg.
;; ...
(t
(cons (car l1) (remove-redundant (cdr l1) (cdr l2))))
and when you check if the first element of l1 exists in l2 there should be another loop or recursion to check against all the elements in l2, eg.
(defun same-state (l1 l2)
(find l1 l2 :key #'cadr :test #'equal))
(defun remove-redundant (l1 l2)
(cond
((null l2) l1)
((null l1) nil)
((same-state (cadar l1) l2)
(remove-redundant (cdr l1) (cdr l2)))
(t (cons (car l1)
(remove-redundant (cdr l1) (cdr l2))))))
;; => ((R (1 2 3 8 e 4 7 6 5)) (D (1 2 3 7 8 4 e 6 5)))
You will need two loops: one to go through the first list, and then one per element of that to find matches in the second list.
I'm still learning Scheme.
If have these two list of lists:
'((1 2 (3 4) 5) (12 13 4))
'((3 4 9) (7 6 5 4))
I want to get this list:
'((1 2 (3 4) 5) (12 13 4) (3 4 9) (7 6 5 4))
But with cons:
(cons '((1 2 (3 4) 5) (12 13 4)) '((3 4 9) (7 6 5 4)))
I get this list:
'(((1 2 (3 4) 5) (12 13 4)) (3 4 9) (7 6 5 4))
NOTE:
In this example the both lists has two sublists. But they can have n sub-lists.
I have tried with append but it doesn't work when one of the list of lists is only a list:
(append '(1 2 3 4) '((23 24 25 26) (a b c)))
> '(1 2 3 4 (23 24 25 26) (a b c))
Is there a function that do it or do I have to implement it?
The behavior that you want is very specific, you won't find it in the standard library. Good news is, it's simple to implement in a portable and efficient way that covers all the possible cases, assuming that the input lists are non-empty:
(define (my-append lst1 lst2)
(cond ((and (pair? (car lst1)) (pair? (car lst2)))
(append lst1 lst2))
((pair? (car lst1))
(append lst1 (list lst2)))
((pair? (car lst2))
(append (list lst1) lst2))
(else
(append (list lst1) (list lst2)))))
For example:
(my-append '((1 2 (3 4) 5) (12 13 4)) '((3 4 9) (7 6 5 4)))
=> '((1 2 (3 4) 5) (12 13 4) (3 4 9) (7 6 5 4))
(my-append '(1 2 3 4) '((23 24 25 26) (a b c)))
=> '((1 2 3 4) (23 24 25 26) (a b c))
The function firstnprimes is supposed to return the first n primes. Arguments are n the number of primes, nlist a list from 2-m of integers. and slist is the solution list and is initially empty and is added to and reconstructed each call to firstnprimes.
It works by removing the first number from the list and then removing all multiples of that number from nlist with listminusnonprimes; which I know works. The problem is that I can't control this action, I figure for each pass if slist's length was equal to the number of primes you want then you're done.
Code:
(define firstnprimes
(lambda (n nlist slist)
(let ((slist (cons (car nlist) slist)))
(if (zero? n)
slist
(firstnprimes (- n 1) (listMinusNonprimes (car nlist) (car nlist) nlist) slist)))))
(define listminusnonprimes
(lambda (num d lst)
(if (null? lst)
'()
(if (= d (car lst))
(listminusnonprimes num (+ num d) (cdr lst))
(cons (car lst) (listminusnonprimes num d (cdr lst)))))))
Your definition of listminusnonprimes is wrong. Imagine the call (listminusnonprimes 3 3 '(3 5 7 9 11 ...)) (as this would happen after you remove all multiples of 2). Now 3 is removed, and recursively you call (listminusnonprimes 6 3 '(5 7 9 11 ...)), but 6 is not there, so the call does nothing and the result is (3 5 7 9 11 ...).
I would suggest implementing this function using the mod operation.
You don't need (let ((slist (cons (car nlist) slist))). Also, use append instead of cons as shown
(define firstnprimes
(lambda (n nlist slist)
(if (zero? n)
slist
(firstnprimes (- n 1) (listminusnonprimes (car nlist) (car nlist) nlist) (append slist (list (car nlist)))))))
So,
(firstnprimes 2 '(2 4 7 9 21 36) '()) => '(2 7)
(firstnprimes 3 '(2 4 7 9 21 36) '()) => '(2 7 9)
Lots of problems with your implementation though. First, the list has to be in increasing order. Also, the list has to start with a prime number. Also, the number of prime numbers in the nlist has to be less than or equal to n.
(firstnprimes 4 '(2 4 7 9 21 36) '()) => '(2 7 9 21) which is wrong
Here is a slightly better implementation of your concept.
(define firstnprimes
(lambda (n nlist slist)
(if (or (zero? n) (null? nlist))
slist
(firstnprimes (- n 1) (listminusnonprimes (car nlist) (car nlist) nlist) (append slist (list (car nlist)))))))
(define listminusnonprimes
(lambda (num d lst)
(if (null? lst)
'()
(if (< d (car lst))
(listminusnonprimes num (+ num d) lst)
(if (= d (car lst))
(listminusnonprimes num (+ num d) (cdr lst))
(cons (car lst) (listminusnonprimes num (+ num d) (cdr lst))))))))
Now,
(firstnprimes 2 '(2 4 7 9 21 36) '()) => '(2 7)
(firstnprimes 3 '(2 4 7 9 21 36) '()) => '(2 7 9)
(firstnprimes 4 '(2 4 7 9 21 36) '()) => '(2 7 9)
But the first element still has to be prime though
Write a recursive Scheme procedure count-dist elements that takes a list with duplicate elements and returns the number of distinct elements in the list.
This is my code, but it is not working correctly. Please help! Thanks!!
(define (count-dist-elements lis)
(cond
((null? lis) 0)
((null? (cdr lis))0)
((member (car lis)(cdr lis)))
(else(+ 1(count-dist-elements (cdr lis))))))
p/s: let it be (count-dist-elements '(1 2 1 1 2 3 4 5 5 6 6 7 7 8 8 8 9))
It looks like you're getting pretty close.
What happens when you pass your function a list with one element? What should your function return in this case?
What about a two-element list with the same element (eg. (5 5))? Does your function return a sensible value?
First: Why are you returning zero in the (null? (cdr lis)) case?
Second: What do you think your code returns in the case where the first element also occurs later in the list? Are you sure?
(define (count-dist-elements lst dist-elems count)
(cond ((null? lst) count)
((member (car lst) dist-elems)
(count-dist-elements (cdr lst) dist-elems count))
(else
(count-dist-elements (cdr lst)
(cons (car lst) dist-elems)
(+ 1 count)))))
(count-dist-elements '(a b b c) '() 0) ==> 3
(count-dist-elements '(1 2 1 1 2 3 4 5 5 6 6 7 7 8 8 8 9) '() 0) ==> 9
Or, if you want it recursive and not iterative (and, it has to use a function call like the one shown),
(define (count-dist-elements lst . dist-elems)
(let ((dist-elems (if (null? dist-elems) '() (car dist-elems))))
(cond ((null? lst) 0)
((member (car lst) dist-elems)
(count-dist-elements (cdr lst) dist-elems))
(else
(+ 1 (count-dist-elements (cdr lst) (cons (car lst) dist-elems)))))))
Gives the same results.
(count-dist-elements '(1 2 1 1 2 3 4 5 5 6 6 7 7 8 8 8 9)) ==> 9