Comparing two lists in scheme - scheme

I am trying to recursively compare and output the smallest number in 2 equal sized set of lists. Example (testFunc '(3 5 9) '(1 2 11)) will return '(1 2 9). I have tried the following:
(define (testFunc X Z)
(if (< (car X) (car Z)) ((car X) (testFunc((cdr X) (cdr Z))))
((car Z) (testFunc((cdr X) (cdr Z))))))
My thought process and what I am trying to achieve:
compare the first element of X and Z. If x(1) is smaller than z(1) then print x(1) and drop the first element from both lists using cdr and repeat the process by calling testFunc else print z(1) and do the same thing until we went through each position.
Appreciate all the help in advance. Thanks!

To call testFunc, you must use (testFunc arg1 arg2). You must not use (testFunc(arg1 arg2)). Scheme is parenthesis-sensitive; you must not add (or remove) extra parentheses.
Likewise, to bunch up the results, you need to use (cons item rest), and not just (item rest).
Have you considered using just (map min list1 list2)?

What you want is the k-minor numbers from 2 lists where k is the size of both lists. There are many ways to do this.
Here's one idea:
First append both lists.
Then sort them from lower to higher.
Then take the first three.
But that wouldn't be exactly recursive (sort is recursive but the procedure as such is not).
So another idea uses tail recursion using a list that saves the returning result and we'll name it res and a procedure that gets the minor item from a list called min-list.
Check if length of res is k. If so, return res.
Otherwise let minorA= (min-list A), minorB=(min-list B)
Finally:
if minorA < minor B
recursive call with A=(remove minorA A) B=B, res=(cons minorA res), k=k
else recursive vall with A=A B=(remove minorB B), res=(cons minorB res), k=k
And this idea is in fact recursive.
I got the code written but I want you to try and code it yourself so please tell us of any doubt.
Happy coding!
EDIT:
I've read the comments and it seems you can't use min. Does this mean you cannot use the one that comes in racket/base? If so, you can write your own procedure to check which is the minimal value but if you're not allowed even that, then we'll have to try something else. (I'll post here next idea when I get one).
Oh, and please, clarify the form of the input lists, are they ordered from minor to greater? In your example it seems that way but if it's not always like that then the procedure can change a bit.

Related

How to write functions of functions in Scheme

I am supposed to write a function called (nth-filtered f n), where f is a function of one variable and n is a natural number, which evaluates to the nth natural number such that f applied to that number is #t.
If we called
(nth-filtered even? 1) we would get 2
(nth-filtered prime? 10) we would get 29
How do I make it so that it works for any sequential function? What should I think about when approaching this type of problem?
A variable is a variable and + is also a variable. The main difference between a function and some other data type is that you can wrap a function name in parentheses with arguments and it will become a new value.
eg.
(define (double fun)
(lambda (value)
(fun (fun value))))
(define (add1 v)
(+ 1 v))
(define add2 (double add1))
(add2 1) ; ==> 3
Now the contract doesn't say so you deduct by looking that you do (fun ...) that fun needs to be a function. Imagine this:
(define test (double 5)) ; probably works OK
(test 1)
The last one fails since you get application: 5 is not a procedure or something similar. The error message is not standardized.
How to attack your task is by making a helper that has the same arguments as your function but in addition the current number that I guess starts at 1. As I demonstrated you use the function variable as a function and recurse by always increasing the number and reducing n when the f call was #t. The actual function will just use the helper by passing all the parameters in addition to your state variable.
Your problem requires a fold, which is the standard way to iterate other a list while keeping a record of things done so far.
Here a very rackety method using for/fold:
(define (nth-filtered predicate index)
(for/fold ([count 0]
[current #f] #:result current)
([n (in-naturals 1)]) ; we start at 1 but we could start at 0
#:break (= count index)
(values (if (predicate n) (add1 count) count)
n)))
for/fold takes a list of initial state. Here we define count as the number of times the given predicate returned #t and current as the currently tested value.
Then it takes a list of iterators, in this case we only iterate infinitely over (in-naturals).
To make it stop, we provide a #:break condition, which is "when the number of truthy predicates (count) is equal to the requested amount (index)".
for/fold requests that it's body finishes with a list of values for each "state" variable, in order to update them for the next iteration. Here we provide two values: one is the new count, the other is just the current n.
You can try it out, it works as you requested:
> (nth-filtered even? 1)
2
> (require math/number-theory)
> (nth-filtered prime? 10)
29
> (nth-filtered prime? 5)
11

Scheme procedure with 2 arguments

Learned to code C, long ago; wanted to try something new and different with Scheme. I am trying to make a procedure that accepts two arguments and returns the greater of the two, e.g.
(define (larger x y)
(if (> x y)
x
(y)))
(larger 1 2)
or,
(define larger
(lambda (x y)
(if (> x y)
x (y))))
(larger 1 2)
I believe both of these are equivalent i.e. if x > y, return x; else, return y.
When I try either of these, I get errors e.g. 2 is not a function or error: cannot call: 2
I've spent a few hours reading over SICP and TSPL, but nothing is jumping out (perhaps I need to use a "list" and reference the two elements via car and cdr?)
Any help appreciated. If I am mis-posting, missed a previous answer to the same question, or am otherwise inappropriate, my apologies.
The reason is that, differently from C and many other languages, in Scheme and all Lisp languages parentheses are an important part of the syntax.
For instance they are used for function call: (f a b c) means apply (call) function f to arguments a, b, and c, while (f) means apply (call) function f (without arguments).
So in your code (y) means apply the number 2 (the current value of y), but 2 is not a function, but a number (as in the error message).
Simply change the code to:
(define (larger x y)
(if (> x y)
x
y))
(larger 1 2)

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.

Using conditionals in Scheme

I have to create the following:
A Scheme procedure named 'proc2' which takes 4 numbers as arguments
and returns the value of the largest argument minus the smallest.
So I want to write
(define proc2
lambda(a b c d)
...
)
Is there any way I can evaluate (> a b), (> a c), (> a d) at the same time? I want to get the largest (and the smallest)number without having to write nested ifs.
Can you use the max and min procedures? if the answer is yes, it's pretty simple:
(- (max a b c d) (min a b c d))
If not, remember that <, >, <=, >= accept a variable number of arguments, so this is valid code and will tell you if a is smaller than b and b is smaller than c and c is smaller than d (although you'll have to test more combinations of b, c, d to make sure that a is the smallest value).
(< a b c d)
Also remember to consider the cases when two or more numbers are equal (that's why it's a good idea to use <= instead of <).
Anyway, you'll have to use conditionals. Maybe nested ifs, or perhaps a cond to make things simpler - you can work out the details yourself, I'm guessing this is homework.
If you want to find the smallest and largest members of the list and you are not allowed to use the standard min and max library functions, then I can think of three approaches
Write your own min and max functions (hint: recursion). Apply both to the list to find your two values. Perform the subtraction.
Write a combined function (again, recursive) which will pass through the list once, returning another two-member list which contains the max and min. If the first element in the returned list is the max, then (apply - (find-min-and-max 3 2 8 7)), where find-min-and-max is your function, would return the result of the subtraction.
Use map.
Option 1 is less efficient than option 2 but much simpler to write. Option 3 is more complex than either but actually does what you asked (that is, compare a to b, c and d "at the same time").
For example, if I defined the following function:
(define (compare test x l)
(map (lambda (y) (test x y)) l))
then
(compare < 3 '(1 2 4))
would return (#f #f #t)
How is this useful to you? Well, if (compare < x l) returns all true, then x is smaller than all elements of l. If it returns all false, then x is bigger than all elements of l. So you could use map to build the code you want, but I think it would be ugly and not the most efficient way to do it. It does do what you specifically asked for, though (multiple simultaneous comparisons of list elements).

How to convert this code to Scheme

So basically this code's purpose is to simply print out the first n even numbers.
for (i = 0; i <=n; i+= 2)
{
print i;
}
Thing is though, I don't understand Scheme at all. So, help please.
There are several ways to convert the code in the question to Scheme. The first one I can think of:
(define (print-even n)
(let loop ((i 0))
(if (<= i n)
(begin
(print i)
(newline)
(loop (+ i 2))))))
Notice this:
The solution is written as a recursive procedure
Instead of a for loop, I'm using a construct called a named let, which permits the initialization of some iteration variables (i in this case, initialized to 0) and the repeated execution of a recursive procedure (loop in this case), producing an effect similar to a for, even in performance
The stop condition in the "loop" is handled with essentially the same expression: repeat the body of the iteration as long as (<= i n), when that condition becomes false, the iteration ends
The begin surrounds the body of the "loop", just as the curly braces {} do in the original code
The print procedure performs the expected operation; for readability I added a new line after printing each number
The increment part of the original loop i += 2 is handled by the expression (+ i 2), inside the recursive call
So you see, the process being executed is essentially the same, only the way to write it (the syntax!) is different. Give it a try, type this:
(print-even 6)
... And the following will get printed on the screen:
0
2
4
6
Another possible way to implement the procedure, more similar to the original code, although (this is completely subjective) less idiomatic than the previous one:
(define (print-even n)
(do ((i 0 (+ i 2))) ((> i n))
(print i)
(newline)))
Finally, if you're using Racket this will seem even more familiar to you:
#lang racket
(define (print-even n)
(for ((i (in-range 0 (+ n 1) 2)))
(print i)
(newline)))
The first big difference between Scheme and other languages is this: In Scheme, you do (almost) everything recursively.
To implement a simple loop, for instance, you would define a recursive function. This function would first check to see whether it's time to break out of the loop; if is is, it would return the final value. (There is no final value in this case, so it would just return something like (void) or '().) Otherwise, the function would do whatever it's supposed to do, then call itself again.
Any loop variables (such as i) become arguments to the function.
Hopefully this helps you understand how to do this.
The Scheme way to do something like this is using a recursive function like the one below.
(define (doit value n)
(if (<= value n)
(begin
;;...perform loop body with x...
(display value)(newline)
(doit (+ value 2) n))))
To call this function you call (doit 2 n) where n is your n in the for loop.
With regards to learning Scheme, I recommend the first two links below.
For additional information on Scheme see
SICP
How to Design Programs
Schemers
Related Stackoverflow Question
Scheme Cookbook Looping Constructs

Resources