How do I create a version of filter using map (racket ISL) - racket

I am Tasked (in exercise 8) with creating a function in Intermediate Student Language (Racket) that receives a list of numbers and a list of lists of numbers; each list is the same length. Name the first list breakpoints and the second LoR (list of rows). This function should be defined using map and should filter each row in LoR so that only numbers larger than that the n'th row in LoR only contains values larger than the n'th value in breakpoints-- here is an example for clarity:
(define breakpoints (list 7 2 15))
(define LoR (list (list 3 25 13)
(list 1 2 11)
(list 22 4 8)))
would output...
(list (list 25 13) (list 11) (list 22))
Doing this without using map would be fine and I understand the problem in that sense, but I am having trouble figuring out how to use map. I was thinking recursively in the sense that if the list of rows is not empty, I would cons the (filtered first row) to the (recursive call of the function using the rest of breakpoints and LoR) as so:
(define (parallel-filter breakpoints LoR)
(cond((empty? breakpoints) empty)
(else (cons ...
(parallel-filter (rest breakpoints) (rest LoR))))))
However, I'm not sure how to replace the ellipse with a map statement that would make the function work correctly-- as I understand, map's first parameter must be a one-parameter function and I'm not sure how to use map for this purpose. How do I proceed?
edited to correct output

We can solve this problem by combining map and filter, but first bear in mind this:
You can't use just map, because it will always return a list of the same length as the original. For excluding some elements we must use filter (or alternatively: use foldr to implement our own version of filter)
map can receive more than one list as parameter, as long as its function receives enough parameters - one from each list
Your sample output is wrong for the first sublist
With all of the above in mind, here's one possible solution:
(define (parallel-filter breakpoints LoR)
(map (lambda (brk lst) ; `brk` is from `breakpoints` and `lst` is from `LoR`
(filter (lambda (ele) (> ele brk)) ; filter each sublist from `LoR`
lst))
breakpoints
LoR))
It works as expected:
(parallel-filter breakpoints LoR)
=> (list (list 25 13) (list 11) (list 22))

Related

How to order a list in sublists in Lisp?

I have a list like this:
(4 5 6 3 12 22 4 4 55 43 1 4 0)
and want an output like this:
((4 5 6) (3) (12 22) (4) (4 55) (43) (1 4) (0))
I think you can guess the order, it has an ascending order, I'm totally new with Lisp and need some help
Here is one possible solution in TXR Lisp:
(defun ascending-partitions (list)
(let ((indices (mappend (do if (>= #1 #2) (list #3))
list (cdr list) (range 1))))
(split list indices)))
We obtain the numeric index positions of the elements in the list which are not greater than their predecessors; then we use the split function to cut the list into pieces at these indices.
Calculating the indices is done by processing three lists through the mappend function: the original list, in parallel with that same list with the first element removed (cdr list), and an infinite list of incrementing integers starting at 1 produced by (range 1).
The do macro writes an anonymous function for us, in which the #1, #2 and #3 variables embedded in the expression are its three arguments, in that order. mappend call this function with successive triplets of values taken from the lists in parallel. Thus #1 takes values from list, #2 takes successive values from (cdr list) and #3 takes successive values from the list of integers. Whenever #1 is at least as large as its successor #2, we collect the positional index #3 into a one-element list. mappend catenates these together.
In contrast to this, we could write a more direct solution that requires more code, but makes better use of machine resources:
(defun ascending-partitions (list)
(let (partition output prev)
(each ((item list)) ;; use (dolist (item list) in Common Lisp
(when (and prev (<= item prev))
(when partition
(push (nreverse partition) output)
(set partition nil))) ;; use setf or setq in Common Lisp
(push item partition)
(set prev item)) ;; ditto
(when partition
(push (nreverse partition) output))
(nreverse output)))

Using Lisp: define a function that takes a list and a number and returns true if the number occurs in the list

I am new to lisp and I have a problem, I'm trying to find the number in the list but it is not working. I haven't made the return statement yet
(defun num (x 'y)
(if (member x '(y)) 't nil))
(write (num 10 '(5 10 15 20)))
My output just outputs the nil instead of doing the function and I'm confused of what I am doing wrong.
Solution
(defun member-p (element list)
"Return T if the object is present in the list"
(not (null (member element list))))
The not/null pattern is equivalent to (if (member element list) t nil) but is more common.
In fact, you do not really need this separate function,
member is good enough.
The -p suffix stands for predicate, cf. integerp and upper-case-p.
Your code
You cannot quote lambda list elements, so you need to replace defun num (x 'y) with defun num (x y)
You need not quote t
Quoting '(y) makes no sense, replace it with y.
You do not need to write the function call, the REPL will do it for you.
See also
When to use ' (or quote) in Lisp?
Can you program without REPL on Lisp?
You are almost certainly expected to not just use member, but to write a function which does what you need (obviously in real life you would just use member because that's what it's for).
So. To know if an object is in a list:
if the list is empty it's not;
if the head of the list is equal to the object it is;
otherwise it is in the list if it's in the tail of the list.
And you turn this into a function very straightforwardly:
(defun num-in-list-p (n l)
;; is N in L: N is assumed to be a number, L a list of numbers
(cond ((null l)
nil)
((= n (first l))
t)
(t
(num-in-list-p n (rest l)))))
You could use the built in position function which will return the index of the number if it is in the list:
(position 1 '(5 4 3 2 1))
If you want to define your own function:
CL-USER> (defun our-member(obj lst)
(if(zerop (length lst))
nil
(if(equal(car lst)obj)
T
(our-member obj (cdr lst)))))
OUR-MEMBER
CL-USER> (our-member 1 '(5 4 3 2 1))
T
CL-USER> (our-member 99 '(1 2 3 4 5))
NIL
We can create a function called "our-member" that will take an object (in your case a number) and a list (in your case a list of numbers) as an argument. In this situation our "base-case" will be whether or not the length of the list is equal to zero. If it is and we still haven't found a match, we will return nil. Otherwise, we will check to see if the car of the list (the first element in the list) is equal to the obj that we passed. If so, we will return T (true). However, if it is not, we will call the function again passing the object and the cdr of the list (everything after the car of the list) to the function again, until there are no items left within the list. As you can see, The first example of a call to this function returns T, and the second example call returns NIL.
What makes this utility function a good example is that it essentially shows you the under workings of the member function as well and what is going on inside.

DrRacket - Find Largest Number in a set

(for judges ([judge1 judge2 judge3 judge4 judge5 judge6 judge7 judge8])
(define i 0)
(define j 1)
(cond [(< judges[i] judges[j])
(cond [(equal? judges[j] judges(length))
(define highest-score judges[j])]
[else
(judges[i] judges[j])
(judges[j] judges[j +1])])]
[else
(cond [(equal? judges[i] judges[length -1])
(define highest-score judges[i])]
[else
(judges[j] judges[j +1])])]))
I want to be able to find the largest number in a set of values, which for this problem includes values from judge1, judge2... judge8. The way I'm trying to solve this problem is by taking the first two numbers on a list and comparing them; I can't seem to find much on DrRacket documentation on proper syntax for the type of operation I want to perform.
An easy way (in terms of writing code) to find the the maximum element is to sort the list, and grab the last element of that list. As #pdoherty926 mentioned, the easiest way to sort a list in Racket is with the sort function. You just give it a list and a comparitor, and it sorts the list for you:
> (sort '(5 2 6 1) <)
'(1 2 5 6)
And since you want the max value just grab the last element:
> (last (sort '(5 2 6 1) <))
6
Although if you want to find the maximum value of other (non-list) data structures, for is an attractive option. While your algorithm looks good, your syntax is off. In this particular case, I would actually recommend using for/fold. Basically, it lets you have an accumulator, which will hold your highest judge so far, as well as the list of judges you are iterating through, and the body for how you want to modify the accumulator. In this case, your loop will look something like:
;; A judge is a non-negative number
(define judges '(5 6 1 2))
(for/fold ([largest -1])
([j (in-list judges)])
...)
Where you replace the ... with the next value for largest. The entire loop evaluates to the final value for largest.
The interesting thing here is that j is an actual judge, not just an index to the judges list. So your body does not need to refer to the judges list at all. It should look something like:
(max j largest)
Since a judge is just a number. I will leave you to put the body in the loop as an exercise.
As an aside, since judges are just numbers, you can just use max directly with apply:
> (apply max '(5 6 1 2))
6
As one additional note, if for some reason you do want the actual index of the current judge you are examining, you can use in-naturals:
(for/fold ([largest -1])
([j (in-list judges)]
[index (in-naturals)])
...)
Following recursive function also works to find largest number in a list:
(define (largestnum slist)
(cond
((= (length slist) 2) ; if only 2 numbers, compare them
(if (> (car slist) (list-ref slist 1))
(car slist)
(list-ref slist 1)))
(else ; else recurse to compare car with largest of cdr
(let ((cdrLargest (largestnum (cdr slist))))
(if (> (car slist) cdrLargest)
(car slist)
cdrLargest)))))
(define judges '(5 6 1 2))
(largestnum judges)
Output:
6

Number Partitioning in R5RS

I was asked in an internship interview to do a R5RS program that creates a function, let's say two-subsets. This function has to return #t if the list L contains two subsets with equal sums of elements and with equal numbers of elements, otherwise it returns #f. It takes in entry the list L (only positive numbers) and some parameters (that I judge useful. There is no conditions on the number of parameters) all equal to 0 at the beginning.
The requirements as I still remember were as follow:
- Do not define other functions and call them inside the "two-subsets" function.
- It can only use the following constructs: null?, cond, car, cdr, else, + ,=, not, and, #t, #f, two-subsets (itself for recursive call), the names of the parameters, such as list, sum, ...etc, numeric constants and parentheses.
There were some given examples on the results that we are supposed to have, let's say:
(two-subsets '(7 7) 0 0 0) returns #t. The two subsets are {7} and {7}.
(two-subsets '(7 7 1) 0 0) returns #t. The two subsets are {7} and {7}.
(two-subsets '(5 3 2 4) 0 0) returns #t. The two subsets are {2, 5} and {3, 4}.
(two-subsets '(1 2 3 6 9) 0 0) returns #f.
I started by writing the signature that it looks to me it should be something like this:
(define two-subsets (lambda (L m n ... other parameters)
(cond
The problem is really complicated and it's complexity is obviously more than O(n), I read on it on https://en.wikipedia.org/wiki/Partition_problem .
I tried to start by defining the algorithm first before coding it. I thought about taking as parameters: sum of the list L so in my conditions I'll iterate only on the combinations which sum is <= sum(L)/2. By doing that I can reduce a little bit the complexity of the problem, but still I couldn't figure out how to do it.
It looks like an interesting problem and I really want to know more about it.
Here is a version which does not depend on the numbers being all positive. I am reasonably sure that, by knowing they are, you can do much better than this.
Note this assumes that:
the partition does not need to be exhaustive;
but the sets must not be empty.
I'd be very interested to see a version which relies on the elements of the list being +ve!
(define (two-subsets? l sl sld ssd)
;; l is the list we want to partition
;; sl is how many elements we have eaten from it so far
;; sld is the length difference in the partitions
;; ssd is the sum difference in the partitions
(cond [(and (not (= sl 0))
(= sld 0)
(= ssd 0))
;; we have eaten some elements, the differences are zero
;; we are done.
#t]
[(null? l)
;; out of l, failed
#f]
;; this is where I am sure we could be clever about the set containing
;; only positive numbers, but I am too lazy to think
[(two-subsets? (cdr l)
(+ sl 1)
(+ sld 1)
(+ ssd (car l)))
;; the left-hand set worked
#t]
[(two-subsets? (cdr l)
(+ sl 1)
(- sld 1)
(- ssd (car l)))
;; the right-hand set worked
#t]
[else
;; finally drop the first element of l and try the others
(two-subsets? (cdr l) sl sld ssd)]))

Define a syntax error in Lisp function

I am bad at Lisp. Help me please to find a syntax error. I need to write a function which swaps two elements in list. This function must consist loop-cycle. Here is what if have so far.
(defun swap-two-element(z x y)
(let ((newlist nil) (newlist2 nil) (copyz z) (copyz2 z) (newx nil))
(loop
(when (= (- (length z) (length copyz2)) y)
(return (set newx car z)))
(setq newlist2 (append newlist2(car copyz2))
copyz2 (cdr copyz2)))))
Call example: (swap-two-element '(a b c d) 2 3)
Replace the word set with the word values and you are good to go.
PS. You need to address the warnings though, and explain what the function is supposed to do so that we could help you with the algorithm.
You really need to tidy up your question. The title says nothing, the code is badly formatted and you really need to play around with loop to get started. I won't give you your solution since you need to learn this by trying. Here is an example you can make use of to do your assignment.
;; this orders a list by their odd index
;; NB: index starts at zero so first element is even
(defun order-odd-index (list)
(loop :for element :in list ; iterates your list
:for index :from 0 ; starts from 0 and goes on
:if (oddp index) ; if in a loop
:collect element :into odd-list ; variable is automatically created
:else ; else in a loop
:collect element :into even-list
:finally (return (append odd-list even-list)))) ; what to do in the end
(order-odd-index '(4 67 3 2 7 9)) ; ==> (67 2 9 4 3 7)
I use keywords (like :for instead of for) to indicate what symbols are loop keywords and what are not. It's optional but I think it looks a lot cleaner.
Now your problem can be solved with collecting element into 5 variables. Two of them is when index is equal to one of the places (given as arguments) to be switched the other 3 are before, in between and greater. In the finally you can just append those variables in the correct order and you're done.