Get all child nodes without cycles only recursion - functional-programming

Can someone provide me with pseudo code please? I can't use for, while etc. I can only call my functions.

If you want to get all child nodes of an arbitrary binary tree node, you may do this:
(define (traverse node)
(cond ((null? node) '())
((not (pair? node)) node)
(else (cons (traverse (left-child node))
(traverse (right-child node))))))
For N-ary tree you could use kind of get-child functions instead of left and right child functions.

Related

Racket recursion

I'm new to Racket and I'm trying to define a function that takes a list of divisors and a list of numbers to test, and applies direct recursion and a function 'drop-divisible' for each element in the list of divisors.
I defined a function drop-divisible which takes a number and a list of numbers, and returns a new list containing only those numbers not "non-trivially divisible" by the number. This function is not the problem, it works. So what I have trouble with is the function who is gonna call this function, and itself.
Here is what I've come up with. I can imagine that this is far from correct, but I have no idea what to do.
(define (sieve-with divisors testlist)
(if (null? divisors)
'()
(begin
(drop-divisible (first divisors) testlist)
(sieve-with (rest divisors) testlist))))
You need to use tail recursion:
(define (sieve-with divisors list)
(cond [(empty? divisors) list]
[else (sieve-with (rest divisors)
(drop-divisible (first divisors) list))]))
Also, stay away from begin as much as possible. Stick to the functional paradigm.

Reverse a list in scheme

I'm trying to reverse a list in scheme and I came up with to the following solution:
(define l (list 1 2 3 4))
(define (reverse lista)
(car (cons (reverse (cdr (cons 0 lista))) 0)))
(display (reverse l))
Although it works I don't really understand why it works.
In my head, it would evaluate to a series of nested cons until cons of () (which the cdr of a list with one element).
I guess I am not understanding the substitution model, could someone explain me why it works?
Obs:
It is supposed to work only in not nested lists.
Taken form SICP, exercise 2.18.
I know there are many similar questions, but as far as I saw, none presented
this solution.
Thank you
[As this happens quite often, I write the answer anyway]
Scheme implementations do have their builtin versions of reverse, map, append etc. as they are specified in RxRS (e.g. https://www.cs.indiana.edu/scheme-repository/R4RS/r4rs_8.html).
In the course of learning scheme (and actually any lisp dialect) it's really valuable to implement them anyway. The danger is, one's definition can collide with the built-in one (although e.g. scheme's define or lisp's label should shadow them). Therefore it's always worth to call this hand-made implementation with some other name, like "my-reverse", "my-append" etc. This way you will save yourself much confusion, like in the following:
(let ([append
(lambda (xs ys)
(if (null? xs)
ys
(cons (car xs) (append (cdr xs) ys))))])
(append '(hello) '(there!)))
-- this one seems to work, creating a false impression that "let" works the same as "letrec". But just change the name to "my-append" and it breaks, because at the moment of evaluating the lambda form, the symbol "my-append" is not yet bound to anything (unlike "append" which was defined as a builtin procedure).
Of course such let form will work in a language with dynamic scoping, but scheme is lexical (with the exception of "define"s), and the reason is referential transparency (but that's so far offtopic that I can only refer interested reader to one of the lambda papers http://repository.readscheme.org/ftp/papers/ai-lab-pubs/AIM-453.pdf).
This reads pretty much the same as the solutions in other languages:
if the list is empty, return an empty list. Otherwise ...
chop off the first element (CAR)
reverse the remainder of the list (CDR)
append (CONS) the first element to that reversal
return the result
Now ... given my understanding from LISP days, the code would look more like this:
(append (reverse (cdr lista)) (list (car lista)))
... which matches my description above.
There are several ways to do it. Here is another:
(define my-reverse
(lambda (lst)
(define helper
(lambda (lst result)
(if (null? lst)
result
(helper (cdr lst) (cons (car lst) result)))))
(helper lst '())))

How do I stop recursion and return something in racket?

NOTE: I would like to do this without rackets built in exceptions if possible.
I have many functions which call other functions and may recursively make a call back to the original function. Under certain conditions along the way I want to stop any further recursive steps, and no longer call any other functions and simply return some value/string (the stack can be ignored if the condition is met).. here is a contrived example that hopefully will show what I'm trying to accomplish:
(define (add expr0 expr1)
(cond
[(list? expr0) (add (cadr expr0) (cadr (cdr expr0)))]
[(list? expr1) (add (cadr expr1) (cadr (cdr expr1)))]
[else (if (or (equal? expr0 '0) (equal? expr1 '0))
'(Adding Zero)
(+ expr0 expr1))]
))
If this were my function and I called it with (add (add 2 0) 3), Then the goal would be to simply return the entire string '(Adding Zero) ANYTIME that a zero is one of the expressions, instead of making the recursive call to (add '(Adding Zero) 3)
Is there a way to essentially "break" out of recursion? My problem is that if i'm already deep inside then it will eventually try to evaluate '(Adding Zero) which it doesn't know how to do and I feel like I should be able to do this without making an explicit check to each expr..
Any guidance would be great.
In your specific case, there's no need to "escape" from normal processing. Simply having '(Adding Zero) in tail position will cause your add function to return (Adding Zero).
To create a situation where you might need to escape, you need something a
little more complicated:
(define (recursive-find/collect collect? tree (result null))
(cond ((null? tree) (reverse result))
((collect? tree) (reverse (cons tree result)))
((not (pair? tree)) (reverse result))
(else
(let ((hd (car tree))
(tl (cdr tree)))
(cond ((collect? hd)
(recursive-find/collect collect? tl (cons hd result)))
((pair? hd)
(recursive-find/collect collect? tl
(append (reverse (recursive-find/collect collect? hd)) result)))
(else (recursive-find/collect collect? tl result)))))))
Suppose you wanted to abort processing and just return 'Hahaha! if any node in the tree had the value 'Joker. Just evaluating 'Hahaha! in tail position
wouldn't be enough because recursive-find/collect isn't always used in
tail position.
Scheme provides continuations for this purpose. The easiest way to do it in my particular example would be to use the continuation from the predicate function, like this:
(call/cc
(lambda (continuation)
(recursive-find/collect
(lambda (node)
(cond ((eq? node 'Joker)
(continuation 'Hahaha!)) ;; Processing ends here
;; Otherwise find all the symbols
;; in the tree
(else (symbol? node))))
'(Just 1 arbitrary (tree (stucture) ((((that "has" a Joker in it)))))))))
A continuation represents "the rest of the computation" that is going to happen after the call/cc block finishes. In this case, it just gives you a way to escape from the call/cc block from anywhere in the stack.
But continuations also have other strange properties, such as allowing you to jump back to whatever block of code this call/cc appears in even after execution has left this part of the program. For example:
(define-values a b (call/cc
(lambda (cc)
(values 1 cc))))
(cc 'one 'see-see)
In this case, calling cc jumps back to the define-values form and redefines a and b to one and see-see, respectively.
Racket also has "escape continuations" (call/ec or let/ec) which can escape from their form, but can't jump back into it. In exchange for this limitation you get better performance.

Idiomatic functional way to move disc in Towers of Hanoi

I am learning Scheme and as a toy example I am doing a solution verifier (not a solver) for Towers of Hanoi.
I want to use a purely functional style (just to get into the mindset) and I represent the tower as a simple list of three lists. The starting state can look something like this:
'((0 1 2 3 4) () ())
How would I implement a function that takes a state, a source index and a target index and returns the new state? In an imperative style this would be something trivial like:
state[target].push(state[source].pop())
But every functional solution I can think of is terribly convoluted. For example:
(define (makeMove state source target)
(letrec ((recMake (lambda(tower pos disc)
(if (null? tower) '()
(cons (if (eqv? pos source)
(cdr (car tower))
(if (eqv? pos target)
(cons disc (car tower))
(car tower)))
(recMake (cdr tower)
(+ pos 1)
disc))))))
(recMake state 0 (car (list-ref state source)))))
This seems to work, but there must be a better way. I suppose a map would be somewhat better than recursion, but still too much. Would it be easier if I represented state differently?
Also, feel free to criticize my code. I don't really know what I am doing.
EDIT:
If possible, I prefer that you not assume that the number of towers are always 3.
Here's a super-straightforward way. I'm not sure what the significance of the disc "numbers" are in your implementation, but I made it behave the same as your answer does, pushing and popping them.
(define (make-move state source target)
(define (alter-tower tower index disc)
(cond ((= index source) (cdr tower)) ; remove a disc
((= index target) (cons disc tower)) ; add a disc
(else tower))) ; this tower wasn't changed
(let ((disc (car (list-ref state source))))
(let ((s0 (alter-tower (list-ref state 0) 0 disc))
(s1 (alter-tower (list-ref state 1) 1 disc))
(s2 (alter-tower (list-ref state 2) 2 disc)))
(list s0 s1 s2))))
If you assume the existence of a map-with-index function, which comes standard in many languages and libraries but is not built into Scheme, then you could roll up the bottom set of operations on each tower into a call to that, and it would be much cleaner.
In general, try to come up with pure functions down to the lowest level possible which do what you want. In this solution, I invented a pure function "alter-tower" which can return the result of your command on a single tower, and that's what makes the rest of the solution very straightforward.
Since you asked for feedback, I note that = is identical for eqv? when applied to numbers, that internal defines work in Scheme and act as you'd expect (e.g. you can call them recursively) and that the usual naming convention in Lisp is to separate multi-word identifiers with hyphens, instead of using camel-case.
Good luck!
EDIT: Here's a version, for example, that uses Racket's list comprehensions:
(define (make-move state source target)
(define (alter-tower tower index disc)
(cond ((= index source) (cdr tower)) ; remove a disc
((= index target) (cons disc tower)) ; add a disc
(else tower))) ; this tower wasn't changed
(let ((disc (car (list-ref state source))))
(for/list ([(tower idx) (in-indexed state)])
(alter-tower tower idx disc))))
Many functional languages have a map that can take a predicate which consumes the index, so those two lines might instead look like:
(map (lambda (tower idx) (alter-tower tower idx disc)) state)
So depending on your Scheme dialect and libraries it might be different. (I don't think there's an SRFI for this, but I might be mistaken.) Or you could always write the above version of map yourself.

Recursively check for atoms in a list

I am attempting to write a small recursive program that tests a list and returns t if every element is an atom. The problem I am having is that when the function receives an empty list, it returns t instead of the desired result of nil. I cannot come up with a way to have it return nil for an initially empty list and still function properly in a recursive manner.
(defun only-atoms (in)
(if (null in)
t
(and (atom (first in)) (only-atoms (cdr in)) )
)
)
The function can be implemented without recursion using e.g. every, as in:
(defun only-atoms (list)
(and list (every #'atom list)))
When it comes to your stated problem that the function returns T instead of the desired result of NIL when the function is called with an empty list:
Your recursive implementation explicitly returns T if (null in) is true, which explains your finding. Simply change it to the desired value NIL. Consider changing the if construct to and.
Only make the recursive call when the list has more than one item. A well placed test for (rest in) will do. Provide a true value instead of making the recursive call if the list is at its last item.
Carefully locate the only-atoms call to ensure that the function can be tail-recursive.
For example:
(defun only-atoms (list)
(and list
(atom (first list))
(or (null (rest list))
(only-atoms (rest list)))))
Use COND, which allows you to test for several cases:
empty list -> nil
one element list -> atom? ; hint: don't use LENGTH
else -> atom? for first element and recursive call for rest elements
The empty list does fulfill the condition that every element is an atom! Your requirement that it should contain at least one element is an additional requirement.
The simplest way to express "every element of the list is an atom" is (every #'atom list). You can combine it with your additional requirement with and.
If you insist on doing it recursively in SICP-style, separate your requirements:
(defun not-empty-and-all-atoms (list)
(and list
(all-atoms list)))
(defun all-atoms (list)
(if (endp list)
t
(and (atom (first list))
(all-atoms (rest list)))))
This solution works correctly:
(defun lat-p (lst)
(labels ((lat-p* (lst)
(cond
((null lst) t)
((atom (car lst)) (lat-p* (cdr lst)))
(t nil))))
(if lst
(lat-p* lst)
nil)))
However a much more elegant solution(with no recursion) would be:
(defun lat-p (lst)
(and lst (every #'atom lst)))
You can split your function in two, and provide the initial nil screening before you enter recursion. The following code is one way to do so (I tried to keep it as close to provided code as possible):
(defun only-atoms (in)
(defun only-atoms-iter (in)
(if (null in)
t
(and (atom (first in)) (only-atoms-iter (cdr in)))))
(unless (null in)
(only-atoms-iter in)))
This is also a good opportunity to make your function tail recursive:
(defun only-atoms (in)
(defun only-atoms-iter (in state)
(if (null in)
state
(only-atoms-iter (cdr in) (and state (atom (first in))))))
(unless (null in)
(only-atoms-iter in t)))

Resources