Append two functions recursively with Racket? - racket

I'm using racket language, but i'm having some trouble getting some expected results for a recursive function. My goal is to input an integer n and output the element n times, as a list.
' exclude the ' and the text, #lang racket
; take n (integer) e (scheme) build new list
; 2 `() -> () ()
; 3 `a -> a a a
; 4 `(a) -> (a) (a) (a) (a)
(define (list n e)
(if (= n 0) e
(append e(list (- n 1) e)) ))
; (list 0 '())
; prints '()
; (list 2 '())
; should print '() '()

Your problem would appear to be that append isn't doing what you're expecting it to - it unwraps and discards top-level empty lists. (e.g. (append '(1) '() '(2) '() '(3)) ;; => '(1 2 3)).
So, swapping cons in for append will result in (what I believe to be) the expected output.
(define (my-list n empty-list)
(if (= n 0)
empty-list
(cons
empty-list
(my-list (- n 1) empty-list))))
(my-list 2 '()) ;; => '(() ())
You should also reconsider clobbering Racket's built-in list function.
This answer has a useful breakdown of what append is doing internally and why it's undesirable in this scenario.

Related

How to concatenate all the elements of the argument lists into a single list

I am trying to concatenate all elements in the list argument into a single list.
I have this code:
(define (concatenate . lsts)
(let rec ([l lsts]
[acc '()])
(if (empty? l)
acc
(rec (cons (list* l)
acc)))))
An example of output is here:
> (concatenate '(1 2 3) '(hi bye) '(4 5 6))
'(1 2 3 hi bye 4 5 6)
But I keep getting this error:
rec: arity mismatch;
the expected number of arguments does not match the given number
expected: 2
given: 1
Can someone please explain this?
Another answer explains the OP error,
and shows how the code can be fixed using append.
But there could be reasons for append to be disallowed in this assignment
(of course, it could be replaced with, for example, an inner "named let" iteration).
This answer will present an alternative approach and describe how it can be derived.
#lang racket
(require test-engine/racket-tests)
(define (conc . lols) ;; ("List of Lists" -> List)
;; produce (in order) the elements of the list elements of lols as one list
;; example: (conc '(1 2 3) '(hi bye) '(4 5 6)) => '(1 2 3 hi bye 4 5 6)
(cond
[(andmap null? lols) empty ] ;(1) => empty result
[else
(cons (if (null? (car lols)) ;(2) => head of result
(car (apply conc (cdr lols)))
(caar lols))
(apply conc ;(3) => tail of result
(cond
[(null? (car lols))
(list (cdr (apply conc (cdr lols)))) ]
[(null? (cdar lols))
(cdr lols) ]
[else
(cons (cdar lols) (cdr lols)) ]))) ]))
(check-expect (conc '() ) '())
(check-expect (conc '() '() ) '())
(check-expect (conc '(1) ) '(1))
(check-expect (conc '() '(1) ) '(1))
(check-expect (conc '() '(1 2) ) '(1 2))
(check-expect (conc '(1) '() ) '(1))
(check-expect (conc '(1) '(2) ) '(1 2))
(check-expect (conc '(1 2) '(3 4) ) '(1 2 3 4))
(check-expect (conc '(1 2 3) '(hi bye) '(4 5 6)) '(1 2 3 hi bye 4 5 6))
(test)
Welcome to DrRacket, version 8.6 [cs].
Language: racket, with debugging; memory limit: 128 MB.
All 8 tests passed!
>
How was this code derived?
"The observation that program structure follows data structure is a key lesson in
introductory programming" [1]
A systematic program design method can be used to derive function code from the structure
of arguments. For a List argument, a simple template (natural recursion) is often appropriate:
(define (fn lox) ;; (Listof X) -> Y ; *template*
;; produce a Y from lox using natural recursion ;
(cond ;
[(empty? lox) ... ] #|base case|# ;; Y ;
[else (... #|something|# ;; X Y -> Y ;
(first lox) (fn (rest lox))) ])) ;
(Here the ...s are placeholders to be replaced by code to create a particular list-argumented
function; eg with 0 and + the result is (sum list-of-numbers), with empty and cons it's
list-copy; many list functions follow this pattern. Racket's "Student Languages" support
placeholders.)
Gibbons [1] points out that corecursion, a design recipe based on result structure, can also
be helpful, and says:
For a structurally corecursive program towards lists, there are three questions to ask:
When is the output empty?
If the output isn’t empty, what is its head?
And from what data is its tail recursively constructed?
So for simple corecursion producing a List result, a template could be:
(define (fn x) ;; X -> ListOfY
;; produce list of y from x using natural corecursion
(cond
[... empty] ;(1) ... => empty
[else (cons ... ;(2) ... => head
(fn ...)) ])) ;(3) ... => tail data
Examples are useful to work out what should replace the placeholders:
the design recipe for structural recursion calls for examples that cover all possible input variants,
examples for co-programs should cover all possible output variants.
The check-expect examples above can be worked through to derive (1), (2), and (3).
[1] Gibbons 2021 How to design co-programs
Assuming you are allowed to call append, for simplicity. You have
(define (concatenate . lsts)
(let rec ([l lsts]
[acc '()])
(if (empty? l)
acc
(rec (cons (list* l) ; only ONE
acc) ; argument
))))
calling rec with only one argument. I have added a newline there so it becomes more self-evident.
But your definition says it needs two. One way to fix this is
(define (conc . lsts)
(let rec ([ls lsts]
[acc '()])
(if (empty? ls)
acc
(rec (cdr ls) ; first argument
(append acc (car ls)) ; second argument
))))
Now e.g.
(conc (list 1 2) (list 3 4))
; => '(1 2 3 4)
I used append. Calling list* doesn't seem to do anything useful here, to me.
(edit:)
Using append that way was done for simplicity. Repeatedly appending on the right is actually an anti-pattern, because it leads to quadratic code (referring to its time complexity).
Appending on the left with consequent reversing of the final result is the usual remedy applied to that problem, to get the linear behavior back:
(define (conc2 . lsts)
(let rec ([ls lsts]
[acc '()])
(if (empty? ls)
(reverse acc)
(rec (cdr ls)
(append (reverse (car ls))
acc)))))
This assumes that append reuses its second argument and only creates new list structure for the copy of its first.
The repeated reverses pattern is a bit grating. Trying to make it yet more linear, we get this simple recursive code:
(define (conc3 . lols)
(cond
[(null? lols) empty ]
[(null? (car lols))
(apply conc3 (cdr lols)) ]
[else
(cons (caar lols)
(apply conc3
(cons (cdar lols) (cdr lols))))]))
This would be even better if the "tail recursive modulo cons" optimization was applied by a compiler, or if cons were evaluated lazily.
But we can build the result in the top-down manner ourselves, explicitly, set-cdr!-ing the growing list's last cell. This can be seen in this answer.

Edit every even-indexed element in a list

I'm pretty new to lisp and I want to make function that every even-indexed element replace it with new one element list that holds this element. For example
(1 2 3 4 5) -> (1 (2) 3 (4) 5), (1 2 3 4 5 6) -> (1 (2) 3 (4) 5 (6))
Right now I came up with solution that each of the lements put in it's own list, but I cant get exactly how to select every even-indexed element:
(DEFUN ON3 (lst)
((ATOM (CDR lst)) (CONS (CONS (CAR lst) NIL) NIL))
(CONS (CONS (CAR lst) NIL) (ON3 (CDR lst))))
Your code doesn't work. You'll need to use if or cond such that the code follow one of the paths in it. Right now you have an error truing to call a function called (atom (cdr lst)). If it had been something that worked it would be dead code because the next line is always run regardless. It is infinite recursion.
So how to count. You can treat every step as a handle on 2 elements at a time. You need to take care of the following:
(enc-odds '()) ; ==> ()
(enc-odds '(1)) ; ==> (1)
(enc-odds '(1 2 3 ...) ; ==> (1 (2) (enc-odds (3 ...))
Another way is to make a helper with extra arguments:
(defun index-elements (lst)
(labels ((helper (lst n)
(if (null lst)
lst
(cons (list (car lst) n)
(helper (cdr lst) (1+ n))))))
(helper lst 0)))
(index-elements '(a b c d))
; ==> ((a 0) (b 1) (c 2) (d 3))
For a non-recursive solution, loop allows for constructing simultaneous iterators:
(defun every-second (list)
(loop
for a in list
for i upfrom 1
if (evenp i) collect (list a)
else collect a))
(every-second '(a b c d e))
; ==> (A (B) C (D) E)
See http://www.gigamonkeys.com/book/loop-for-black-belts.html for a nice explanation of loop

Reverse the order of pairs

I am trying to write a function in Racket that will reverse the order of pairs. For example, given the list '(1 2) the function should produce '(2 1). Here is my code so far:
(define (reverse aList)
(cons (second aList)
(first aList))
This is not producing the correct answer, however. When I test with '(a b) it returns '(b . a) instead of '(b a). How do I get rid of the period between the b and a?
You should have:
(define (reverse-pair lst)
(cons (second lst) (cons (first lst) empty)))
As stated in Racket's docs:
The cons function actually accepts any two values, not just a list for the second argument. When the second argument is not empty and not itself produced by cons, the result prints in a special way. The two values joined with cons are printed between parentheses, but with a dot (i.e., a period surrounded by whitespace) in between.
So,
> (cons 1 2)
'(1 . 2)
> (cons 1 (cons 2 empty)) ; equivalent to (list 1 2)
'(1 2)

How to use foldr in Racket to eliminate numbers in a list that are greater than any subsequent numbers

I have to write a function in Racket using foldr that will take a list of numbers and remove list elements that are larger than any subsequent numbers.
Example: (eliminate-larger (list 1 2 3 5 4)) should produce (1 2 3 4)
I can do it without using foldr or any higher-order functions but I can't figure it out with foldr. Here's what I have:
(define (eliminate-larger lst)
(filter (lambda (z) (not(equal? z null)))
(foldr (lambda (x y)
(cons (determine-larger x (rest lst)) y)) null lst))
)
(define (determine-larger value lst)
(if (equal? (filter (lambda (x) (>= x value)) lst) lst)
value
null)
)
determine-larger will take in a value and a list and return that value if it is greater than or equal to all elements in the list. If not, it returns null. Now the eliminate-larger function is trying to go through the list and pass each value to determine-larger along with a list of every number after it. If it is a "good" value it will be returned and put in the list, if it's not a null is put in the list. Then at the end the nulls are being filtered out. My problem is getting the list of numbers that follow after the current number in the foldr function. Using "rest lst" doesn't work since it's not being done recursively like that. How do I get the rest of the numbers after x in foldr?
I really hope I'm not doing your homework for you, but here goes ...
How do I get the rest of the numbers after x in foldr?
Because you're consuming the list from the right, you can structure your accumulator such that "the rest of the numbers after x" are available as its memo argument.
(define (eliminate-larger lst)
(foldr
(lambda (member memo)
(if (andmap (lambda (n) (<= member n)) memo)
(cons member memo)
memo))
'()
lst))
(eliminate-larger (list 1 2 3 5 4)) ;; (1 2 3 4)
This is admittedly a naive solution, as you're forced to traverse the entire accumulator with each iteration, but you could easily maintain a max value, in addition to your memo, and compare against that each time through.
Following works:
(define (el lst)
(define (inner x lsti)
(if(empty? lsti) (list x)
(if(<= x (apply max lsti))
(cons x lsti)
lsti)))
(foldr inner '() lst))
(el (list 1 2 3 5 4))
Output:
'(1 2 3 4)
The cond version may be preferable:
(define (el lst)
(define (inner x lsti)
(cond
[(empty? lsti) (list x)]
[(<= x (apply max lsti)) (cons x lsti)]
[else lsti] ))
(foldr inner '() lst) )

returning the best element from the list L according to function F?

i am trying to write a function in lisp which have 2 parameters one function F and one list L
if i place '> in place of F and list L is '(1 2 3 4 5) it will return 5 as 5 is biggest.
and if we put '< then it compares all list elements and gives the smallest one as output.
and so on.
we can even put custom written function in place of F for comparison.
i wish i could provide more sample code but i am really stuck at the start.
(DEFUN givex (F L)
(cond
(F (car L) (car (cdr L))
;after this i got stuck
)
)
another attemp to write this function
(defun best(F list)
(if (null (rest list)) (first list)
(funcall F (first List) (best (F list)))))
You are almost there, just the else clause returns the f's return value instead of the the best element:
(defun best (F list)
(let ((first (first list))
(rest (rest list)))
(if (null rest)
first
(let ((best (best f rest)))
(if (funcall F first best)
best
first)))))
Examples:
(best #'< '(1 2 3))
==> 3
(best #'> '(1 2 3))
==> 1
Note that this recursive implementation is not tail-recursive, so it is not the most efficient one. You might prefer this instead:
(defun best (f list)
(reduce (lambda (a b) (if (funcall f a b) b a)) list))
Or, better yet,
(defmacro fmax (f)
`(lambda (a b) (if (,f a b) b a)))
(reduce (fmax <) '(1 2 3))
==> 1
(reduce (fmax >) '(1 -2 3 -4) :key #'abs)
==> 1
(reduce (fmax <) '(1 -2 3 -4) :key #'abs)
==> 4