Back again with another Racket question. New to higher order functions in general, so give me some leeway.
Currently trying to find the alternating sum using the foldr/foldl functions and not recursion.
e.g. (altsum '(1 3 5 7)) should equal 1 - 3 + 5 - 7, which totals to -4.
I've thought about a few possible ways to tackle this problem:
Get the numbers to add in one list and the numbers to subtract in another list and fold them together.
Somehow use the list length to determine whether to subtract or add.
Maybe generate some sort of '(1 -1 1 -1) mask, multiply respectively, then fold add everything.
However, I have no clue where to start with foldl/foldr when every operation is not the same for every item in the list, so I'm having trouble implementing any of my ideas. Additionally, whenever I try to add more than 2 variables in my foldl's anonymous class, I have no idea what variables afterward refer to what variables in the anonymous class either.
Any help or pointers would be greatly appreciated.
We can leverage two higher-order procedures here: foldr for processing the list and build-list for generating a list of alternating operations to perform. Notice that foldr can accept more than one input list, in this case we take a list of numbers and a list of operations and iterate over them element-wise, accumulating the result:
(define (altsum lst)
(foldr (lambda (ele op acc) (op acc ele))
0
lst
(build-list (length lst)
(lambda (i) (if (even? i) + -)))))
It works as expected:
(altsum '(1 3 5 7))
=> -4
Your idea is OK. You can use range to make a list of number 0 to length-1 and use the oddness of each to determine + or -:
(define (alt-sum lst)
(foldl (lambda (index e acc)
(define op (if (even? index) + -))
(op acc e))
0
(range (length lst))
lst))
As an alternative one can use SRFI-1 List Library that has fold that allows different length lists as well as infinite lists and together with circular-list you can have it alterate between + and - for the duration of lst.
(require srfi/1) ; For R6RS you import (srfi :1)
(define (alt-sum lst)
(fold (lambda (op n result)
(op result n))
0
(circular-list + -)
lst))
(alt-sum '(1 3 5 7))
; ==> -4
Related
I have found the following piece of code that it makes permutation in Scheme. I mean if I enter like arguments '(1 2 3) it will give me:
((1 2 3) (1 3 2) (2 1 3) (2 3 1) (3 1 2) (3 2 1))
The code is the following:
(define (remove x lst)
(cond
((null? lst) '())
((= x (car lst))(remove x (cdr lst)))
(else (cons (car lst) (remove x (cdr lst))))))
(define (permute lst)
(cond
((= (length lst) 1)(list lst))
(else (apply append(map(lambda (i) (map (lambda (j)(cons i j))
(permute (remove i lst))))lst)))))
The first function remove, it seems straightforward that only gets rid of the caracter denoted by x, even if its repeated or not, by comparing it with the beginning of the list and calling recursively with the rest of it.
The part that I quite do not get it, is the permute function. For what I know map appies a function to every element of an argument (in this case a list), and apply just applies one function one time completely to all the arguments. So what is exactly doing this line:
(apply append(map(lambda (i) (map (lambda (j)(cons i j))
(permute (remove i lst))))lst)))))
For me it seems that it just wants to create a pair with two elements: i and j, which they will become a list with the elements permuted (if we take the assumption that a list is just a bunch of concatenated pairs). But the part that calls again to permute and remove with i, what is that part doing? It is just removing the head of the list to generate subsets of the list having the head of the pair, element i, fixed until it runs out of elements?
Any help?
Thanks
Let's pick this apart, going from the inside out. Fix lst and apply the inner expression to one of its elements.
> (define lst '(1 2 3))
> (define i 1)
> (permute (remove i lst))
((2 3) (3 2))
Looks good: the inner expression removes an element and generates permutations of the remainder of the list, recursively. Now map the lambda over these permutations:
> (map (lambda (j) (cons i j)) (permute (remove i lst)))
((1 2 3) (1 3 2))
So the inner map produces all permutations that start with some i, which we've set to 1 here.
The outer map makes sure all permutations are generated by considering all elements of lst as the first element.
> (map (lambda (i) (map (lambda (j) (cons i j))
> (permute (remove i lst))))
> lst)
(((1 2 3) (1 3 2)) ((2 1 3) (2 3 1)) ((3 1 2) (3 2 1)))
But this generates lists with too much nesting. Applying append flattens a list of lists,
> (append '(1 2) '(3 4) '(5 6))
(1 2 3 4 5 6)
> (apply append '((1 2) (3 4) (5 6)))
(1 2 3 4 5 6)
so we get a flat list of permutations out.
I've always found it easier to understand the algorithm on a higher
level before diving into an implementation and trying to understand
what's happening there. So the question is: what are the permutations
of a list, and how would you find them?
The permutations of a single element list are evidently just the list
itself.
The permutations of (a b) are the set [(a b) (b a)].
The permutations of (a b c) are the set
[(a b c) (a c b) (b c a) (b a c) (c a b) (c b a)]
In general there are n! permutations of a list of length n - we have n
choices for the first element, and once we've picked that, (n-1) choices
for the second element, (n-2) for the third element, and so on. This
decrease in the degrees of freedom as we fix more and more of the first
elements of the list is very suggestive: maybe we can represent the
finding the permutations of a list of length n in terms of the
permutations of a list of length (n - 1), and so on until we reach the
permutations of a single-element list.
It turns out that the permutations of a list a precisely the set
[element prepended to the permutations of list \ element, for every
element in list].
Looking at the (a b c) case confirms that this is
true - we have a preceding (b c) and (c b), which are the
permutations of (b c), b preceding (a c) and (c a) and so on. This
operation of prepending the element to the sublist could be defined as
(define (prepend j)
(cons element j))
and the operation of doing it for all the
permutations of the sublist would then be (map prepend (permute
sublist)). Now, defining a new prepend function for each element is
maybe overkill - especially since they all have the same form. So a
better approach is just to use a lambda, which captures the value of
the element under consideration. The desired operation is
then (map (lambda (j) (cons element j)) (permute sublist)). Now, we
want to apply this operation to each element of the list, and the way to
do that is using another map, giving:
(map (lambda (element)
(lambda (j) (cons element j) (permute sublist)))
list)
Now, this looks good, but there is a problem: each stage of the recursion takes single
elements and turns them into a list. That's fine for lists of length 1,
but for longer lists it repeats for every recursive call, and we get
very deeply nested lists. What we really want to do is to put all
these lists on the same footing, which is exactly what the (apply append ...) takes care of. And that's almost all of that line. The only
thing missing is how the sublist is generated in the first place. But
that's easy as well - we'll just use remove, so that sublist = (remove element list). Putting everything together, and we have
(apply append (map (lambda (i)
(lambda (j) (cons i j))
(permute (remove i lst)))
lst))
The base case takes care of the length = 1 case, and all of the others can be found from there
Example
(trace '((1 2 3) (4 5 6) (7 8 9))) should evaluate to 15 (1+5+9).
Hint: use map to obtain the smaller matrix on which trace can be applied recursively. The Matrix should be squared.
i tried to do it but i cant seem to do it, i tried to get the diagonals first.
define (diagonals m n)
(append
(for/list ([slice (in-range 1 (- (* 2 n) 2))])
(let ((z (if (< slice n) 0 (add1 (- slice n)))))
(for/list ([j (in-range z (add1 (- slice z)))])
(vector-ref (vector-ref m (sub1 (- n j))) (- slice j))))
is there any way to solve that question in a very simple recursive way using map.
i tried to solve it like that.
define (nth n l)
(if (or (> n (length l)) (< n 0))
(if (eq? n 0) (car l)
(nth (- n 1) (cdr l)))))
(+ (nth 3 '(3 4 5)) (nth 2 '(3 4 5)) (nth 3 '(3 4 5)))
but it didnt work too.
Although I don't think answering homework questions is a good idea in general, I can't resist this because it is an example of both what is so beautiful about Lisp programs and what can be so horrible.
What is so beautiful:
the recursive algorithm is almost identical to a mathematical proof by induction and it's just so pretty and clever;
What is so horrible:
matrices are not semantically nested lists and it's just this terrible pun to pretend they are (I'm not sure if my use of first & rest makes it better or worse);
it just conses like mad for no good reason at all;
I'm pretty sure its time complexity is n^2 when it could be n.
Of course Lisp programs do not have to be horrible in this way.
To compute the trace of a matrix:
if the matrix is null, then the trace is 0;
otherwise add the top left element to the trace of the matrix you get by removing the first row and column.
Or:
(define (awful-trace m)
(if (null? m)
;; the trace of the null matrix is 0
0
;; otherwise the trace is the top left element added to ...
(+ (first (first m))
;; the trace of the matrix without its first row and column which
;; we get by mapping rest over the rest of the matrix
(awful-trace (map rest (rest m))))))
And you may be tempted to think the following function is better, but it is just as awful in all the ways described above, while being harder to read for anyone not versed in the auxiliary-tail-recursive-function-with-an-accumulator trick:
(define (awful-trace/not-actually-better m)
(define (awful-loop mm tr)
(if (null? mm)
tr
(awful-loop (map rest (rest mm))
(+ tr (first (first mm))))))
(awful-loop m 0))
Try:
(apply + (map (lambda (index row) (list-ref row index))
'(0 1 2)
'((1 2 3) (4 5 6) (7 8 9))))
Of course, turn that into a function.
To handle matrices larger than 3x3, we need more indices.
Since map stops when it traverses the shortest of the lists, the (0 1 2) list can just be padded out by hand as large as ... your best guess at the the largest matrix you think you would ever represent with nested lists in Scheme before you graduate and never see this stuff again.
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.
I am new to Racket, and I am trying to write a recursive function that takes a number n and returns the sum of the squares of the first n integers. For example, (this-function 3) returns 14 because 14 is 9 + 4 + 1 + 0.
I tried creating two separate functions, one that squares each number and returns a list of the squared numbers, and a second that sums up the list. The function the squares each number is:
(define (squared my-list)
(cond [(empty? my-list) empty]
[(zero? my-list) 0]
[else (cons (expt my-list 2)
(cons (squared (sub1 my-list)) empty))]))
which if I run (squared 3) returns (cons 9 (cons (cons 4 (cons (cons 1 (cons 0 empty)) empty)) empty)).
When I run the second function (the sum function):
(define (sum numbers)
(cond
[(empty? numbers) 0]
[else (+ (first numbers) (sum (rest numbers)))]))
and run (sum (squared 3)) I get an error message because (squared 3) returns an extra "cons" in the list.
How can I fix this?
Your logic in squared is a little bit off. I'll explain the issues clause-by-clause.
[(empty? my-list) empty]
This doesn't make any sense since my-list will never even be a list. In fact, my-list is poorly named. The parameter squared takes is a number, not a list. This clause can be completely removed.
[(zero? my-list) 0]
This is what the actual terminating case should be, but it shouldn't return 0. Remember, squared has to return a list, not a number. This case should return empty.
[else (cons (expt my-list 2)
(cons (squared (sub1 my-list)) empty))]))
Finally, this clause is far too complicated. You have the right idea—to cons the new number onto the rest of the list—but you're cons'ing too many times. Remember, the result of (squared (sub1 my-list)) is itself a list, and the second argument of cons is the rest of the list. You don't need the extra cons—you can just eliminate it completely.
Combining these changes, you get this, which does what you want:
(define (squared my-list)
(if (zero? my-list) empty
(cons (expt my-list 2)
(squared (sub1 my-list)))))
(I also replaced cond with if since cond is no longer necessary.)
That said, this code is not very Racket-y. You had a good idea to break up your function into two functions—in functional programming, functions should really only ever do one thing—but you can break this up further! Specifically, you can leverage Racket's built-in higher-order functions to make this type of thing extremely easy.
You can replace your entire squared function by appropriately combining map and range. For example, the following creates a list of the squares from 0–3.
(map (curryr expt 2) (range 4))
(You need to call (range 4) because the list generated by range goes from 0 to n-1.)
Next, you can easily sum a list using apply. To sum the above list, you'd do something like this:
(apply + (map (curryr expt 2) (range 4)))
That gives you the appropriate result of 14. Obviously, you could encapsulate this in its own function for clarity, but it's a lot clearer what the above code is doing once you learn Racket's functional constructs.
(However, I'm not sure if you're allowed to use those, since your question looks a lot like homework. Just noted for future reference and completeness.)
The most straightforward solution is to use the closed form:
(define (sum-of-squares n)
(* 1/6 n (+ n 1) (+ n n 1)))
Credit: WolframAlpha
one function for providing a list of squares and one function for summing up the list is not necessary.
This will do the trick, and is recursive as required.
(define (my-sq n)
(cond [(zero? n) 0]
[else
(+ (* n n) (my-sq (- n 1)))]))
(my-sq 3) -> 14
I want to use the Scheme language to create a special list with high efficiency. E.g.:
Function name: make-list
parameter: max
(make-list max) -> (1 2 3 4 5 6 7 ... max)
I can complete this task by using recursion method.
#lang racket
(define (make-list max)
(define lst '())
(define count 1)
(make-list-helper lst max count))
(define (make-list-helper lst max count)
(cond
[(> count max) lst]
[else
(set! lst (append lst (list count)))
(make-list-helper lst max (add1 count)]))
However, this method can be considered to be low. I have no idea how to improve its efficiency of making a list. Can anybody help me out?
The key principle is to avoid Schlemiel the Painter's algorithm, which you don't: using append repeatedly takes more and more as the list becomes longer. Prepending the element is O(1), while appending is O(length of list); so make the innermost make-list-helper return a singular list (max), and use cons to prepend elements on recursion.
(I would prefer iterative solution, but I'm a common lisper, so I'd better avoid insisting on anything for scheme).
No code included to avoid spoiling you the fun of learning.
(define (make-list max)
(let f ((i max)(a '()))
(if (zero? i)
a
(f (- i 1) (cons i a)))))
This seems to be a simple exercise for iteration.
The above is as simple as it gets, and you will use it every where in Scheme.
Make sure you understand how the entire snippet works.
Another definition of "efficiency" might be: writing the procedure with the least amount of code. With that in mind, the shortest solution for the question would be to use an existing procedure to solve the problem; for example if max = 10:
(define (make-list max-val)
(build-list max-val add1))
(make-list 10)
=> '(1 2 3 4 5 6 7 8 9 10)
The above makes use of the build-list procedure that's part of Racket:
Creates a list of n elements by applying proc to the integers from 0 to (sub1 n) in order. If lst is the resulting list, then (list-ref lst i) is the value produced by (proc i).
Yet another option, also for Racket, would be to use iterations and comprehensions:
(define (make-list max-val)
(for/list ([i (in-range 1 (add1 max-val))]) i))
(make-list 10)
=> '(1 2 3 4 5 6 7 8 9 10)
Either way, given that the procedures are part of the language's core libraries, you can be sure that their performance is quite good, no need to worry about that unless a profiler indicates that they're a bottleneck.