I am trying to transform my C++ code to the Racket since I am learning Racket. My simplified C++ code is:
struct Node
{
char value = '\0';
std::vector<Node> kids;
explicit Node(char ch) : value(ch) {}
};
void ParseTree(const std::string& tokens, size_t& i, Node& root)
{
while (i < tokens.size())
{
const Token& token = tokens[i++];
if (token == '<') // children begin
{
ParseTree(tokens, i, root.kids.back());
}
else if (token == '>') // children end, go up
{
return;
}
else
{
root.kids.emplace_back(token);
}
}
}
Node ParseTree(const std::string& s)
{
size_t i = 0;
Node root('$');
ParseTree(Parse(s), i, root);
return root;
}
So very simple code. My translation to Racket is:
(define (parse-tree tokens)
(if(empty? tokens)
'()
(cond
[(eq? '< (car tokens))
(list (parse-tree (cdr tokens)))]
[(eq? '> (car tokens))
(parse-tree (cdr tokens))] ; no return, how to step up?
[else
(cons (car tokens)(parse-tree (cdr tokens)))])))
The problem here is I am not returning up in (eq? '> (car tokens) so new nodes are added to the bottom.
A small test:
(parse-tree '(1 < 2 < 3 4 > > Z < X >))
Should be:
'(1 (2 (3 4)) Z (X))
It is:
'(1 (2 (3 4 Z (X))))
How to fix it?
The problem with your original approach is that you're trying to directly port an imperative solution, one that even uses pass-by-reference to keep track of the state of the traversal. That won't work, the first step would be to rethink the solution in a functional-programming style.
These kinds of problems where we have to keep track of where we're inside a nested structure, are better solved using a stack data structure. I'll use a list to implement a stack of lists, with the following helper for appending a new element on the topmost list:
(define (append-top ele stack)
(cons (append (car stack) (list ele))
(cdr stack)))
Now for the actual solution. Assuming that the input list is well-formed with the same number of < and > and in the correct order (no error checking is performed):
(define (parse-tree tokens)
(let parse ([tokens tokens] [stack '(())])
(cond [(null? tokens)
; solution is at the top of the stack, return it
(car stack)]
[(eq? (car tokens) '<)
; start new sublist at the top of the stack
(parse (cdr tokens) (cons '() stack))]
[(eq? (car tokens) '>)
; pop top element of the stack, append it to previous
; frame, continue with solution where we left it
(parse (cdr tokens) (append-top (car stack) (cdr stack)))]
[else
; add current element to top of stack
(parse (cdr tokens) (append-top (car tokens) stack))])))
It works as expected!
(parse-tree '(1 < 2 < 3 4 > > Z < X >))
=> '(1 (2 (3 4)) Z (X))
Related
Write a Lisp program to check whether a binary tree is a Binary Search Tree.
The left sub-tree of a node has a key less than or equal to its parent node's key. The right sub-tree of a node has a key greater than to its parent node's key.
A list can be used to represent the structure of a binary tree as follows:
'(8 (3 (1 () ()) (6 (4 () ())( 7 () ()))) (10 (()) (14 (13) ()))) where this would return true.
I am trying to write a binary recursive approach but I'm a beginner and I have no idea where to go from here.
(defun isBST (L)
(cond
((null (first L)) t)
((and (not (null (caadr L)) ) (< (first L) (caadr L)) ) nil)
((and (not (null (caaddr L))) (> (car L) (caaddr L))) nil)
((and (not (isBST (cadr L))) (not (isBST (caddr L)))) ))
)
You can express your definitions in code to make your life easier.
A node is represented as a list of three things: a key, a left subtree, and a right subtree.
(defun node-key (node)
(first node))
(defun node-left-subtree (node)
(second node))
(defun node-right-subtree (node)
(third node))
For a tree to be a binary search tree, four conditions must be met, unless both subtrees are empty:
the left subtree must be a binary search tree
the right subtree must be a binary search tree
the largest key of the left subtree (if present) must be smaller than the root key
the smallest key of the right subtree (if present) must be bigger than the root key
Note: the naming convention in Lisp is to write everything in lower case, with word parts separated by dashes. A predicate, i. e. a function that is used to obtain a truth value, ends with p. The predicate for a binary search tree might be named bst-p or binary-search-tree-p. The function to obtain the largest key of a bst might be called bst-largest-key.
In order to get the largest (smallest) key of a BST, you only need to recurse on the right (left) subtree.
Here's a scheme procedure that might help you.
(define (is-bst l)
(define (loop node proc)
(if (null? node)
#t
(and (proc (car node))
(loop (cadr node)
(curry > (car node)))
(loop (caddr node)
(curry < (car node))))))
(loop l (const #t)))
It can be frustrating to fix a program when your input data is the source of the bugs. I had to fix your (()) and (13). Use multiple lines and the auto-indenter to easily find mistakes.
(is-bst '(8 (3 (1 () ())
(6 (4 () ())
(7 () ())))
(10 ()
(14 (13 () ())
()))))
;; #t
Invalidate one of the nodes to ensure is-bst detects a non-bst.
(is-bst '(8 (3 (1 () ())
(6 (4 () ())
(7 () ())))
(10 ()
(2 (13 () ()) ;; 14 changed to 2; invalid tree
()))))
;; #f
To make a slight improvement, notice we called (car node) three times in the procedure above. This should be avoided with the use of let.
(define (is-bst l)
(define (loop node proc)
(if (null? node)
#t
(let ((value (car node)))
(and (proc value)
(loop (cadr node)
(curry > value))
(loop (caddr node)
(curry < value))))))
(loop l (const #t)))
Another interesting way is using streams, which can be easily implemented using basic procedures. We could write a generic traverse procedure to traverse our trees.
(define (traverse bst)
(if (null? bst)
empty-stream
(stream-append (traverse (cadr bst))
(stream (car bst))
(traverse (caddr bst)))))
(define tree
'(8 (3 (1 () ())
(6 (4 () ())
(7 () ())))
(10 ()
(14 (13 () ())
()))))
(stream->list (traverse tree))
;; '(1 3 4 6 7 8 10 13 14)
Now we write is-bst to simply check that the values come out in ascending order.
(define (is-bst l)
(define (loop x s)
(if (stream-empty? s)
#t
(let ((y (stream-first s)))
(and (< x y)
(loop y (stream-rest s))))))
(loop -inf.0
(traverse l)))
(is-bst tree)
; #t
(is-bst '(1 (2 () ())
(3 () ())))
; #f
Because a stream is used, the values come out lazily. If an early #f is found, iteration of the stream is stopped and the computation is finished.
As a project to help me understand continuations in Racket, I decided to try and write a co-routine implementation without using mutable or global variables. Here is what I have so far, but it seems to end up in a deadlock of some kind. Am I missing something obvious?
#!/usr/bin/env racket
#lang racket
(define (make-proc-args args)
(let/cc cc
(cons cc args)))
(define (fork proc)
(let ([current (make-proc-args '())])
(proc current)))
(define (yield to args)
(let ([current (make-proc-args args)])
((car to) current)))
(define c
(fork
(lambda (p)
(let loop ([i 0]
[parent p])
(unless (> i 10)
(loop (+ i 1) (yield parent (list i))))))))
(let loop ([child c])
(println (car child))
(loop (yield child '())))
(define (make-proc-args args)
(let/cc cc
(cons cc args)))
This when called returns it's continuation as a object. If you look at this code:
(define (fork proc)
(let ([current (make-proc-args '())])
(proc current)))
The continuation of (make-proc-args '()) is the application of the let with current bound and proc called. In the context of:
(fork
(lambda (p)
(let loop ([i 0]
[parent p])
(unless (> i 10)
(loop (+ i 1) (yield parent (list i)))))))
It means (yield parent (list i)) will time travel back and call and (proc current) will be called again.. The let with start with i and 0.. But one would expect the continuation of the yield to be stored, right? Wrong!
(define (yield to args)
(let ([current (make-proc-args args)])
((car to) current)))
The continuation that is captured is ((car to) current) which happen to be the same again and again and again.
The easiest way to solve this is to make the continuation have not the calling of your stored continuation as it's own continuation. Thus you need to do something like this:
(define (fork proc)
(let/cc cc
(let ([current (cons cc '())])
(proc current))))
(define (yield to args)
(let/cc cc
(let ([current (cons cc args)])
((car to) current))))
Notice that in both of these the continuation is what happens when yield and fork returns naturally and not when the body of a let is finished.
Also know that continuations are delimited at top level so you should perhaps test with all code in a let block to catch bugs you might have since continuations behave differently at top level. The define is not allowed top level, but if you put it in a let you get #<void> as the last value as child because that is the value define forms make, not the pairs you expect.
(define (worker p)
(let loop ([i 0]
[parent p])
(unless (> i 10)
(loop (+ i 1) (yield parent i)))))
(let ((c (fork worker)))
(let loop ([child c])
(when (pair? child)
(println child)
(loop (yield child '())))))
This prints:
(#<continuation> . 0)
(#<continuation> . 1)
(#<continuation> . 2)
(#<continuation> . 3)
(#<continuation> . 4)
(#<continuation> . 5)
(#<continuation> . 6)
(#<continuation> . 7)
(#<continuation> . 8)
(#<continuation> . 9)
(#<continuation> . 10)
As a last tip. Perhaps you should make a struct for your continuation object or at least abstract?
Working on CLISP in Sublime Text.
Exp. in CLISP : less than 1 year
It's already for a while that I'm trying to solve this exercice... without success... as you might guess.
In fact I have to create a function which will modify the list and keeps only sublists which are equals or greater than the given number (watch below)
The list on which I have to work :
(setq liste '((a b) c (d) (e f) (e g x) f))
I'm supposed to find this as result :
(lenght 2 liste) => ((a b) (e f) (e g x))
liste => ((a b) (e f) (e g x))
Here my code :
(defun lenght(number liste)
(cond
((atom liste) nil)
((listp (car liste))
(rplacd liste (lenght number (cdr liste))) )
((<= (lenght number (car liste)) number)
(I don't know what to write) )
((lenght number (cdr liste))) ) )
It will be very kind if you could give me only some clue so as to let me find the good result.
Thanks guys.
Modifying the list does not make much sense, because it gets hairy at the head of the list to retain the original reference. Return a new list.
This is a filtering operation. The usual operator in Common Lisp for that is remove-if-not (or remove-if, or remove, depending on the condition). It takes a predicate that should return whether the element should be kept. In this case, it seems to be (lambda (element) (and (listp element) (>= (length element) minlength))).
(defun filter-by-min-length (minlength list)
(remove-if-not (lambda (element)
(and (listp element)
(>= (length element) minlength)))
list))
In many cases, when the condition is known at compile time, loop produces faster compiled code:
(defun filter-by-min-length (minlength list)
(loop :for element :in list
:when (and (listp element)
(>= (length element) minlength))
:collect element))
This returns a new list that fulfills the condition. You'd call it like (let ((minlength-list (filter-by-min-length 2 raw-list))) …).
Many basic courses insist on recursively using primitive operations on cons cells for teaching purposes at first.
The first attempt usually disregards the possible stack exhaustion. At each step, you first look whether you're at the end (then return nil), whether the first element should be discarded (then return the result of recursing on the rest), or if it should be kept (then cons it to the recursion result).
If tail call optimization is available, you can refactor this to use an accumulator. At each step, instead of first recursing and then consing, you cons a kept value onto the accumulator and pass it to the recursion. At the end, you do not return nil, but reverse the accumulator and return that.
Well, I have found the answer that I was looking for, after scratching my head until blood...
Seriously, here is the solution which is working (and thanks for the correction about length which helped me to find the solution ^^) :
(defun filter-by-min-length (min-length liste)
(cond
((atom liste) nil)
((and (listp (car liste))(>= (length (car liste)) min-length))
(rplacd liste (filter-by-min-length min-length (cdr liste))) )
((filter-by-min-length min-length (cdr liste))) ) )
A non-modifying version
(defun filter-by-min-length (min-length le)
(cond ((atom le) nil)
((and (listp (car le)) (>= (length (car le)) min-length))
(cons (car le) (filter-by-min-length min-length (cdr le))))
(t (filter-by-min-length min-length (cdr le)))))
Test:
(defparameter *liste* '((a b) c (d) (e f) (e g x) f))
(filter-by-min-length 2 *liste*)
;; ((A B) (E F) (E G X))
*liste*
;; ((A B) C (D) (E F) (E G X) F) ; -> *liste* not modified
For building good habits, I would recommend to use defparameter instead of setq, since the behaviour of setq might not always be defined (see here). In the link, it is said:
use defvar, defparameter, or let to introduce new variables. Use setf
and setq to mutate existing variables. Using them to introduce new
variables is undefined behaviour
I'm trying to traverse a tree in lisp and print out all the parent-child relations.
Here is my input: (5 (3 (4 (1)) (g) (9 (6))) (n (8 (0)) (q) (7) (b (f (c (a))))))
I'm trying to get it to print out something along the lines of:
5>3
5>n
3>4
3>g
3>9
4>1
9>6
n>8
n>q
n>7
n>b
8>0
b>f
f>c
c>a
my current code is below:
(defun par-child-print (l)
(print l)
(cond ((not (null (caadr l)))
(print "start")
(print (car l))
(print ">")
(print (caadr l))
(print "end")
(cond ((not (atom (car l))) (when (not (eq (car l) NIL)) (par-child-print (car l)))));
(when (not (eq (cdr l) NIL)) (par-child-print (cdr l)))
)
(t
)));
The problem is that my output only sometimes prints the parent (and also it doesnt make it through the whole tree). Any ideas?
I also have this that makes it through the whole tree, but doesn't even attempt to keep track of parents:
(defun atom-print (l)
(print l)
(cond ((atom l) (print l));
(t
(when (not (eq (car l) NIL)) (atom-print (car l)))
(when (not (eq (cdr l) NIL)) (atom-print (cdr l)))
)));
Each list in the tree consists of two parts, a name and a list of children. Those are the same as the CAR and the CDR of the list, but for semantic reasons you could start by defining aliases for them:
(defun name (tree) (car tree))
(defun children (tree) (cdr tree))
These abstract away the details of how the tree is implemented. Then, given a tree you want to do two things:
Print a line per child with the parents name and the childs name. This could be done like this:
(dolist (child (children tree))
(format t "~&~a > ~a" (name tree) (name child)))
Print each child the same way. This is done by calling the function recursively on them:
(dolist (child (children tree))
(print-tree child))
So the whole function would look like this:
(defun print-tree (tree)
(dolist (child (children tree))
(format t "~&~a > ~a" (name tree) (name child)))
(dolist (child (children tree))
(print-tree child)))
(print-tree '(5 (3 (4 (1)) (g) (9 (6))) (n (8 (0)) (q) (7) (b (f (c (a)))))))
; 5 > 3
; 5 > N
; 3 > 4
; 3 > G
; 3 > 9
; 4 > 1
; 9 > 6
; N > 8
; N > Q
; N > 7
; N > B
; 8 > 0
; B > F
; F > C
; C > A
There's a problem with jkiiski's answer: it works on the given input, but only because each child has children of its own. Here's a variant on that answer that has the same behaviour on the sample input, but that also works on other trees.
(defun print-tree (tree)
(dolist (child (cdr tree))
(format t "~&~a > ~a" (car tree) (if (consp child)
(car child)
child)))
(dolist (child (cdr tree))
(if (consp child)
(print-tree child))))
(print-tree '(A (B (C 1 2 3) 4)))
A > B
B > C
B > 4
C > 1
C > 2
C > 3
I have:
(defun getTotalValue(pack)
(cond ((null pack) 0)
(t (+ (car (car pack)))) (getTotalValue (cdr pack))
)
)
Which, to my understanding, will add up all the first elements of the items in a list. A test function call would be:
(getTotalValue '((10 c u) (3 s u) (5 h d) (7 s d) (12 h u)))
However, when I run the code above, it only prints out the first element of the first item in the list, 10. Why won't it add up the first elements of all the items?
You had parenthesizing problem -- two misplaced close parenthesis after (car (car pack)), so the cond expression terminates there and the recursion happens but the result is thrown away.
(defun getTotalValue (pack)
(cond ((null pack) 0)
(t (+ (car (car pack)) (getTotalValue (cdr pack))))))