Is there any way to create a copy of a binary tree using a recursive breadth first implementation? - data-structures

Essentially what I am trying to do is take a binary tree with data definition
binary_tree: number | (symbol binary_tree binary_tree)
and create a new version of the tree where each leaf (a number) is replaced with a counter number. I am trying to do this left-to-right and then top-down, so using a breadth first search seems like the obvious choice to visit every node in order. However, my problem is this. I need to accumulate a new binary tree to return it. Is there any possible way to do this since we are visiting each node in order?
So in short if I have a tree defined like this:
(define bt '(foo (bar 26 12) (baz 11 (quux 117 14))))
i need to process and accumulate a new list such that
(define bt '(foo (bar 0 1) (baz 2 (quux 3 4))))
Here is my code:
(define (number-leaves bst)
(define (helper queue counter)
(cond[(non-empty-queue? queue)
(define x (dequeue! queue))
(cond [(number? x)(cons counter (helper queue (+ 1 counter)))]
[(symbol? (car x))(begin (enqueue! queue (car(cdr x)))
(enqueue! queue (car(cdr(cdr x))))
(cons (list(car x)) (helper queue counter)))])]
['()]))
(begin (define q (make-queue))
(enqueue! q bst)
(helper q 0)))
as of now this function returns
(foo bar baz 0 1 2 quux 3 4)
It seems to me that it is impossible to accumulate into a recursive data definition while processing the tree breadth first. What can I do? (NB: car = first and cdr = rest in the EOPL racket dialect)

I think you will need to do two passes.
breath first while making a lookup based on the pairs that hold the leaf and their incremental new value. It's important to use the pairs since the numbers by themselves are not guaranteed unique, thus (eq? 2 2) can be #t even though they are different places.. Comparing the pairs that holds the twos are guaranteed to be only eq? with the very same value.
A standard post order tree traversal where you fetch the new values from the lookup.
The lookup should be a hash for efficiency, but it can be a assoc list for small trees. If you expect the hash to do O(1) when iterating over all the element twice will still only make it O(n).

Related

Modified Sieve for finding Prime Numbers in Scheme

I am working on coming up with a solution for coming with a list of prime numbers using the Sieve of Eratosthenes. So the program is supposed to find prime numbers up to a specific number "n". I believe I have come up with an incomplete solution but not sure how to proceed from here.
;;;This is a helper function
(define sievehelper
(lambda (list)
;;; This is the base condition where we are comparing
;;; that the divisor is less than the square root of n""
(if (> (car list) (sqrt (car (reverse list))))
'()
;;; If the base condition has not be reached, then send it through
;;; this filter function where not-divisible by will go through
;;; the specified list and only output the list which contains
;;; the numbers that are not divisible by (car list)
(filterfunc (not-divisible-by (car list))
list)))
I have tested the other helper function fliterfunc on its own and it works fine.
;;;; This is the main function that calls the above helper function
(define sieve
(lambda (n)
;;; `makelist` is a helper function to generate the list from 2 to n
(sievehelper (makelist n))))
I have tested the makelist helper function separately and it works fine.
My question is with the helper function "sievehelper" in terms of how to iterate through the different elements in the list as the divisor.
Any help is appreciated. Thank you.
One piece of code that leads to getting stuck is (if ( > (car list) (sqrt (car(reverse list)))), which looks a lot like the loop condition you might use in other languages (and the word "iterate" hints at peeking at other languages, as well).
I would recommend that you start over, with a different strategy.
When you work with lists, you usually want to recurse on their structure alone.
Assume that you have the list of all integers, starting with 2.
As a first step, you want to keep the two, and remove all its multiples from the remainder of the list.
Now, the result of that removal will give you a list that starts with the next prime number - i.e. 3 - so you can repeat the procedure with that partial result which will remove all multiples of 3, and repeat again with that partial result, and so on until there is no more list.
(Note that this is far from as efficient as it could be, but is more a "get started with thinking recursively" level of suggestion. Read Will's answer for more.)
Applying some wishful thinking and assuming that there is a procedure remove-multiples-of which does what it sounds like, this could look like this:
(define (my-sieve-helper ls)
(if (null? ls)
'()
(cons (car ls)
(my-sieve-helper (remove-multiples-of (car ls) (cdr ls))))))
So, remove-multiples-of...
This is the same as keeping all the numbers that are not divisible by a number, so let's dream up another function:
(define (remove-multiples-of x ls) (filter (not-divisible-by x) ls))
where (not-divisible-by x) is a procedure that takes a number and returns whether that number is not divisible by x.
(define (not-divisible-by n) (lambda (x) (not (zero? (remainder x n)))))
And now we can add a suitable wrapper.
I did this:
(define (from-to m n)
(if (> m n)
'()
(cons m (from-to (+ m 1) n))))
(define (my-sieve n) (my-sieve-helper (from-to 2 n)))
Test:
> (my-sieve 100)
'(2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97)
Well, your question presents an interesting case of under-specification that can be advantageous, delaying the actual specification -- not just implementation as usual -- of subroutines used by your piece of code.
Here we have sievehelper which uses the non-implemented non-specified filterfunc and not-divisible-by. Despite their suggestive names these function can do anything, as long as they work, when used together, and make the function using them, sievehelper, also do its work as intended. Delayed specification for the win!
So let's first see what can be intended with the sievehelper as given, what does it do? Assuming the obvious meaning of the two subroutines, it seems to be intended to perform a one-step filtering of its working sequence, culling it from any multiples of its "head" element, the one in its car position.
It would signal the stopping condition by returning (). That stopping condition is a*a > z, for the input list of [a,b,c,...,z].
Otherwise, it does not perform the looping, but just the one step of it. Your sieve doesn't account for that at all, so will need to be changed to continually call this helper, performing step after step as is usual in sieving algorithms, until the square of the first element is bigger than the last element in the working sequence, when it is indeed safe to stop the culling as all the multiples in the sequence will have already been removed from it as multiples of the smaller primes ...... provided that those smaller primes were present in the initial sequence.
So this discovered requirement falls on the third non-implemented subrouting in use, makelist. You do mention that it must create the list of sequential natural numbers from 2 to n, and now we understand why we needed it to do so.
So then, in order to iterate through the different versions of the input list as each divisor is filtered out from it in turn, using your sievehelper definition as given, your sieve function must be changed as e.g.
(define sieve
(lambda (n)
(let ((init (makelist n)))
(let loop ((this init )
(next (sievehelper init)))
(if (null? next)
this
(cons (car this)
(loop next
(sievehelper next))))))))
(The above code incorporates the fix by ad-absurdum from the followup Q&A entry, to the error that this code originally contained).
This code comes from the perspective of working with a pair -- the current sequence, and its next iteration. On each step the next version of the list is found after all the multiples of its head element are removed from it by sievehelper (including the head element itself, the next found prime) -- or the empty list is instead returned to signal the end of processing when all the numbers in the list are known to already be prime, by construction.
Trying it out in Racket:
> (sieve 50)
'(2 3 5 7 11 13 17 19 23 29 31 37 41 43 47)
To run it, further definitions had to be made:
(define filterfunc filter)
(define (not-divisible-by n) ; NB! this critically depends on
(let ((m n)) ; filterfunc working over its
(lambda (x) ; argument list _in order_ NB!
(let ((ret (not (= x m))))
(if (>= x m) (set! m (+ m n)) #f)
ret))))
(define (makelist n)
(range 2 (+ 1 n))) ; in Racket
Defining the not-divisible-by as we did here, enumerating the multiples of each prime internally by iterated additions, makes it be the sieve of Eratosthenes indeed. And stopping early (at the square root of the limit), as in your original code, keeps its time complexity on the sane side, closer to optimal.

Scheme - Return list of N Repetitions of said list

First off, this is a homework question so just looking for guidance and not an answer.
Write a function named (cycle ALIST N) that accepts a list of elements ALIST and an integer N. This function returns a list containing N repetitions of the elements of ALIST. If N is non-positive, this function returns the empty list.
I will be honest in that I'm not sure how to begin solving this problem. I've been thinking of writing a helper function then using cons calling this n times but just looking if I'm on the correct track here.
One of the more common ways to tackle recursive problems is to begin thinking about it at the end. In other words, under what conditions should you stop? —When are you done? If you can write this base case down, then you only need to ask, what do I do when I am one step away from stopping? This is the recursive step, and for relatively simple recursive problems you are done as the whole problem is either "continue" to do the same thing or "stop."
Knowing the base case usually tells you what kind of extra information you may need to carry around, if any.
In the case of scheme and racket, which support tail call optimization, you may end up with different kinds of recursion. For example:
(define (normal-factorial n)
(if (zero? n)
1
(* n (normal-factorial (- n 1)))))
(define (tail-factorial n)
(letrec ((tf (lambda (product index)
(if (zero? index)
product
(tf (* product index) (- index 1))))))
(tf n (- n 1))))
In the first case, we build up a product without ever multiplying until the very end, while in the second we multiply as soon as possible and carry around this temporary product the whole time.
Not all problems easily lend themselves to one kind of recursion or the other.
You have different strategies you can make. The simplest is probably not the most effiecent but the one that produces less code:
(require srfi/26) ; cut
(define (cycle lst n)
(define dup-lst (map (cut make-list n <>) lst))
(foldr append '() dup-lst))
So what this does is that the map creates a list of lists where each is n elements of each. The foldr flattens it by using append.
With more hands on you can make it more efficient. I'm thinking roll your own recursion consing the elements from end to beginning in an accumulator:
(define (cycle lst n)
(let helper ((lst (reverse lst)) (c n) (acc '()))
(cond ((null? lst) acc)
((<= c 0) (helper ...))
(else (helper ...)))))
I've left out the recursive parts. What this does is a base case on the empty list, a reset recur with a c reset to n and the cdr when c is zero and the default case keeping lst while reducing c and cons-ing the first element of lst to acc. This is a O(n) solution.

Finding the largest list in a definition of lists in lists?

I have a question regarding finding the largest list in a group of lists in scheme.
For example, we define:
(define manylsts (list (list 9 (list 8 7)) 6 (list 5 (list 4 3 2) 1)))
How would I go about finding the largest list in manylsts?
Thank you
You make a procedure that evaluates to zero if it's argument is not a list. (eg. 9), then if its a list you foldl over the elements using length of the argument as accumulator with a lambda that does max between the recursion of the first argument with the accumulator. It would look something like this:
(define (max-children tree)
(if <??>
(foldl (λ (x acc)
(max <??> (max-children <??>)))
(length <??>)
<??>)
0))
Of course there are many ways of doing this, including explicit recursion, but this was the first thing I though of.
I will answer this question as you asked it.
You said you want to
finding the largest list in manylsts
Since you included a non-listed element inside manylsts you want to have a definition that tells you how big is an element (if is a list).
So I wrote the function elemenlen that returns the length of a list if the given element is a list and 0 otherwise.
(define elemenlen
(λ (a)
(if (list? a) (length a) 0)
))
Then I decided I was going to sort them in order of length and then return the first element. So I need a function that returns a boolean value to use it with sort function included in racket/base.
(define list<
(λ (listA listB)
(< (elemenlen listA) (elemenlen listB))))
(define list>
(λ (listA listB)
(not (list< listA listB))))
The first function returns #t if listA is smaller than listB. The second function returns #t if listA is bigger than listB.
Lastly, biggestElement does the whole trick, sorts the elements in list L in descending order (based on length) and returns the first element.
(define biggestElement
(λ (L)
(car (sort L list>)
)))
The function is used like this:
>(biggestElement '((3 2 1) 1 (1 (2 3) 3))
'(1 (2 3) 3)
That is just one way of doing it, there are other ways of doing it, keep it up and tell us if it helped you.
As you see, I decomposed the big problem into little problems. This is a very handy way of doing your DrRacket homework.

Racket random list-ref function

Define a function that takes a non-empty list and returns an element of the list selected at random and with equal probability. (Do not use the built-in list-ref procedure.)
I'm stuck on this. I feel like you would need to count the number of times the function has run recursively and compare it to the random number you get, but I don't know how to do that in BSL+. Any help would be really great.
Here is a solution. To get the ball rolling the first element of the list is chosen as a candidate to be returned. Then for each element of the remaining elements in the list, we randomly choose if the candidate is to be replaced.
For example: For a list with two elements '(a b) first the element 'a is chosen.
The a coin is flipped: With probability 50% 'b is returned instead.
Examine the code to see how the algorithm works for larger lists:
(define (pick-random xs)
(pick-random/helper (rest xs) (first xs) 1))
(define (pick-random/helper xs chosen k)
(cond
[(empty? xs) chosen]
[else ; with probability 1/(k+1) choose the first element of xs
(if (= (random (+ k 1)) 0)
(pick-random/helper (rest xs) (first xs) (+ k 1))
(pick-random/helper (rest xs) chosen (+ k 1)))]))
If you want to google the theory, this type of algorithm belongs to "sampling algorithms".
I take the comment about not using list-ref as a direction to think about the problem recursively.
An assumption is made that 'equal probability' does not take into account the flaws of naive software-based RNGs.
Note that we use []-notation in the function definition to say that steps, unless specified, will have a (default) value of (random (length lst)). This means it will initially have a random amount of 'steps into' the list.
#lang racket
(define (random-element lst [steps (random (length lst))])
(if (= steps 0)
(first lst)
(random-element (rest lst)
(sub1 steps))))
Since steps is internally specified (as (sub1 steps), subtract one from steps) it will always have an explicit value except when the function is applied like so:
(random-element '(42 1337 128 256))
; 256

Another way of writing a mimum value procedure in Scheme?

So if i have the following, which returns the smallest value out of a set of four numbers:
(define (minimum2 a b c d)
(cond ((and (< a b) (< a c) (< a d)) a)
((and (< b c) (< b d)) b)
((< c d) c)
(else d)))
But, I want to write it so that I compare a to b and find the smallest value between those two, then compare c and d, and find the smallest value between those, and then compare those two smallest values together to find the actual minimum. If what I wrote was tough to understand, think of it like a tournament bracket, where a "plays" b, and the winner plays the other winner between c and d. Thank you in advance for the help!
Here's one way to do it:
(define (min4 a b c d)
(define (min2 x y)
(if (< x y) x y))
(min2 (min2 a b) (min2 c d)))
Another way to do it, if you don't want to use an internal function:
(define (min4 a b c d)
(let ((min-ab (if (< a b) a b))
(min-cd (if (< c d) c d)))
(if (< min-ab min-cd) min-ab min-cd)))
Here are two ways to do this. I think that the first, using reduce, is much more idiomatic, but it's not doing the tournament style structure, though it uses the same number of comparisons. The second, which does a tournament style structure, is actually just a special case of a generalized merge-sort. The reason that the number of comparisons is the same is that in the tournament style comparison,
min(a,b,c,d) = min(min(a,b),min(c,d))
and in the reduce formulation,
min(a,b,c,d) = min(min(min(a,b),c),d)
Both require three calls the lowest level min procedure.
A reduce based approach
This solution uses a fold (more commonly called reduce in Lisp languages, in my experience). Scheme (R5RS) doesn't include reduce or fold, but it's easy to implement:
(define (reduce function initial-value list)
(if (null? list)
initial-value
(reduce function (function initial-value (car list))
(cdr list))))
A left-associative fold is tail recursive and efficient. Given a binary function f, an initial value i, and a list [x1,…,xn], it returns f(f(…f(f(i, x1), x2)…), xn-1), xn).
In this case, the binary function is min2. R5R5 actually already includes an n-ary (well, it actually requires at least one arguments, it's at-least-one-ary) min, which means min would already work as a binary function, but then again, if you wanted to use the built in min, you'd just do (min a b c d) in the first place. So, for the sake of completeness, here's a min2 that accepts exactly two arguments.
(define (min2 a b)
(if (< a b)
a
b))
Then our n-ary min* is simply a reduction of min2 over an initial value and a list. We can use the . notation in the argument list to make this a variadic function that requires at least one argument. This means that we can do (min* x) => x, in addition to the more typical many-argument calls.
(define (min* a . rest)
(reduce min2 a rest))
For example:
(min* 4 2 1 3)
;=> 1
A true tournament-style solution based on merge sort
A proper tournament style min is actually isomorphic to merge sort. Merge sort recursively splits a list in half (this can be done in place using the indices of the original list, as opposed to actually splitting the list into new lists), until lists of length one are produced. Then adjacent lists are merged to produce lists of length two. Then, adjacent lists of length two are merged to produce lists of length four, and so on, until there is just one sorted list. (The numbers here don't always work out perfectly if the length of the input list isn't a power of two, but the same principle applies.) If you write an implementation of merge sort that takes the merge function as a parameter, then you can have it return the one element list that contains the smaller value.
First, we need a function to split a list into left and right sides:
(define (split lst)
(let loop ((left '())
(right lst)
(len (/ (length lst) 2)))
(if (< len 1)
(list (reverse left) right)
(loop (cons (car right) left)
(cdr right)
(- len 1)))))
> (split '(1 2 3 4))
((1 2) (3 4))
> (split '(1))
(() (1))
> (split '(1 2 3))
((1) (2 3))
Merge sort is now pretty easy to implement:
(define (merge-sort list merge)
(if (or (null? list) (null? (cdr list)))
list
(let* ((sides (split list))
(left (car sides))
(right (cadr sides)))
(merge (merge-sort left merge)
(merge-sort right merge)))))
We still need the merge procedure. Rather than the standard one that takes two lists and returns a list of their sorted elements, we need one that can take two lists, where each has at most one element, and at most one of the lists may be empty. If either list is empty, the non-empty list is returned. If both lists are non-empty, then the one with the smaller element is returned. I've called it min-list.
(define (min-list l1 l2)
(cond
((null? l1) l2)
((null? l2) l1)
(else (if (< (car l1) (car l2))
l1
l2))))
In this case, you can define min* to make a call to merge-sort, where the merge procedure is min-list. Merge-sort will return a list containing one element, so we need car to take that element from the list.
(define (min* a . rest)
(car (merge-sort (cons a rest) min-list)))
(min* 7 2 3 6)
;=> 2

Resources