I'm trying to write a function which adds parentheses like this: (parens '(a b c d e)) returns (a (b (c (d (e))))). I'm just not seeing the pattern very well. What I have so far just returns a list with parentheses around each element. I can't seem to figure out how to make it look like that.
(DEFUN PARENS (L)
(COND ((NULL L) NIL)
(T (CONS (LIST (CAR L)) (PARENS (CDR L))))))
There are no parenthesis in a list. You're starting with a list of five elements, (a b c d e), and getting back a list of two elements, (a (b (c (d (e))))). The first element is a, and the second is another list, (b (c (d (e)))).
It's very easy to get close to this using reduce:
CL-USER> (reduce 'list '(a b c d e) :from-end t)
(A (B (C (D E))))
You can think of reduce as "injecting" the function list into (a b c d e) to produce
(list a (list b (list c (list d e))))
It's almost what you want. You actually want:
(list a (list b (list c (list d (list e)))))
How would you produce that? You can recurse down the list, and for each sublist (x . ys) you want to return (list x (recurse ys)), with the exception being when ys is (). You don't want to recurse into (), because you don't want a list with two elements, you actually want nothing. So the trick is stop recursing earlier than you typically do with a list. Thus:
(defun parens (l)
(cond
((endp l) '())
((endp (rest l)) l)
((list (first l) (parens (rest l)))))) ; *
CL-USER> (parens '(a b c d e))
(A (B (C (D (E)))))
CL-USER> (parens '(a b))
(A (B))
CL-USER> (parens '(a))
(A)
CL-USER> (parens '())
NIL
*Omitting the t test in the last clause is intentional. If there are no body forms in a cond clause, then the value of the test is returned. Thus (list …) serves both as the test form and the value form.
We can actually clean that up a little bit. The case of ((endp l) '()) could be ((endp l) l) since l is the empty list. But that means that in both the first and second cases, we can return l. We can call (rest '()) in Common Lisp and get back (), so (rest l) will be () when l is something like (e) and when l is (). This means that we can use:
(defun parens (l)
(cond
((endp (rest l)) l)
((list (first l) (parens (rest l))))))
If we just have one test, though, we might as well just use if:
(defun parens (l)
(if (endp (rest l))
l
(list (first l) (parens (rest l)))))
You can actually do it with reduce and some special consideration for the end:
(defun unflatten (list)
(reduce #'list list
:from-end t
:end (1- (length list))
:initial-value (last list)))
Note that last returns a list of the last n (default 1) elements.
Related
I wanted to square all elements in a list by the Scheme programming language.
my code is:
(define (square n) (* n *n))
(define (fun items factor)
(if (null? items)
0
(cons (* (fun (car items)
factor))
(fun (cdr items)
factor) ) ) ) )
(display (fun '( 1 2 3 4) square))
I'm showing these errors:
ERROR: In procedure car:
ERROR: In procedure car:
Wrong type (expecting pair): 1
You have a couple of errors:
The square procedure has an extra * that shouldn't be there
If we're building a list as output, then the base case should return the empty list '(), not 0.
The part where you operate on the current element of the list is incorrect, you should simply call the factor procedure on the car of the list, and there's no need to multiply again, square will take care of that.
This should fix them:
(define (square n) (* n n))
(define (fun items factor)
(if (null? items)
'()
(cons (factor (car items))
(fun (cdr items) factor))))
In real life, you don't need to implement this procedure yourself, map is already built-in and it's as simple to use as this:
(map square '(1 2 3 4))
=> '(1 4 9 16)
Here is other method:
(define factor-list
(lambda (l factor return)
(if (null? l)
(return '())
(factor-list (cdr l)
factor
(lambda (rest)
(return (cons (factor (car l))
rest)))))))
(define input '(1 2 3 4))
(factor-list input (lambda (x) (* x x)) (lambda (x) x))
Tail recursive implementation of map (to not to overwrite built-in map I called it *map).
(define (square x) (* x x))
(define (*map func lst (acc '()))
"Apply func on each element of the list."
(cond ((null? lst) (reverse acc))
(else (*map func (cdr lst) (cons (func (car lst)) acc)))))
Run it by:
(*map square '(1 2 3)) ;; '(1 4 9)
So, id like to take in a list of numbers, atomize it (to remove nested integers), then find the max value. I have two functions written that accomplish this individually, but can't figure out how to combine them in LISP so I can make one call and have them both run. Any help would be appreciated.
:Atomize function to remove nests
:(atomify ‘( a (b c) (e (f (g h) i)) j)->(a b c e f g h i j)
(defun atomify (numbers)
(cond ((null numbers) nil)
((atom (car numbers))
(cons (car numbers)
(atomify (cdr numbers))))
(t
(append (atomify (car numbers))
(atomify (cdr numbers))))))
:Max value of a list of integers function
(defun large_atom (numbers)
(if (null numbers)
0
(max (first numbers)
(large_atom (rest numbers)))))
Jamie. Your way has two steps:
1. Flatten list
2. Find max value from result of 1'st step
In this case it's true way. But you need do it with one function call. It's easy. Just use labels, apply and of course max
(defun foo (lst)
(labels ((flatten (lst acc)
(cond
((null lst)
acc)
((consp (car lst))
(flatten (cdr lst) (flatten (car lst) acc)))
(t
(flatten (cdr lst) (cons (car lst) acc))))))
(apply #'max (flatten lst nil))))
Another way, is do not flatten source list. But in this case you need find first value to compare with other values. Try it yourself.
Here is another way to solve the problem: rather than flattening the list, this walks down it recursively. This is very explicit about what the structure of the list must be: a good list is a non-null proper list each of whose elements is either an integer or a good list.
The problem with this approach is that it's not tail recursive so it will necessarily fail on very large structures (and even if it was tail recursive CL does not promise to deal with tail recursion.
(defun greatest-integer (good-list)
;; a good list is one of:
;; - a cons of a good list and either a good list or ()
;; - a cons of an integer and either a good list or ()
;; In particular it can't be () and it can't be an improper list
;;
(destructuring-bind (a . b) good-list
;; a can be an integer or a good list, b can be null or a good list
(etypecase b
(null
(etypecase a
(integer a)
(cons (greatest-integer a))))
(cons
(max (etypecase a
(integer a)
(cons (greatest-integer a)))
(greatest-integer b))))))
I have writte a list reverse function in lisp and I wanted to test it but I had an error and I couldn't solve it
the function and calling is below :
(defun myreverse (list)
(cond((null list) nil))
(cons (myreverse(cdr list) (car list))))
(myreverse '(1 2 3))
any help will be appreciated...
The arguments when you defun myreverse are (list), thus when you call it (myreverse '(1 2 3)) list gets bound to (1 2 3).
Since the list is not null you suddenly do (myreverse '(2 3) 1) and list gets bound to (2 3), but what do 1 get bound to? You have no more than one argument thus the call is invalid and warrants an error.
Hint1: There is a way to make optional arguments:
(defun test (a &optional (b 0) (c 0))
(+ a b c))
(test 10) ; ==> 10
(test 10 1 2) ; ==> 13
Hint2: You need to build a list not just pass a bare element. The passed list will be the tail of the next round until the every element is added.
The bad answer (or one of the bad answers):
(defun reverse (list)
(cond ((null list) list)
(t (append (reverse (cdr list)) (cons (car list) nil)))))
A better answer:
(defun reverse (list)
(reverse-aux list nil))
(defun reverse-aux (list result)
(cond ((null list) result)
(t (reverse-aux (cdr list) (cons (car list) result)))))
It's the basic example we use in comparison to the definition of 'append' in lessons to differentiate tail recursion.
I have the filter-function and the reverse-function done out in my own code
(define reverse_
(lambda (xs)
(if (null? xs)
xs
(append (reverse_ (cdr xs))
(list (car xs))))))
and
(define filter_
(lambda (p? xs)
(if (null? xs)
xs
(append (if (p? (car xs))
(list (car xs))
(list))
(filter_ p? (cdr xs))))))
I want to combine the two functions into the (reverse-filter) function i.e you could type (reverse-filter symbol? '(1 2 3 a b c)) and it would return -> c b a.
It works now by simply typing (reverse_ (filter_ symbol? '(1 2 3 a b c))) -> c b a but I just want to combine the two.
Any help on doing this in the general case and in this specific one would be much appreciated
For the general case, we can use the curry and compose procedures (which hopefully are available in your interpreter), they allow us to manipulate other procedures:
((compose (curry filter_ symbol?) reverse_)
'(1 2 3 a b c))
=> '(c b a)
For illustrative purposes, here's a naive implementation of both procedures, to understand what they're doing under the hood:
(define (curry f x)
(lambda (y) (f x y)))
(define (compose f g)
(lambda (x) (f (g x))))
compose is the right and lazy thing to do, however since lists are iterated from head to tail but created from tail to head creating the reverse result is actually more efficient when done in one go:
(define (reverse-filter p? xs)
(define (helper lst acc)
(if (null? lst)
acc
(helper (cdr lst)
(let ((a (car lst)))
(if (p? a)
(cons a acc)
acc)))))
(helper xs '()))
(reverse-filter symbol? '(1 2 3 a b c))
; ==> (c b a)
I'm working on a function that takes in a list of structures and then using that list of structures produces a function that processes a list of symbols into a number. Each structure is made up of a symbol, that will be in the second list consumed, and a number. This function produced has to turn the list of symbols into a number by assigning each symbol a value based on the previous structures. Using abstract list functions btw.
Example: ((function (list (make-value 'value1 10) (make-value 'value2 20)))
(list 'value1 'value2 'nothing 'value1)) would produced 40.
Heres my code but it only works for specific cases.
(define (function lst)
(lambda (x) (foldr + 0 (map (lambda (x)
(cond
[(equal? x (value-name(first lst)))(value-value (first lst))]
[else (value-value (second lst))]))
(filter (lambda (x) (member? x (map value-name lst)))x)))))
Looks like a homework. Basic shape of your solution is ok. I think the reason you have a problem here is that there is no decomposition in your code so it's easy to get lost in parentheses.
Let's start with your idea of fold-ing with + over list of integers as a last step of computation.
For this subtask you have:
1) a list of (name, value) pairs
2) a list of names
and you need to get a list of values. Write a separate function which does exactly that and use it. Like this
(define (function lst)
(lambda (x) (foldr +
0
(to-values x lst)))
(define (to-values names names-to-values)
(map (lambda (name)
(to-value name names-to-values))))
(define (to-value n ns-to-vs)
...)
Here we map over the names with another little function. It will lookup the n value in ns-to-vs and return it or 0 if there is no one.
There are two approaches for solving the problem with foldr, it'd be interesting to study and understand both of them. The first one, attempted in the question, is to first produce a list with all the values and let foldr take care of adding them. It can be implemented in a simpler way like this:
(define (function lst)
(lambda (x)
(foldr +
0
(map (lambda (e)
(cond ((assoc e lst) => value-value)
(else 0)))
x))))
Alternatively: maybe using foldr is overkill, applying + is simpler:
(define (function lst)
(lambda (x)
(apply +
(map (lambda (e)
(cond ((assoc e lst) => value-value)
(else 0)))
x))))
In the second approach we take the input list "as is" and let foldr's lambda perform the addition logic. This is more efficient than the first approach using foldr, because there's no need to create an intermediate list - the one generated by map in the first version:
(define (function lst)
(lambda (x)
(foldr (lambda (e a)
(cond ((assoc e lst) => (lambda (p) (+ a (value-value p))))
(else a)))
0
x)))
In both approaches I'm using assoc for finding the element in the list; it's easy to implement as a helper function if you're not allowed to use it or if it doesn't work for the values created with make-value: assoc takes a list of name-value pairs and returns the first pair with the given name. The => syntax of cond passes the pair returned by assoc to a lambda's parameter and executes it.
And because you're using Racket, there's a bit of syntactic sugar that can be used for returning a function from another function, try this equivalent code, for simplicity's sake:
(define ((function lst) x)
(foldr +
0
(map (lambda (e)
(cond ((assoc e lst) => value-value)
(else 0)))
x)))
Or this:
(define ((function lst) x)
(foldr (lambda (e a)
(cond ((assoc e lst) => (lambda (p) (+ a (value-value p))))
(else a)))
0
x))
Anyway, the result is as expected:
((function (list (make-value 'value1 10) (make-value 'value2 20)))
(list 'value1 'value2 'nothing 'value1))
=> 40