i made a function which takes a list and two elements of the list. It should return #t if the second argument appears in the list argument before the third argument:
The procedure should also return #f if either of the supposed elements doesn't appear at all.
here is what I got so far:
(define (before-in-list? lst a b )
(cond
((empty? lst ) #f)
((eq? (car lst ) a) ( map b (cdr lst)) #t)
((eq? (car lst ) b) #f)
(else (before-in-list? (cdr lst ) a b ))))
to test it, i used:
(before-in-list? '(back in the ussr) '(in) '(ussr))
(before-in-list? '(back in the ussr) '(the) '(ussr))
the problem is that it gives me f every time.
any tips on how to fix it please?
The way you're using map doesn't make sense. Also, you should use equal? for more general comparisons, and the a and b parameters should not be lists. Try this:
(define (before-in-list? lst a b)
(cond
((empty? lst ) #f)
((equal? (car lst) a)
(if (member b (cdr lst)) #t #f))
((equal? (car lst) b) #f)
(else (before-in-list? (cdr lst ) a b))))
(before-in-list? '(back in the ussr) 'in 'ussr)
=> #t
(before-in-list? '(back in the ussr) 'the 'ussr)
=> #t
Related
I'm trying to create a function called evenElememt that takes a list as a parameter and appends all the elements in even positions to a new list and displays the new list.
My attempt:
(define newList '())
(define elementHelper
(lambda lst
((cdr lst)
(cons newList (car lst))
(elementHelper(cdr lst)))
)
)
(define evenElement
(lambda (lst)
(cond
((null? lst) ())
((null? (cdr lst)) ())
(else (elementHelper lst)
(display lst))
)
)
)
Example output: if I enter (evenElement '('a 'b 'c 'f 't 'y)), the output should be (b f y).
This is essentially the same as Can I print alternate elements of a list in Racket?, except that you want to print even positions (1-indexed) instead of odd positions.
(define (even-positions lst)
(cond ((null? lst)
'())
((null? (cdr lst))
'())
(else
(cons (second lst)
(even-positions (cddr lst))))))
(even-positions '(a b c f t y)) returns '(b f y).
Then, this is the function you are looking for:
(define (display-even-positions lst)
(display (even-positions lst)))
You don't need elementHelper. Just make evenElement return the result instead of displaying it.
You also don't need the global variable newList. The function should construct the result as it goes.
(define evenElement
(lambda (lst)
(cond
((null? lst) '())
((null? (cdr lst)) '())
(else (cons (car (cdr lst))
(evenElement (cdr (cdr lst)))))
)
)
)
(display (evenElement '(a b c f t y)))
This is what I have to sort strings:
;create a function that checks if a list of strings is sorted
(define (stringCmpr l)
(if (<= (length l) 1)
true
(and (string<=? (car l) (cadr l))(stringCmpr (cdr l))
)
)
)
;Create a funciton that checks if a list of numbers is sorted
(define (numCmpr l)
(if (<= (length l) 1)
true
(and (<= (car l) (cadr l)) (numCmpr (cdr l))
)
)
)
;create function that checks whether a list containes numbers of
strings checks if the list is sorted
(define (is-sorted? l)
(if (number? (car l))
(numCmpr l)
(stringCmpr l)
)
)
(define (bubble-pass lst)
(cond
((empty? lst) lst)
((= (length lst) 1) lst)
((and (= (length lst) 2) (string>? (first lst) (second lst)))
(list
(second lst) (first lst)))
((and (= (length lst) 2) (string<? (first lst) (second lst)))
lst)
((string>? (first lst) (second lst))
(append
(list (second lst))
(bubble-pass (append (list (first lst)) (rest (rest lst))))
)
)
(else
(append (list (first lst) (second lst)) (bubble-pass (rest
(rest lst))))
)
)
)
(define (string-bubble-sort lst)
(if (is-sorted? lst)
lst
(string-bubble-sort (bubble-pass last))
)
)
This works for sorting strings in order from A-Z
This is what I have so far for the general sort (func represents the comparer: <, > =, string<?, etc):
;create a function that checks if a list of strings is sorted
(define (gen-stringCmpr l func)
(if (<= (length l) 1)
true
(and (func (car l) (cadr l))(gen-stringCmpr (cdr l) func)
)
)
)
;Create a funciton that checks if a list of numbers is sorted
(define (gen-numCmpr l func)
(if (<= (length l) 1)
true
(and (func (car l) (cadr l)) (gen-numCmpr (cdr l) func)
)
)
)
;create funciton that checks whether a list contains numbers or
strings checks if the list is sorted
(define (general-sorted? l func)
(if (number? (car l))
(gen-numCmpr l func)
(gen-stringCmpr l func)
)
)
; Purpose: Create a function that bubble sorts a list given a
; comparison function
;Signature:
; list function-> list
;Examples:
(check-expect (general-bubble-sort (list "B" "A" "C") string<?) (list
"A" "B" "C"))
(check-expect (general-bubble-sort (list "B" "A" "C") string>?) (list
"C" "B" "A"))
(check-expect (general-bubble-sort (list 6 4 5) <) (list 4 5 6))
(check-expect (general-bubble-sort (list 2 3 1) >) (list 3 2 1))
Stub:
(define (general-bubble-sort lst func) '( "spinach")
Template:
Code:
(define (general-bubble-pass lst func)
(cond
((empty? lst) last)
((= (length lst) 1) last)
((and (= (length lst) 2) (equal? (func (first lst) (second lst))
false)) (list (second lst) (first lst)))
((and (= (length lst) 2) (func (first lst) (second lst))) last)
((equal? (func (first lst) (second lst)) false)
(append
(list (second last))
(general-bubble-pass (append (list (first lst)) (rest (rest
lst))) func)
)
)
(else
(append (list (first lst) (second lst)) (general-bubble-pass
(rest (rest lst)) func))
)
)
)
(define (general-bubble-sort lst func)
(if (general-sorted? lst func)
lst
(general-bubble-sort (general-bubble-pass lst func) func)
)
)
You aren't properly using your abstractions here because of overly permissive signatures. Technically you want your final bubble sort to work like this:
; general-bubble-sort: (X) [List-of X] [X X -> Boolean] -> [List-of X]
By constraining the types of what we take in and telling users how they should use it, we eliminate the checking we need to do in general-sorted?. We just know that we have to pass the correct function to it, otherwise it is the users fault for not passing the correct function. You can also abstract more of your code between your two functions. Like this:
(define (general-sorted? l func)
(or (<= (length l) 1) (and (func (car l) (cadr l)) (general-sorted? (cdr l)))))
Your second function has a lot going on in it, lets combine some of the cases and also not use (equal? x boolean). That is bad practice. Instead we should use a boolean expression to get us true when appropriate. We should also make use of accumulators here as it clearly says what piece of data we are keeping track of as we are recurring down:
(define (general-bubble-pass lst func)
(local [(define (general-bubble-pass-acc lst bubble)
(cond
[(empty? lst) (list bubble)]
[(not (func (first lst) bubble)) (cons bubble (general-bubble-pass-acc (rest lst) (first lst)))]
[else (cons (first lst) (general-bubble-pass-acc (rest lst) bubble))]))]
(if (<= (length lst) 1) lst (general-bubble-pass-acc (rest lst) (first lst)))))
Your final bubble sort function doesn't change.
My else statement line is giving me an error. Is any of my other line of codes affecting the else expression?
(define (sumAdd list)
(cond
((null? list) '())
((null? (cdr list)) list)
((symbol? list) sumAdd(cdr list))
(else (+ (car list)(sumAdd (cdr list))))
)
)
If I understand correctly, you want to sum all the numbers in a list with mixed element types. If that's the case, there are several errors in your code:
(define (sumAdd list) ; `list` clashes with built-in procedure
(cond
((null? list) '()) ; base case must be zero for addition
((null? (cdr list)) list) ; why discard the last element?
((symbol? list) sumAdd(cdr list)) ; that's not how procedures are called
(else (+ (car list) (sumAdd (cdr list)))))) ; this line is fine :)
This is the correct way to implement the procedure:
(define (sumAdd lst)
(cond
((null? lst) 0) ; base case is zero
((symbol? (car lst)) (sumAdd (cdr lst))) ; skip current element
(else (+ (car lst) (sumAdd (cdr lst)))))) ; add current element
It works as expected:
(sumAdd '(1 a 2 b 3 c))
=> 6
I've been self-teaching myself Scheme R5RS for the past few months and have just started learning about mutable functions. I've did a couple of functions like this, but seem to find my mistake for this one.
(define (lst-functions)
(let ((lst '()))
(define (sum lst)
(cond ((null? lst) 0)
(else
(+ (car lst) (sum (cdr lst))))))
(define (length? lst)
(cond ((null? lst) 0)
(else
(+ 1 (length? (cdr lst))))))
(define (average)
(/ (sum lst) (length? lst)))
(define (insert x)
(set! lst (cons x lst)))
(lambda (function)
(cond ((eq? function 'sum) sum)
((eq? function 'length) length?)
((eq? function 'average) average)
((eq? function 'insert) insert)
(else
'undefined)))))
(define func (lst-functions))
((func 'insert) 2)
((func 'average))
You're not declaring the lst parameter in the procedures that use it, but you're passing it when invoking them. I marked the lines that were modified, try this:
(define (lst-functions)
(let ((lst '()))
(define (sum lst) ; modified
(cond ((null? lst) 0)
(else
(+ (car lst) (sum (cdr lst))))))
(define (length? lst) ; modified
(cond ((null? lst) 0)
(else
(+ 1 (length? (cdr lst))))))
(define (average)
(/ (sum lst) (length? lst)))
(define (insert x)
(set! lst (cons x lst)))
(lambda (function)
(cond ((eq? function 'sum) (lambda () (sum lst))) ; modified
((eq? function 'length) (lambda () (length? lst))) ; modified
((eq? function 'average) average)
((eq? function 'insert) insert)
(else
'undefined)))))
Now it works as expected:
(define func (lst-functions))
((func 'insert) 2)
((func 'average))
=> 2
((func 'sum))
=> 2
((func 'length))
=> 1
Some of your functions are recursive but defined without argument. Thus (sum (cdr lst)) shouldn't work since sum uses lst. You could do it by defining a helper:
(define (sum-rec lst)
(if (null? lst)
0
(+ (car lst) (sum-rec (cdr lst)))))
Or perhaps with an accumulator:
(define (sum-iter lst acc)
(if (null? lst)
acc
(sum-iter (cdr lst) (+ (car lst) acc)))
Your sum would of course use it passing the lst:
(define (sum)
(sum-iter lst 0))
Or you can just have the driver partial apply them like this:
(lambda (function)
(cond ((eq? function 'sum) (lambda () (sum-iter lst))
...))
A side note. length? is a strangely named function. A question mark in the end of a name is usually reserved for functions that return a true or a false value and this clearly returns a number.
I'm having trouble using my member? function. I need to recurse on my set? function until the last element in my list 'lst' is reached. I believe I have the navigation down correctly, but maybe my inputs syntax is wrong. I know there are three cases:
1) What happens if the list is empty? that means that there aren't any duplicates in it
2) What happens if the current element of the list exists somewhere in the rest of the list? then it means that there's a duplicate in the list (hint: the member procedure might be useful)
3) If none of the above are true, continue with the next element.
Here is my code.
(define (member? e lst)
(if (null? lst) #f
(if (equal? e (car lst)) #t
(member? e (cdr lst)))))
(define (set? lst)
(if (null? lst) #t ;Case1
(if (member? (car lst) lst) #f ;Case2
(set? (cdr lst))))) ;Case3
;Example tests for the set? function
(set? '(x y z))
(set? '(a 1 b 2 c 3))
(set? '())
(set? '(6 2 2))
(set? '(x y z x))
There's a small mistake with your code, look how it gets fixed:
(define (set? lst)
(if (null? lst)
#t
(if (member? (car lst) (cdr lst)) ; in here
#f
(set? (cdr lst)))))
In particular, notice what this line is doing:
(member? (car lst) lst)
That won't work: the test is checking whether the first element in lst is a member of lst - and that'll always be true. The solution is simple, just check to see if the current element is in the rest of the list, if it's there, then we know that we've found a duplicate:
(member? (car lst) (cdr lst))
And by the way, the above code would look much nicer using cond, which is great when you have nested ifs:
(define (set? lst)
(cond ((null? lst) #t)
((member? (car lst) (cdr lst)) #f)
(else (set? (cdr lst)))))