drRacket structure error - racket

When I write these codes and program gives error;
"leaf-name: expects a leaf, given empty"
(define-struct leaf (parent children name level-of-vertex))
(define A (make-leaf empty '(B C D) 'A 1))
(define B (make-leaf A '(E F) 'B 2))
(define C (make-leaf A 'G 'C 2))
(define D (make-leaf A '(H J) 'D 2))
(define E (make-leaf B empty 'E 3))
(define F (make-leaf B '(K L) 'F 3))
(define G (make-leaf C empty 'G 3))
(define H (make-leaf D empty 'H 3))
(define J (make-leaf D empty 'J 3))
(define K (make-leaf F empty 'K 4))
(define L (make-leaf F empty 'L 4))
(define binarytree (list A B C D E F G H J K L empty))
(define (findchild child)
(display (leaf-name (leaf-children child))))
(findchild E)
How I can solve this error?

Change
(define binarytree (list A B C D E F G H J K L empty))
to
(define binarytree (list A B C D E F G H J K L))
After the above change, note that that:
(define E (make-leaf B empty 'E 3))
Thus
(leaf-children E)
empty
That's why (leaf-name (leaf-children E))) becomes (leaf-name empty) and you get the error.

I imagine (leaf-children node) would evaluate to a list of objects and not a leaf. In fact, E doesn't have children.
When you select parent you use an actual object, but with children you have quotes list of symbols as children. Thus they are not a list of objects but symbols.
Without mutation you can either point upward or downward. With both you need to do one then the other by mutation. Perhaps from leaf to root. The binarytree is strange since I'd guess the full binary tree is supposed to be A.

Related

For loop which prints out every 3rd number

I'm trying to make a for loop that iterates over a list of numbers and prints out every 3rd number.
Edit: I've only figured out how to use the for loop but I'm not entirely sure if there's a specific function I can use to only show every 3rd number. I feel like I might be on the right path when using car/cdr function except I'm getting an error
rest: contract violation
expected: (and/c list? (not/c empty?))
given: 0
My code:
(for/list ([x (in-range 20)] #:when (car(cdr(cdr x)))) (displayln x))
I'm trying to make a for loop that iterates over a list of numbers and prints out every 3rd number.
Typically it is more useful to create a new list with the desired values, and then print those values, or pass them to a function, or do whatever else may be needed. for/list does indeed return a list, and this is one reason for problems encountered by OP example code. (Other problems in OP code include that x is a number with [x (in-range 20)], so (cdr x) is not defined).
A possible solution would be to recurse over the input list, using take to grab the next three values, keeping the third, and using drop to reduce the input list:
;; Recurse using `take` and `drop`:
(define (every-3rd-1 lst)
(if (< (length lst) 3)
'()
(cons (third (take lst 3))
(every-3rd-1 (drop lst 3)))))
Another option would be to recurse on the input list using an auxiliary counter; starting from 1, only keep the values from the input list when the counter is a multiple of 3:
;; Recurse using an auxilliary counter:
(define (every-3rd-2 lst)
(define (every-3rd-helper lst counter)
(cond [(null? lst)
'()]
[(zero? (remainder counter 3))
(cons (first lst) (every-3rd-helper (rest lst) (add1 counter)))]
[else (every-3rd-helper (rest lst) (add1 counter))]))
(every-3rd-helper lst 1))
Yet another possibility would be to use for/list to build a list; here i is bound to values from the input list, and counter is bound to values from a list of counting numbers:
;; Use `for/list` to build a list:
(define (every-3rd-3 lst)
(for/list ([i lst]
[counter (range 1 (add1 (length lst)))]
#:when (zero? (remainder counter 3)))
i))
This function (or any of them, for that matter) could be usefully generalized to keep every nth element:
;; Generalize to `every-nth`:
(define (every-nth n lst)
(for/list ([i lst]
[counter (range 1 (add1 (length lst)))]
#:when (zero? (remainder counter n)))
i))
Finally, map could be used to create a list containing every nth element by mapping over a range of every nth index into the list:
;; Use `map` and `range`:
(define (every-nth-map n lst)
(map (lambda (x) (list-ref lst x)) (range (sub1 n) (length lst) n)))
If what OP really requires is simply to print every third value, rather than to create a list of every third value, perhaps the code above can provide useful materials allowing OP to come to a satisfactory conclusion. But, each of these functions can be used to print results as OP desires, as well:
scratch.rkt> (for ([x (every-3rd-1 '(a b c d e f g h i j k l m n o p))])
(displayln x))
c
f
i
l
o
scratch.rkt> (for ([x (every-3rd-2 '(a b c d e f g h i j k l m n o p))])
(displayln x))
c
f
i
l
o
scratch.rkt> (for ([x (every-3rd-3 '(a b c d e f g h i j k l m n o p))])
(displayln x))
c
f
i
l
o
scratch.rkt> (for ([x (every-nth 3 '(a b c d e f g h i j k l m n o p))])
(displayln x))
c
f
i
l
o
scratch.rkt> (for ([x (every-nth-map 3 '(a b c d e f g h i j k l m n o p))])
(displayln x))
c
f
i
l
o
Here is a template:
(for ([x (in-list xs)]
[i (in-naturals]
#:when some-condition-involving-i)
(displayln x))

Remove from list from other list

I have list witch contain other lists (2 levels only)
((S U S U R) (S U S R) (S U R))
How to remove the lists from list which contains some pairs, the same combination of 2 element on first ans second position in list or 3th and 4th position (in my example "S U") and to return ((S U S R) (S U R))
I need to transform
((S U S U R) (S U S R) (S U R)) to => ((S U S R) (S U R))
((S U R S U) (S U S R) (S U R)) to => ((S U R S U) (S U S R) (S U R)) - do not change, because here is pairs have S U, R S, U and no S U 2 or more times
REMOVE-IF
(remove-if #'oddp '(1 2 3 4 5))
=> (2 4)
LAMBDA
(funcall (lambda (x) (string x)) :example)
=> "EXAMPLE"
EQUALP
(equalp '(S U) (list 's 'u))
=> T
SUBSEQ
(subseq '(a b c d) 0 3)
=> (A B C)
Careful:
(subseq '(a b c d) 0 10)
=> ERROR
You can also use LENGTH to get the size of a list. You could also use following functions...
NTHCDR
(nthcdr '(s u s u r u) 5)
=> (U)
LDIFF
(let ((list '(a b c d)))
(ldiff list (nthcdr 10 list)))
=> (A B C D)
(let ((list '(a b c d)))
(ldiff list (nthcdr 2 list)))
=> (A B)
What you want to do
You want to remove elements from the input list that satisfy the following predicate: given a list, a subset of this list is equal to (S U) (see comments).
Your code will looks like this:
(defun remove-s-u-at-pos-3 (list)
(remove-if (lambda (...) ...) list))
You need to extract a part of each visited list and compare it to (S U).

Return elements if they are in two given lists in lisp

How can i return elements if they are in two given lists?
Example:
L1 = (a b c d e a b c)
L2 = (a d f g k c c)
Result = (a a a c c c c d d)
I want to remove elements that arent in both lists and, then, append the resultant lists
You can start with a hash table, mapping a list element to a pair, first being elements from the first list, second - elements from the second. Then you collect the elements:
(defun common-elements (l1 l2 &key (test 'eql))
(let ((ht (make-hash-table :test test)) ret)
(dolist (e l1)
(let ((pair (gethash e ht)))
(if pair
(push e (car pair))
(setf (gethash e ht) (cons (list e) nil)))))
(dolist (e l2)
(let ((pair (gethash e ht)))
(when pair ; no need to store e when it is not in l1
(push e (cdr pair)))))
(maphash (lambda (e pair)
(declare (ignore e))
(when (cdr pair) ; we know (car pair) is non-nil
(setq ret (nconc (car pair) (cdr pair) ret))))
ht)
ret))
(common-elements '(a b c d e a b c) '(a d f g k c c))
==> (A A A C C C C D D)
Note that the order in which the list elements are returned is not defined.

Count elements and return them

I want to count the elements in a list and return a list containing the elements paired with them respective quantity
Something like that:
Input:
(count-elements '(a b d d a b c c b d d))
Output:
((a 2) (b 3) (d 4) (c 2))
How can I do it? I'm not having any success trying to pair the element and its accounting
Your problem can be divided into three broad parts:
Duplicate recognition/ deletion : This can be done by either removing all the duplicates of every element, or by knowing that the current element is a duplicate(and thus not counting it as a new element.). This(the former strategy) can be done by using the function remove-duplicates
Counting: A way to actually count the elements. This can be done by the function count
Combination: A way to combine the results into a list. This can be done by the macro push.
The Code:
(defun count-elements (lst)
(loop for i in (remove-duplicates lst)
with ans = nil
do (push (list i (count i lst)) ans)
finally (return ans)))
CL-USER> (count-elements '(a a b c))
((C 1) (B 1) (A 2))
CL-USER> (count-elements '(a b c d d a b s a c d))
((D 3) (C 2) (A 3) (S 1) (B 2))
CL-USER>
NOTE: The result might not be arranged as you would expect, because of the value returned by remove-duplicates
EDIT: As pointed out by coredump, a better version of count-elements would be:
(defun count-elements (lst)
(map 'list
(lambda (e)
(list e (count e lst)))
(remove-duplicates lst)))
which, instead of using loop, uses map.

LISP Displaying binary tree level by level

I have a list that looks like (A (B (C D)) (E (F))) which represents this tree:
A
/ \
B E
/ \ /
C D F
How do I print it as (A B E C D F) ?
This is as far as I managed:
((lambda(tree) (loop for ele in tree do (print ele))) my-list)
But it prints:
A
(B (C D))
(E (F))
NIL
I'm pretty new to Common LISP so there may be functions that I should've used. If that's the case then enlight me.
Thanks.
Taking your question at face value, you want to print out the nodes in 'breadth-first' order, rather than using one of the standard, depth-first orderings: 'in-order' or 'pre-order' or 'post-order'.
in-order: C B D A E F
pre-order: A B C D E F
post-order: C D B F E A
requested order: A B E C D F
In your tree structure, each element can be either an atom, or a list with one element, or a list with two elements. The first element of a list is always an atom.
What I think the pseudo-code needs to look like is approximately:
Given a list 'remains-of-tree':
Create empty 'next-level' list
Foreach item in `remains-of-tree`
Print the CAR of `remains-of-tree`
If the CDR of `remains-of-tree` is not empty
CONS the first item onto 'next-level'
If there is a second item, CONS that onto `next-level`
Recurse, passing `next-level` as argument.
I'm 100% sure that can be cleaned up (that looks like trivial tail recursion, all else apart). However, I think it works.
Start: (A (B (C D)) (E (F)))
Level 1:
Print CAR: A
Add (B (C D)) to next-level: ((B (C D)))
Add (E (F)) to next-level: ((B (C D)) (E (F)))
Pass ((B (C D) (E (F))) to level 2:
Level 2:
Item 1 is (B (C D))
Print CAR: B
Push C to next-level: (C)
Push D to next-level: (C D)
Item 2 is (E (F))
Print CAR: E
Push F to next-level: (C D F)
Pass (C D F) to level 3:
Level 3:
Item 1 is C
Print CAR: C
Item 2 is D
Print CAR: D
Item 3 is F
Print CAR: F
It seems that the way you represent your list is inconsistent. For your example, I imagine it should be: (A ((B (C D)) (E (F)))). This way, a node is consistently either a leaf or a list where the car is the leaf and the cadr is the children nodes.
Because of this mistake, I am assuming this is not a homework. Here is a recursive solution.
(defun by-levels (ts)
(if (null ts)
'()
(append
(mapcar #'(lambda (x) (if (listp x) (car x) x)) ts)
(by-levels (mapcan #'(lambda (x) (if (listp x) (cadr x) '())) ts)))))
by-levels takes a list of nodes and collects values of the top-level nodes, and recursively find the next children to use as the next nodes.
Now,
(defun leafs-of-tree-by-levels (tree)
(by-levels (list tree)))
(leafs-of-tree-by-levels '(a ((b (c d)) (e (f)))))
; (A B E C D F)
I hope that makes sense.
My Lisp is a little rusty, but as Jonathan suggested, a breadth-first tree walk should do it - something along these lines
Edit: I guess I read the problem a little too quickly before. What You have is basically a syntax tree of function applications, so here is the revised code. I assume from your description of the problem that if C and D are children of B then you meant to write (B (C)(D))
; q is a queue of function calls to print
(setq q (list the-original-expression))
; for each function call
(while q
; dequeue the first one
(setq a (car q) q (cdr q))
; print the name of the function
(print (car a))
; append its arguments to the queue to be printed
(setq q (append q)(cdr a))
)
This is the history:
q: ( (A (B (C)(D))(E (F))) )
print: A
q: ( (B (C)(D))(E (F)) )
print: B
q: ( (E (F))(C)(D) )
print: E
q: ( (C)(D)(F) )
print: C
q: ( (D)(F) )
print: D
q: ( (F) )
print: F
q: nil