I am supposed to create a function that takes two lists as the arguments and returns a list of pairs from combining the input lists where the pairs are a combination of the elements at the given index.
Example Input:
(zipper '(1 2 3) '(4 9 5 7))
Example Output:
'((1 4) (2 9) (3 5))
If one input list is longer than the other, extra elements of the longer list are ignored. The implementation has to be recursive.
The code I created:
(define (zipper list1 list2)
(if (or (empty? list1) (empty? list2))
'()
(list (list (zipper (rest list1) (rest list2)) ))))
The output:
'((((((((()))))))))
'((((((()))))))
'()
Can someone please help? I've also tried using 'cons' to put the elements together, so am not sure how the elements are getting lost. I'm brand new to Racket. Thanks.
Pretty simple, all we have to do is make a function that will return empty as a base case if either list is empty, otherwise we will cons the (first list1, first list2) to the recursive call.
(define (zipper list1 list2)
(cond [(or (empty? list1)
(empty? list2)) empty]
[else (cons
(cons (first list1)
(first list2)) ;; List of first elements
(zipper (rest list1) (rest list2)))]))
Related
I would like to create a function for class that would take two arguments L and L1 as lists and put all even numbers from L into L1.
I've tried for several hours to make it work, but unfortunatelly I couldn't.
This is my Scheme code:
(define (pair L L1)
(cond
((and (not (empty? L)) (= (modulo (first L) 2) 0))
(begin (append (list (first L)) L1) (pair (rest L) L1)))
((and (not (empty? L)) (= (modulo (first L) 2) 1))
(pair (rest L) L1))
(else L1)
))
I assume you want to use L1 as an accumulator, and at the end return its content.
About your code:
It's enough to check once in the first clause of cond if L is empty (null?).
append is fine when you want to append a list. In your case you append one element, so cons is much better.
You don't have to take modulo of a number, to check if it's even. There is build in even? predicate.
So, after all this considerations, your code should look something like this:
(define (pair L L1)
(cond ((null? L) L1)
((even? (first L))
(pair (rest L) (cons (first L) L1)))
(else (pair (rest L) L1))))
Now let's test it:
> (pair '(0 1 2 3 4 5 6 7) '())
(6 4 2 0)
As you can see, it returns numbers in reverse order. It's because as we move down the list L from head to tail, we cons new values to the head (and not tail, like append would) of the list L1. To fix it, it's enough to (reverse L1) in the first cond clause instead of simply returning L1.
I highly recommend "Little Schemer" book. After reading it, you will be able to write any kind of recursive functions even in your sleep ;)
I've just started to learn racket and I need to loop a list with an index.
Now, I'm using for:
#lang racket
(for ([index (in-range 0 (length list1))])
(if (number? (list-ref list1 index))
(function-numeric list1 index list2)
(function-no-numeric list1 index list3)))
function-numeric and function-no-numeric return a list, and I need to create a list with those lists return by those functions. But I don't know how to do it.
Maybe with map could be easier, but I don't it.
How can I return a list of lists with my for loop?
For starters, using indexes is the worst possible way to traverse a list and should be avoided: each list-ref operation is O(n), because to reach element i you have to traverse all i-1 elements before it, making the whole traversal a whopping O(n^2) operation. If you absolutely need them, then generate a separate list with the indexes.
For collecting the returned data in a list, we can make use of for/list to accumulate the result of each iteration, and we can even traverse in parallel more than one sequence of elements. Let's put all together:
(for/list ([element list1]
[index (in-range (length list1))])
(if (number? element)
(function-numeric list1 index list2)
(function-no-numeric list1 index list3)))
I just hope you're not using list-ref again inside function-numeric and function-no-numeric. Maybe there's a better way to structure your algorithm, to avoid indexes altogether - lists should not be used in the same way we use arrays! If your algorithm can't be modified to avoid indexes, then consider using a vector instead, which is optimized for fast item retrieval using indexes.
If you have just started to learn Racket, I really recommend against for and for/list. You should understand the basic first: what is a list.
A list (also known as linked list) is either:
empty; or
a cons of an element with another list
For example,
empty is an empty list.
(cons 9 empty) is a list with one element: 9.
(cons 3 (cons 9 empty)) is a list with two elements: 3 and 9.
Given a list, here are primitive operations (besides cons) that you can do.
(empty? lst): check whether or not lst is empty. For example, (empty? empty) evaluates to #t but (empty? (cons 1 empty)) evaluates to #f.
(first lst): returns the first element of lst if lst is a cons. Error if lst is an empty. For example, (first (cons 2 (cons 1 empty))) evaluates to 2 but (first empty) results in an error.
(rest lst): returns the rest of lst if lst is a cons. Error if lst is an empty. For example, (rest (cons 2 (cons 1 empty))) evaluates to (cons 1 empty) but (first empty) results in an error.
With a combination of first and rest, you can access any element. If you have a list (cons 5 (cons 4 (cons 3 (cons 2 empty)))) and you want to access the second element (which should be 4), you would compute:
(rest lst) which will give you (cons 4 (cons 3 (cons 2 empty)))
(first (rest lst)) which will give you 4.
list is simply an abbreviation to construct a list easily
(list) is an abbreviation for empty.
(list 9) is an abbreviation for (cons 9 empty)
(list 1 2 3) is an abbreviation for (cons 1 (cons 2 (cons 3 empty))).
Other list operations are implemented using only the above primitive operations. For instance, list-ref is implemented as follows:
(define (my-list-ref xs i)
(cond
;; a list is either empty
[(empty? xs) (error 'out-of-bound)]
;; or a cons, where it's safe to use first and rest
[(= i 0) (first xs)]
[else (my-list-ref (rest xs) (- i 1))]))
;; (my-list-ref (list) 0) => out-of-bound error
;; (my-list-ref (list 4 5 6) 0) => 4
;; (my-list-ref (list 4 5 6) 1) => 5
;; (my-list-ref (list 4 5 6) 2) => 6
As Óscar López mentioned, although list looks similar to array, the way to think about them is very different. Using list-ref takes O(i) which is fine if you want to get the i-th element once, but it is not the right way to access all elements (or even a lot of elements). Instead, simply access all of them in one pass. For example, if I have a list (list 2 3 4) and I want to obtain another list with 10 added to each element of the original list, I would write:
(define (add10-all xs)
(cond
;; a list is either empty, where (add10-all empty) should return empty
[(empty? xs) empty]
;; or a cons, where we want to to add 10 to the first element,
;; recur on the rest, and create a resulting cons
[else (cons (+ 10 (first xs)) (add10-all (rest xs)))]))
;; (add10-all (list)) => (list)
;; (add10-all (list 2 3 4)) => (list 12 13 14)
In your case, you probably want:
;; assume function-numeric consumes an element from list1 and the whole list2
;; assume function-no-numeric consumes an element from list1 and the whole list3
(define (foo list1 list2 list3)
(cond
[(empty? list1) empty]
[else
(define e (first list1))
(define out (if (number? e)
(function-numeric e list2)
(function-no-numeric e list3)))
(cons out (foo (rest list1) list2 list3))]))
(foo list1 list2 list3)
or
;; assume function-numeric consumes an element from list1 and the corresponding element in list2
;; assume function-no-numeric consumes an element from list1 and the corresponding element in list3
(define (foo list1 list2 list3)
(cond
[(empty? list1) empty]
[else
(define e (first list1))
(define out (if (number? e)
(function-numeric e (first list2))
(function-no-numeric e (first list3))))
(cons out (foo (rest list1) (rest list2) (rest list3)))]))
(foo list1 list2 list3)
It could be that you want to do something else, but the structure should be similar to the above two code. For instance, if you happen to really need an index to compute function-numeric and function-no-numeric, you would write:
;; assume function-numeric consumes (1) an element from list1 (2) the corresponding element in list2 (3) an index
;; assume function-no-numeric consumes (1) an element from list1 (2) the corresponding element in list3 (3) an index
(define (foo list1 list2 list3 i)
(cond
[(empty? list1) empty]
[else
(define e (first list1))
(define out (if (number? e)
(function-numeric e (first list2) i)
(function-no-numeric e (first list3) i)))
(cons out (foo (rest list1) (rest list2) (rest list3) (+ i 1)))]))
(foo list1 list2 list3 0)
I'm new to racket and trying to write a function that checks if a list is in strictly ascending order.
'( 1 2 3) would return true
'(1 1 2) would return false (repeats)
'(3 2 4) would return false
My code so far is:
Image of code
(define (ascending? 'list)
(if (or (empty? list) (= (length 'list) 1)) true
(if (> first (first (rest list))) false
(ascending? (rest list)))))
I'm trying to call ascending? recursively where my base case is that the list is empty or has only 1 element (then trivially ascending).
I keep getting an error message when I use check-expect that says "application: not a procedure."
I guess you want to implement a procedure from scratch, and Alexander's answer is spot-on. But in true functional programming style, you should try to reuse existing procedures to write the solution. This is what I mean:
(define (ascending? lst)
(apply < lst))
It's shorter, simpler and easier to understand. And it works as expected!
(ascending? '(1 2 3))
=> #t
(ascending? '(1 1 2))
=> #f
Some things to consider when writing functions:
Avoid using built in functions as variable names. For example, list is a built in procedure that returns a newly allocated list, so don't use it as an argument to your function, or as a variable. A common convention/alternative is to use lst as a variable name for lists, so you could have (define (ascending? lst) ...).
Don't quote your variable names. For example, you would have (define lst '(1 2 3 ...)) and not (define 'lst '(1 2 3 ...)).
If you have multiple conditions to test (ie. more than 2), it may be cleaner to use cond rather than nesting multiple if statements.
To fix your implementation of ascending? (after replacing 'list), note on line 3 where you have (> first (first (rest list))). Here you are comparing first with (first (rest list)), but what you really want is to compare (first lst) with (first (rest lst)), so it should be (>= (first lst) (first (rest lst))).
Here is a sample implementation:
(define (ascending? lst)
(cond
[(null? lst) #t]
[(null? (cdr lst)) #t]
[(>= (car lst) (cadr lst)) #f]
[else
(ascending? (cdr lst))]))
or if you want to use first/rest and true/false you can do:
(define (ascending? lst)
(cond
[(empty? lst) true]
[(empty? (rest lst)) true]
[(>= (first lst) (first (rest lst))) false]
[else
(ascending? (rest lst))]))
For example,
> (ascending? '(1 2 3))
#t
> (ascending? '(1 1 2))
#f
> (ascending? '(3 2 4))
#f
If you write down the properties of an ascending list in bullet form;
An ascending list is either
the empty list, or
a one-element list, or
a list where
the first element is smaller than the second element, and
the tail of the list is ascending
you can wind up with a pretty straight translation:
(define (ascending? ls)
(or (null? ls)
(null? (rest ls))
(and (< (first ls) (first (rest ls)))
(ascending? (rest ls)))))
This Scheme solution uses an explicitly recursive named let and memoization:
(define (ascending? xs)
(if (null? xs) #t ; Edge case: empty list
(let asc? ((x (car xs)) ; Named `let`
(xs' (cdr xs)) )
(if (null? xs') #t
(let ((x' (car xs'))) ; Memoization of `(car xs)`
(if (< x x')
(asc? x' (cdr xs')) ; Tail recursion
#f)))))) ; Short-circuit termination
(display
(ascending?
(list 1 1 2) )) ; `#f`
I have a homework problem that is asking me to tell if two sets are equal in content, regardless of order.
Ex: (set-equal? (list 1 2 3) (list 3 2 1)) is true
I have gotten this code so far,
(define (set-equal? list1 list2)
(cond
[(and (empty? list1) (empty? list2)) true]
[(and (cons? list1) (empty? list2)) false]
[(and (empty? list1) (cons? list2)) false]
[(and (cons? list1) (cons? list2))
(if (member? (first list1) list2)
(set-equal? (rest list1) list2)
(set-equal? (rest list1) list2))]))
This code obviously doesn't work because even if two lists are equal, the recursion will lead to (empty) for list 1 and list 2 will still have data, making the final output false.
I think I should approach this way:
Check the data in list1 against data in list2 and if there are equal data, remove it from both lists. Then keep checking until either both lists are empty (giving true) or one is empty and one still has data (outputting false). The problem is, I don't know how to code this.
Can anyone give me a little hint on how to fix this problem?
Recall the mathematical definition of what it means for a set A to be subset of B.
A is a subset of B
<=> for all a in A : a is a member of B
The mathematical definition can be written in Racket like this:
(define (subset? A B)
(for/and ([a A])
(member a B)))
The definition of equality between two sets A and B is:
A = B
<=> A is a subset of B and B is a subset of A
The Racket version is:
(define (set-equal? A B)
(and (subset A B)
(subset B A)))
However for finite sets we can do better (in terms of speed):
For finite sets:
A = B
<=> A is a subset of B and size(A) = size(B)
And in Racket:
(define (set-equal? A B)
(and (= (length A) (length B))
(subset? A B)))
Assumptions
The lists actually represent sets in that they have no duplicate members.
Dead Simple Solution
#lang racket
(define a '(1 2 3))
(define b '(3 2 1))
(define c '(1))
(define (set-equal? a b)
(equal? (list->set a)
(list->set b)))
Usage
eq-sets.rkt> (set-equal? a b)
#t
eq-sets.rkt> (set-equal? a c)
#f
eq-sets.rkt> (set-equal? a a)
#t
A Listy Approach
This isn't very elegant or very efficient in terms of running time, but it shows a lambda and how the function just needs to return the result of evaluating a boolean expression:
(define (set-equal2? a b)
(and (= (length a)
(length b))
(not (false?
(andmap
(lambda (e) (member e b))
a)))))
Notes
and short circuits if the lengths are unequal.
(not (false? (andmap... is used to return #t rather than a value that evaluates to #t for example (set-equal?2 a a) would return '(1 2 3) instead of #t without it because that's how andmap works. Whether it is worth going through the ceremony of (not (false? ... depends on how you feel about types.
Is there a stipulation that you have to use recursion? If not you can do the following:
If they're of unequal length, then the result is false. There's no need to proceed any further in this case. And, we know that and(expr..) will return false as soon as it finds a false expression going to left to right.
From the documentation:
(and expr ...)
If no exprs are provided, then result is #t.
If a single expr is provided, then it is in tail position, so the results of the and expression are the results of the expr.
Otherwise, the first expr is evaluated. If it produces #f, the result of the and expression is #f. Otherwise, the result is the same as an and expression with the remaining exprs in tail position with respect to the original and form.
Given that they're of equal length, sort the input lists in ascending (or descending as long as they're both sorted the same way) and check if they're equal.
(define (set-equal? list1 list2)
(and (equal? (length list1) (length list2)) (equal? (sort list1 <) (sort list2 <)))
)
(set-equal? (list 1 2 3) (list 3 2 1))
(set-equal? (list 2 1 2) (list 1 2 2))
(set-equal? (list 2 1 2) (list 7 2 2))
output:
true
true
false
Racket allows you to write procedures as if you were writing mathematical expressions. The math expression for 2 sets being equal could go as follows:
Two sets A and B are equal if for each x in A, there is x B.
Thus, first you need to write a procedure that tells you whether an item is part of a set.
;procedure in? : Tells if an element x is in set S.
;If S is empty, then x is not in it,
;if the first element of S is eq. to x then x is in it.
;otherwise, check with next element.
(define in?
(lambda (x S)
(cond ((empty? S) #f)
((equal? (car S) x) #t)
(else (in? x (cdr S)))
)))
Now we can use that procedure to tell if two lists are equal.
;procedure equal-sets? : Tells if 2 sets are equal.
;Uses andmap as a for-each loop.
(define equal-sets?
(lambda (A B)
(andmap (lambda (x) (in? x B)) A) ) )
Let us know of any doubt!
Ben Rudgers' solution with list->set is the best.
But we can fix solution from question with minimal changes:
(define (set-equal? list1 list2)
(cond
[(and (empty? list1) (empty? list2)) true]
[(and (cons? list1) (empty? list2)) false]
[(and (empty? list1) (cons? list2)) false]
[(and (cons? list1) (cons? list2))
(if (member (first list1) list2)
; compare rest of list1 with rest of list2
(set-equal? (rest list1) (remove (first list1) list2))
; if (first list1) is not a member of list2 then they are not equal
#f)]))
Now it works but we can better:
(define (set-equal? list1 list2)
(cond
[(and (empty? list1) (empty? list2)) true]
[(and (cons? list1) (empty? list2)) false]
[(and (empty? list1) (cons? list2)) false]
[else ; the last condition always true when first 3 are not
(and (member (first list1) list2)
(set-equal? (rest list1)
(remove (first list1) list2)))]))
And now we can drop some conditions and replace cond by if:
(define (set-equal? list1 list2)
(if (empty? list1)
(empty? list2)
(and (member (first list1) list2)
(set-equal? (rest list1)
(remove (first list1) list2)))))
Note: don't use this in real projects due to poor performance.
I am having a bit of problems with recursion. Just want to make sure I get better. Let's say I want to see if a n number is in a list. If it is, it returns true, otherwise, false.
(define (contains? n lst)
(cond
[(empty? lst) false]
[(cons? lst)
..... (first lst)
(contains? (rest lst)
the recursion part always tricks me. Is it necessary to call cons? here? Because if you are just looking for the first of a list, it isn.t
(define (contains? n lst)
(cond
[(empty? lst) false]
[(= n (first lst)) true]))
(check-expect (contains? 1 (list 1 2)) true)
(check-expect (contains? 1 empty) false)
No, you don't have to use cons? in the case of a list of numbers (or in general: a list of atoms): either the list is empty or is non-empty. You'd only use cons? to check if the parameter is not a list, but in general you don't have to validate this: if it isn't a list, then the function fails (as it should).
A wholly different matter happens when you have a list of lists: in that case we have to use cons? (or equvalently: pair?) to test if the first element is a list itself, and also advance the recursion over it. But for the current example, what you do have to consider, is in these three cases:
(define (contains? n lst)
(cond
[(empty? lst) false] ; the list is empty
[(= (first lst) n) true] ; current element is the one we're looking for
[else (contains? n (rest lst))])) ; current element is not the one, keep looking