Write the function (split x key) that returns a list containing two sublists based on x such that all elements in the first sublist are less than or equal to key and all elements in the second sublist are greater than key.
So, for example,
(split '(40 90 80 10 60 30 20 50 70) 40)
should return
((20 30 10 40) (70 50 60 80 90))
I know a helper function with extra list parameters can simplify the problem, but I am not sure how to do it.
You can use filter:
(define (split lst num)
(list (filter (lambda (e) (>= num e)) lst)
(filter (lambda (e) (> e num)) lst)))
(split '(40 90 80 10 60 30 20 50 70) 40)
or partition:
(require racket/list)
(define (split2 lst num)
(call-with-values
(lambda ()
(partition (lambda (e) (>= num e)) lst))
list))
(split2 '(40 90 80 10 60 30 20 50 70) 40)
It is very constricted to try performing this with roll your own recursion without having a helper. You'd get lots of duplicated bad code.
Here is how to make a helper function:
(define (add-previous lst)
(define (helper previous lst)
(if (null? lst)
'()
(cons (+ previous (car lst))
(helper (car lst) (cdr lst)))))
(helper 0 lst))
This can be written easier with a named let:
(define (add-previous lst)
(let helper ((previous 0) (lst lst))
(if (null? lst)
'()
(cons (+ previous (car lst))
(helper (car lst) (cdr lst))))))
For your problem you should add two result accumulator parameters in addition to the lst. You'll typically have 2 predicates and an alternative. One for the end of the list, where you use the 2 accumulated results, one for less or equal to key where you recurse and cons the current element to the accumulator for those and the alternative where you do the same except cons to the other result accumulator.
Related
I have 3 functions union, largest, and largest_of_two. Union takes two lists and combines them into one (this function has been tested and works). largest is supposed to return the largest element in a given list but only returns #f whether I call it via largest_of_two or on its own. Any help will be greatly appreciated.
(define (union l1 l2)
(cond (
(null? l1) l2)
((cons (car l1) (union (cdr l1) l2)))
)
)
(define (largest x a_list)
(cond
((null? a_list) x)
((< x (car a_list)) (= x (car a_list)))
(else (largest x (cdr a_list)))
)
)
(define (largest_of_two l1 l2)
(largest (car l1) (cdr (union l1 l2)))
)
(display(largest_of_two '(19 30 13 29 38) '(1 50 5 20 41)))
The fundamental problem is that (= x (car a_list)) is a comparison, but you need to make a recursive call here:
(define (largest x a_list)
(cond ((null? a_list) x)
((< x (car a_list)) ; if x is less than the first element
(largest (car a_list) (cdr a_list))) ; call with first element and cdr
(else
(largest x (cdr a_list)))))
When x is less than the first element of the list, you want to call largest again with the first element and a reduced list as arguments.
Yet, calling largest with two arguments like this seems awkward. If I want to find the largest element of the list (1 6 1 8 0 3) I have to call (largest 1 '(6 1 8 0 3)), which is not ideal. A better approach would be to discard the smaller of the first two elements on each iteration until there is only one element left:
(define (largest xs)
(cond ((null? xs) #f) ; empty input: no largest member
((null? (cdr xs)) ; only one member
(car xs))
((> (car xs) (cadr xs)) ; first member is larger than the second
(largest (cons (car xs) (cddr xs)))) ; keep the first member
(else
(largest (cdr xs))))) ; discard the first member
It doesn't make sense to return a numeric result when the input list is empty, so #fis returned in that case. If the input list contains only a single value, then that value is returned (note that this code does not verify that a list of one element contains a number, so (largest '(z)) --> z).
Otherwise the list contains at least two values. If the first is larger than the second, the first is consed onto the rest of the list with the second removed ((cddr xs)) and largest is called again on the result. Otherwise the first value is not larger than the second, so the first element is discarded ((cdr xs)) and largest is called on that result.
There is another minor issue with the posted definition of union in the conditional form:
((cons (car l1) (union (cdr l1) l2)))
There is only one test expression here. Now, this is legal Scheme because when a selected conditional clause contains only a test expression, the value of the test expression is returned. But this is not idiomatic, and it is hard to read. The posted definition for largest used else in a similar situation, and it should be used here, too. Or, just use an if form:
(define (union xs ys)
(if (null? xs)
ys
(cons (car xs) (union (cdr xs) ys))))
Be consistent; use formatting and line breaks to make code clear. And while we are talking about style, please don't scatter parentheses about haphazardly, and prefer kebab-case (aka lisp-case) to snake_case for identifiers in lisps.
With the new definition for largest, largest-of-two has a simpler definition:
(define (largest-of-two xs ys)
(largest (union xs ys)))
> (largest-of-two '(1 4 2 6 3 11 6 -2) '(3 8 -3 7 10 4))
11
Filtering is often called reduce in Scheme and functional languages. It is already explained in detail here. I quote the implementation:
(define (reduce fn list init)
(if (null? list) init
(fn (car list)
(reduce fn (cdr list) init))))
This is a very general function, which takes the operation, the list to operate on and an accumulator, which holds the value of each step.
You just need to implement your maximum function for two arguments.
(define (max a b)
(if (> a b)
a
b))
And then you can pass it to reduce. You just need to add an initial value.
(reduce max '(19 30 13 29 38) 0)
In your case it might be better to split your input list, because all elements can be negative.
(let ((lst '(19 30 13 29 38)))
(reduce max (cdr lst) (car lst)))
If you want to do anything twice or for even more arguments, just use map.
(map (lambda (lst)
(reduce max (cdr lst) (car lst)))
'((19 30 13 29 38)
(1 50 5 20 41)))
The following puts everything in one function.
(define (largest-of . lists)
(define (reduce fn list init)
(if (null? list) init
(fn (car list)
(reduce fn (cdr list) init))))
(define (max a b)
(if (> a b)
a
b))
(map (lambda (lst)
(reduce max (cdr lst) (car lst)))
lists))
(largest-of '(19 30 13 29 38) '(1 50 5 20 41)) ;; => (38 50)
This works also for more than two lists. It is just limited by the maximum number of arguments of your Scheme implementation.
And it works for just one argument.
(largest-of (largest-of '(19 30 13 29 38) '(1 50 5 20 41))) ;; => (50)
You just need to unbox the value with car.
What I need to add to count the number of zeros only in the even lists?
For example,
(count-zeroes '((1 1 1) (1 0 0) (1 1 1) (1 0 0)))
4
it is for one list.
(define count-zeroes
(lambda (list)
(cond ((null? list) 0)
((= 0 (car list)) (+ 1 (count-zeroes (cdr list))))
(else (+ 0 (count-zeroes (cdr list))))
)
)
)
(define count-zeroes
(lambda (list)
(cond ((null? list) 0) ; a
((= 0 (car list)) (+ 1 (count-zeroes (cdr list)))) ; b
(else (+ 0 (count-zeroes (cdr list))))))) ; c
If list is initially a list of lists, then (null? list) in line a can be true (when you get to the end of the list), but the condition (= 0 (car list)) in the line b will never be true, since (car list) will always be another list, and 0 isn't a list.
A better way to break this down would probably be to first extract the even positioned sublists, then flatten them into a single list, and then count the zeros in those. That's not the most efficient way to do it (you'll create some intermediate storage), but you should probably implement something like that first, and then gradually optimize it afterward.
It's also worth noting that lists are typically indexed starting with position zero, so the second, fourth, etc., elements in the list are the ones with odd positions, not even positions. Here's the kind of abstraction that might help you in getting started with this kind of approach:
(define first car)
(define rest cdr)
(define list* cons)
(define (odds list)
(if (null? list) '()
(evens (cdr list))))
(define (evens list)
(if (null? list) '()
(list* (first list)
(odds (rest list)))))
(define sample '((0 0 1) (0 1 0) (0 1 1) (1 0 0) (1 0 1) (1 1 0) (1 1 1)))
;; (display (odds sample))
;; => ((0 1 0) (1 0 0) (1 1 0))
An interesting question. If you are operating on a lists of lists you need to add car-cdr recuresion.
(define (count-zeroes lst) ;;don't override core function names with a variable
(cond ((null? lst) 0)
((pair? (car lst))
(+ (count-zeroes (car lst))
(count-zeroes (cdr lst))))
((= 0 (car lst))
(+ 1 (count-zeroes (cdr lst))))
(else (count-zeroes (cdr lst))))))
No as to only evens you are no longer counting zeros, so a new function name is in order. You could make up a higher order function like this.
(define (count-zeros-of selector lst)
(count-zeroes (selector lst)))
And make a general selector
(define (take-every-Xnth-at-y x y lst)
(cond ((null? lst) '())
((= y 0) (cons (car lst)
(take-every x (- x 1) (cdr lst))))
(else (take-every x (- y 1) (cdr lst)))))
To put it all together
(define (count-zeroes-of-even lst)
(count-zeroes-of
(lambda (lst) ;;to bad we can't do partial application
(take-every-Xnth-at-y 2 1 lst))
lst)
Note each of these parts do their one thing and do it well.
I'm working on implementing a bubble sorting algorithm in Scheme, and I must say that the functional way of programming is a strange concept and I am struggling a bit to grasp it.
I've successfully created a function that will bubble up the first largest value we come across, but that's about all it does.
(bubbleH '(5 10 9 8 7))
(5 9 8 7 10)
I am struggling with the helper function that is required to completely loop through the list until no swaps have been made.
Here's where I am at so far, obviously it is not correct but I think I am on the right track. I know that I could pass in the number of elements in the list myself, but I am looking for a solution different from that.
(define bubbaS
(lambda (lst)
(cond (( = (length lst) 1) (bubba-help lst))
(else (bubbaS (bubba-help lst))))))
Using the bubble-up and bubble-sort-aux implementations in the possible-duplicate SO question I referenced...
(define (bubble-up L)
(if (null? (cdr L))
L
(if (< (car L) (cadr L))
(cons (car L) (bubble-up (cdr L)))
(cons (cadr L) (bubble-up (cons (car L) (cddr L)))))))
(define (bubble-sort-aux N L)
(cond ((= N 1) (bubble-up L))
(else (bubble-sort-aux (- N 1) (bubble-up L)))))
..., this is simple syntactic sugar:
(define (bubbleH L)
(bubble-sort-aux (length L) L))
With the final bit of syntactic sugar added, you should get exactly what you specified in your question:
(bubbleH '(5 10 9 8 7))
=> (5 7 8 9 10)
You can tinker with everything above in a repl.it session I saved & shared.
Here's my own tail-recursive version.
The inner function will bubble up the largest number just like your bubbleH procedure. But instead of returning a complete list, it will return 2 values:
the unsorted 'rest' list
the largest value that has bubbled up
such as:
> (bsort-inner '(5 1 4 2 8))
'(5 2 4 1)
8
> (bsort-inner '(1 5 4 2 8))
'(5 2 4 1)
8
> (bsort-inner '(4 8 2 5))
'(5 2 4)
8
Now the outer loop just has to cons the second value returned, and iterate on the remaining list.
Code:
(define (bsort-inner lst)
(let loop ((lst lst) (res null))
(let ((ca1 (car lst)) (cd1 (cdr lst)))
(if (null? cd1)
(values res ca1)
(let ((ca2 (car cd1)) (cd2 (cdr cd1)))
(if (<= ca1 ca2)
(loop cd1 (cons ca1 res))
(loop (cons ca1 cd2) (cons ca2 res))))))))
(define (bsort lst)
(let loop ((lst lst) (res null))
(if (null? lst)
res
(let-values (((ls mx) (bsort-inner lst)))
(loop ls (cons mx res))))))
For a recursive version, I prefer one where the smallest value bubbles in front:
(define (bsort-inner lst)
; after one pass, smallest element is in front
(let ((ca1 (car lst)) (cd1 (cdr lst)))
(if (null? cd1)
lst ; just one element => sorted
(let ((cd (bsort-inner cd1))) ; cd = sorted tail
(let ((ca2 (car cd)) (cd2 (cdr cd)))
(if (<= ca1 ca2)
(cons ca1 cd)
(cons ca2 (cons ca1 cd2))))))))
(define (bsort lst)
(if (null? lst)
null
(let ((s (bsort-inner lst)))
(cons (car s) (bsort (cdr s))))))
Write a procedure (first-half lst) that returns a list with the first half of its elements. If the length of the given list is odd, the returned list should have (length - 1) / 2 elements.
I am given these program as a example and as I am new to Scheme I need your help in solving this problem.
(define list-head
(lambda (lst k)
(if (= k 0)
'()
(cons (car lst)(list-head (cdr lst)(- k 1)))))))
(list-head '(0 1 2 3 4) 3)
; list the first 3 element in the list (list 0 1 2)
Also the expected output for the program I want is :
(first-half '(43 23 14 5 9 57 0 125))
(43 23 14 5)
This is pretty simple to implement in terms of existing procedures, check your interpreter's documentation for the availability of the take procedure:
(define (first-half lst)
(take lst (quotient (length lst) 2)))
Apart from that, the code provided in the question is basically reinventing take, and it looks correct. The only detail left to implement would be, how to obtain the half of the lists' length? same as above, just use the quotient procedure:
(define (first-half lst)
(list-head lst (quotient (length lst) 2)))
It looks like you are learning about recursion? One recursive approach is to walk the list with a 'slow' and 'fast' pointer; when the fast pointer reaches the end you are done; use the slow pointer to grow the result. Like this:
(define (half list)
(let halving ((rslt '()) (slow list) (fast list))
(if (or (null? fast) (null? (cdr fast)))
(reverse rslt)
(halving (cons (car slow) rslt)
(cdr slow)
(cdr (cdr fast))))))
Another way to approach it is to have a function that divides the list at a specific index, and then a wrapper to calculate floor(length/2):
(define (cleave_at n a)
(cond
((null? a) '())
((zero? n) (list '() a))
(#t
((lambda (x)
(cons (cons (car a) (car x)) (cdr x)))
(cleave_at (- n 1) (cdr a))))))
(define (first-half a)
(car (cleave_at (floor (/ (length a) 2)) a)))
I have a function that takes a number such as 36, and reverses it to say '(6 3)
Is there anyway to combine that 6 3 to make it one number?
Here is the code that I have written.
(define (number->rdigits num)
(if (rdigits (/ (- num (mod num 10)) 10)))))
(define reversible?
(lambda (n)
(cond
[(null? n) #f]
[else (odd? (+ n (list (number->rdigits n))))])))
Thanks!
You can do this using an iterative function that takes each element of the list in turn, accumulating a result. For example:
(define (make-number lst)
(define (make a lst)
(if (null? lst)
a
(make (+ (* 10 a) (car lst)) (cdr lst))))
(make 0 lst))
(display (make-number '(6 3)))
The make function uses an accumulator a and the rest of the digits in lst to build up the final result one step at a time:
a = 0
a = 0*10 + 6 = 6
a = 6*10 + 3 = 63
If you had more digits in your list, this would continue:
a = 63*10 + 5 = 635
a = 635*10 + 9 = 6359
A less efficient implementation that uses a single function could be as follows:
(define (make-number lst)
(if (null? lst)
0
(+ (* (expt 10 (length (cdr lst))) (car lst)) (make-number (cdr lst)))))
This function needs to calculate the length of the remainder of the list for each iteration, as well as calling the expt function repeatedly. Also, this implementation is not properly tail recursive so it builds up multiple stack frames during execution before unwinding them all after it reaches its maximum recursion depth.