How to double a list using tail recursive? - racket

(define (lst-double-helper lst acc)
(if (empty? list)
acc
(lst-double-helper (rest lst) (cons (* (first lst) 2) acc))))
(define (lst-double lst)
(lst-double-helper lst '()))
I feel I'm doing it in the right way. But this gives me an error
(lst-double '(1,2,3))
*: contract violation
expected: number?
given: ',2
argument position: 1st
other arguments...:
Why do it expect the second argument to be a number?

A couple of comments:
List elements are separated by spaces, not commas. That's the error being reported.
The base case of the recursion must refer to the parameter lst, not to list.
Your tail-recursive solution reverses the list, an extra reverse is needed at the end to restore the original order
With the above changes in place, it works as expected:
(define (lst-double-helper lst acc)
(if (empty? lst) ; parameter is called `lst`
acc
(lst-double-helper (rest lst) (cons (* (first lst) 2) acc))))
(define (lst-double lst)
(reverse ; required to restore original order
(lst-double-helper lst '())))
(lst-double '(1 2 3)) ; use spaces to separate elements
=> '(2 4 6)
Be aware that a tail-recursive solution that traverses an input list and conses its elements to build an output list, will necessarily reverse the order of the elements in the input list. This is ok, and it's normal to do a reverse at the end. Possible alternatives to avoid reversing the elements at the end would be to reverse the input list at the beginning or to write a non-tail-recusive solution.

One such way is by using continuation-passing style. Here we add a parameter named return which effectively encodes a return-like behavior with a lambda. double now takes two arguments: the list to double, xs, and the continuation of the result, return –
(define (double xs return)
(if (empty? xs)
(return empty)
(double (cdr xs)
(lambda (result)
(return (cons (* 2 (car xs))
result))))))
As an example, the result of double applied to a list of '(1 2 3) is sent to print
(double '(1 2 3) print)
;; '(2 4 6)
;; => #<void>
double evaluates to whatever the final continuation evaluates to; in this case, print evaluates to #<void>. We can use the identity function to effectively get the value out –
(double '(1 2 3) identity)
;; => '(2 4 6)
Racket allows you to easily specify default arguments, so we can modify double to use identity as the default continuation
(define (double xs (return identity))
;; ...
)
This style results in convenient programs that work in two call styles at simultaneously: continuation-passing style –
(double '(10 11 12) print)
;; '(20 22 24)
;; => #<void>
(double '(10 11 12) length)
;; => 3
(double '(10 11 12) car)
;; => 20
(double '(10 11 12) cdr)
;; => '(22 24)
... or in direct style, using the default identity continuation
(print (double '(10 11 12)))
;; '(20 22 24)
(length (double '(10 11 12)))
;; => 3
(car (double '(10 11 12)))
;; => 20
(cdr (double '(10 11 12)))
;; => '(22 24)

use map.
(map (lambda (a) (* a 2)) '(1 2 3))

For nested lists:
(define (atom? x)
(and (not (null? x))
(not (pair? x))))
(define (lst-double-helper lst acc)
(cond ((empty? lst) acc)
((atom? (car lst)) (lst-double-helper (rest lst) (cons (* (first lst) 2) acc)))
(else (lst-double-helper (rest lst) (cons (lst-double (first lst))
acc) ))))
(define (lst-double lst)
(reverse ; required to restore original order
(lst-double-helper lst '())))
but actually to make this function tail-recursive is a little bit meaningless,
because as #simmone mentioned, map would do it
(define (list-doubler lst)
(map (lambda (x) (* 2 x)) lst))
(list-doubler '(1 2 3))
;; '(2 4 6)

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.

Lisp nested list iteration

I just started to learn Common Lisp and this is my first functional programming language.
I am trying to learn about iterating through lists. I wrote these two functions:
(defun reverseList (liste)
(defvar reversedList(list))
(loop for i downfrom (-(length liste)1) to 0 do
(setf reversedList (append reversedList (list(nth i liste)))))
reversedList ;return
)
(defun countAppearance(liste element)
(defvar count 0)
(loop for i from 0 to (-(length liste) 1)do
(if (= (nth i liste) element)
(setf count (+ count 1))))
count
)
Both work fine for a regular list(ex: (1 3 5 7 3 9) but I want them to work for nested lists too.
Examples:
countAppearance - Input: (1 (3 5) (3 7 8) 2) 3 -> Expected output:2
reverseList - Input: (1 (2 3)) -> Expected output: ((3 2) 1)
Before I will show you solutions for nested lists, some notes about your code:
There is already function reverse for non-nested lists, so you don't have to reinvent the wheel.
=> (reverse (list 1 2 3 4 5))
(5 4 3 2 1)
If you need some local variables, use let or let*.
Lisp uses kebab-case, not camelCase, so rename reverseList as reverse-list and so on.
For (setf ... (+ ... 1)), use incf.
For iterating over list, use dolist.
Function count-occurrences can be written using recursion:
(defun count-occurrences (lst elem)
(cond ((null lst) 0)
((= (car lst) elem) (+ 1 (count-occurrences (cdr lst) elem)))
(t (count-occurrences (cdr lst) elem))))
CL-USER 3 > (count-occurrences (list 1 2 3 1 2 3) 2)
2
Or it can be written with let, dolist and incf:
(defun count-occurrences2 (lst elem)
(let ((count 0))
(dolist (e lst)
(when (= e elem) (incf count)))
count))
CL-USER 4 > (count-occurrences2 (list 1 2 3 1 2 3) 2)
2
Solutions for nested lists use recursion:
(defun deep-reverse (o)
(if (listp o)
(reverse (mapcar #'deep-reverse o))
o))
CL-USER 11 > (deep-reverse '(1 (2 3)))
((3 2) 1)
(defun deep-count (lst elem)
(cond ((null lst) 0)
((listp (car lst)) (+ (deep-count (car lst) elem)
(deep-count (cdr lst) elem)))
((= (car lst) elem) (+ 1 (deep-count (cdr lst) elem)))
(t (deep-count (cdr lst) elem))))
CL-USER 12 > (deep-count '(1 (3 5) (3 7 8) 2) 3)
2
Welcome to functional programming.
Firstly, there are some problems with the code that you have provided for us. There are some spaces missing from the code. Spaces are important because they separate one thing from another. The code (xy) is not the same as (x y).
Secondly, there is an important difference between local and global variables. So, in both cases, you want a local variable for reversedList and count. This is the tricky point. Common Lisp doesn't have global or local variables, it has dynamic and lexical variables, which aren't quite the same. For these purposes, we can use lexical variables, introduced with let. The keyword let is used for local variables in many functional languages. Also, defvar may not do what you expect, since it is way of writing a value once, which cannot be overwritten - I suspect that defparameter is what you meant.
Thirdly, looking at the reverse function, loop has its own way of gathering results into a list called collect. This would be a cleaner solution.
(defun my-reverse (lst)
(loop for x from (1- (length lst)) downto 0 collect (nth x lst)))
It can also be done in a tail recursive way.
(defun my-reverse-tail (lst &optional (result '()))
(if lst
(my-reverse-tail (rest lst) (cons (first lst) result))
result))
To get it to work with nested lists, before you collect or cons each value, you need to check if it is a list, using listp. If it is not a list, just add it onto the result. If it is a list, add on instead a call to your reverse function on the item.
Loop also has functionality to count items.

Use function within a function

I have a function called clean-up which basically does what the already available flatten function does. I then have a function called multiplier, which takes in a list and multiplies all the numbers within it. The one issue is that sometimes there could be a weird syntax for the list used in multiplier, and it doesn't multiply every number together. For example:
Example Input
(multiplier '((1 (2 3)) 4 5 (6)))
Correct Output
720
My Output
*: contract violation
expected: number?
given: '(6 . 1)
argument position: 2nd
other arguments...
We don't like errors now do we? This multiplier function works in a normal-looking list, something like (multiplier '(1 2 3 4 5 6)). So I wrote the clean-up function to turn some confusing-looking list into a normal-looking list. However, I don't know how to call it to clean-up my list before trying to parse through and do the multiplication. I can verify that the clean-up function does its job perfectly. Can anyone help? Here is the code I have for both:
(define (clean-up s)
(cond [(null? s) '()]
[(not (pair? s)) (list s)]
[else (append (clean-up (car s)) (clean-up (cdr s)))]
))
(define multiplier
(lambda (s)
(cond [(null? s) 1]
[(number? (car s)) (* (car s) (multiplier(cdr s)))]
[list? (car s) (append (car s) (multiplier(cdr s)))]
[else (multiplier (cdr s))]
)))
There is no need for the clean-up function to solve the problems encountered in multiplier. However, you could call clean-up on the input first simply with:
scratch.rkt> (multiplier (clean-up '((1 (2 3)) 4 5 (6))))
720
Or, you could create a helper function to do this for you:
(define (multiplier-workaround s)
(multiplier (clean-up s)))
scratch.rkt> (multiplier-workaround '((1 (2 3)) 4 5 (6)))
720
A workaround like this might help you out in a pinch, but it does not fix the real problems in the code.
Some of the problems here may be easier to see with better code formatting. It is bad style to leave hanging parentheses in Lisps as if these are C-style languages; but that probably isn't causing you problems here. Yet it is good style to show the structure of your expressions using indentation. With proper indentation it becomes apparent that there are missing parentheses in the line with the list? predicate:
(define multiplier
(lambda (s)
(cond [(null? s) 1]
[(number? (car s))
(* (car s) (multiplier(cdr s)))]
[list? (car s)
(append (car s) (multiplier (cdr s)))]
[else
(multiplier (cdr s))])))
Further investigation of that line shows that the code is attempting to append (car s) to the result of (multiplier (cdr s)); yet, (car s) is now known to be a list, and multiplier is supposed to return a number! The intention here was surely to multiply the result of calling multiply on the list (car s) together with the result of (multiplier (cdr s)):
(define multiplier
(lambda (s)
(cond [(null? s) 1]
[(number? (car s))
(* (car s)
(multiplier (cdr s)))]
[(list? (car s))
(* (multiplier (car s))
(multiplier (cdr s)))]
[else
(multiplier (cdr s))])))
It isn't clear why the else branch is needed, unless OP wants to be able to process lists such as (a (1 (2 b) (3 (c (4 5) 6) d) e))). For code that is expecting nested lists of numbers, this would be fine:
(define multiplier-2
(lambda (s)
(cond [(null? s) 1]
[(number? (car s))
(* (car s) (multiplier (cdr s)))]
[else
(* (multiplier (car s))
(multiplier (cdr s)))])))
Both functions now work for OP example expression, and the corrected OP code also works for input with spurious values:
scratch.rkt> (multiplier '((1 (2 3)) 4 5 (6)))
720
scratch.rkt> (multiplier-2 '((1 (2 3)) 4 5 (6)))
720
scratch.rkt> (multiplier '(a (1 (2 3)) 4 5 b (6) c))
720
I think buildin flatten have more error handling.
(define (multiplier lst)
(apply * (filter number? (flatten lst))))
;;; TEST
(define test-lst1 (list + (vector 1) '(1 (2 3) c) "w" 4 5 '(6) + - * sqr))
(define test-lst2 '(1(a 2(3 b (c 4(d 5 e(6) (f)))))))
(multiplier test-lst1) ; 720
(multiplier test-lst2) ; 720

Racket: Product of even number

I am trying to produce the product of the even numbers in a given list.
I am trying to replicate the following example:
Example:
(product-even-numbers '(2 1 6 3 5))
==> 12
This is my version of the definition for product-even-numbers:
(define (product-even-numbers lst)
(define/match (recurse lst accumulator)
;; A _ pattern matches any syntax object
[(_ _) (* car (recurse cdr))])
(recurse lst 1))
I am getting the following error:
(product-even-numbers '(2 1 6 3 5))
. . recurse: arity mismatch;
the expected number of arguments does not match the given number
expected: 2
given: 1
arguments...:
I understand that i am missing the second argument, but I do not know what the second argument is supposed to be.
Why are you using pattern matching? this would be easier to understand without it, and first of all you need to get the recursion and the logic right:
(define (product-even-numbers lst)
(define (recurse lst acc)
(cond ((null? lst) acc)
((even? (car lst)) (recurse (cdr lst) (* (car lst) acc)))
(else (recurse (cdr lst) acc))))
(recurse lst 1))
In this case, it's clear that the second argument is the accumulated product we have so far. And we need to consider three cases: empty list, even element, odd element. For example:
(product-even-numbers '(2 1 6 3 5))
=> 12
(define (product-even-numbers lst)
(local [(define tmp (foldr * 1 (filter even? lst)))]
(if (= 1 tmp) 'nothing tmp)))
If output 1 means no any even number.
(define (product-even-numbers2 lst)
(foldr * 1 (filter even? lst))) ; or use (apply * (filter even? lst))

Map! procedure in Racket

The map! procedure should modify the existing list to have the values of the operator applied to the original values.
For example:
(define a '(1 2 3 4 5))
(define double (lambda (x) (* x 2)))
(map! double a)
returns
done
Then when a is evaluated, a should return
(2 4 6 8 10)
map! procedure must do that work.
(define (map! operator given-list)
(if (null? given-list) 'done
(<the procedure that does the modification>)))
My guess1:
(map (lambda (x) (set! x (operator x))) given-list)
(map! double a)
returns:
'(#<void> #<void> #<void> #<void> #<void>)
My guess2:
(cons (operator (car given-list)) (map! double (cdr given-list)))
(map! double a)
returns:
'(2 4 6 8 10 . done)
My guess3:
(set! given-list (map operator given-list))
(map! double a)
returns:
'(2 4 6 8 10)
My guess4:
(let ((element (car given-list)))
(set! element (operator given-list) (map! operator (cdr given-list)))
(map! double a)
returns:
'done
but, when "a" is evaluated, it still says:
'(1 2 3 4 5)
What do I have to do for this?????
You cannot use set! for this. You need to use set-car! on the cons cell you're changing. Here's how you might write it:
(define (map! f lst)
(let loop ((rest lst))
(unless (null? rest)
(set-car! rest (f (car rest)))
(loop (cdr rest)))))
If you have SRFI 1, it's even easier (if we ignore for a moment that SRFI 1 already defines map! ;-)):
(define (map! f lst)
(pair-for-each (lambda (pair)
(set-car! pair (f (car pair))))
lst))