scheme mode"list" function - scheme

I'm trying to find the most repeated element in a list. The problem is I have to use the count function, which finds how many time a specific value is repeated in a list (for example, (count 7 '(4 8 9 2 4 8 9)) => 0, (count 2 '(4 8 9 2 2 4 8 9 2)) => 3).
I finished the count function and I think I'm close with the mode function. Any help will be appreciated.
(define (count item list)
(cond
[(null? list) '()]
[(= item (car list)) (+ 1 (count item (cdr list)))]
[#t (count item (cdr list))]))
(define (mode lst)
(cond
[(null? lst) '()]
[(> (count (car lst) lst) (mode (cdr lst))) (car lst)]
[else (mode (cdr lst))]))

It's mode night, as it seems - check a previous question, which uses a different approach: it assumes that the input list is sorted. But of course - the mode procedure can be implemented in terms of count with a non-sorted input list, although less efficiently - it's an O(n^2) solution:
(define (mode lnum)
(let loop ((lst lnum) ; list to traverse
(max-counter 0) ; number of times the mode appears
(max-current #f)) ; the mode
(if (null? lst) ; if the list is empty
max-current ; return the mode
(let ((n (count (car lst) lnum))) ; # of times current element appears
(if (> n max-counter) ; if it appears more times
(loop (cdr lst) n (car lst)) ; then we found a new maximum
(loop (cdr lst) max-counter max-current)))))) ; else continue
The idea is simple, count how many times is each element in the list, and keep track of the element which appears the most.
And FYI, neither this nor the other linked solutions (which require that a sort is performed before) implement the most efficient algorithm for finding a mode in an unsorted list. See this answer, the most-common procedure implemented there also computes the mode of a list, but in O(n).

Related

What is happening in each line of this code?

I know the overall code is to return the last nth elements of the list, however, I don't understand the process, like in each line what is happening(and why, if possible)?
(define (last-n lst n)
(define (help-func lst drop)
(cond
((> drop 0)
(help-func (cdr lst ) (- drop 1)))
(else
(cdr lst ))))
(if (= (length lst ) n )
lst
(help-func lst (- (length lst ) 1 n ))))
There's a small bug, when n is greater than the length of the list you should return the whole list (or signal an error), I fixed it. Here's a break-down of the code:
(define (last-n lst n)
(define (help-func lst drop)
(cond
; iterate while there are elements to drop
((> drop 0)
; advance on the list, and we're one
; element closer to reach our target
(help-func (cdr lst) (- drop 1)))
(else
; else we reached the point we wanted, stop
(cdr lst))))
; if n is at least as big as the list
(if (>= n (length lst))
; return the whole list
lst
; else calculate how many elements
; we need to drop and start the loop
(help-func lst (- (length lst) 1 n))))
FYI, Racket already has this functionality, just use the take-right built-in procedure, it'll even be faster, requiring a single pass over the list (you're calling length a couple of times, and in a clever algorithm that would be unnecessary)

Nested List Issue in Lisp

So I have to write a method that takes in a list like (nested '(4 5 2 8)) and returns (4 (5 () 2) 8).
I figured I needed to write 3 supporting methods to accomplish this. The first gets the size of the list:
(define (sizeList L)
(if (null? L) 0
(+ 1 (sizeList (cdr L)))))
input : (sizeList '(1 2 3 4 5 6 7))
output: 7
The second drops elements from the list:
(define (drop n L)
(if (= (- n 1) 0) L
(drop (- n 1) (cdr L))))
input : (drop 5 '(1 2 3 4 5 6 7))
output: (5 6 7)
The third removes the last element of a list:
(define (remLast E)
(if (null? (cdr E)) '()
(cons (car E) (remLast (cdr E)))))
input : (remLast '(1 2 3 4 5 6 7))
output: (1 2 3 4 5 6)
For the nested method I think I need to do the car of the first element, then recurse with the drop, and then remove the last element but for the life of me I can't figure out how to do it or maybe Im just continually messing up the parenthesis? Any ideas?
Various recursive solutions are possible, but the problem is that the more intuitive ones have a very bad performance, since they have a cost that depends on the square of the size of the input list.
Consider for instance this simple solution:
; return a copy of list l without the last element
(define (butlast l)
(cond ((null? l) '())
((null? (cdr l)) '())
(else (cons (car l) (butlast (cdr l))))))
; return the last element of list l
(define (last l)
(cond ((null? l) '())
((null? (cdr l)) (car l))
(else (last (cdr l)))))
; nest a linear list
(define (nested l)
(cond ((null? l) '())
((null? (cdr l)) l)
(else (list (car l) (nested (butlast (cdr l))) (last l)))))
At each recursive call of nested, there is a call to butlast and a call to last: this means that for each element in the first half of the list we must scan twice the list, and this requires a number of operations of order O(n2).
Is it possible to find a recursive solution with a number of operations that grows only linearly with the size of the list? The answer is yes, and the key to this solution is to reverse the list, and work in parallel on both the list and its reverse, through an auxiliary function that gets one element from both the lists and recurs on their cdr, and using at the same time a counter to stop the processing when the first halves of both lists have been considered. Here is a possible implementation of this algorithm:
(define (nested l)
(define (aux l lr n)
(cond ((= n 0) '())
((= n 1) (list (car l)))
(else (list (car l) (aux (cdr l) (cdr lr) (- n 2)) (car lr)))))
(aux l (reverse l) (length l)))
Note that the parameter n starts from (length l) and is decreased by 2 at each recursion: this allows to manage both the cases of a list with an even or odd number of elements. reverse is the primitive function that reverses a list, but if you cannot use this primitive function you can implement it with a recursive algorithm in the following way:
(define (reverse l)
(define (aux first-list second-list)
(if (null? first-list)
second-list
(aux (cdr first-list) (cons (car first-list) second-list))))
(aux l '()))

How do you obtain the largest n elements of a list using Scheme?

I'm stuck on a homework question and could use any hints or suggestions. I need to find the n largest numbers in a list using Scheme. I am trying to do this by creating helper functions that are called by the main function. So far I have this:
(define (get_max_value L)
(if (null? L)
'()
(apply max L)
)
(define (biggest_nums L n)
(if (null? n)
'()
(cons (get_max_value L) (biggest_nums L (- n 1)))
)
)
When I type (biggest_num '(3 1 4 2 5) 3) at the command prompt drRacket just hangs and doesn't even return an error message. Where am I going wrong?
The simplest solution is to first sort the numbers in ascending order and then take the n first. This translates quite literally in Racket code:
(define (biggest_nums L n)
(take (sort L >) n))
It works as expected:
(biggest_nums '(3 1 4 2 5) 3)
=> '(5 4 3)
Two mains problems with your code:
L always stays the same. L doesn't decrease in size when you make the recursive call, so the max will always be the same number in every recursive call.
You don't ever check n to make sure it contains the correct amount of numbers before returning the answer.
To solve these two problems in the most trivial way possible, you can put a (< n 1) condition in the if, and use something like (cdr L) to make L decrease in size in each recursive call by removing an element each time.
(define (biggest-nums n L)
(if (or (empty? L)
(< n 1))
'()
(cons (apply max L) (biggest-nums (- n 1) (cdr L)))))
So when we run it:
> (biggest-nums 3 '(1 59 2 10 33 4 5))
What should the output be?
'(59 33 10)
What is the actual output?
'(59 59 33)
OK, so we got your code running, but there are still some issues with it. Do you know why that's happening? Can you step through the code to figure out what you could do to fix it?
Just sort the list and then return the first n elements.
However, if the list is very long and n is not very large, then you probably don't want to sort the whole list first. In that case, I would suggest something like this:
(define insert-sorted
(lambda (item lst)
(cond ((null? lst)
(list item))
((<= item (car lst))
(cons item lst))
(else
(cons (car lst) (insert-sorted item (cdr lst)))))))
(define largest-n
(lambda (count lst)
(if (<= (length lst) count)
lst
(let loop ((todo (cdr lst))
(result (list (car lst))))
(if (null? todo)
result
(let* ((item (car todo))
(new-result
(if (< (car result) item)
(let ((new-result (insert-sorted item result)))
(if (< count (length new-result))
(cdr new-result)
new-result))
result)))
(loop (cdr todo)
new-result)))))))

Can I implement quicksort efficiently with Scheme?

This is what I've done:
(define qsort
(lambda (l)
(let ((lesser '()))
(let ((greater '()))
(cond
((null? l) '())
(else (map (lambda (ele)
(if (> (car l) ele)
(set! lesser (cons ele lesser))
(set! greater (cons ele greater)))) (cdr l))
(append (qsort lesser) (cons (car l) (qsort greater))))
)))))
I noticed that when provided with an already sorted list, it becomes extremely sluggish.
After some searching, I found that if the "pivot" is selected in a random manner, the performance can be improved.
However the only way I know to achieve this is by list-ref, and it seems to be O(n).
To make matters even worse, I have to implement a cdr-like function to remove n-th element in the list, which might also be extremely inefficient.
Maybe I'm in the wrong direction. Could you give me some advice?
true quicksort runs on random-access arrays, with in-place partitioning. e.g. see this.
you can start by converting your list to vector with list->vector, then implementing the quicksort by partitioning the vector with mutating swaps, in C fashion.
Randomizing it is easy: just pick a position randomly, and swap its contents with the first element in range being sorted, before each partition step. When you're done, convert it back with vector->list.
Efficient implementation of quicksort may run without recursion, in a loop, maintaining a stack of bigger parts boundaries, always descending on the smaller ones (then, when at the bottom, switching to the first part in the stack). Three-way partitioning is always preferable, dealing with equals in one blow.
Your list-based algorithm is actually an unraveled treesort.
see also:
http://www.reddit.com/r/programming/comments/2h0j2/real_quicksort_in_haskell
Pseudo-quicksort time complexity
Although there's already an accepted answer, I thought you might appreciate a Scheme translation of the Sheep Trick from The Pitmanual. Your code is actually quite similar to it already. Scheme does support do loops, but they're not particularly idiomatic, whereas named lets are much more common, so I've used the latter in this code. As you've noted, choosing the first element as the pivot cause perfomance problems if the list is already sorted. Since you have to traverse the list on each iteration, there might be some clever thing you could do to pick the pivots for the left and right sides for the recursive calls in advance.
(define (nconc l1 l2)
;; Destructively concatenate l1 and l2. If l1 is empty,
;; return l2. Otherwise, set the cdr of the last pair
;; of l1 to l2 and return l1.
(cond
((null? l1)
l2)
(else
(let loop ((l1 l1))
(if (null? (cdr l1))
(set-cdr! l1 l2)
(loop (cdr l1))))
l1)))
(define (quicksort lst)
(if (null? lst) lst
(let ((pivot (car lst))
(left '())
(right '()))
(let loop ((lst (cdr lst))) ; rebind to (cdr lst) since pivot wasn't popped
(if (null? lst)
(nconc (quicksort left)
(cons pivot
(quicksort right)))
(let ((tail (cdr lst)))
(cond
((< (car lst) pivot)
(set-cdr! lst left)
(set! left lst))
(else
(set-cdr! lst right)
(set! right lst)))
(loop tail)))))))
(quicksort (list 9 1 8 2 7 3 6 4 5))
;=> (1 2 3 4 5 6 7 8 9)
Scheme does support do, so if you are interested in that (it does make the Common Lisp and Scheme version very similar), it looks like this:
(define (quicksort lst)
(if (null? lst) lst
(do ((pivot (car lst))
(lst (cdr lst)) ; bind lst to (cdr lst) since pivot wasn't popped
(left '())
(right '()))
((null? lst)
(nconc (quicksort left)
(cons pivot
(quicksort right))))
(let ((tail (cdr lst)))
(cond
((< (car lst) pivot)
(set-cdr! lst left)
(set! left lst))
(else
(set-cdr! lst right)
(set! right lst)))
(set! lst tail)))))
(display (quicksort (list 9 1 8 2 7 3 6 4 5)))
;=> (1 2 3 4 5 6 7 8 9)
A truly efficient implementation of Quicksort should be in-place and implemented using a data structure that can be accessed efficiently by index - and that makes immutable linked lists a poor choice.
The question asks whether Quicksort can be efficiently implemented with Scheme - the answer is yes, as long as you don't use lists. Switch to using a vector, which is mutable and has O(1) index-based access over its elements, like an array in C-like programming languages.
If your input data comes in a linked list, you can always do something like this, it'll probably be faster than directly sorting the list:
(define (list-quicksort lst)
(vector->list
(vector-quicksort ; ToDo: implement this procedure
(list->vector lst))))

Scheme return a list with first half of its elements

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)))

Resources