Create a new Sort in LISP - sorting

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

Related

SICP solution to Fibonacci, set `a + b = a`, why not `a + b = b`?

I am reading Tree Recursion of SICP, where fib was computed by a linear recursion.
We can also formulate an iterative process for computing the
Fibonacci numbers. The idea is to use a pair of integers a and b,
initialized to Fib(1) = 1 and Fib(0) = 0, and to repeatedly apply the
simultaneous transformations
It is not hard to show that, after applying this transformation n
times, a and b will be equal, respectively, to Fib(n + 1) and Fib(n).
Thus, we can compute Fibonacci numbers iteratively using the procedure
(rewrite by Emacs Lisp substitute for Scheme)
#+begin_src emacs-lisp :session sicp
(defun fib-iter (a b count)
(if (= count 0)
b
(fib-iter (+ a b) a (- count 1))))
(defun fib (n)
(fib-iter 1 0 n))
(fib 4)
#+end_src
"Set a + b = a and b = a", it's hard to wrap my mind around it.
The general idea to find a fib is simple:
Suppose a completed Fibonacci number table, search X in the table by jumping step by step from 0 to X.
The solution is barely intuitive.
It's reasonably to set a + b = b, a = b:
(defun fib-iter (a b count)
(if (= count 0)
a
(fib-iter b (+ a b) (- count 1))
)
)
(defun fib(n)
(fib-iter 0 1 n))
So, the authors' setting seems no more than just anti-intuitively placing b in the head with no special purpose.
However, I surely acknowledge that SICP deserves digging deeper and deeper.
What key points am I missing? Why set a + b = a rather than a + b = b?
As far as I can see your problem is that you don't like it that order of the arguments to fib-iter is not what you think it should be. The answer is that the order of arguments to functions is very often simply arbitrary and/or conventional: it's a choice made by the person writing the function. It does not matter to anyone but the person reading or writing the code: it's a stylistic choice. It doesn't particularly seem more intuitive to me to have fib defined as
(define (fib n)
(fib-iter 1 0 n))
(define (fib-iter next current n)
(if (zero? n)
current
(fib-iter (+ next current) next (- n 1))))
Rather than
(define (fib n)
(fib-iter 0 1 n))
(define (fib-iter current next n)
(if (zero? n)
current
(fib-iter (+ next current) current (- n 1))))
There are instances where this isn't true. For instance Standard Lisp (warning, PDF link) defined mapcar so that the list being mapped over was the first argument with the function being mapped the second. This means you can't extend it in the way it has been extended for more recent dialects, so that it takes any positive number of lists with the function being applied to the
corresponding elements of all the lists.
Similarly I think it would be extremely unintuitive to define the arguments of - or / the other way around.
but in many, many cases it's just a matter of making a choice and sticking to it.
The recurrence is given in an imperative form. For instance, in Common Lisp, we could use parallel assignment in the body of a loop:
(psetf a (+ a b)
b a)
To reduce confusion, we should think about this functionally and give the old and new variables different names:
a = a' + b'
b = a'
This is no longer an assignment but a pair of equalities; we are justified in using the ordinary "=" operator of mathematics instead of the assignment arrow.
The linear recursion does this implicitly, because it avoids assignment. The value of the expression (+ a b) is passed as the parameter a. But that's a fresh instance of a in new scope which uses the same name, not an assignment; the binding just induces the two to be equivalent.
We can see it also like this with the help of a "Fibonacci slide rule":
1 1 2 3 5 8 13
----------------------------- <-- sliding interface
b' a'
b a
As we calculate the sequence, there is a two-number window whose entries we are calling a and b, which slides along the sequence. You can read the equalities at any position directly off the slide rule: look, b = a' = 5 and a = b' + a' = 8.
You may be confused by a referring to the higher position in the sequence. You might be thinking of this labeling:
1 1 2 3 5 8 13
------------------------
a' b'
a b
Indeed, under this naming arrangement, now we have b = a' + b', as you expect, and a = b'.
It's just a matter of which variable is designated as the leading one farther along the sequence, and which is the trailing one.
The "a is leading" convention comes from the idea that a is before b in the alphabet, and so it receives the newer "updates" from the sequence first, which then pass off to b.
This may seem counterintuitive, but such a pattern appears elsewhere in mathematics, such as convolution of functions.

Implementing a math formula in Scheme (DrRacket)

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.

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.

relation between foldr and append in Scheme

try to figure out how to use "append" in Scheme
the concept of append that I can find like this:
----- part 1: understanding the concept of append in Scheme-----
1) append takes two or more lists and constructs a new list with all of their elements.
2) append requires that its arguments are lists, and makes a list whose elements are the elements of those lists. it concatenates the lists it is given. (It effectively conses the elements of the other lists onto the last list to create the result list.)
3) It only concatenates the top-level structure ==> [Q1] what does it mean "only concatenates the top-level"?
4) however--it doesn't "flatten" nested structures.
==> [Q2] what is "flatten" ? (I saw many places this "flatten" but I didn't figure out yet)
==> [Q3] why append does not "flatten" nested structures.
---------- Part 2: how to using append in Scheme --------------------------------
then I looked around to try to use "append" and I saw other discussion
based on the other discussion, I try this implementation
[code 1]
(define (tst-foldr-append lst)
(foldr
(lambda (element acc) (append acc (list element)))
lst
'())
)
it works, but I am struggling to understand that this part ...(append acc (list element)...
what exactly "append" is doing in code 1, to me, it just flipping.
then why it can't be used other logics e.g.
i) simply just flip or
iii).... cons (acc element).....
[Q4] why it have to be "append" in code 1??? Is that because of something to do with foldr ??
again, sorry for the long question, but I think it is all related.
Q1/2/3: What is this "flattening" thing?
Scheme/Lisp/Racket make it very very easy to use lists. Lists are easy to construct and easy to operate on. As a result, they are often nested. So, for instance
`(a b 34)
denotes a list of three elements: two symbols and a number. However,
`(a (b c) 34)
denotes a list of three elements: a symbol, a list, and a number.
The word "flatten" is used to refer to the operation that turns
`(3 ((b) c) (d (e f)))
into
`(3 b c d e f)
That is, the lists-within-lists are "flattened".
The 'append' function does not flatten lists; it just combines them. So, for instance,
(append `(3 (b c) d) `(a (9)))
would produce
`(3 (b c) d a (9))
Another way of saying it is this: if you apply 'append' to a list of length 3 and a list of length 2, the result will be of length 5.
Q4/5: Foldl really has nothing to do with append. I think I would ask a separate question about foldl if I were you.
Final advice: go check out htdp.org .
Q1: It means that sublists are not recursively appended, only the top-most elements are concatenated, for example:
(append '((1) (2)) '((3) (4)))
=> '((1) (2) (3) (4))
Q2: Related to the previous question, flattening a list gets rid of the sublists:
(flatten '((1) (2) (3) (4)))
=> '(1 2 3 4)
Q3: By design, because append only concatenates two lists, for flattening nested structures use flatten.
Q4: Please read the documentation before asking this kind of questions. append is simply a different procedure, not necessarily related to foldr, but they can be used together; it concatenates a list with an element (if the "element" is a list the result will be a proper list). cons just sticks together two things, no matter their type whereas append always returns a list (proper or improper) as output. For example, for appending one element at the end you can do this:
(append '(1 2) '(3))
=> '(1 2 3)
But these expressions will give different results (tested in Racket):
(append '(1 2) 3)
=> '(1 2 . 3)
(cons '(1 2) '(3))
=> '((1 2) 3)
(cons '(1 2) 3)
=> '((1 2) . 3)
Q5: No, cons will work fine here. You wouldn't be asking any of this if you simply tested each procedure to see how they work. Please understand what you're using by reading the documentation and writing little examples, it's the only way you'll ever learn how to program.

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