scheme define list as local variable - functional-programming

My target is do define list as local variable in order to get max element from it. My code:
#lang racket
(define (f a b c)
(list (+ (* a a) (* b b) (* c c)) (+ a c))
(define (max-of-list-2 lst)
(foldr max (first lst) (rest lst)))
(max max_from_list 12))
(f 5 6 7)
In second row I have defined list with calculated falues. My target is to pass it to next row in order to get max number from it, and finaly to get max from max of list and 12. What I do wrong. How to handle it?

You can use several defines at the top of your function.
So you meant
(define (f a b c)
(define lst (list (+ (* a a) (* b b) (* c c))
(+ a c)))
(define (max-of-list-2 lst)
(foldr max (first lst) (rest lst)))
(max (max-of-list-2 lst) 12))
but that's just equivalent to
(define (f a b c)
(foldr max 12 (list (+ (* a a) (* b b) (* c c))
(+ a c))))

You need to use an inner define, like this:
(define (f a b c)
(define max_from_list (list (+ (* a a) (* b b) (* c c)) (+ a c)))
(define (max-of-list-2 lst)
(foldr max (first lst) (rest lst)))
(max max_from_list 12))

It's somewhat difficult to work out your intentions, but this is the best understanding I can come up with -
(define (max a b)
(if (< a b)
b
a))
(define (f a . more)
(if (empty? more)
(max a 12)
(max a (apply f more))))
(f 5 6 7)
; => 12
(f 5 20 30)
; => 30

Related

How to look for an element in a list of lists in racket

I'm trying to find an element in a list of lists and print the lists that contain that element.
For the test: (search-table '((1 2 3) (4 2) (3 3 4) (5 3 2 1)) 1), the output is:
'((1 2 3) (5 3 2 1))
This is my code in DrRacket so far:
(define (search-table table item)
(if(equal? table null)
'()
(cons(search-table first table item))(search-table rest table item)))
But this code is giving me an error message which says:
if: bad syntax;
has 4 parts after keyword in: (if (equal? table null) (quote ()) (cons (search-table first table item)) (search-table rest table item))
Please help me with this as I am very new to Racket.
If the value is a member of the list, cons the list onto the result
(define (search-table lists value)
(cond ((null? lists) '())
((member value (car lists))
(cons (car lists) (search-table (cdr lists) value)))
(else (search-table (cdr lists) value))))
(search-table '((a b c d) (b c) (c d e f) (a b c)) 'a)
;; '((a b c d) (a b c))
You tagged this with tail-recursion tho, so let's do it with constant space
(define (search-table lists value)
(let loop ((lists lists) (acc null))
(cond ((null? lists) acc)
((member value (car lists))
(loop (cdr lists) (cons (car lists) acc)))
(else (loop (cdr lists) acc)))))
(search-table '((a b c d) (b c) (c d e f) (a b c)) 'a)
;; '((a b c) (a b c d))
But that result is in reverse order; according to your question anyway – we can "fix" that using a continuation as our accumulator instead of a list
(define (search-table lists value)
(let loop ((lists lists) (acc identity))
(cond ((null? lists)
(acc null))
((member value (car lists))
(loop (cdr lists) (lambda (rest)
(acc (cons (car lists) rest)))))
(else
(loop (cdr lists) acc)))))
(search-table '((a b c d) (b c) (c d e f) (a b c)) 'a)
;; '((a b c d) (a b c))
You tagged this with functional-programming tho, so let's do it using higher order functions
(define (search-table lists value)
(filter (lambda (list) (member value list))
lists))
(search-table '((a b c d) (b c) (c d e f) (a b c)) 'a)
;; '((a b c d) (a b c))

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

Is there a more efficient way to write this recursive process?

I was asked to write a procedure that computes elements of Pascal's triangle by means of a recursive process. I may create a procedure that returns a single row in the triangle or a number within a particular row.
Here is my solution:
(define (f n)
(cond ((= n 1) '(1))
(else
(define (func i n l)
(if (> i n)
l
(func (+ i 1) n (cons (+ (convert (find (- i 1) (f (- n 1))))
(convert (find i (f (- n 1)))))
l))))
(func 1 n '()))))
(define (find n l)
(define (find i n a)
(if (or (null? a) (<= n 0))
'()
(if (>= i n)
(car a)
(find (+ i 1) n (cdr a)))))
(find 1 n l))
(define (convert l)
(if (null? l)
0
(+ l 0)))
This seems to work fine but it gets really inefficient to find elements of a larger row starting with (f 8). Is there a better procedure that solves this problem by means of a recursive process?
Also, how would I write it, if I want to use an iterative process (tail-recursion)?
There are several ways to optimize the algorithm, one of the best would be to use dynamic programming to efficiently calculate each value. Here is my own solution to a similar problem, which includes references to better understand this approach - it's a tail-recursive, iterative process. The key point is that it uses mutation operations for updating a vector of precomputed values, and it's a simple matter to adapt the implementation to print a list for a given row:
(define (f n)
(let ([table (make-vector n 1)])
(let outer ([i 1])
(when (< i n)
(let inner ([j 1] [previous 1])
(when (< j i)
(let ([current (vector-ref table j)])
(vector-set! table j (+ current previous))
(inner (add1 j) current))))
(outer (add1 i))))
(vector->list table)))
Alternatively, and borrowing from #Sylwester's solution we can write a purely functional tail-recursive iterative version that uses lists for storing the precomputed values; in my tests this is slower than the previous version:
(define (f n)
(define (aux tr tc prev acc)
(cond ((> tr n) '())
((and (= tc 1) (= tr n))
prev)
((= tc tr)
(aux (add1 tr) 1 (cons 1 acc) '(1)))
(else
(aux tr
(add1 tc)
(cdr prev)
(cons (+ (car prev) (cadr prev)) acc)))))
(if (= n 1)
'(1)
(aux 2 1 '(1 1) '(1))))
Either way it works as expected for larger inputs, it'll be fast for n values in the order of a couple of thousands:
(f 10)
=> '(1 9 36 84 126 126 84 36 9 1)
There are a number of soluitons presented already, and they do point out that usign dynamic programming is a good option here. I think that this can be written a bit more simply though. Here's what I'd do as a straightforward list-based solution. It's based on the observation that if row n is (a b c d e), then row n+1 is (a (+ a b) (+ b c) (+ c d) (+ d e) e). An easy easy to compute that is to iterate over the tails of (0 a b c d e) collecting ((+ 0 a) (+ a b) ... (+ d e) e).
(define (pascal n)
(let pascal ((n n) (row '(1)))
(if (= n 0) row
(pascal (- n 1)
(maplist (lambda (tail)
(if (null? (cdr tail)) 1
(+ (car tail)
(cadr tail))))
(cons 0 row))))))
(pascal 0) ;=> (1)
(pascal 1) ;=> (1 1)
(pascal 2) ;=> (1 2 1)
(pascal 3) ;=> (1 3 3 1)
(pascal 4) ;=> (1 4 6 4 1)
This made use of an auxiliary function maplist:
(define (maplist function list)
(if (null? list) list
(cons (function list)
(maplist function (cdr list)))))
(maplist reverse '(1 2 3))
;=> ((3 2 1) (3 2) (3))

How can i remove parentheses in scheme?

i have a function in scheme, this function calls another function many times, and every time this function appends return value of another function to result value.
but finally i want to get a result such that '(a b c), however i get a result such that '((a) (b) (c)) how can i fix this problem? i have searched but i couldn't find good solution.
my little code like that not all of them.
(append res (func x))
(append res (func y))
(append res (func z))
my code like this
(define (check a )
'(1)
)
(define bos '())
(define (func a)
(let loop1([a a] [res '()])
(cond
[(eq? a '()) res]
[else (let ([ x (check (car a))])
(loop1 (cdr a) (append res (list x)))
)]
)
))
Try this:
(define (func a)
(let loop1 ([a a] [res '()])
(cond
[(eq? a '()) res]
[else
(let ([ x (check (car a))])
(loop1 (cdr a) (append res x)))])))
Notice that the only change I made (besides improving the formatting) was substituting (list x) with x. That will do the trick! Alternatively, but less portable - you can use append* instead of append:
(append* res (list x))
As a side comment, you should use (null? a) for testing if the list is empty. Now if we test the procedure using the sample code in the question, we'll get:
(func '(a b c))
=> '(1 1 1)
It seems that instead of
(loop1 (cdr a) (cdr b) c (append res (list x)))
you want
(loop1 (cdr a) (cdr b) c (append res x))
Basically the trick is to use cons instead of list. Imagine (list 1 2 3 4) which is the same as (cons 1 (cons 2 (cons 3 (cons 4 '())))). Do you see how each part is (cons this-iteration-element (recurse-further)) like this:
(define (make-list n)
(if (zero? n)
'()
(cons n (make-list (sub1 n)))))
(make-list 10) ; ==> (10 9 8 7 6 5 4 3 2 1)
Usually when you can choose direction you can always make it tail recursive with an accumulator:
(define (make-list n)
(let loop ((x 1) (acc '()))
(if (> x n)
acc
(loop (add1 x) (cons x acc))))) ; build up in reverse!
(make-list 10) ; ==> (10 9 8 7 6 5 4 3 2 1)
Now this is a generic answer. Applied to your working code:
(define (func a)
(let loop1 ([a a] [res '()])
(cond
[(eq? a '()) (reverse res)]
[else
(let ([x (check (car a))])
(loop1 (cdr a) (cons (car x) res)))])))
(func '(a b c)) ; ==> (1 1 1)
append replaces the cons so why not put the car og your result to the rest of the list. Since you want the result in order I reverse the result in the base case. (can't really tell from the result, but I guessed since you ise append)

Finding permutations with foldl/map?

The professor showed us a drawn-out method to find all permutations of a list, i.e. (a b c) => ((a b c) (a c b) (b a c) (b c a) (c b a) (c a b)), but she said it could be done much more efficiently with foldl or map.
Totally new to the functional mindset. I cannot figure this out for the life of me.
There are scheme versions (you mensioned "foldl" so there is haskell version too on this page) on http://rosettacode.org/wiki/Permutations#Scheme:
(define (insert l n e)
(if (= 0 n)
(cons e l)
(cons (car l)
(insert (cdr l) (- n 1) e))))
(define (seq start end)
(if (= start end)
(list end)
(cons start (seq (+ start 1) end))))
(define (permute l)
(if (null? l)
'(())
(apply append (map (lambda (p)
(map (lambda (n)
(insert p n (car l)))
(seq 0 (length p))))
(permute (cdr l))))))
How about this one?
#lang racket
(define l '(apple banana cheese desk))
(remove-duplicates (for/list ([i 1000000]) (shuffle l)))
Naturally, you'll want to increase the constant for long lists....
(#nothelpfulsorry)

Resources