Need help finding second largest number in a list. Racket [closed] - recursion

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I've been struggling with this question for a lot now. Could someone please explain the logic behind the program by using the simplest way possible possibly recursion?
Thank you.

Have 2 variables (say x and y)
Move through the list of numbers
Keep largest in x and previous largest (previous x value) in y
At end return y value.
Remember to compare each value to current values of both x and y.
I have tested it and it works but I am sure you want to code it yourself. Take care to choose the starting values of x and y.
Edit
With reference to discussion in comments (using -inf.0 as initial value as in answer by #naomik) :
(define steps 0)
(define (gt x y)
(set! steps (add1 steps))
(> x y))
(define (lt x y)
(set! steps (add1 steps))
(< x y))
(define (2ndLargest L)
(let loop ((x -inf.0) ; largest
(y -inf.0) ; second largest
(L L))
(cond
[(empty? L)
(printf "steps=~a;~n" steps)
y]
[(or (= (first L) x)(= (first L) y))
(loop x y (rest L))]
[(gt (first L) x)
(loop (first L) x (rest L))]
[(gt (first L) y)
(loop x (first L) (rest L))]
[else
(loop x y (rest L))]
)))
(define (2ndLargest2 L)
(let loop ((x -inf.0) ; largest
(y -inf.0) ; second largest
(L L))
(cond
[(empty? L)
(printf "steps=~a;~n" steps)
y]
[(or (= (first L) x)(= (first L) y))
(loop x y (rest L))]
[(lt (first L) y) ; FIRST CHECK IF LESS THAN Y;
(loop x y (rest L))]
[(gt (first L) x)
(loop (first L) x (rest L))]
[(gt (first L) y)
(loop x (first L) (rest L))]
)))
(define L '(8 3 4 5 6 2 7 3 10 12 -1 11))
(2ndLargest L)
(2ndLargest2 L)
(set! L '(11 8 3 4 5 6 2 7 3 10 -1 12))
(2ndLargest L)
(2ndLargest2 L)
(set! L '(8 3 4 5 6 11 7 3 10 12 -1))
(2ndLargest L)
(2ndLargest2 L)
Output:
steps=21;
11
steps=48;
11
steps=70;
11
steps=88;
11
steps=107;
11
steps=131;
11
Steps are more if current is checked to be if less than y first.

I took a swing at this using foldl – It works similarly to mso's answer by keeping track of the two (distinct) highest numbers in the list using an accumulator (cons x1 x2), where x1 is the highest and x2 is the second highest
This answer will return -inf.0 for an input of an empty list or an input of a single-number list
#lang racket
(define (second-largest xs)
(cdr (foldl (lambda (y acc)
(let ((x1 (car acc))
(x2 (cdr acc)))
(cond ((> y x1) (cons y x1))
((= y x1) (cons y x2))
((> y x2) (cons x1 y))
(else (cons x1 x2)))))
(cons -inf.0 -inf.0)
xs)))
(second-largest '(8 3 4 5 6 2 12 7 3 10 12 -1 11))
;; => 11

Related

How to build a rolling window procedure using racket/scheme?

When written this way the error says: 4 parts after if:
(define (rolling-window l size)
(if (< (length l) size) l
(take l size) (rolling-window (cdr l) size)))
and when there's another paranthesis to make it 3 parts:
(define (rolling-window l size)
(if (< (length l) size) l
((take l size) (rolling-window (cdr l) size))))
then it says: application: not a procedure;
How to write more than one expression in if's else in racket/scheme?
Well that's not really the question. The question is "How to build a rolling window procedure using racket?". Anyway, it looks like you're probably coming from another programming language. Processing linked lists can be a little tricky at first. But remember, to compute the length of a list, you have to iterate through the entire list. So using length is a bit of an anti-pattern here.
Instead, I would recommend you create an auxiliary procedure inside your rolling-window procedure which builds up the window as you iterate thru the list. This way you don't have to waste iterations counting elements of a list.
Then if your aux procedure ever returns and empty window, you know you're done computing the windows for the given input list.
(define (rolling-window n xs)
(define (aux n xs)
(let aux-loop ([n n] [xs xs] [k identity])
(cond [(= n 0) (k empty)] ;; done building sublist, return sublist
[(empty? xs) empty] ;; reached end of xs before n = 0, return empty window
[else (aux-loop (sub1 n) (cdr xs) (λ (rest) (k (cons (car xs) rest))))]))) ;; continue building sublist
(let loop ([xs xs] [window (aux n xs)] [k identity])
(cond ([empty? window] (k empty)) ;; empty window, done
([empty? xs] (k empty)) ;; empty input list, done
(else (loop (cdr xs) (aux n (cdr xs)) (λ (rest) (k (cons window rest)))))))) ;; continue building sublists
(rolling-window 3 '(1 2 3 4 5 6))
;; => '((1 2 3) (2 3 4) (3 4 5) (4 5 6))
It works for empty windows
(rolling-window 0 '(1 2 3 4 5 6))
;; => '()
And empty lists too
(rolling-window 3 '())
;; => '()
Here is an alternative:
#lang racket
(define (rolling-window n xs)
(define v (list->vector xs))
(define m (vector-length v))
(for/list ([i (max 0 (- m n -1))])
(vector->list (vector-copy v i (+ i n)))))
(rolling-window 3 '(a b c d e f g))
(rolling-window 3 '())
(rolling-window 0 '(a b c))
Output:
'((a b c) (b c d) (c d e) (d e f) (e f g))
'()
'(() () () ()) ; lack of spec makes this ok !
Following modification of OP's function works. It includes an outlist for which the initial default is empty list. Sublists are added to this outlist till (length l) is less than size.
(define (rolling-window l size (ol '()))
(if (< (length l) size) (reverse ol)
(rolling-window (cdr l) size (cons (take l size) ol))))
Testing:
(rolling-window '(1 2 3 4 5 6) 2)
(rolling-window '(1 2 3 4 5 6) 3)
(rolling-window '(1 2 3 4 5 6) 4)
Output:
'((1 2) (2 3) (3 4) (4 5) (5 6))
'((1 2 3) (2 3 4) (3 4 5) (4 5 6))
'((1 2 3 4) (2 3 4 5) (3 4 5 6))
Any improvements on this one?
(define (rolling-window l size)
(cond ((eq? l '()) '())
((< (length l) size) '())
((cons (take l size) (rolling-window (cdr l) size)))))

Implementation of Heaps Algorithm in Scheme (permutation generation)

I want to implement Heap's algorithm in Scheme (Gambit).
I read his paper and checked out lots of resources but I haven't found many functional language implementations.
I would like to at least get the number of possible permutations.
The next step would be to actually print out all possible permutations.
Here is what I have so far:
3 (define (heap lst n)
4 (if (= n 1)
5 0
6 (let ((i 1) (temp 0))
7 (if (< i n)
8 (begin
9 (heap lst (- n 1))
10 (cond
11 ; if even: 1 to n -1 consecutively cell selected
12 ((= 0 (modulo n 2))
13 ;(cons (car lst) (heap (cdr lst) (length (cdr lst)))))
14 (+ 1 (heap (cdr lst) (length (cdr lst)))))
15
16 ; if odd: first cell selectd
17 ((= 1 (modulo n 2))
18 ;(cons (car lst) (heap (cdr lst) (length (cdr lst)))))
19 (+ 1 (heap (car lst) 1)))
20 )
21 )
22 0
23 )
24 )
25 )
26 )
27
28 (define myLst '(a b c))
29
30 (display (heap myLst (length myLst)))
31 (newline)
I'm sure this is way off but it's as close as I could get.
Any help would be great, thanks.
Here's a 1-to-1 transcription of the algorithm described on the Wikipedia page. Since the algorithm makes heavy use of indexing I've used a vector as a data structure rather than a list:
(define (generate n A)
(cond
((= n 1) (display A)
(newline))
(else (let loop ((i 0))
(generate (- n 1) A)
(if (even? n)
(swap A i (- n 1))
(swap A 0 (- n 1)))
(if (< i (- n 2))
(loop (+ i 1))
(generate (- n 1) A))))))
and the swap helper procedure:
(define (swap A i1 i2)
(let ((tmp (vector-ref A i1)))
(vector-set! A i1 (vector-ref A i2))
(vector-set! A i2 tmp)))
Testing:
Gambit v4.8.4
> (generate 3 (vector 'a 'b 'c))
#(a b c)
#(b a c)
#(c a b)
#(a c b)
#(b c a)
#(c b a)

0/1 Knapsack in Scheme

Am in on the right track for programming the knapsack problem in scheme? My program doesn't have to account for objects "values" , only their weights. The goal is to take the best combination of items so that I have approximately half of the weight in my bag.
(define (split-equip wlst)
(define (sum lst)
(define (sum-h accum lst1)
(if (null? lst)
(/ accum (length lst))
(sum-h (+ (car lst1) accum) (cdr lst1))))
(sum-h 0 lst))
(define (split-equip-h)
(let ((target-w (/ (sum wlst) 2)))
I am tempted to write my program to output a list with all of the different combinations of weights possible and then traversing the list until I find the best set of weights, but not sure how to implement this.
Since this is already your second attempt at this (the first question was deleted), I'll show you a solution in Racket. You should read it like pseudo-code and translate it into the Scheme variant you have been taught.
Disclaimer: I suck at these kind of exercises. That should be another reason for you to understand and reformulate this. But the results of my code still seem correct.
Here's the code:
#lang racket
(define (knapsack lst)
(define half (/ (apply + lst) 2)) ; compute half of total
(printf "list : ~a\nhalf : ~a\n" lst half)
(define (combs lst1 (lst2 null)) ; compute all the combinations
(if (null? lst1)
(if (null? lst2)
null
(list (reverse lst2)))
(append
(combs (cdr lst1) lst2) ; case 1 -> we don't carry the iten
(combs (cdr lst1) (cons (car lst1) lst2))))) ; case 2 -> we do
(for/fold ((delta half) (res null)) ((c (in-list (combs lst)))) ; determine the best fit
(let* ((sm (apply + c)) (newdelta (abs (- half sm))))
(cond
((< newdelta delta) (values newdelta (list c)))
((= newdelta delta) (values delta (cons c res)))
(else (values delta res))))))
(time
(let-values (((delta res) (knapsack (cdr (range 0 24 3)))))
(printf "result: ~a\ndelta : ~a\n" res delta)))
and here's what it says:
list : (3 6 9 12 15 18 21)
half : 42
result: ((3 6 12 21) (3 6 15 18) (3 9 12 18) (3 18 21) (6 9 12 15) (6 15 21) (9 12 21) (9 15 18))
delta : 0
cpu time: 6 real time: 5 gc time: 0
Hope this helps. Don't hesitate to ask questions if there's something you don't get!

I can't get a Scheme function to recursively invoke f on a nested list for the correct result

I didn't do too hot on a test I took recently in a class. However, since everyone else bombed it as well, our professor is willing to give us some "make up" points by proving to her that we know Scheme (not so great at it...). She'd ask different questions from what was on the test, though. So I'm working on the questions that were on the test to get better with Scheme, and I can't seem to get the following one to work.
Write a Scheme function reduce which takes two parameters: f, a function which takes a single parameter, and x, an arbitrary value. The reduce function recursively invokes f using each nested list contained in x and then replaces the original nested list with the result of invoking f.
For example, invoking (reduce (lambda(x) (cons 'list x)) '(3 7 9 z s (3 (78 2 3)))) should return:
'(list 3 7 9 z s (list 3 (list 78 2 3)))
Also, invoking (reduce (lambda (x) (cdr x)) '(3 7 9 z s (3 (78 2 3)))) should return:
'(7 9 z s ((2 3))), where the first element is removed from each nested list.
This is the code I came up with:
(define reduce
(lambda (f x)
(if (null? x)'()
(let ((var (car x)))
(cond
((cons? var) (cons (f var) (reduce f (cdr x))))
((symbol? var) (cons var (reduce f (cdr x))))
((number? var) (cons var (reduce f (cdr x)))))))))
If I enter the example inputs, these are my results:
(reduce (lambda(x) (cons 'list x)) '(3 7 9 z s (3 (78 2 3))))
(list 3 7 9 'z 's (list 'list 3 (list 78 2 3)))
there's an extra 'list coming from who knows where
;
(reduce (lambda(x) (cdr x)) '(3 7 9 z s (3 (78 2 3))))
(list 3 7 9 'z 's (list (list 78 2 3)))
it only removes the 3 in the 2nd nested loop. It should remove the 3 in the first one, 3 in the middle and the 78 in the 3rd. It also shouldn't have the word "list" in it
;
I'm assuming the problem is in the line ((cons? var), but I can't seem to figure out how to fix it.
We didn't go too far into the Scheme language, so we haven't learned a whole lot of special methods; it's mainly all just recursion.
Any help would be much appreciated.
Thanks.
Here's my implementation:
(define (reduce f x)
(define (inner x)
(if (list? x)
(f (map inner x))
x))
(inner x))
Examples:
> (reduce (lambda (x) `(list ,#x)) '(3 7 9 z s (3 (78 2 3))))
(list 3 7 9 z s (list 3 (list 78 2 3)))
> (reduce cdr '(3 7 9 z s (3 (78 2 3))))
(7 9 z s ((2 3)))
Here's a version that doesn't use map directly, but basically reimplements map (albeit using a hardcoded transformer):
(define (reduce f x)
(define (transform lst)
(if (null? lst)
'()
(cons (process (car lst)) (transform (cdr lst)))))
(define (process x)
(if (list? x)
(f (transform x))
x))
(process x))

Finding the position of a number in a list

Hey guys, I have a homework question that's been frustrating me to no end! I'm supposed to create index-of-least that will take a non-empty list and return the index of the smallest number in the list. The index of the (car ls) = 0, index of the (car (cdr ls)) = 1, and so on.
A helper needs to be created that will keep track of the current-position, least-position, least-value, and list. So far, I have this program (that doesn't load) that shows the basic algorithm.. But I'm having a hard time keeping track of everything and putting it into chez scheme code.
(define index-helper
(lambda (ls current-position least-position least-value)
(if (> (car ls) least-value)
(add1 (car ls (cdr ls (add1 current-position))))
(car ls (cdr ls (add1 current-position))))))
;trace
;ls: (4231) c-pos: 0 least-value: 5 least-pos: 0
;ls: (231) c-pos: 1 least-value: 4 least-pos: 1
;ls: (31) c-pos 2 least-value: 2 least-pos: 2
;ls: 1 c-pos: 3 l-v: 2 l-pos: 2
;ls '() c-pos: 4 l-v: 1 l-pos: 4
;*least-position = current-position
I already googled this and found similar questions in python, but I don't understand the code because I'm new to programming. :P
If anyone can give me a hint, I'd really appreciate it!
You want two functions. The first function find the least element x. The second function finds the index of the element x in the list.
Something like:
(define (find-least xs)
(foldl (lambda (e acc) (min e acc)) (car xs) xs))
(define (elem-index x xs)
(define (elem-index-find x xs ind)
(cond
((empty? xs) ind)
((eq? x (car xs))
ind)
(else (elem-index-find x (cdr xs) (+ ind 1)))))
(if (empty? xs)
(error "empty list")
(elem-index-find x xs 0)))
(define (index-of-least xs)
(let ((least (find-least xs)))
(elem-index least xs)))
Test:
> (index-of-least (list 5 8 4 9 1 3 7 2))
4
Or, in one pass:
(define (index-of-least-1-pass xs)
(define (index-do least ind-least ind xs)
(cond
((empty? xs) ind-least)
((< (car xs) least)
(index-do (car xs) (+ ind 1) (+ ind 1) (cdr xs)))
(else
(index-do least ind-least (+ ind 1) (cdr xs)))))
(index-do (car xs) 0 0 (cdr xs)))
Test:
> (index-of-least-1-pass (list 5 8 4 9 1 3 7 2))
4
In index-do helper function first you check if the intermediate list is empty; this is a base case, when we have got just one element int the list, and return its index.
Next condition checks if the next element of the intermediate list is greater than the current least value, and if so, we call helper with the new value of least and its index.
The last condition is selected, when the next element is not greater than the least, and it calls the helper function with the same values of least and ind-least, and the intermediate list with head element removed until there are no elements in the list, and we approached the base case, when there are no elements in the list.
A good example for named let:
(define (index-of-least xs)
(let loop ((i 0) (p 0) (x (car xs)) (xs (cdr xs)))
(cond ((null? xs) p)
((< (car xs) x) (loop (+ i 1) (+ i 1) (car xs) (cdr xs)))
(else (loop (+ i 1) p x (cdr xs))))))
(index-of-least (list 5 8 4 9 1 3 7 2)) => 4

Resources