Implementing a math formula in Scheme (DrRacket) - scheme

Let me start off by saying that I am a complete novice when it comes to Scheme/Racket. I am trying to implement the following formula:
αi = (3/h)((ai+1 – ai) – (ai – ai-1))
Here is how I've defined my function:
(define alpha_values (lambda (y_values h n) (...))
What I would like it to do is to run the function with a list of y_values along with some constant h and a number n, then compute and return a list of α values. n will go from 1 to n-1, so the first and last element of the list are not going to be iterated upon.
For example, if the list of y_values is '(2 4 6 8) and h is 1 and n is 3 then there should be two α values returned: one for i=1 (y=4), and one for i=2 (y=6), like so: 3*((6-4)-(4-2)) = 0 and 3*((8-6)-(6-4)) = 0 returns '(0 0) for α.
Truthfully, I'm lost as to how to even begin to implement this. I thought about using map but I don't know if it's possible to skip the first and last element while doing so. I've tried doing so recursively using car and cdr but I ran into the issue of "losing" an element in the list needed for the calculation when recursively calling the function again without the first element. I would appreciate some insight as to how to approach the implementation of this formula – not an answer, just an idea as to how to get the ball rolling.

Whenever you are unsure about how to approach a particular problem, consider breaking it down to smaller tasks that are easier to manage, think about, and implement.
For example, going backwards from the end result, you want to produce a list of alphas, whereby each alpha is created from h and an interval {a_i-1, a_i, a_i+1} using the noted formula.
So one small function you can create would be the function, lets call it compute-alpha, that takes an interval and h as arguments, then produces an alpha using the formula. Ie:
(define (compute-alpha interval h)
...)
The body of this function will simply be the formula, and it will behave as follows:
> (compute-alpha '(2 4 6) 1)
0
> (compute-alpha '(4 6 8) 1)
0
But then you realize that you don't have the intervals (eg. '(2 4 6), '(4 6 8) etc) in order to use compute-alpha. So next step is to define another small function, lets call it build-intervals, that takes y-values and n as arguments, and produces a list of intervals. Ie:
(define (build-intervals y-values n)
...)
and behaves as follows:
> (build-intervals '(2 4 6 8) 3)
'((2 4 6) (4 6 8))
> (build-intervals '(1 2 3 4 5 6 7) 4)
'((1 2 3) (2 3 4) (3 4 5))
Now, all that is left is applying compute-alpha on every interval produced by build-intervals. And this is where map shines:
(define (alpha-values y-values h n)
(map (lambda (interval)
(compute-alpha interval h))
(build-intervals y-values n)))
Then you can have:
> (alpha-values '(2 4 6 8) 1 3)
'(0 0)
Once you implement build-intervals and compute-alpha, you might notice ways of combining them to reduce alpha-values to a single function that iterates y-values only once before producing the list of alphas.

Related

Using argmax to find largest number in a list of elements

Ok so I define 3 lists:
(define mylist '((pause 5 5 5)(note 3 4 5)(pause 3 4 4)))
(define myseqlist '(sequential-music-element (note 5 5 5) (note 4 3 4) (note 5 3 4)))
(define myparlist '(parallel-music-element (note 5 2 5) (note 4 2 4) (note 5 3 1)))
I have the predicates note? and pause? , essentially it checks if a list starts with 'note or 'pause then returns true or false.
However I can have list containing notes and pauses, which is callled a sequential-music-element (see myseqlist above) or parallel-music-element (see myparlist above)
How can I define a function that returns the degree of polyphony, that takes one of the 4 elements as a parameter? (see below for my attempt)
pause degree of polyphony = 0
note degree of polyphony = 1
sequence-music-element? return the degree of the child with the largest degree
parallel-music-element? return the sum of the degrees of the children
How do I complete this function:
(define (degree-of-polyphony elem)
(cond [(note? elem) 1]
[(pause? elem) 0]
[(sequential-music-element? elem) (argmax ??? )]))
I am not sure how to make use of argmax in this case. It should check for the highest polyphony for the entire list of elements that degree-of-polyphony takes as a parameter.
Example: (degree-of-polyphony myseqlist) should return 1 since it has at least one note, if its all pauses, it should return 0.
If you just have to check if there's at least one note in the list, I'd go with this:
(define (note? ele)
(and (pair? ele)
(eq? (car ele) 'note)))
(define (degree-of-polyphony elem)
(cond [(note? elem) 1]
[(pause? elem) 0]
[(sequential-music-element? elem)
(if (ormap note? elem) 1 0)]))
ormap checks if there's at least one element that meets the given condition, argmax would be useful if we needed to find a maximum value.

Racket variable memory

Given this code:
(define (wrapper n)
(define (sum-ints)
(set! n (+ n 1))
(display n)(newline)
(if (= n 3)
n
(+ n (sum-ints))))
(sum-ints))
Calling this procedure with n = 0
(wrapper 0) =>
1
2
3
6
I had expected the process to increment n to a value of 3, and then as it returns, add 3 to 3 to 3 for an output of 3 3 3 9.
Does the inner procedure store a shadow copy of n?
Oog, mutation is nasty. The issue here is that "plus" is evaluated left-to-right. Specifically, let's consider the case when n=2. The expression (+ n (sum-ints)) is evaluated left-to-right. First, the identifier + evaluates to the plus function. Then, n evaluates to 2. Then, the recursive call is made, and the result is 3. Then, we add them together and the result is 5.
You'll see the same result in Java, or any other language that defines left-to-right evaluation of subexpressions.
Solution to this particular problem, IMHO: don't use mutation. It's needed in only
about 10% of the cases that people want to use it.

Create a new Sort in LISP

I want to define a new sorting method in LISP that sticks to this formula.
2 > 3 > 4 > 5 > 6 > 7 > 8 > 9 > 10 > J > Q > K > A
As seen in Poker.
So for example I called it on this:
(mysortmethod '((3 H)(2 H)(J D)(8 C)(5 C)))
I would get this:
((2 H)(3 H)(5 C)(8 C)(J D))
as the sorted list where the 2nd element in each bracket is ignored.
I have absolutely no idea how to do this. Could someone point me in the right direction or perhaps explain to me a method?
This is a pretty standard type of Lisp exercise. First you need a convenient way to figure out the ordering. One easy way to is to keep a sequence of the pips (if you have lots, maybe a hash table mapping pips to positions would be better) and a function that compares their positions:
(defconstant +pips+ #(2 3 4 5 6 7 8 9 10 J Q K A))
(defun pip< (pip1 pip2)
(< (position pip1 +pips+)
(position pip2 +pips+)))
Then you can use the standard sort function (remember, it's destructive, so save the result, and don't call it with quoted data, since you shouldn't modify literal data), passing pip< as the predicate and first as the key, because you use first to get the pip from each card (since you're representing cards as lists of a pip and a suit):
CL-USER> (let ((hand (copy-tree '((3 H)(2 H)(J D)(8 C)(5 C)))))
(sort hand 'pip< :key 'first))
;=> ((2 H) (3 H) (5 C) (8 C) (J D))

Iterative tree calculation in scheme

I'm trying to implement a function defined as such:
f(n) = n if n < 4
f(n) = f(n - 1) + 2f(n - 2) + 3f(n - 3) + 4f(n - 4) if n >= 4
The iterative way to do this would be to start at the bottom until I hit n, so if n = 6:
f(4) = (3) + 2(2) + 3(1) + 4(0) | 10
f(5) = f(4) + 2(3) + 3(2) + 4(1) | 10 + 16 = 26
f(6) = f(5) + 2f(4) + 3(3) + 4(2) | 26 + 2(10) + 17 = 63
Implementation attempt:
; m1...m4 | The results of the previous calculations (eg. f(n-1), f(n-2), etc.)
; result | The result thus far
; counter | The current iteration of the loop--starts at 4 and ends at n
(define (fourf-iter n)
(cond [(< n 4) n]
[else
(define (helper m1 m2 m3 m4 result counter)
(cond [(= counter n) result]
[(helper result m1 m2 m3 (+ result m1 (* 2 m2) (* 3 m3) (* 4 m4)) (+ counter 1))]))
(helper 3 2 1 0 10 4)]))
Several problems:
The returned result is one iteration less than what it's supposed to be, because the actual calculations don't take place until the recursive call
Instead of using the defined algorithm to calculate f(4), I'm just putting it right in there that f(4) = 10
Ideally I want to start result at 0 and counter at 3 so that the calculations are applied to m1 through m4 (and so that f(4) will actually be calculated out instead of being preset), but then 0 gets used for m1 in the next iteration when it should be the result of f(4) instead (10)
tl;dr either the result calculation is delayed, or the result itself is delayed. How can I write this properly?
I think the appropriately "Scheme-ish" way to write a function that's defined recursively like that is to use memoization. If a function f is memoized, then when you call f(4) first it looks up 4 in a key-value table and if it finds it, returns the stored value. Otherwise, it simply calculates normally and then stores whatever it calculates in the table. Therefore, f will never evaluate the same computation twice. This is similar to the pattern of making an array of size n and filling in values starting from 0, building up a solution for n. That method is called dynamic programming, and memoization and dynamic programming are really different ways of looking at the same optimization strategy - avoiding computing the same thing twice. Here's a simple Racket function memo that takes a function and returns a memoized version of it:
(define (memo f)
(let ([table (make-hash)])
(lambda args
(hash-ref! table
args
(thunk (apply f args))))))
Now, we can write your function f recursively without having to worry about the performance problems of ever calculating the same result twice, thus going from an exponential time algorithm down to a linear one while keeping the implementation straightforward:
(define f
(memo
(lambda (n)
(if (< n 4)
n
(+ (f (- n 1))
(* 2 (f (- n 2)))
(* 3 (f (- n 3)))
(* 4 (f (- n 4))))))))
Note that as long as the function f exists, it will keep in memory a table containing the result of every time it's ever been called.
If you want a properly tail-recursive solution, your best approach is probably to use the named let construct. If you do (let name ([id val] ...) body ...) then calling (name val ...) anywhere in body ... will jump back to the beginning of the let with the new values val ... for the bindings. An example:
(define (display-n string n)
(let loop ([i 0])
(when (< i n)
(display string)
(loop (add1 i)))))
Using this makes a tail-recursive solution for your problem much less wordy than defining a helper function and calling it:
(define (f n)
(if (< n 4)
n
(let loop ([a 3] [b 2] [c 1] [d 0] [i 4])
(if (<= i n)
(loop (fn+1 a b c d) a b c (add1 i))
a))))
(define (fn+1 a b c d)
(+ a (* 2 b) (* 3 c) (* 4 d)))
This version of the function keeps track of four values for f, then uses them to compute the next value and ditches the oldest value. This builds up a solution while only keeping four values in memory, and it doesn't keep a huge table stored between calls. The fn+1 helper function is for combining the four previous results of the function into the next result, it's just there for readability. This might be a function to use if you want to optimize for memory usage. Using the memoized version has two advantages however:
The memoized version is much easier to understand, the recursive logic is preserved.
The memoized version stores results between calls, so if you call f(10) and then f(4), the second call will only be a table lookup in constant time because calling f(10) stored all the results for calling f with n from 0 to 10.

Scheme - find most deeply nested lists

I need to find the leaves in a list in Scheme.
For example, if I have (1 (2 3) (4 (5) (7 (8) (10 11 12)))))), my leaves are (8) and (10 11 12). So my function will return (1 (2 3) (4 (5) (7 leaf1 leaf2))))).
Definition: a leaf is an element with the deepest nesting possible.
Examples: In (1 (2 (3))) the element (3) is a leaf.
In ((1 2) (3 4)) the elements (1 2) and (3 4) are leaves.
I tried to use the map function, that will check if the list is composed from lists. If it is - so I call the function again, and if not, I break and change the lists to symbols of leafs. It doesn't work.
I have been stuck on it for 2 days. I am trying to find an idea, not an implementation. Thanks.
This is a little tricky to get right. Here are a few suggestions on one way to do it:
As stated, the problem is to walk the list, finding the most deeply nested lists that don't contain any other lists (these are sometimes called "lists of atoms"), and replacing them with something else. It's possible to do this in one recursive function, but I think it's clearer to break it up into parts:
First, we need a predicate (a function that returns a boolean #t or #f) to determine whether a list is a list of atoms. (This is sometimes called lat?). You can write this as a simple recursive function, or you could use the library functions any and list?
Then we need a function (define (max-lat-depth lst) ...) to find how deeply nested the most-deeply-nested list of atoms in its argument is. This will be a doubly recursive function -- it needs to check the first of each list as well as all the elements in the rest. We can define max-lat-depth as follows:
a. If the argument is a lat itself, the maximum depth is zero, so (max-lat-depth '(1 2 3)) == 0
b. If the first element of the argument isn't a list, it can't affect the maximum nesting depth overall. So in this case the max-lat-depth of the whole argument will be the same as the max-lat-depth of the rest (cdr) of the list: (max-lat-depth '(1 (2 (3 4))) == (max-lat-depth '((2 (3 4))) == 2
c. The tricky case: if the first element of the argument is a list (as in ((1 2) (3 4))), we'll need to recur on both the first (or car) and rest (or cdr) of lst, returning the maximum of these values. However, we need to add 1 to one of these two results before taking the maximum. I'll let you figure out which one and why.
Finally, we write a function (define (replace-lats-at-depth depth lst r) ...) that will take a nesting depth as returned from max-lat-depth, a list lst, and a replacement r. It will return a copy of lst where all the lists-of-atoms at depth depth have been replaced by r. For example:
(replace-lats-at-depth 0 '(1 2 3) '*) == '*
(replace-lats-at-depth 1 '(1 (2) 3) '*) == '(1 * 3).
Like max-lat-depth, replace-lats-at-depth recurs on both the first and rest of lst. It will call cons on the result of its recursive calls to construct a new tree structure. Also like max-lat-depth, it has several cases, and it will need to subtract 1 from depth in one of its recursive calls.
Once you have replace-lats-at-depth working to replace the nested lists with a constant value r, it shouldn't be too hard to improve it with a function that produces leaf1, leaf2, etc. as in your original example.
I hope that's helpful without saying too much. Let me know if not and I can try to clarify.

Resources