The argument is a list and I am trying to extract the largest missing number from the list.
I have sorted the list in the function select, but I am having a hard time getting the function select to return the sorted list. When the list returns from sorting it, I am subtracting the highest and second highest to determine the difference and checking to see if the difference is greater than 1.
Could someone let me know how to return the sorted list from Selected to LargestGap?
(define (LargestGap L)
(cond ( (null? L) '() )
; ( car (select L))
( (> (- (car(cdr(select L))) (car(select L))) 0) (LargestGap (cdr(select L))))
(- (car(select L)) 1)))
(define (select L)
(cond ( (null? L) '() )
( else
(cons (Largest L (car L))
(select (delete L (Largest L (car L))))))))
(define (delete L A)
(cond ( (null? L) '() )
( (= (car L) A) (cdr L))
(else (cons (car L)(delete (cdr L) A)))))
(define (Largest L A)
(cond ( (null? L) A)
( (> (car L) A) (Largest (cdr L)(car L)))
(else (Largest (cdr L) A ))))
I am not sure if I got your question correctly. I guess you want to avoid calling select function many times in LargestGap function. If this is what your question is then:
Make another function:
(define (get-largest-gap L)
(LargestGap (select L)))
Make function LargestGap such that is accepts sorted list:
(define (LargestGap L)
(cond ( (null? L) '() )
( (> (- (cadr L) (car L)) 0) (LargestGap (cdr L)))
(- (car L) 1)))
Related
I am trying to find a way to split a list up into three parts. I have used a helper function and the parameters should be as follows: It evaluates to a list of three lists, containing 1) the items in the list less than pivot, 2) the items in the list equal to pivot, and 3) the items in the list greater than pivot.
(define (partition lst item)
(define (partition-iter lst less same greater)
(cond ((null? lst)(list less same greater ))
((< (car lst) item)(partition-iter (cdr lst)
(cons (car lst) less)
same
greater ))
((= (car lst) item)
less
(cons (car lst) same)
(else
(partition-iter (cdr lst) (cons (car lst) greater))))))
(partition-iter lst '() '() '()))
everything up to the else clause should work but after that i'm stuck. Any help is appreciated
The current helper function, partition-iter, will not work due to some severe mistakes in its design. But first, let me provide two versions which work:
The first (simple) version,
#lang racket
; LoN = List-of-Numbers
; partition :: LoN Number -> List-of-LoN
(define (partition1 lst pivot)
(local([; auxiliary function
; part :: LoN LoN LoN LoN -> List-of-LoN
define (part xs LT EQ GT)
; if empty list
(if (null? xs) (list LT EQ GT)
;else
(let* ([head (first xs)]
[tail (rest xs)]
[prtd (part tail LT EQ GT)]
[LT* (first prtd)]
[EQ* (second prtd)]
[GT* (third prtd)])
;--in--
(cond
; if x < pivot, add the element to LT
[(< head pivot) (list {cons head LT*} EQ* GT*)]
; if x = pivot, add the element to EQ
[(= head pivot) (list LT* {cons head EQ*} GT*)]
; if x > pivot, add the element to GT
[else (list LT* EQ* {cons head GT*})]
)
) ) ]
)
;--in--
(part lst null null null)
)
)
The second version, which is closer to your implementation, but uses fold:
#lang racket
; partition :: LoN Number -> List-of-LoN
(define (partition2 lst pivot)
(local([; auxiliary function
; part :: LoN LoN LoN LoN -> List-of-LoN
define (part x LT-EQ-GT)
(local ([define-values (LT* EQ* GT*) (apply values LT-EQ-GT)])
;--in--
(cond
; if x < pivot, add the element to LT
[(< x pivot) (list {cons x LT*} EQ* GT*)]
; if x = pivot, add the element to EQ
[(= x pivot) (list LT* {cons x EQ*} GT*)]
; if x > pivot, add the element to GT
[else (list LT* EQ* {cons x GT*})]
)
) ]
)
;--in--
(foldr part '(() () ()) lst)
)
)
Try eg.,
(partition2 '(1 2 3 4 4 3 4 5 6) 4) ;; yields '((1 2 3 3) (4 4 4) (5 6)).
Notice that the second (fold-) version is faster (and better imo).
Finally, your implementation has mistakes in the following lines (line-numbering begins at 1):
-- lines 4-7 should be:
(partition-iter (cdr lst) (cons (car lst) less) same greater)
-- lines 9-10 should be:
(partition-iter (cdr lst) less (cons (car lst) same) greater)
-- line 12 should be:
(partition-iter (cdr lst) less same (cons (car lst) greater))
Finally, with your current implementation, you should use foldl or foldr (or something like that) in your last line.
Here's you code, indented so that the corresponding items are visually aligned:
(define (partition lst item)
(define (partition-iter lst less same greater)
(cond
((null? lst)
(list less same greater ))
((< (car lst) item)
(partition-iter (cdr lst)
(cons (car lst) less)
same
greater))
((= (car lst) item)
less
(cons (car lst) same)
(else
(partition-iter (cdr lst)
(cons (car lst) greater))))))
(partition-iter lst '() '() '()))
I think you can see there's something wrong with it right away, now. It's asymmetrical, all out of wack, even if the parens are balanced. An else clause inside another cond clause? What is that??
The moral is, don't be afraid to use white space to see better. Lots and lots of white space.
Without it, Scheme tends to look like an impenetrable wall of words, parens or no parens. And the recommended indentation style. Does. Not. Help.
The fix is obvious, minimal, and simple: just complete the code in the same style you (??) started writing it. Handle the other two cases, building the three interim lists while iterating along the input list by taking repeated cdrs in each of the three cases:
(define (partition lst item)
(define (partition-iter lst less same greater)
(cond
((null? lst)
(list less same greater ))
((< (car lst) item)
(partition-iter (cdr lst)
(cons (car lst) less)
same
greater ))
((= (car lst) item)
(partition-iter (cdr lst)
less
(cons (car lst) same)
greater ))
(else ; (> (car lst) item) ; keep it here for documentation!
(partition-iter (cdr lst)
less
same
(cons (car lst) greater) )) ))
(partition-iter lst '() '() '()))
I don't even have to load it into DrRacket now to see that it's alright.
Symmetry is beautiful. Symmetry is right.
BTW, in a pattern-matching pseudocode with guards, it could be written as
partition lst item = partition-iter lst [] [] []
where
partition-iter [] less same greater = [less, same, greater]
partition-iter [a, ...lst] less same greater
| a < item = partition-iter lst [a, ...less] same greater
| a == item = partition-iter lst less [a, ...same] greater
| else = partition-iter lst less same [a, ...greater]
which I think is much more visually apparent. Going back and forth between it and the proper Scheme is a matter of purely syntactical transformations.
I want to write a simple function (highest L k), which take a list and interger K>0, return a new list with k highest numbers.
(highest '(6 7 8 5 3 2) 3) give (6 7 8)
(define (highest L k)
(if (= k 0)
'()
(cons (highesthelper (car L) L)
((highest (remove (highesthelper (car L) L) L) (- k 1))))))
(define (remove E L)
(cond
((null? L)'())
((= E (car L)) (cdr L))
(else (cons (car L) (remove E (cdr L))))))
(define (highesthelper Hi L)
(cond
((null? L) Hi)
((> Hi (car L)) highesthelper Hi (cdr L))
(else (highesthelper (car L) (cdr L)))))
(highest '(1 7 4 5 3) 2)
I can run the helper and remove function without problem, but the highest function give me bugs, can someone help me?
Thanks
I fixed a few simple mistakes. Note in particular the (> Hi (car L)) case of highesthelper.
(define (highest L k)
(if (= k 0)
'()
(cons (highesthelper (car L) L)
(highest (remove (highesthelper (car L) L) L) (- k 1)))))
(define (remove E L)
(cond
((null? L) '())
((= E (car L)) (cdr L))
(else (cons (car L) (remove E (cdr L))))))
(define (highesthelper Hi L)
(cond
((null? L) Hi)
((> Hi (car L)) (highesthelper Hi (cdr L)))
(else (highesthelper (car L) (cdr L)))))
(highest '(1 7 4 5 3) 2)
I am currently confused with the idea behind functional programming in general. I currently have a working solution to my problem (That is, finding the min and max of a list, and returning these in a new list) but to do that, my solution essentially requires 3 functions, and this bothers me, because I am sure there is a way to do it with just 1 function in scheme.
So.. my question is, how do I combine the outputs of 2 functions into 1 concise function? (The driver function)
Here is what I have...
(define (findMax lst) ; Find and return maximum number in a list
(cond [(null? lst) '()]
[(= (length lst) 1) (list-ref lst 0)]
[(> (list-ref lst 0) (list-ref lst (- (length lst) 1))) (findMax (drop-right lst 1))]
[(< (list-ref lst 0) (list-ref lst (- (length lst) 1))) (findMax (cdr lst))]
(else
(findMax (cdr lst))
)
)
)
(define (findMin lst) ; Find and return smallest number in a list
(cond [(null? lst) '()]
[(= (length lst) 1) (list-ref lst 0)]
[(> (list-ref lst 0) (list-ref lst (- (length lst) 1))) (findMin (cdr lst))]
[(< (list-ref lst 0) (list-ref lst (- (length lst) 1))) (findMin (drop-right lst 1))]
(else
(findMin (cdr lst))
)
)
)
I use a driver function to take both of these functions, and make a new list shown here:
(define (findEnds lst)
(list (findMin lst) (findMax lst))
)
So essentially, if given a list:
(6 7 8 4 9 2)
the output would be:
(2 9)
I know there is some way to use lambda possibly to do all of this in 1 function, but I need to be pointed in the right direction. Thanks!
Here's my version (note that I've changed it to return the result as a single dotted pair, rather than a list with two elements†):
(define (min/max lst)
(if (empty? lst)
#f
(let ((next (min/max (cdr lst))))
(define cur (car lst))
(if (not next)
(cons cur cur)
(cons (min (car next) cur) (max (cdr next) cur))))))
Example:
> (min/max '(3 1 4 1 5 9))
(1 . 9)
†If you really want to use a list of two elements, change all the cons to list, and change the (cdr next) to (cadr next).
This is actually a really good challenge that might help with learning some Scheme concepts. I've implemented min/max using fold-left. It might also be fun using a named-let
(define (min/max lst)
(fold-left
(lambda (acc num)
(cons (min num (car acc)) (max num (cdr acc))))
(cons +inf.0 -inf.0)
lst))
This program takes a list where elements are repeated, e.g L = (a a a b b b c c c d), and output a list of items and number of repetition e.g ((a 3)(b 3)(c 3) d)
(define counter 0)
(define (compress liste)
(if (or (null? liste) (null? (cdr liste)))
liste
(let ((compressed-cdr (compress (cdr liste))))
(if (equal? (car liste) (car compressed-cdr))
((+ counter 1) compressed-cdr)
((cons (car liste) counter) (= counter 0) (compressed-cdr))))
))
However, I get this error:
Error: application: not a procedure; expected a procedure that can be applied to arguments
given: 1 arguments ...
The error is at the true predicate of the second if condition.
Building the result list in a top-down manner, with the "head-sentinel trick", for simplicity:
(define (rle lst)
(if (null? lst)
'()
(let ((res (list 1))) ; head sentinel
(let loop ((p res) ; result's last cons cell
(elt (car lst))
(cnt 1)
(lst (cdr lst)))
(if (and (not (null? lst))
(equal? elt (car lst)))
(loop p elt (+ cnt 1) (cdr lst))
(begin
(set-cdr! p (list (if (= 1 cnt) elt (list elt cnt))))
(if (null? lst)
(cdr res) ; skip the head in result, on return
(loop (cdr p) (car lst) 1 (cdr lst)))))))))
As #uselpa explained, this is called run-length encoding; for the uniformity of the result I'd suggest using (x 1) representation for non-repeating elements.
And the error "Error: application: not a procedure; expected a procedure", as others have said, means that the system expected to find a procedure but found something else, so can't apply it. Scheme expects to find a procedure as the first form in a list: (proc args ...), and tries to apply it to the arguments. But in your code it is not a procedure, but some other type of data.
If your Scheme has left fold, or reduce, you can run through it twice - first collecting the uniform results, and then applying your special format while reversing (left fold's results are usually built in reversed order):
(define (fold f init lst) ; if fold is not defined,
(reduce f init (cons init lst))) ; define it in terms of reduce
(define (rle lst)
(fold (lambda (x acc) ; NB! MIT-Scheme: (acc x)
(if (= 1 (cadr x)) (cons (car x) acc) (cons x acc)))
'()
(fold (lambda (x acc) ; NB! MIT-Scheme: (acc x)
(if (or (null? acc) (not (equal? (caar acc) x)))
(cons (list x 1) acc)
(cons (list x (+ (cadar acc) 1)) (cdr acc))))
'()
lst)))
As the error message says, the problem is located "at the true predicate of the second if condition":
((+ counter 1) compressed-cdr)
In this case, (+ counter 1) should evaluate to a procedure but it evaluates to a number. I think the problem is that you don't know how to increment the counter.
Your false predicate has the same problem:
((cons (car liste) counter) (= counter 0) (compressed-cdr))))))
where (cons (car liste) counter) yields a list and not a procedure.
I don't think we could really work with this code. I suggest looking at R Sahu's answer, which is close. Alternatively, I can show you a tail-recursive version which you could also have a look at. BTW, this is called run-length encoding, hence I've called my procedure rle:
(define (rle lst)
(define (newres prv cnt res)
(case cnt
((0) res)
((1) (cons prv res))
(else (cons (list prv cnt) res))))
(let loop ((lst lst) (prv null) (cnt 0) (res null))
(if (null? lst)
(if (zero? cnt)
(reverse res)
(loop null null 0 (newres prv cnt res)))
(let ((c (car lst)))
(if (eq? c prv)
(loop (cdr lst) prv (add1 cnt) res)
(loop (cdr lst) c 1 (newres prv cnt res)))))))
It was hard for me to figure out where the problem is in your code. I tried the following that seems to work.
(define (compress liste)
(define (helper in prev out)
(if (null? in)
(list (list (car out) (length out)))
(if (equal? prev (car in))
(helper (cdr in) prev (append out (list (car in))))
(cons (list (car out) (length out)) (compress in)))))
(if (null? liste)
'()
(helper (cdr liste) (car liste) (list (car liste))))
)
It uses helper to gather the output for matching items. When it finds a mismatch, it calls the main function to process the rest of the list. helper simply prepends its results to the results obtained from the main function.
A slightly improved version:
(define (compress liste)
(define (helper in prev out)
(if (null? in)
(list (list prev out))
(if (equal? prev (car in))
(helper (cdr in) prev (+ 1 out))
(cons (list prev out) (compress in)))))
(if (null? liste)
'()
(helper (cdr liste) (car liste) 1))
)
Here's tail-recursive version:
(define (compress liste)
(define (helper-1 in out)
(if (null? in)
'()
(helper-2 (cdr in) (car in) 1 out)))
(define (helper-2 in prev count out)
(if (null? in)
(append out (list (list prev count)))
(if (equal? prev (car in))
(helper-2 (cdr in) prev (+ 1 count) out)
(helper-1 in (append out (list (list prev count)))))))
(helper-1 liste '()))
This is my first experience with Scheme. I have a list with integers and I wanna get the sum of all even number in list.
; sum_even
(define (sum_even l)
(if (null? l) l
(cond ((even? (car l)) 0)
((not(even? (car l))) (car l)))
(+ (sum_even (car l) (sum_even(cdr l))))))
(sum_even '(2 3 4))
(define (sum_even l)
(cond ((null? l) 0)
((even? (car l)) (+ (car l) (sum_even (cdr l))))
(else (sum_even (cdr l)))))
Not tested
You're not exactly asking a question. Are you checking if your solution is correct or looking for an alternate solution?
You can also implement it as follows via
(apply + (filter even? lst))
edit: If, as you mentioned, you can't use filter, this solution will work and is tail-recursive:
(define (sum-even lst)
(let loop ((only-evens lst) (sum 0))
(cond
((null? only-evens) sum)
((even? (car only-evens))
(loop (cdr only-evens) (+ (car only-evens) sum)))
(else (loop (cdr only-evens) sum)))))
(define (sum-even xs)
(foldl (lambda (e acc)
(if (even? e)
(+ e acc)
acc))
0
xs))
Example:
> (sum-even (list 1 2 3 4 5 6 6))
18
Here is another one with higher order functions and no explicit recursion:
(use srfi-1)
(define (sum-even ls) (fold + 0 (filter even? ls)))
Consider using the built-in filter function. For example:
(filter even? l)
will return a list of even numbers in the list l. There are lots of ways to sum numbers in a list (example taken from http://groups.engin.umd.umich.edu/CIS/course.des/cis400/scheme/listsum.htm):
;
; List Sum
; By Jerry Smith
;
(define (list-sum lst)
(cond
((null? lst)
0)
((pair? (car lst))
(+(list-sum (car lst)) (list-sum (cdr lst))))
(else
(+ (car lst) (list-sum (cdr lst))))))