while loop in racket? - scheme

I am familiar with while loops in other languages but here I have written a small function that computes the derivative of a sum of terms but it only does the first 2 I was wondering if there was a way to alter this to take into account more than 2?
expressions, E, are represented as lists so 2x + 2y + x^3 is represented as (+ (* 2 x) (* 2 y) (expt x 3))
note that I already have functions written to compute the exponential but it is part of a sum and it stops after the first 2
(define (make-sum v1 v2)
(list '+ v1 v2))
(define (diff-sum x E)
(make-sum (diff x (first-operator E)) (diff x (last-operator E))))

In professional-level Racket, for loops are a standard approach to do something to a sequence. For example, the following produces a simple multiplication table:
(define numbers (list 1 2 3 4 5 6))
(for/list ([item numbers])
(list item (* item 2) (* item 3)))
It's a loop that walks through each number, processes it, and produces a new list of results. Fairly standard; almost every programming language has a notion of iteration across a collection.
In the kind of Racket that you'd have to write for an introductory computer science class, you might have to resort to explicit recursion or a higher order function like map instead, depending on your instructor. These other ways of expressing iteration have the same power as the above loop: we just phrase it a little differently.
For example, the same computation to create the small multiplication table above would be expressed as the following with explicit recursion:
(define (my-loop numbers)
(cond [(empty? numbers) '()]
[else
(define item (first numbers))
(cons (list item (* item 2) (* item 3))
(my-loop (rest numbers)))]))
(my-loop numbers)
and implicitly with the use of map:
(define (f item)
(list item (* item 2) (* item 3)))
(map f numbers)

Related

Alternating Sum Using Foldr/Foldl (Racket)

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

Define a scheme function that computes the trace of a square matrix

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.

mutable variables racket for finding range

I am trying to solve this C question to find a function that takes in 2 integer parameters, a and b and produces the range of all the elements between them, I am trying to do this in Racket.
This is what I have got so far, I don't know how to move ahead. Would I need to use mutable variables?
(define (list-range a b)
(local [(define sum a)]
(build-list (+ (- a b) 1)
lambda (x y)
[(<= sum b)(+ sum 1)]
))
Please help me understand and solve this
This builds a list from from inclusive to to exclusive.
The inclusive/exclusive thing is the convention in Racket.
It is simply the most convenient due to the fact that list
indices start from 0.
#lang racket
(define (list-range from to)
(build-list (- to from)
(lambda (i) (+ from i))))
(list-range 5 7)
Output:
'(5 6)

Racket recursive function for returning the sum of a list of squared numbers

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

make a list in scheme with high efficiency

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.

Resources