This question already has answers here:
Find main diagonal in matrix - Scheme
(3 answers)
Closed 4 years ago.
I have a list of lists(matrix) and i would like to access using (map or apply) the main diagonal.
The problem is larger, to make a matrix of a list of images removing the duplicates but i did that part.
(make-list (length (filter (lambda (x) (<= (image-height x) max-height)) L))
(filter (lambda (x) (<= (image-height x) max-height)) L)) )
I don't have a clue how to access using map or apply the elements of the main diagonal..
Remember that map requires a procedure that takes as many arguments as you have lists to map. In this case we want to access the ith element of a list, this is the built-in procedure list-ref which takes a list L and an index i and returns the ith element of L. So then we just need the indexes of the diagonal elements. This is (list 0 1 2 ...) which we can generate using build-list.
(define (diagonal M)
(define indexes (build-list (length M) values))
(map list-ref M indexes))
You don't have to build the second list if you use recursion. In this case you build the diagonal in a recursive function where we take the leading element of the first row, then recur on the rest of the elements in the rest of the rows:
(define (diagonal M)
(if (null? M)
'()
(cons (caar M)
(diagonal (map cdr (cdr M))))))
It's going to take basically the same amount of operations in terms of building the diagonal, but the second one doesn't require a new list be generated up front and doesn't require determining the size of the matrix, so it's a little better.
Related
First off, this is a homework question so just looking for guidance and not an answer.
Write a function named (cycle ALIST N) that accepts a list of elements ALIST and an integer N. This function returns a list containing N repetitions of the elements of ALIST. If N is non-positive, this function returns the empty list.
I will be honest in that I'm not sure how to begin solving this problem. I've been thinking of writing a helper function then using cons calling this n times but just looking if I'm on the correct track here.
One of the more common ways to tackle recursive problems is to begin thinking about it at the end. In other words, under what conditions should you stop? —When are you done? If you can write this base case down, then you only need to ask, what do I do when I am one step away from stopping? This is the recursive step, and for relatively simple recursive problems you are done as the whole problem is either "continue" to do the same thing or "stop."
Knowing the base case usually tells you what kind of extra information you may need to carry around, if any.
In the case of scheme and racket, which support tail call optimization, you may end up with different kinds of recursion. For example:
(define (normal-factorial n)
(if (zero? n)
1
(* n (normal-factorial (- n 1)))))
(define (tail-factorial n)
(letrec ((tf (lambda (product index)
(if (zero? index)
product
(tf (* product index) (- index 1))))))
(tf n (- n 1))))
In the first case, we build up a product without ever multiplying until the very end, while in the second we multiply as soon as possible and carry around this temporary product the whole time.
Not all problems easily lend themselves to one kind of recursion or the other.
You have different strategies you can make. The simplest is probably not the most effiecent but the one that produces less code:
(require srfi/26) ; cut
(define (cycle lst n)
(define dup-lst (map (cut make-list n <>) lst))
(foldr append '() dup-lst))
So what this does is that the map creates a list of lists where each is n elements of each. The foldr flattens it by using append.
With more hands on you can make it more efficient. I'm thinking roll your own recursion consing the elements from end to beginning in an accumulator:
(define (cycle lst n)
(let helper ((lst (reverse lst)) (c n) (acc '()))
(cond ((null? lst) acc)
((<= c 0) (helper ...))
(else (helper ...)))))
I've left out the recursive parts. What this does is a base case on the empty list, a reset recur with a c reset to n and the cdr when c is zero and the default case keeping lst while reducing c and cons-ing the first element of lst to acc. This is a O(n) solution.
I have a question regarding finding the largest list in a group of lists in scheme.
For example, we define:
(define manylsts (list (list 9 (list 8 7)) 6 (list 5 (list 4 3 2) 1)))
How would I go about finding the largest list in manylsts?
Thank you
You make a procedure that evaluates to zero if it's argument is not a list. (eg. 9), then if its a list you foldl over the elements using length of the argument as accumulator with a lambda that does max between the recursion of the first argument with the accumulator. It would look something like this:
(define (max-children tree)
(if <??>
(foldl (λ (x acc)
(max <??> (max-children <??>)))
(length <??>)
<??>)
0))
Of course there are many ways of doing this, including explicit recursion, but this was the first thing I though of.
I will answer this question as you asked it.
You said you want to
finding the largest list in manylsts
Since you included a non-listed element inside manylsts you want to have a definition that tells you how big is an element (if is a list).
So I wrote the function elemenlen that returns the length of a list if the given element is a list and 0 otherwise.
(define elemenlen
(λ (a)
(if (list? a) (length a) 0)
))
Then I decided I was going to sort them in order of length and then return the first element. So I need a function that returns a boolean value to use it with sort function included in racket/base.
(define list<
(λ (listA listB)
(< (elemenlen listA) (elemenlen listB))))
(define list>
(λ (listA listB)
(not (list< listA listB))))
The first function returns #t if listA is smaller than listB. The second function returns #t if listA is bigger than listB.
Lastly, biggestElement does the whole trick, sorts the elements in list L in descending order (based on length) and returns the first element.
(define biggestElement
(λ (L)
(car (sort L list>)
)))
The function is used like this:
>(biggestElement '((3 2 1) 1 (1 (2 3) 3))
'(1 (2 3) 3)
That is just one way of doing it, there are other ways of doing it, keep it up and tell us if it helped you.
As you see, I decomposed the big problem into little problems. This is a very handy way of doing your DrRacket homework.
Define a function that takes a non-empty list and returns an element of the list selected at random and with equal probability. (Do not use the built-in list-ref procedure.)
I'm stuck on this. I feel like you would need to count the number of times the function has run recursively and compare it to the random number you get, but I don't know how to do that in BSL+. Any help would be really great.
Here is a solution. To get the ball rolling the first element of the list is chosen as a candidate to be returned. Then for each element of the remaining elements in the list, we randomly choose if the candidate is to be replaced.
For example: For a list with two elements '(a b) first the element 'a is chosen.
The a coin is flipped: With probability 50% 'b is returned instead.
Examine the code to see how the algorithm works for larger lists:
(define (pick-random xs)
(pick-random/helper (rest xs) (first xs) 1))
(define (pick-random/helper xs chosen k)
(cond
[(empty? xs) chosen]
[else ; with probability 1/(k+1) choose the first element of xs
(if (= (random (+ k 1)) 0)
(pick-random/helper (rest xs) (first xs) (+ k 1))
(pick-random/helper (rest xs) chosen (+ k 1)))]))
If you want to google the theory, this type of algorithm belongs to "sampling algorithms".
I take the comment about not using list-ref as a direction to think about the problem recursively.
An assumption is made that 'equal probability' does not take into account the flaws of naive software-based RNGs.
Note that we use []-notation in the function definition to say that steps, unless specified, will have a (default) value of (random (length lst)). This means it will initially have a random amount of 'steps into' the list.
#lang racket
(define (random-element lst [steps (random (length lst))])
(if (= steps 0)
(first lst)
(random-element (rest lst)
(sub1 steps))))
Since steps is internally specified (as (sub1 steps), subtract one from steps) it will always have an explicit value except when the function is applied like so:
(random-element '(42 1337 128 256))
; 256
So if i have the following, which returns the smallest value out of a set of four numbers:
(define (minimum2 a b c d)
(cond ((and (< a b) (< a c) (< a d)) a)
((and (< b c) (< b d)) b)
((< c d) c)
(else d)))
But, I want to write it so that I compare a to b and find the smallest value between those two, then compare c and d, and find the smallest value between those, and then compare those two smallest values together to find the actual minimum. If what I wrote was tough to understand, think of it like a tournament bracket, where a "plays" b, and the winner plays the other winner between c and d. Thank you in advance for the help!
Here's one way to do it:
(define (min4 a b c d)
(define (min2 x y)
(if (< x y) x y))
(min2 (min2 a b) (min2 c d)))
Another way to do it, if you don't want to use an internal function:
(define (min4 a b c d)
(let ((min-ab (if (< a b) a b))
(min-cd (if (< c d) c d)))
(if (< min-ab min-cd) min-ab min-cd)))
Here are two ways to do this. I think that the first, using reduce, is much more idiomatic, but it's not doing the tournament style structure, though it uses the same number of comparisons. The second, which does a tournament style structure, is actually just a special case of a generalized merge-sort. The reason that the number of comparisons is the same is that in the tournament style comparison,
min(a,b,c,d) = min(min(a,b),min(c,d))
and in the reduce formulation,
min(a,b,c,d) = min(min(min(a,b),c),d)
Both require three calls the lowest level min procedure.
A reduce based approach
This solution uses a fold (more commonly called reduce in Lisp languages, in my experience). Scheme (R5RS) doesn't include reduce or fold, but it's easy to implement:
(define (reduce function initial-value list)
(if (null? list)
initial-value
(reduce function (function initial-value (car list))
(cdr list))))
A left-associative fold is tail recursive and efficient. Given a binary function f, an initial value i, and a list [x1,…,xn], it returns f(f(…f(f(i, x1), x2)…), xn-1), xn).
In this case, the binary function is min2. R5R5 actually already includes an n-ary (well, it actually requires at least one arguments, it's at-least-one-ary) min, which means min would already work as a binary function, but then again, if you wanted to use the built in min, you'd just do (min a b c d) in the first place. So, for the sake of completeness, here's a min2 that accepts exactly two arguments.
(define (min2 a b)
(if (< a b)
a
b))
Then our n-ary min* is simply a reduction of min2 over an initial value and a list. We can use the . notation in the argument list to make this a variadic function that requires at least one argument. This means that we can do (min* x) => x, in addition to the more typical many-argument calls.
(define (min* a . rest)
(reduce min2 a rest))
For example:
(min* 4 2 1 3)
;=> 1
A true tournament-style solution based on merge sort
A proper tournament style min is actually isomorphic to merge sort. Merge sort recursively splits a list in half (this can be done in place using the indices of the original list, as opposed to actually splitting the list into new lists), until lists of length one are produced. Then adjacent lists are merged to produce lists of length two. Then, adjacent lists of length two are merged to produce lists of length four, and so on, until there is just one sorted list. (The numbers here don't always work out perfectly if the length of the input list isn't a power of two, but the same principle applies.) If you write an implementation of merge sort that takes the merge function as a parameter, then you can have it return the one element list that contains the smaller value.
First, we need a function to split a list into left and right sides:
(define (split lst)
(let loop ((left '())
(right lst)
(len (/ (length lst) 2)))
(if (< len 1)
(list (reverse left) right)
(loop (cons (car right) left)
(cdr right)
(- len 1)))))
> (split '(1 2 3 4))
((1 2) (3 4))
> (split '(1))
(() (1))
> (split '(1 2 3))
((1) (2 3))
Merge sort is now pretty easy to implement:
(define (merge-sort list merge)
(if (or (null? list) (null? (cdr list)))
list
(let* ((sides (split list))
(left (car sides))
(right (cadr sides)))
(merge (merge-sort left merge)
(merge-sort right merge)))))
We still need the merge procedure. Rather than the standard one that takes two lists and returns a list of their sorted elements, we need one that can take two lists, where each has at most one element, and at most one of the lists may be empty. If either list is empty, the non-empty list is returned. If both lists are non-empty, then the one with the smaller element is returned. I've called it min-list.
(define (min-list l1 l2)
(cond
((null? l1) l2)
((null? l2) l1)
(else (if (< (car l1) (car l2))
l1
l2))))
In this case, you can define min* to make a call to merge-sort, where the merge procedure is min-list. Merge-sort will return a list containing one element, so we need car to take that element from the list.
(define (min* a . rest)
(car (merge-sort (cons a rest) min-list)))
(min* 7 2 3 6)
;=> 2
I am learning Scheme and I am trying to generate permutations with repetitions of certain size.
For example, given n=4 and set S = {a, b, c, d, e, f}, I'd like to generate all possible permutations: {a,a,a,a},{a,a,a,b},...,{a,a,a,f},{a,a,b,a},{a,a,b,b},...,{a,a,b,f},...{f,a,a,a},{f,a,a,b}...,{f,a,a,f},...{f,f,f,f}.
The trouble is that I can't understand how to pick 'a' 4 times, and remember that i had picked it 4 times, then pick 'a' 3 times, and 'b' one time, and remember all this, so I don't pick it again.
I know that these kinds of problems are best solved with recursive algorithms, but it just makes everything more complicated, like, how do I remember in the recursion, what elements have I picked.
I don't know how to approach this problem at all. I would be very glad if someone wrote out the thought process of solving this problem. I'd appreciate it very much!
Please help me.
Thanks, Boda Cydo.
It's good to start from the procedure's interface and expected results. Your procedure is going to be called (permutations size elements) and is expected to return a list of permutations of the items in ELEMENTS, each permutation being SIZE items long. Figure you're going to represent a "permutation" as a list. So if you called (permutations 1 '(a b c)) you'd expect an output of ((a) (b) (c)).
So the trick about recursive procedures, is you have to figure out what the base condition is that you can answer easily, and the recursive step which you can answer by modifying the solution of a simpler problem. For PERMUTATIONS, figure the recursive step is going to involve decreasing SIZE, so the base step is going to be when SIZE is 0, and the answer is a list of a zero-length permutation, i. e. (()).
To answer the recursive step, you have to figure out what to do to the result for size N - 1 to get a result for size N. To do this, it can help to write out some expected results for small N and see if you can discern a pattern:
ELEMENTS = (a b)
SIZE (PERMUTATIONS SIZE ELEMENTS)
0 ( () )
1 ( (a) (b) )
2 ( (a a) (a b) (b a) (b b) )
3 ( (a a a) (a a b) (a b a) (a b b) (b a a) ... )
So basically what you want to do is, given R = (permutations n elements), you can get (permutations (+ n 1) elements) by taking each permutation P in R, and then for each element E in ELEMENTS, adjoin E to P to create a new permutation, and collect a list of them. And we can do this with nested MAPs:
(define (permutations size elements)
(if (zero? size)
'(())
(flatmap (lambda (p) ; For each permutation we already have:
(map (lambda (e) ; For each element in the set:
(cons e p)) ; Add the element to the perm'n.
elements))
(permutations (- size 1) elements))))
I'm using FLATMAP for the outer mapping, because the inner MAP creates lists of new permutations, and we have to append those lists together to create the one big flat list of permutations that we want.
Of course, this is all assuming you know about and have a good handle on sequence operations like MAP. If you don't it'd be real difficult to come up with an elegant solution like I just did here.
Here is another version: I used reduce, not flatmap. I wrote it in MIT-scheme.
(define (per s)
(define (ins c before after)
(if (null? after)
(list (append before (list c)))
(append (list (append before (list c) after))
(ins c
(append before (list (car after)))
(cdr after)))))
(define (iter l)
(cond ((null? l)
'(()))
(else
(let ((rest (iter (cdr l))))
(reduce-left append
()
(map (lambda (x) (ins (car l) () x) )
rest))))))
(iter s))
(per '(1 3 2 4))
Hint: You can use parameters to a recursive call to "remember" what other recursive calls have done. ;)