I have tried to make a program creating a binary tree with a list as an input, but I am running into a few errors. For one, if I have less than 5 elements, it does not output anything at all, and when I have more than 5 elements, while I do receive the output I want, It also prints the final side of the tree computed as well. If any of you could help me with debugging it, it would be greatly appreciated! Please find below, sample input, sample output, as well as my code.
(make-cbtree '(8 3 10 1))
(8 (3 (1 () ()) ()) (10 () ()))
(make-cbtree '(8 3 10 1 6))
(8 (3 (1 () ()) (6 () ())) (10 () ()))
;;This program will take a list and print a binary tree
(defun entry (tree) ;Node
(car tree)
)
(defun left (tree) ;This function gets the left branch
(cadr tree)
)
(defun right (tree) ;Function will get the right branch
(caddr tree)
)
(defun make-tree (entry left right) ;This function creates the node for a binary tree
(if (= z y)
(print(list entry left right))
) ;if z=y then prints the list
(list entry left right)
)
(defun add (x tree) ;This function will add the element from list into tree
(cond ((null tree) (make-tree x '() '())) ;Empty node, return nil
((= x (entry tree)) tree) ;if element from list equals node
;;if element from list is less than node then call make-tree function and add element to left side
((< x (entry tree)) (make-tree (entry tree) (add x(left tree)) (right tree)))
;;if element from list is greater than node then call make-tree function and add element to right side
((> x (entry tree)) (make-tree (entry tree) (left tree) (add x (right tree))))
)
)
(defun make-cbtree(elements) ;Call this function to create a binary tree
(dolist (x elements) ;Using dolist to go through all elements in list
(setf z (+ z 1))
(setf tree (add x tree))
)
)
;;Default values
(setf tree '())
(defvar z 0)
(defvar y 5)
(make-cbtree '(8 3 10 1))
For a start, if you are going to define an abstraction for a binary tree, define the abstraction, not part of it. In particular you at least want an object which represents an empty tree and a test for a tree being empty, so your code is not full of obscure stuff which has leaked up from below the abstraction:
;;; A binary tree has an entry, a left and a right node
;;; The implementation is a three-element list
(defconstant empty-tree nil)
(defun empty-tree-p (tree)
(eq tree empty-tree))
(defun entry (tree)
(first tree))
(defun left (tree)
(second tree))
(defun right (tree)
(third tree))
(defun make-tree (entry left right)
(list entry left right))
Secondly I have no idea what the obscure global variables are for – were they some leftover debugging thing? They don't need to exist and are certainly breaking your code. Removing them will make it work I think.
Below is a version which works, does not use assignment, and uses the abstractions defined above throughout.
(defun add (x tree)
;; Add an entry to a tree
(cond ((empty-tree-p tree)
(make-tree x empty-tree empty-tree))
((= (entry tree) x)
tree)
((< (entry tree) x)
(make-tree (entry tree) (add x (left tree)) (right tree)))
(t
(make-tree (entry tree) (left tree) (add x (right tree))))))
(defun add-elts-to-tree (elts tree)
;; Add a number of elements to a tree
(if (null elts)
tree
(add-elts-to-tree (rest elts) (add (first elts) tree))))
(defun list->tree (l)
(add-elts-to-tree l empty-tree))
Now, because I've defined an abstraction for trees, I can, if I want, completely replace the implementation:
;;; A binary tree has an entry, a left and a right node
;;; The implementation is a function of one argument
(defconstant empty-tree (lambda (k)
(declare (ignore k))
nil))
(defun empty-tree-p (tree)
(eq tree empty-tree))
(defun make-tree (entry left right)
(lambda (k)
(ecase k
((entry) entry)
((left) left)
((right) right))))
(defun entry (tree)
(funcall tree 'entry))
(defun left (tree)
(funcall tree 'left))
(defun right (tree)
(funcall tree 'right))
Related
I'm trying to write the code to find the minimum level in a tree (minimum number of nested sublists kinda)
The tree is given like this:
(A (B (E (I))(F))(C (G))(D))
which would look like:
A
/ | \
B C D
/\ |
E F G
|
I
Which would result... level 1. Max level is level 3 but I just need the minimum level.
I tried using the min function but whatever I do, it will either return 1 or 0 cause if the list is null, I return 0 and min (0 or anything) is always 0. Any ideas how to solve this without mapping/lambda funct?
I tried doing something like this:
(defun nrlevels (tail)
(cond
((null tail) 0)
((listp (car tail))
(min (+ 1 (nrlevels (car tail)))
(nrlevels (cdr tail))))
(t (nrlevels (cdr tail)))))
But as I said, that min will get to compare (Eventually) something with 0 and 0 being the minimum, the end result will be 0. I don't know how to escape this loop.
You are putting both the level recursion and the recursion that represents iteration over the children of a node into a single recursion. The problem is to distinguish between visiting nodes having no children and having reached the end of a children list.
You need to separate these things. I find it easiest to put the iteration over the children list into a loop:
(defun minimum-child-level (tree)
(if (atom tree)
0
(1+ (loop :for child :in tree
:when (listp child)
:minimize (minimum-child-level child)))))
or reduce:
(defun minimum-child-level (tree)
(if (atom tree)
0
(1+ (reduce #'min
(mapcar #'minimum-child-level
(remove-if-not #'listp tree))))))
EDIT: You could do it by interpreting a min accumulator and recursing one or the other way, but I do not recommend this for production code:
(defun minimum-child-level (tree &optional min-so-far)
(cond ((endp tree) ; end of child list
(if min-so-far
(1+ min-so-far) ; there were children
0)) ; no children
((atom (first tree)) ; ignore symbols, go to next child
(minimum-child-level (rest tree) min-so-far))
(t ; sublist
;; recurse into child
(let ((child-minlevel (minimum-child-level (first tree))))
;; go to next child
(minimum-child-level (rest tree)
(if min-so-far
(min min-so-far child-minlevel)
child-minlevel))))))
Given I have the list that might vary in its' structure- it might have multiple lists within list, how do I iterate through every element?
Example of the list: (or (and (not a) (not b)) (or (and x) t)))
It's a tipical situation for maptree function.
(defun maptree (fn tree)
(cond
((null tree) tree)
((atom tree) (funcall fn tree))
(t (cons
(maptree fn (first tree))
(maptree fn (rest tree))))))
So you can do (maptree #'what-to-do your-list).
I will just print all elements, you can provide any function you want, it'll b executed on each element of your tree.
CL-USER> (let ((lis
'(or (and (not a) (not b)) (or (and x) t))))
(maptree #'print lis))
OR
AND
NOT
A
NOT
B
OR
AND
X
T
This is a good case for a recursive function. You probably want something like this:
(defun iterate (l) (if (atom l) (do-something-with l) (mapcar #'iterate l)))
The function do-something-with obviously defines what you want to do with each element. Further, the mapcar could be replaced by another mapping function, depending on whether you want to accumulate the results of do-something-with or not.
From SICP I remember accumulate-tree which can be considered a reduce for trees. In CL it might look like this:
(defun accumulate-tree (tree term combiner null-value)
(labels ((rec (tree)
(cond ((null tree) null-value)
((atom tree) (funcall term tree))
(t (funcall combiner (rec (car tree))
(rec (cdr tree)))))))
(rec tree)))
You can do stuff like adding all numbers in the tree:
(defparameter *value-tree* '(1 2 (3 4 (5 6)) 3))
(accumulate-tree *value-tree*
(lambda (x) (if (numberp x) x 0))
#'+
0) ; => 24
To implement #coredumps map-tree you use cons as combiner and nil ass nil value:
(defun map-tree (function tree)
(accumulate-tree tree function #'cons nil))
I want to calculate the maximum of every sublist/level/superficial level from a list of number
Ex: (1 2 5 (4 2 7 (4 6) 9) 7 8) => (8 9 6)
What I have now is:
maximum (l) ;;function to compute the maximum number for a simple list, it works
(defun max-superficial (lista acc acc2) ;;main function: lista - my list, acc - my final list
;;of results, acc2 - accumulation list for a sublist
(typecase lista
(null
(typecase acc2
;; if my list is empty and I have nothing accumulated, just return the final list
(null acc)
;;if my list is empty but I have something in my accumulation list, just add the maximum
;;of acc2 to my final list
(t (nconc acc (list (maximum acc2))))))
(cons (destructuring-bind (head . tail) lista
(typecase head
(list
;;if my list isn't empty and the head of the list is a list itself, call
;;the function again for the head with an empty accumulation list and then call it again
;;for the tail
(nconc acc
(list (max-superficial head acc nil))
(max-superficial tail acc acc2)))
;; otherwise just accumulate the head and call the function for the tail
---problem here (t (nconc acc2 (list head))
(print '(wtf))
(print acc)
(print acc2)
(print head)
(max-superficial tail acc acc2)))))))
The problem is that I only wrote this program and I want to test it and on the list "---problem here" it won't add my head to the accumulation list.
For: (max-superficial '(1 2) nil nil) --result should be ==> wtf nil (1) 1 wtf nil (1 2) 2 2
My result: wtf nil nil 1 wtf nil nil 2 nil
I checked separately and (nconc some-list (list 3)) does exactly what it's supposed to... adds the number 3 to the back of the some-list. I don't know why nconc acc2 (list head) doesn't work
Tried replacing nconc with append and it's not working either. Apparently, you can't add an element to an empty list using append/nconc. Then how?
A simpler implementation:
(defun max-superficial/sublists (list)
(loop for num in list
if (listp num) append (max-superficial/sublists num) into sublists
else if (numberp num) maximize num into max
else do (error "Not a number or list: ~a" num)
finally (return (cons max sublists))))
;; If you want the max of each "level" or depth in a tree,
;; then you need to be able to operate on levels. Here are some
;; functions that are analogous to FIRST, REST, and POP:
(defun top-level (tree)
(remove-if-not #'numberp tree))
(defun rest-levels (tree)
(apply #'append (remove-if-not #'listp tree)))
(defmacro pop-level (tree)
`(let ((top (top-level ,tree)))
(setf ,tree (rest-levels ,tree))
top))
(defun max-superficial (tree &key use-sublists)
"It wasn't clear if you wanted the max in each sublist or the max
at each depth, so both are implemented. Use the :use-sublists key
to get the max in each sublist, otherwise the max at each depth
will be computed."
(if use-sublists
(max-superficial/sublists tree)
(loop for top-level = (pop-level tree)
collect (if top-level (reduce #'max top-level)) into result
unless tree do (return result))))
Here's a (not particularly efficient) solution:
(defun max-avoiding-nil (a b)
(cond ((null a) b)
((null b) a)
(t (max a b))))
(defun depth-maximum (a b)
(cond ((null a) b)
((null b) a)
(t
(cons (max-avoiding-nil (car a) (car b))
(depth-maximum (cdr a) (cdr b))))))
(defun tree-max-list (list depth)
(reduce #'depth-maximum tree
:key (lambda (elt) (tree-max elt depth))
:initial-value '()))
(defun tree-max (tree depth)
(if (listp tree)
(tree-max-list tree (1+ depth))
(append (make-list depth 'nil) (list tree))))
(defun tree-maximums (tree)
(tree-max-list tree 0))
(tree-maximums '(1 2 5 (4 2 7 (4 6) 9) 7 8)) => (8 9 6)
(tree-maximums '()) => nil
(tree-maximums '(1)) => (1)
(tree-maximums '((2))) => (nil 2)
(tree-maximums '((2) (3))) => (nil 3)
Having nested lists as the input, I'm trying to find how to output the number of 'siblings' an element has. In terms of trees, how many other leaf nodes belong to the same parent/root node.
My code is giving the wrong outputs (it's a really bad code) and I'm not sure how to entirely approach the question
(define (siblings lst n)
(cond
[(empty? lst) false]
[(member? n lst) (sub1 (length lst))]
[else (siblings (rest lst) n)]))
sample outcomes: if given (list (list 2 1) 3 (list 4)) and 3, produce 0
(list (list 1 2 3) (list (list 4 5 6 ))) and 5 -> 2
Your code has to do two separate things:
Find the branch that contains n
Count the number of siblings in that branch, accounting for the possibility of other branches starting there.
Finding the branch that contains n, assuming that n can only appear once:
(define (find-branch root n)
(cond ((empty? root) empty)
((memq n root)
root)
((list? (first root))
(let ((subresult (find-branch (first root) n)))
(if (not (empty? subresult))
subresult
(find-branch (rest root) n))))
(else (find-branch (rest root) n))))
Since you're using "Beginning Student," that takes all the tools out of your toolbox. Fortunately, it still has number?, so if it's safe to assume that anything that isn't a number in this assignment is a list, you can define list? like this:
(define (list? n) (not (number? n)))
Given your example tree as input, it would return:
(4 5 6)
The above example unnecessarily uses memq repeatedly on the rest of the
input list as a result of using recursion to iterate over the same list.
Here's a more efficient version of the above, but you can't implement it in Beginning Student:
(define (find-branch root n)
(cond ((empty? root) false)
((memq n root) root)
(else (foldl (λ (a b)
(if (empty? a) b a))
empty
(map (λ (sublist)
(find-branch sublist n))
(filter list? root))))))
You pass the result of that to a function to count the siblings. I previously provided a version that would work in the real Racket, but not the Beginning Student version used by teachers:
(define (count-siblings root mem)
(count (λ (sib)
(and (not (eq? sib mem))
(not (list? sib)))) root))
Here's a version that's compatible with Beginning Student:
(define (count-siblings lst n counter)
(cond
[(empty? lst) counter]
[(and (not (list? (first lst)))
(not (eq? n (first lst))))
(count-siblings (rest lst) n (add1 counter))]
[else (count-siblings (rest lst) n counter)]))
Finally, put the two together:
(define (find/count-siblings root n)
(count-siblings (find-branch root n) n 0))
I'm trying to develop a simple function that returns the smallest and largest value in Lisp. So far I have the basic solution working for a single Lisp and here is the code
(defun get-smallest-large (lst &optional (smallest 0) (largest 0))
(setf smallest (first lst))
(setf largest 0)
(dolist (nxt lst)
(if (< nxt smallest)
(setf smallest nxt)
(if (> nxt largest)
(setf largest nxt))))
(cons smallest largest))
This works like:
(defun get-smallest-large '(1 2 -1 3))
= (-1 . 3)
Now, I can't for the life of me figure out how to change this solution to deal with nested lists so for instance, I entered this:
(defun get-smallest-large '(5 (-2 20 (3)) -6 (-7 13)))
= (-7 . 20)
How would I go about this?
Here's one way you can approach it: when you recurse into sublists, process the return values as if they were elements of the outer list also. Example (in Scheme, which is my "native language"; requires SRFI 26):
(define (min-max x (min #f) (max #f))
(cond ((null? x) (if min (values min max) (values)))
((cons? x) (call-with-values (cut min-max (car x) min max)
(cut min-max (cdr x) <...>)))
(else (values (if (and min (< min x)) min x)
(if (and max (> max x)) max x)))))
And here's a direct Common Lisp translation of same, by which I mean that it's not idiomatic CL at all, but presented for CL programmers unfamiliar with Scheme to get an idea of what the Scheme code does. In particular, the Scheme requirement for proper tail recursion still holds, even though CL does not provide that.
(defun min-max (x &optional min max)
(cond ((null x) (if min (values min max) (values)))
((consp x)
(multiple-value-call #'min-max (cdr x) (min-max (car x) min max)))
(t (values (if (and min (< min x)) min x)
(if (and max (> max x)) max x)))))
Your code assumes that all the elements of the list are numbers. But if you have a nested list, then the list can contain lists of numbers, or lists of lists of numbers and so on.
Your list processing loop has to inspect the type of each element and handle that accordingly.
If you see a list, you want to make a recursive call to get-smallest-large to fetch the smallest and largest value from just that list. In the recursive call, you pass those extra two parameters, so that the function will not return a smaller maximum than you have already seen or larger minimum.
Since the return value is a cons, the recursive call might look something like this:
(destructuring-bind (sm . la) (get-smallest-large smallest largest)
(setf smallest sm largest la))
In Common Lisp, functions can return multiple values; code which returns a pair of numbers as a cons looks like something that was a quick and dirty port of code from a Lisp dialect without multiple value support.
This means that instead of returning (cons smallest largest) (return a single value which is a cell holding two numbers) we can return (values smallest largest) (actually return two values). The recursive call which uses the values then condenses to:
(multiple-value-setq (smallest largest) (get-smallest-large smallest largest))
The two setf calls at the beginning of the function will destroy the correctness of the recursion. If the function is given smallest and largest values on entry, it must honor those values and not simply overwrite them by taking an arbitrary value from the list structure. That code also has another problem in that it assumes that (first lst) is a number. It could be a sublist! And yet another problem: the list could be empty!!!
I suggest doing it like this:
(defun get-smallest-large (list &optional smallest largest)
;;
)
That is, default smallest and largest to nil, and deal with nil in the rest of the code as indicating "smallest or largest value not known yet". For instance:
;; the number we are looking at is smallest so far, if we have not
;; seen any number before, or if it is smaller than the smallest one we have
;; seen so far.
(if (or (null smallest) (< nxt smallest))
(setf smallest nxt))
This will also fix another bug. Think about what your function should return if it is called on an empty list. Surely not (0 . 0): zero does not occur in an empty list. A reasonable representation to return in that case is (nil . nil) which indicates that lowest and highest number are not known.
Here's a version that avoids recursion and uses a nice Common Lisp library: iterate:
(ql:quickload :iterate)
(use-package :iterate)
(defun minmax (tree)
(iter
(with head := tree)
(with stack := nil)
(while (or head stack))
(cond
((and (null head) stack)
(setf head (cdr (pop stack))))
((consp (car head))
(push head stack)
(setf head (car head)))
((car head)
(minimize (car head) :into min)
(maximize (car head) :into max)
(setf head (cdr head))))
(finally (return (values min max)))))
This would be a preferred way of doing it for very large, deeply nested trees, it trades some complexity and O(log n) space (used for backtracking) for scalability (other version suggested here would fail to perform on sufficiently large trees, where the limit would be the memory allocated per thread by the Lisp implementation to the stack of this function.)
The benefit of recursive version, however, may be that in principle, it would be easier to make it run several computations in parallel.
Using some macro-magic you can then hide the uninteresting bits of the original minmax function (those which only deal with iterating over tree):
(defmacro-clause (FOR var IN-TREE tree)
"Iterates over TREE in depth-first order"
(let ((stack (gensym)) (head (gensym)))
`(progn
(with ,head := ,tree)
(with ,stack := ,nil)
(with ,var := ,nil)
(while (or ,head ,stack))
(cond
((and (null ,head) ,stack)
(setf ,head (cdr (pop ,stack)))
(next-iteration))
((consp (car ,head))
(push ,head ,stack)
(setf ,head (car ,head))
(next-iteration)))
(setf ,var (car ,head) ,head (cdr ,head)))))
(defun minmax (tree)
(iter
(for leaf :in-tree tree)
(minimize leaf :into min)
(maximize leaf :into max)
(finally (return (values min max)))))
And have much leaner function, which only shows the important parts.
And here's the parallel version of the algorithm using lparallel library:
(ql:quickload :lparallel)
(setf lparallel:*kernel* (lparallel:make-kernel 128))
(lparallel:defpun pminmax (tree &optional min max)
(labels ((%min (&rest numbers)
(iter (for i :in numbers) (when (numberp i) (minimize i))))
(%max (&rest numbers)
(iter (for i :in numbers) (when (numberp i) (maximize i)))))
(cond
((null tree) (cons min max))
((consp (car tree))
(lparallel:plet
((head (pminmax (car tree) min max))
(tail (pminmax (cdr tree) min max)))
(cons (%min (car head) (car tail) min)
(%max (cdr head) (cdr tail) max))))
(t (destructuring-bind (new-min . new-max)
(pminmax (cdr tree) min max)
(cons (%min (car tree) new-min min)
(%max (car tree) new-max max)))))))
Unfortunately, lparallel doesn't yet implement an alternative for multiple-value-bind, so we had to combine the results into a cons cell, but given some persistence it would be possible to implement the parallel version of the above macro and get rid of this unfortunate limitation (which is left as an exercise for the reader).
Use the well known function flatten to flatten first your nested list, before you apply your own minimax function on it.
(defun flatten (x)
(cond ((null x) nil)
((atom x) (list x))
(t (append (flatten (car x))
(flatten (cdr x))))))
Then apply:
(get-smallest-large (flatten '(5 (-2 20 (3)) -6 (-7 13))))
;; returns: (-7 . 20)
It works, because
(flatten '(5 (-2 20 (3)) -6 (-7 13)))
;; returns: (5 -2 20 3 -6 -7 13)
Since the list is flat, you can apply your original function on it.
Using flatten, you can write a universal get-smallest-large* function, which works both with nested and flat lists:
(defun get-smallest-large* (lst &optional (smallest 0) (largest 0))
(get-smallest-large (flatten lst) smallest largest))
;; now you call on any lists - flat or nested:
(get-smallest-large* '(5 (-2 20 (3)) -6 (-7 13)))
If the list is huge, you have to think of generator lists and generator flatten.
This is explained here https://www.cs.northwestern.edu/academics/courses/325/readings/list-gen.php