compare the length of two list and append in racket - functional-programming

I've tried to write a function, merge_longer, in Racket that takes as input two lists, L1 and L2. If L1 is longer than L2 the function appends L2 to L1. Otherwise, it appends L1 to L2.
(define L1 '(4 6 8 9))
(define L2 '(1 2 3))
(define (merge_longer L1 L2) (if (> length(L1) length(L2)) (append L1 L2)(append L2 L1)))
(merge_longer L1 L2)
However, this error is displayed while I run it:
application: not a procedure;
expected a procedure that can be applied to arguments
given: '(4 6 8 9)
arguments...: [none]
Can someone please help me solve this problem?

You were close.
(define (merge-longer l1 l2)
(if (> (length l1) (length l2))
(append l1 l2)
(append l2 l1)))
Note that you can add extra parentheses in Racket.
When you write (l1) it means "apply the function l1 to no arguments".
Since l1 is a list, not a function, you get an error.

Related

Question about foldl function in Racket. (Functional programming)

So I have this line of code:
(foldl cons '() '(1 2 3 4))
And the output I get when I run it is this:
'(4 3 2 1)
Can you please explain to me why I don’t get '(1 2 3 4) instead?
I read the documentation but I am still a bit confused about how foldl works. Also if I wanted to define foldl how would I specify in Racket that the function can take a variable amount of lists as arguments?
Thanks!
Yes. By the definition of left fold, the combining function is called with the first element of the list and the accumulated result so far, and the result of that call is passed (as the new, updated accumulated result so far) to the recursive invocation of foldl with the same combining function and the rest of the list:
(foldl cons '() '(1 2 3))
=
(foldl cons (cons 1 '()) '(2 3))
=
(foldl cons (cons 2 (cons 1 '())) '(3))
=
(foldl cons (cons 3 (cons 2 (cons 1 '()))) '())
=
(cons 3 (cons 2 (cons 1 '())))
And when the list is empty, the accumulated result so far is returned as the final result.
To your second question, variadic functions in Scheme are specified with the dot . in the argument list, like so:
(define (fold-left f acc . lists)
(if (null? (first lists)) ;; assume all have same length
acc
(apply fold-left ;; recursive call
f
(apply f (append (map first lists) ;; combine first elts
(list acc))) ;; with result so far
(map rest lists)))) ;; the rests of lists
Indeed,
(fold-left (lambda (a b result)
(* result (- a b)))
1
'(1 2 3)
'(4 5 6))
returns -27.

creating a lisp function that gives a list of even number from a list

I would like to create a function for class that would take two arguments L and L1 as lists and put all even numbers from L into L1.
I've tried for several hours to make it work, but unfortunatelly I couldn't.
This is my Scheme code:
(define (pair L L1)
(cond
((and (not (empty? L)) (= (modulo (first L) 2) 0))
(begin (append (list (first L)) L1) (pair (rest L) L1)))
((and (not (empty? L)) (= (modulo (first L) 2) 1))
(pair (rest L) L1))
(else L1)
))
I assume you want to use L1 as an accumulator, and at the end return its content.
About your code:
It's enough to check once in the first clause of cond if L is empty (null?).
append is fine when you want to append a list. In your case you append one element, so cons is much better.
You don't have to take modulo of a number, to check if it's even. There is build in even? predicate.
So, after all this considerations, your code should look something like this:
(define (pair L L1)
(cond ((null? L) L1)
((even? (first L))
(pair (rest L) (cons (first L) L1)))
(else (pair (rest L) L1))))
Now let's test it:
> (pair '(0 1 2 3 4 5 6 7) '())
(6 4 2 0)
As you can see, it returns numbers in reverse order. It's because as we move down the list L from head to tail, we cons new values to the head (and not tail, like append would) of the list L1. To fix it, it's enough to (reverse L1) in the first cond clause instead of simply returning L1.
I highly recommend "Little Schemer" book. After reading it, you will be able to write any kind of recursive functions even in your sleep ;)

My Scheme Function: How to Make it Recursive

So in my scheme function, provided below, I need to produce a list of structures. So far, I've made 2 helper functions: One calls a list of numbers counting up from 1 to x. The other calls the structure that corresponds to x.
For example:
(helper1 10) -> (list 1 2 3 4 5 6 7 8 9 10)
(helper2 1) -> (make-person 0 1)
(helper2 2) -> (make-person 1 2)
(helper2 3) -> (make-person 2 3) etc...
How can I make my main function call the list of helper1, where each element is replaced with its corresponding structure.
Note: My main function must be recursive, and it must produce a list of structures.
So far, for my main function I have:
(define (main-function x)
(cond
[(zero? x) empty]
[else
...]))
Also, I am writing in Beginner Student with List Abbreviations.
You'll want to construct an entirely new list, not replace each element with a structure. That's the appearance of the end result, but not how the function works.
Basically, if your main-function takes in a number, then you'll want to create a helper function that actually does the recursion, where you will pass in the result of calling (helper1 x).
Then, in your recursion, you're just recontructing a list with the corresponding structures.
(define (main-function x)
(main-function-helper (helper1 x)))
(define (main-function-helper l)
(cond
[(empty? l) l]
[else (cons (helper2 (first l))
(main-function-helper (rest l)))]))
Another option that may make more sense is to never create the intermediate list:
(define (main-function x)
(main-function-helper 1 x))
(define (main-function-helper counter max)
(cond
[(= counter max) (cons (helper2 counter) empty)]
[else (cons (helper2 counter)
(main-function-helper (add1 counter) max))]))

Scheme: sequential execution

I need to do something basically like this:
(define test
(λ (ls1 ls2)
(cond
((empty? ls2) null)
(else
(append ls1 (car ls2)) (test ls1 (cdr ls2))) (displayln ls1))))
The issue is the else-clause and the function that follows it. I need both clauses of the else-clause to execute and then I need the last function to execute but I can't get the syntax right.
I need (test '(1 2 3) '(4 5 6)) to result in displaying '(1 2 3 4 5 6) and it has to use the recursive call.
Any advice is appreciated.
Thanks.
There is several problem there. First you make an append on a list and an atom (not a list)... at least if (car l2) is not a list. Second you probably think that (append l1 (list (car l2)) modifies l1. But this is not the case. The result is a new list.
To sequence your operation you can do as larsmans have said. But you can also write the following
(define (test l1 l2)
(if (null? l2)
(displayln l1)
(let ((l1-follow-by-car-l2 (append l1 (list (car l2)))))
(test l1-follow-by-car-l2 (cdr l2)) ))
This has exactly the same behavior.
If you desperately want to solve this recursively, and you don't care about the return value, use
(define (test l1 l2)
(if (null? l2)
(displayln l1)
(test (append l1 (list (car l2))) (cdr l2))))
(This is very inefficient btw: O(n × m) memory allocations.)

How would one interleave elements of 2 lists in LISP?

Given 2 lists, how can you produce an output of a 3rd list which has its elements as an interleaved set of L1 and L2? If they are uneven length, nil should be inserted for holes. On a second note, how can I reverse a list? I am super new to LISP and simply modifying existing code... I'd really love to have a good explanation, not just code.
First, I guess you use Common Lisp, as it is the one most used in Lisp courses. So, my examples will be in CL. If you use Scheme, you will get almost the same code. If modern Clojure, it will need some changes, through an idea will be the same.
Interleave
To interleave 2 lists you must go through both of them, collecting elements by turns. You can use loop statement or recursion for this. I'll use recursion since it has more functional style and may be used in any lisp, not only CL. Also note, that there's a feature called tail recursion, which lets you write recursive function that will be compiled to a loop.
So, base skeleton for our function will be:
(defun interleave (l1 l2)
??????
(interleave ?????))
To collect items in recursive functions you will need to return them from each call and then cons together (for a tail recursion you must have one more parameter, which will accumulate values). So, the end of the function will be (cons current-value (interleave ????)).
Also you must alternate lists to take elements from with each other. You may have additional parameter, but you also may just swap them in a recursive call. So, code becomes:
(defun interleave (l1 l2)
?????
(cons current-value (interleave l2 l1)))
Any recursion must stop somewhere. In this case, it must stop when both lists are empty (nil).
This is one condition (let give it number 1), and there are some more conditions:
2. if the list to take from is empty, and the other one is not, we must take nil instead.
3. if both lists are not empty, take first element as a current-value and proceed with it's tail.
There's only one more condition that 2 lists can be in: list to take from is not empty, and the second one is. But in fact we don't care about this and may go forward with a rule number 3.
So, the code (and this is the final one):
(defun interleave (l1 l2)
(cond ((and (eql l1 nil) (eql l2 nil)) nil) ;; rule #1
((eql l1 nil) (cons nil (interleave l2 l1))) ;; rule #2, current value is nil
(true (cons (first l1) (interleave l2 (rest l1)))))) ;; rule #3 in all other cases
Reverse
I'll show two implementations of this function: one with cond and another with built-in reduce function which is extremely useful in practice.
First approach for cond version is to go through the all list with a recursive calls and then go back, collecting elements:
(defun reverse-1-1 (li)
(if (eql li nil)
nil
(append (reverse-1-1 (rest li))
(list (first li)))))
But this is extremely inefficient, since append is O(n), and you must pass n elements, so the final complexity is O(n^2).
To reduce it you may use one more argument to the function (and make it tail recursive, if compiler lets you):
(defun reverse-1-2 (li)
(reverse-aux li nil))
(defun reverse-aux (li accumulator)
(if (eql li nil)
accumulator
(reverse-aux (rest li) (cons (first li) accumulator))))
That's you use one more parameter to collect your elements in while passing through the list, and then just return this accumulator.
There's one more interesting option. Lisp has extremely powerful function reduce (in other functional languages it is sometimes called fold, foldr, foldl or something like that). You may find description for it here, and I'll just show an example:
(defun reverse-2 (li)
(reduce #'cons li :from-end t :initial-value nil))
:from-end tells function to go through the the list from the end, and :initial-value tells to use as the very first reduced argument nil.
Note: in some implementations reduce with option :from-end true may first reverse list by itself, so if you need to create it from scratch or use the most efficient version, use reverse-1-2 instead.
In Common Lisp:
(defun merge-lists (lst1 lst2)
(let ((m (max (length lst1) (length lst2))))
(flatten (mapcar (lambda (a b) (list a b))
(append-nulls lst1 m)
(append-nulls lst2 m)))))
Examples:
(merge-lists '(1 2 3 4) '(5 6 7 8)) ;; => (1 5 2 6 3 7 4 8)
(merge-lists '(1 2 3 4) '(5 6 7)) ;; => (1 5 2 6 3 7 4 NULL)
(merge-lists '(1 2) '(5 6 7 8)) ;; => (1 5 2 6 NULL 7 NULL 8)
The helper functions flatten and append-nulls:
(defun flatten (tree)
(let ((result '()))
(labels ((scan (item)
(if (listp item)
(map nil #'scan item)
(push item result))))
(scan tree))
(nreverse result)))
(defun append-nulls (lst n)
(if (< (length lst) n)
(dotimes (i (- n (length lst)))
(setq lst (append lst (list 'null)))))
lst)
The answer above:
(defun interleave (l1 l2)
(cond ((and (eql l1 nil) (eql l2 nil)) nil) ;; rule #1
((eql l1 nil) (cons nil (interleave l2 l1))) ;; rule #2, current value is nil
(true (cons (first l1) (interleave l2 (rest l1)))))) ;; rule #3 in all other cases
If one of your lists is longer than the other, you will get something like (1 2 3 4 nil 5).
Replace:
((eql l1 nil) (cons nil (interleave l2 l1)))
with:
((null l1) l2)
:P
An example of a more idiomatic solution in Common Lisp:
(defun interleave (a b)
(flet ((nil-pad (list on-list)
(append list (make-list (max 0 (- (length on-list) (length list)))))))
(loop for x in (nil-pad a b)
for y in (nil-pad b a)
append (list x y))))

Resources