I need to make a function in Racket that removes elements similar to each other from the list - lisp

I need to create a function in Racket, but I found the examples a little confusing. I need to create a function that removes the elements similar to each other from the list. You can pass a function that determines the similarity or not (this function is optional). By default, elements are removed if they are equal, using the eq? function. You can takes on that the similarity function is always symmetric.

As long as the count of an element is more than 1, I use remove* to remove their occurrences. The good thing is that both functions have a proc parameter to use as predicates. Also, I use the helper takes the same input list twice but use them differently: l1 is used to recur on, and l2 is used as the accumulator.
(define (remove-similars l f)
(define (remove-lsts l1 l2 f)
(cond [(empty? l1) l2]
[else (if (> (count (lambda (e) (f e (first l1))) l2) 1)
(remove-lsts (rest l1) (remove* (list (first l1)) l2 f) f)
(remove-lsts (rest l1) l2 f))]))
(remove-lsts l l f))

Here's an approach to doing this:
start with an empty list of elements we're collecting, and an empty list of duplicates
look at the list we're trying to filter:
if it is empty, return the reverse of the list we're collecting
if it is not empty:
check whether the first element is similar to any of the duplicates we've already seen: if it is, just iterate on the rest of the list
if it's not, then check whether it is similar to any element of the rest of the list: if it is then it's a duplicate, so iterate on the rest of the list, adding the first element to the list of duplicates;
if it's not either of those it must be unique, so iterate on the rest of the list adding the first element to the list of elements being collected.
Depending on how much of Racket you are allowed to use, it's worth knowing that (member element l similar?) will check whether element is in l using similar? as the predicate. If you aren't allowed to use that then you can write it fairly easily.
Also to define a function which takes an optional argument with a default value you can say
(define (find-similar list (test? similar))
...)
That will make test? be the test function and its default value will be similar's value.

Related

Find max in lisp

I am trying to do Recursive method to find max value in list.
Can anyone explain where I made the mistake on this code and how to approach it next time.
(defun f3 (i)
(setq x (cond (> (car (I)) (cdr (car (I))))
(f3 (cdr (I)))))
)
(f3 '(33 11 44 2) )
also I tried this following method and didn't work:
(defun f3 (i)
(cond ((null I )nil )
(setq x (car (i))
(f3(cdr (i)))
(return-from max x)
)
Thanks a lot for any help. I am coming from java if that helps.
If you're working in Common Lisp, then you do this:
(defun max-item (list)
(loop for item in list
maximizing item))
That's it. The maximizing item clause of loop determines the highest item value seen, and implicitly establishes that as the result value of loop when it terminates.
Note that if list is empty, then this returns nil. If you want some other behavior, you have to work that in:
(if list
(loop for item in list
maximizing item))
(... handle empty here ...))
If the number of elements in the list is known to be small, below your Lisp implementation's limit on the number of arguments that can be passed to a function, you can simply apply the list to the max function:
(defun max-item (list)
(apply #'max list))
If list is empty, then max is misused: it requires one or more arguments. An error condition will likely be signaled. If that doesn't work in your situation, you need to add code to supply the desired behavior.
If the list is expected to be large, so that this approach is to be avoided, you can use reduce, treating max as a binary function:
(defun max-item (list)
(reduce #'max list))
Same remarks regarding empty list. These expressions are so small, many programmers will avoid writing a function and just use them directly.
Regarding recursion, you wouldn't use recursion to solve this problem in production code, only as a homework exercise for learning about recursion.
You are trying to compute the maximum value of a list, so please name your function maximum and your parameter list, not f3 or i. You can't name the function max without having to consider how to avoid shadowing the standard max function, so it is best for now to ignore package issues and use a different name.
There is a corner case to consider when the list is empty, as there is no meaningful value to return. You have to decide if you return nil or signal an error, for example.
The skeleton is thus:
(defun maximum (list)
(if (null list)
...
...))
Notice how closing parentheses are never preceded by spaces (or newlines), and opening parentheses are never followed by spaces (or newlines). Please note also that indentation increases with the current depth . This is the basic rules for Lisp formatting, please try following them for other developers.
(setq x <value>)
You are assigning an unknown place x, you should instead bind a fresh variable if you want to have a temporary variable, something like:
(let ((x <value>))
<body>)
With the above expression, x is bound to <value> inside <body> (one or more expressions), and only there.
(car (i))
Unlike in Java, parentheses are not used to group expressions for readability or to force some evaluation order, in Lisp they enclose compound forms. Here above, in a normal evaluation context (not a macro or binding), (i) means call function i, and this function is unrelated to your local variable i (just like in Java, where you can write int f = f(2) with f denoting both a variable and a method).
If you want to take the car of i, write (car i).
You seem to be using cond as some kind of if:
(cond (<test> <then>) <else>) ;; WRONG
You can have an if as follows:
(if <test> <then> <else>)
For example:
(if (> u v) u v) ;; evaluates to either `u` or `v`, whichever is greater
The cond syntax is a bit more complex but you don't need it yet.
You cannot return-from a block that was undeclared, you probably renamed the function to f3 without renaming that part, or copied that from somewhere else, but in any case return-from is only needed when you have a bigger function and probably a lot more side-effects. Here the computation can be written in a more functionnal way. There is an implicit return in Lisp-like languages, unlike Java, for example below the last (but also single) expression in add evaluates to the function's return value:
(defun add-3 (x)
(+ x 3))
Start with smaller examples and test often, fix any error the compiler or interpreter prints before trying to do more complex things. Also, have a look at the available online resources to learn more about the language: https://common-lisp.net/documentation
Although the other answers are right: you definitely need to learn more CL syntax and you probably would not solve this problem recursively in idiomatic CL (whatever 'idiomatic CL' is), here's how to actually do it, because thinking about how to solve these problems recursively is useful.
First of all let's write a function max/2 which returns the maximum of two numbers. This is pretty easy:
(defun max/2 (a b)
(if (> a b) a b))
Now the trick is this: assume you have some idea of what the maximum of a list of numbers is: call this guess m. Then:
if the list is empty, the maximum is m;
otherwise the list has a first element, so pick a new m which is the maximum of the first element of the list and the current m, and recurse on the rest of the list.
So, we can write this function, which I'll call max/carrying (because it 'carries' the m):
(defun max/carrying (m list)
(if (null list)
m
(max/carrying (max/2 (first list) m)
(rest list))))
And this is now almost all we need. The trick is then to write a little shim around max/carrying which bootstraps it:
to compute the maximum of a list:
if the list is empty it has no maximum, and this is an error;
otherwise the result is max/carrying of the first element of the list and the rest of the list.
I won't write that, but it's pretty easy (to signal an error, the function you want is error).

Can someone explain why im getting mpair contract violation

Define a SCHEME procedure, named (tree-sort l), which takes a list of numbers and outputs the same
list, but in sorted order. Your procedure should sort the list by
(a) inserting the numbers into a binary search tree and, then,
(b) extracting from the binary search tree a list of the elements in sorted order.
To get started, write a procedure called (insert-list L T) which takes a list of numbers L and a binary
search tree T, and returns the tree that results by inserting all numbers from L into T. (Place the argument
L first, so a call to your function should have the form (insert-list L T), where L is a list and T is a
(perhaps empty) binary search tree.)
Then write a function called sort-extract which takes a binary search tree and outputs the elements of
the tree in sorted order. (We did this in class!)
Finally, put these two functions together to achieve (tree-sort l). (Note, all three of these functions
will be graded, so your solutions must consist of three top-level functions, insert-list, sort-extract,
and tree-sort.)
(define (insert-list insert-elements T)
(if (null? insert-elements)
T
(insert-list (cdr insert-elements)
(insert-list (car insert-elements) T))))
(insert-list (list 12) (list 15 (list) (list)))
mcdr: contract violation
expected: mpair?
given: 12
You are getting contract violations because you are calling insert-list with the car which is 12. Since it is not null? you'll try to do car and cdr of it. What is the cdr of 12?
Also for me it seems strange that you are not calling the procedure to add an element to a tree from insert-list. I can't think of any good reason to combine those two procedures in one.
If you had a procedure that takes a value and a tree and returns a tree with that value added you can do this:
(define (insert-list lst tree)
(foldl insert tree lst))
Eg.
(insert-list '(5 2 4) '()) ; ==>
(insert 4 (insert 2 (insert 5 '())))

Where's foldl1 and foldr1 in Racket?

Racket has only foldl and foldr, which require initial value. Haskell in addition has foldl1 and foldr1, which instead of applying a function on the initial value and the first element, applies to first and second element. Currently i implemented them as:
(define (foldl1 f xs)
(foldl f (first xs) (rest xs)))
Is there a better way?
There is a better way, just (require srfi/1) and use reduce and reduce-right. :-D
What you are describing looks like reduce in CL. Your procedure looks ok except it would fail if the list is empty.
Be aware that first and rest are not the same as car and cdr since they only work on proper lists. eg.
(first '(a b c d e . f))
;;==>
;;first: contract violation
;; expected: (and/c list? (not/c empty?))
;; given: '(a b c d e . f)
Now. For racket to signal here it must have traversed the whole list to make sure it ends with null and since it didn't it signaled an error. I did a small test and found out that sorting a 2 million list used 32% more time with first/rest.

How do I do anything with multiple return values in racket?

It seems like in order to use multiple return values in Racket, I have to either use define-values or collect them into a list with (call-with-values (thunk (values-expr)) list). In the latter case, why would someone to choose to return multiple values instead of a list, if just have to collect them into a list anyway? Additionally, both of these are very wordy and awkward to work into most code. I feel like I must be misunderstanding something very basic about multiple-return-values. For that matter, how do I write a procedure accepting multiple return values?
Although I may be missing some of the Scheme history and other nuances, I'll give you my practical answer.
First, one rule of thumb is if you need to return more than 2 or 3 values, don't use multiple values and don't use a list. Use a struct. That will usually be easier to read and maintain.
Racket's match forms make it much easier to destructure a list return value -- as easy as define-values:
(define (f)
(list 1 2))
(match-define (list a b) (f))
(do-something-with a b)
;; or
(match (f)
[(list a b) (do-something-with a b)])
If you have some other function, g, that takes a (list/c a b), and you want to compose it with f, it's simpler if f returns a list. It's also simpler if both use a two-element struct. Whereas call-with-values is kind of an awkward hot mess, I think.
Allowing multiple return value is an elegant idea, because it makes return values symmetric with arguments. Using multiple values is also faster than lists or structs (in the current implementation of Racket, although it could work otherwise).
However when readability is a higher priority than performance, then in modern Racket it can be more practical to use a list or a struct, IMHO. Having said that I do use multiple values for one-off private helper functions.
Finally, there's a long, interesting discussion on the Racket mailing list.
Racket doc gives us the quintessential example why, in disguise:
> (let-values ([(q r) (quotient/remainder 10 3)])
(if (zero? r)
q
"3 does *not* divide 10 evenly"))
"3 does *not* divide 10 evenly"
We get two values directly, and use them separately in a computation that follows.
update: In Common Lisp, with its decidedly practical, down-to-the-metal, non-functional approach (where they concern themselves with each extra cons cell allocation), it makes much more sense, especially as it allows one to call such procedures in a "normal" way as well, automatically ignoring the "extra" results, kind of like
(let ([q (quotient/remainder 10 3)])
(list q))
But in Racket this is invalid code. So yeah, it looks like an extraneous feature, better to be avoided altogether.
Using list as the consumer defeats the purpose of multiple values so in that case you could just have used lists to begin with. Multiple values is actually a way of optimization.
Semanticly returning a list and several values are similar, but where you return many values in a list effort goes into creation of cons cells to make the list and destructuring accessors to get the values at the other end. In many cases however, you wouldn't notice the difference in performance.
With multiple values the values are on the stack and (call-with-values (lambda () ... (values x y z)) (lambda (x y z) ...) only checks the number to see if it's correct.. If it's ok you just apply the next procedure since the stack has it's arguments all set from the previous call.
You can make syntactic sugar around this and some popular ones are let-values and SRFI-8 receive is a slightly simpler one. Both uses call-with-values as primitive.
values is handy because it
checks that the number of elements returned is correct
destructures
For example, using
(define (out a b) (printf "a=~a b=~a\n" a b))
then
(let ((lst (list 1 2 3)))
(let ((a (first lst)) (b (second lst))) ; destructure
(out a b)))
will work even though lst has 3 elements, but
(let-values (((a b) (values 1 2 3)))
(out a b))
will not.
If you want the same control and destructuring with a list, you can however use match:
(let ((lst (list 1 2)))
(match lst ((list a b) (out a b))))
Note that he creation of the structure, e.g. (list 1 2) vs (values 1 2) is equivalent.

Lisp - Elements of a lisp occur in other list

i'm having a problem with this lisp function. I want to create a function that receives two lists, and verifies if the elements of the first list (all of them) occur in the second list, it returns True if this happens.
Currently i have the following code:
(defun ocorre-listas (l1 l2)
(dolist (elem1 l1)
(dolist (elem2 l2)
(if (equal elem1 elem2)
t))))
It's not working, as expected. Should i try to do it just with a simple recursion? I'm really not getting how i can iterate both lists in search of equal elements.
I decided to try without the dolists. This is what i have now, it's still not working.
(defun ocorre-listas (l1 l2)
(cond ((null l1) nil)
((null l2) nil)
((if (/= (first l1)(first l2)) (ocorre-listas l1 (rest l2))))
(t (if (= (first l1) (first l2)) (ocorre-listas (rest l1)(rest l2))))))
I get a warning saying that "t" is an undefined function. Also, every example i try returns null. What am i doing wrong ?
In the second piece of code, if the first list is empty then all of its elements are in the second one.
You don't need the ifs since you are inside a cond
After test if the lists are empty, you'll only need to test if the first element of the first list is in the second one and call the function again with the first list without this element
Instead of trying to do everything in one function, consider splitting it into two (or more) functions, e.g.
One that takes a number and the second list, and tests whether the number appears in the list
Another that iterates over the numbers in the first list, and for each one tests (using the first function) whether it appears in the second list.
As well as DOLIST, consider using MAPCAR and FIND-IF (assuming they are allowed in this assignment.)
So you need to check if every element of l1 is a member of l2. These are both functions in the Common Lisp standard library, so if you're allowed to use them, you can build a simple solution with them.
See the common lisp subsetp
predicate and its implementation:
CL-USER> (subsetp '(1 2 3) '(1 2 3 4)
T
To be able to work on both lists at the same time, the trick is probably to sort the lists before starting the recursion. Then it should be a simple matter of comparing the first element, and applying the same function to the rest of the list recursively, with some CAR/CDR magic added of course...
While there are many ways to do this, I would recommend using a hash table to avoid O(n^2) complexity. Using a hash table, you can achieve O(n) complexity.
here is a union function
(defun my-union (a b)
(let ((h (make-hash-table :test #'equal)))
(mapcar (lambda (x) (setf (gethash x h) x)) a)
(mapcan (lambda (x) (when (gethash x h) (list x))) b)))
here is a function testing for IDENTICAL elements in boths lists
(defun same-elements (a b)
(apply #'= (mapcar #'length (list (my-union a b) a b))))
here is a function making sure a is a subset of b (what you asked)
(defun subset (a b)
(same-elements (my-union a b) a))