QuickSort Scheme - sorting

I need to implement the following quicksort:
(quick-sort pred lst)
lst is the list of numbers to be sorted
pred is the predicate by which the list is ordered, the signature of this predicate is:
(lambda (x y) …)
the code here is working but the problem here that when i get in lst the same number more then once im entering to infinite loop, after hours of debugging i cant find the problem or how to solve it.
(define (quick-sort pred lst)
;Pivot is 1st element of the list
(define (pivot lst)
(if (or (null? lst) (= 1 (length lst)))
'done
(car lst)))
partition get the pivot the list and the predicate and splitting it to two lists
(define (partition piv lst pred)
;predPos is the pred it slef and predNeg is the negative of the pred
(let* ((predPos (lambda (x) (pred x piv) ))
(predNeg (lambda (x) (if (pred x piv) #f #t)))
;Filtering the big list in to two lists
(p1 (filter predPos lst))
(p2 (filter predNeg lst)))
;Recursivly doing the qucicksort on each list. and joining them together.
(cond ((and (null? p1) (null? p2)) (cons piv ()))
((null? p1) (quick-sort pred p2))
((null? p2) (quick-sort pred p1))
(else (joiner (quick-sort pred p1) (quick-sort pred p2))))))
;Joining 2 lists together
(define (joiner p1 p2)
(cond ((null? p1) p2)
((null? p2) p1)
(else (cons (car p1) (joiner (cdr p1) p2)))))
;The main quicksort method () and list size one are sorted!
(let ((piv (pivot lst)))
(if (or (null? lst) (= 1 (length lst)))
lst
(partition piv lst pred))))

If you remove the pivot before partitioning, you are guaranteed to make progress at each recursive step. Without this measure the pivot will stick at the front of its partition and you won't get anywhere.

Related

Scheme - How to find the median using user defined sort and average functions?

I'm new to Scheme, and I've hit a wall. I have my sort and average functions, and I'm trying to change a median function I found on this site. However, no matter what I try, I keep getting errors where I have more than one expression in the median function, or when I try to use sort in the median function it's "undefined".
(define (sort1 L)
(if (or (null? L) (<= (length L) 1)) L
(let loop ((l null) (r null)
(pivot (car L)) (rest (cdr L)))
(if (null? rest)
(append (append (sort1 l) (list pivot)) (sort1 r))
(if (<= (car rest) pivot)
(loop (append l (list (car rest))) r pivot (cdr rest))
(loop l (append r (list (car rest))) pivot (cdr rest)))))))
(define (avg lst)
(let loop ((count 0) (sum 0) (args lst))
(if (not (null? args))
(loop (add1 count) (+ sum (car args)) (cdr args))
(/ sum count))))
(define (median L)
(if (null? L) (error "The list is empty")
(let loop ((L1 L) (L2 L))
(cond ((null? (cdr L2)) (car L1))
((null? (cddr L2)) (list (car L1) (cadr L1)))
(else (loop (cdr L1) (cddr L2)))))))
I'm trying to edit the median function to first sort the list, and if there are an even number of elements, I need to take the average of the list, and use the element closest to the average.
Any help would be appreciated, thank you in advance.
Like I said in a comment, what you want isn't a let, it's function composition.
Your current median function is this:
(define (median L)
(if (null? L)
(error "The list is empty")
(let loop ((L1 L) (L2 L))
(cond ((null? (cdr L2)) (car L1))
((null? (cddr L2)) (list (car L1) (cadr L1)))
(else (loop (cdr L1) (cddr L2)))))))
But as Oscar Lopez pointed out, this doesn't properly compute the median. However, it does some of the work, so keep it. Rename it to median-helper or something.
(define (median-helper L)
(if (null? L)
(error "The list is empty")
(let loop ((L1 L) (L2 L))
(cond ((null? (cdr L2)) (car L1))
((null? (cddr L2)) (list (car L1) (cadr L1)))
(else (loop (cdr L1) (cddr L2)))))))
Then you can use function composition to define the "real" median function:
(define (median lst)
(median-helper (sort1 lst)))
This returns the middle element for odd-length lists, and the middle-two elements for even length lists. If this is want you wanted, great. If not, then you can fix median-helper by returning the average in the second case of the cond. So instead of (list (car L1) (cadr L1)) there, you would have (avg (list (car L1) (cadr L1))).
;; median-helper : (Listof Number) -> Number
(define (median-helper L)
(if (null? L)
(error "The list is empty")
(let loop ((L1 L) (L2 L))
(cond ((null? (cdr L2)) (car L1))
((null? (cddr L2)) (avg (list (car L1) (cadr L1))))
(else (loop (cdr L1) (cddr L2)))))))
;; median : (Listof Number) -> Number
(define (median lst)
(median-helper (sort1 lst)))
I think you're misunderstanding the definition of a median. A very simple (if not particularly efficient) implementation follows:
(define (my-sort L)
(sort L <))
(define (average x y)
(exact->inexact (/ (+ x y) 2)))
(define (median L)
(if (null? L)
(error "The list is empty")
(let* ((n (length L))
(sorted (my-sort L))
(half (quotient n 2)))
(if (odd? n)
(list-ref sorted half)
(average (list-ref sorted half)
(list-ref sorted (sub1 half)))))))
It works as defined:
(median '())
=> The list is empty
(median '(3 2 1 5 4))
=> 3
(median '(6 4 3 1 2 5))
=> 3.5

How do I write a function in DrRacket ISL/Lambda that moves occurrences of certain items to the end of the list?

I'm trying to learn how to do this, and I know it involves stacks, but I can't wrap my head around it unless I see a function in action. We've been given this example of a function to create and I need some help. Here it is:
;leafpile takes a list and returns the result of pushing all
;occurrences of the symbol 'leaf to the end of the list
> (leafpile '(rock grass leaf leaf acorn leaf))
(list 'rock 'grass 'acorn 'leaf 'leaf 'leaf)
We can use a helper function but the function needs to be written in a way to minimize recursive passes
update (heres what I got so far)
(define (leafpile/help ls pile)
(local
[
(define (helper 2ls leafpile)
(cond
[(empty? 2ls) (filter ls 'leaf)]
[(equal? (first 2ls) 'leaf)
(cons (first 2ls) (helper (rest 2ls) leafpile))]
[else (helper (rest 2ls) leafpile)]))]
(helper ls pile)))
OK snow I have this:
(define (helper lsh)
(cond
[(empty? lsh) '()]
[(not(equal? (first lsh) 'leaf))
(cons (first lsh) (helper (rest lsh)))]
[else (helper (rest lsh))]))
(define (count-leaf ls)
(cond
[(empty? ls) 0]
[(not (equal? 'leaf (first ls))) (count-leaf (rest ls))]
[else (add1 (count-leaf (rest ls)))]))
(define (leafpile ls)
(append (helper ls) (make-list (count-leaf ls) 'leaf)))
but I need it in one simple function with the least recursive passes possible.
Here is the solution I came up with:
(define (leafpile lst)
(for/fold ([pile (filter (lambda (leaf?) (not (equal? leaf? 'leaf))) lst)])
([i (build-list (for/fold ([leaves 0])
([leaf? lst])
(if (equal? leaf? 'leaf)
(add1 leaves)
leaves)) values)])
(append pile '(leaf))))
How it works:
The main for/fold loop iterates over a list with a length of the number of leaves there are, and the 'collection value' is a list of all the elements in lst that aren't the symbol 'leaf (achieved by filter).
Sample input/output:
> (leaf-pile '(rock grass leaf leaf acorn leaf))
'(rock grass acorn leaf leaf leaf)
Really simple way to do this:
(define (leaf? v)
(eq? v 'leaf))
(define (leafpile lst)
(append (filter (compose not leaf?) lst)
(filter leaf? lst)))
It really doesn't need to be more to it unless you experience performance issues and I usually don't for small lists. I tend to think of lists with fewer than a million elements as small. The obvious recursive one that might not be faster:
(define (leafpile lst)
(local [(define (leafpile lst n) ; screaming for a named let here!
(cond
((null? lst) (make-list n 'leaf))
((leaf? (car lst)) (leafpile (cdr lst) (add1 n)))
(else (cons (car lst) (leafpile (cdr lst) n)))))]
(leafpile lst 0)))
A tail recursive one that accumulates non leaf values, counts leaf values and uses srfi/1 append-reverse! to produce the end result:
(require srfi/1)
(define (leafpile lst)
(local [(define (leafpile lst acc n) ; I'm still screaming
(cond
((null? lst) (append-reverse! acc (make-list n 'leaf)))
((leaf? (car lst)) (leafpile (cdr lst) acc (add1 n)))
(else (leafpile (cdr lst) (cons (car lst) acc) n))))]
(leafpile lst '() 0)))

Scheme quick-sort with filter

I need to write the function (quick-sort pred lst)
lst is the list of numbers to be sorted
pred is the predicate by which the list is ordered, the signature of this predicate is: (lambda (x y) …)
- (quick-sort < lst) will sort ascending (small to large)
- (quick-sort > lst) will sort descending (large to small)
- (quick-sort (lambda (x y) (< (car x) (car y))) lst) will sort a list
with inner lists according to the first element of the inner list, ascending.
I started with regular quick-sort:
(define (quick-sort lst)
(cond
((null? lst) '())
((= (length lst) 1) lst)
(else (append (quick-sort (filter (lambda (n) (< n (car lst))) lst))
(list (car lst))
(quick-sort (filter (lambda (n) (> n (car lst))) lst))))))
And now I'm trying to do this with pred:
(define (quick-sort pred lst)
(define (quick-sort-help lst)
(cond ((null? lst) ())
((= (length lst) 1) lst)
(else
(append (quick-sort-help (filter (lambda (n) (pred n (car lst))) lst))
(list (car lst))
(quick-sort-help (filter (lambda (n) (not(pred n (car lst)))) lst)))))) (quick-sort-help lst))
And I get an infinite recursion or something.
Can you help me solve this problem please?
Thanks!
First of you don't need the helper function quick-sort-help.
It recurs infinitely because you apply your helper function to lst instead cdr lst. In your regular quicksort you have (filter (lambda (n) (< n (car lst))) and (filter (lambda (n) (> n (car lst))). But then in the one with the predicate you have the problem that (not (pred ...) would cover the cases for <= and not < if the predicate is > and vice versa. So it gets stuck because the first element in the list is always equal with itself.
Here a correct quicksort:
(define (qsort f lst)
(if (null? lst)
null
(let ([pivot (car lst)])
(append (qsort f (filter (λ (n) (f n pivot)) (cdr lst)))
(list pivot)
(qsort f (filter (λ (n) (not (f n pivot))) (cdr lst)))))))

Same-parity in Scheme

I am trying to solve the exercise 2.20 from SICP book. The exercise -
Write a procedure same-parity that takes one or more integers and returns a list of
all the arguments that have the same even-odd parity as the first argument. For example,
(same-parity 1 2 3 4 5 6 7)
(1 3 5 7)
(same-parity 2 3 4 5 6 7)
(2 4 6)
My code -
(define same-parity (lambda (int . l)
(define iter-even (lambda (l2 rl)
(cons ((null? l2) rl)
((even? (car l2))
(iter-even (cdr l2) (append rl (car l2))))
(else (iter-even (cdr l2) rl)))))
(define iter-odd (lambda (l2 rl)
(cons ((null? l2) rl)
((odd? (car l2))
(iter-odd (cdr l2) (append rl (car l2))))
(else (iter-odd (cdr l2) rl)))))
(if (even? int) (iter-even l (list int))
(iter-odd l (list int)))))
For some reason I am getting an error saying "The object (), passed as the first argument to cdr, is not the correct type". I tried to solve this for more than two hours, but I cant find any reason why it fails like that. Thanks for hlep.
Try this:
(define same-parity
(lambda (int . l)
(define iter-even
(lambda (l2 rl)
(cond ((null? l2) rl)
((even? (car l2))
(iter-even (cdr l2) (append rl (list (car l2)))))
(else (iter-even (cdr l2) rl)))))
(define iter-odd
(lambda (l2 rl)
(cond ((null? l2) rl)
((odd? (car l2))
(iter-odd (cdr l2) (append rl (list (car l2)))))
(else (iter-odd (cdr l2) rl)))))
(if (even? int)
(iter-even l (list int))
(iter-odd l (list int)))))
Explanation:
You are using cons instead of cond for the different conditions
in the part where append is called, the second argument must be a proper list (meaning: null-terminated) - but it is a cons-pair in your code. This was causing the error, the solution is to simply put the second element inside a list before appending it.
I must say, using append to build an output list is frowned upon. You should try to write the recursion in such a way that cons is used for creating the new list, this is more efficient, too.
Some final words - as you're about to discover in the next section of SICP, this problem is a perfect fit for using filter - a more idiomatic solution would be:
(define (same-parity head . tail)
(if (even? head)
(filter even? (cons head tail))
(filter odd? (cons head tail))))
First, I check the first element in the list. If it is even, I call the procedure that forms a list out of only the even elements. Else, I call the procedure that forms a list out of odd elements.
Here's my code
(define (parity-helper-even B)(cond
((= 1 (length B)) (cond
((even? (car B)) B)
(else '())
))
(else (cond
((even? (car B)) (append (list (car B)) (parity-helper-even (cdr B))))
(else (parity-helper-even(cdr B)))
))))
(define (parity-helper-odd B)(cond
((= 1 (length B)) (cond
((odd? (car B)) B)
(else '())
))
(else (cond
((odd? (car B)) (append (list (car B)) (parity-helper-odd (cdr B))))
(else (parity-helper-odd (cdr B)))
))))
(define (same-parity first . L) (cond
((even? first) (parity-helper-even (append (list first) L)))
(else (parity-helper-odd (append (list first) L)))))
(same-parity 1 2 3 4 5 6 7)
;Output (1 3 5 7)
While you are traversing the list, you might as well just split it into even and odd parities. As the last step, choose the one you want.
(define (parities args)
(let looking ((args args) (even '()) (odd '()))
(if (null? args)
(values even odd)
(let ((head (car args)))
(if (even? head)
(looking (cdr args) (cons head even) odd)
(looking (cdr args) even (cons head odd)))))))
(define (same-parity head . rest)
(let-values ((even odd) (parities (cons head rest)))
(if (even? head)
even
odd)))
Except for homework assignments, if you are going to look for one then you are likely to need the other. Said another way, you'd find yourself using parities more frequently in practice.
You could simply filter elements by parity of first element:
(define (same-parity x . y)
(define (iter z filter-by)
(cond ((null? z) z)
((filter-by (car z))
(cons (car z) (iter (cdr z) filter-by)))
(else (iter (cdr z) filter-by))))
(iter (cons x y) (if (even? x) even? odd?)))
And try:
(same-parity 1 2 3 4 5 6 7)
(same-parity 2 3 4 5 6 7)

How to sort disorder list of numbers in scheme

What it the proper way to sort a list with values in Scheme? For example I have the values which are not ordered:
x1, x5, x32 .... xn
or
3, 4, 1, 3, 4, .. 9
First I want to for them by increase number and display them in this order:
x1, xn, x2, xn-1
or
1, 6, 2, 5, 3, 4
Any help will be valuable.
This is the same question you posted before, but with a small twist. As I told you in the comments of my answer, you just have to sort the list before rearranging it. Here's a Racket solution:
(define (interleave l1 l2)
(cond ((empty? l1) l2)
((empty? l2) l1)
(else (cons (first l1)
(interleave l2 (rest l1))))))
(define (zippy lst)
(let-values (((head tail) (split-at
(sort lst <) ; this is the new part
(quotient (length lst) 2))))
(interleave head (reverse tail))))
It works as expected:
(zippy '(4 2 6 3 5 1))
=> '(1 6 2 5 3 4)
This R6RS solution does what Chris Jester-Young proposes and it really is how to do it the bad way. BTW Chris' and Óscar's solutions on the same question without sorting is superior to this zippy procedure.
#!r6rs
(import (rnrs base)
(rnrs sorting)) ; list-sort
(define (zippy lis)
(let loop ((count-down (- (length lis) 1))
(count-up 0))
(cond ((> count-up count-down) '())
((= count-up count-down) (cons (list-ref lis count-down) '()))
(else (cons (list-ref lis count-down)
(cons (list-ref lis count-up)
(loop (- count-down 1)
(+ count-up 1))))))))
(define (sort-rearrange lis)
(zippy (list-sort < lis)))
Here is a simple, tail-recursive approach that uses a 'slow/fast' technique to stop the recursion when half the list is traversed:
(define (interleave l)
(let ((l (list-sort < l)))
(let merging ((slow l) (fast l) (revl (reverse l)) (rslt '()))
(cond ((null? fast)
(reverse rslt))
((null? (cdr fast))
(reverse (cons (car slow) rslt)))
(else
(merging (cdr slow) (cddr fast) (cdr revl)
(cons (car revl) (cons (car slow) rslt))))))))
So, you don't mind slow and just want a selection-based approach, eh? Here we go....
First, we define a select1 function that gets the minimum (or maximum) element, followed by all the other elements. For linked lists, this is probably the simplest approach, easier than trying to implement (say) quickselect.
(define (select1 lst cmp?)
(let loop ((seen '())
(rest lst)
(ext #f)
(extseen '()))
(cond ((null? rest)
(cons (car ext) (append-reverse (cdr extseen) (cdr ext))))
((or (not ext) (cmp? (car rest) (car ext)))
(let ((newseen (cons (car rest) seen)))
(loop newseen (cdr rest) rest newseen)))
(else
(loop (cons (car rest) seen) (cdr rest) ext extseen)))))
Now actually do the interweaving:
(define (zippy lst)
(let recur ((lst lst)
(left? #t))
(if (null? lst)
'()
(let ((selected (select1 lst (if left? < >))))
(cons (car selected) (recur (cdr selected) (not left?)))))))
This approach is O(n²), whereas the sort-and-interleave approach recommended by everybody else here is O(n log n).

Resources