List of Leaves in Racket - functional-programming

I am trying to create a list of leaves of a tree in Racket.
(define-struct (Some T)
([value : T]))
(define-type (Option T)
(U 'None (Some T)))
(define-type BST (U 'E Nd))
(define-struct Nd
([root : Integer]
[lsub : BST]
[rsub : BST]))
(: leaves : BST -> (Listof Integer))
;; return the list of leaves from left to right
;; note: the result must be strictly ascending
(define (leaves x)
(match x
('E '())
((Nd ro 'E 'E) (list ro))
((Nd ro ls rs)
(append (leaves ls) (leaves rs)))))
The above function however does not work. I get a list of all the leaves but its not ascending. Can someone please help?
I am learning to code at home so don't have access to teachers or mentors.

Related

Counting number of occurrences of elements in a list

I am writing a function called count-if, which takes in a predicate, p?, and a list, ls. The function returns the number of occurrences of elements in the nested list that satisfy p?
For example: (count-if (lambda (x) (eq? 'z x)) '((f x) z (((z x c v z) (y))))) will return 3. This is what I have written:
(define (count-if p ls) (cond
((null? ls) '())
((p (car ls))
(+ 1 (count-if p (cdr ls))))
(else
(count-if p (cdr ls)))))
But I just get an error. I could use some help finding a better way to go about this problem. Thanks!
What is the signature of count-if? It is:
[X] [X -> Boolean] [List-of X] -> Number
What does the first cond clause return? It returns:
'()
This is a simple type error. Just change the base case to 0 and count-if works.
Edit (for nested).
First we define the structure of the date as Nested.
A symbol is just fed into the score helper function. Otherwise the recursive call is applied on all nested sub-nesteds, and the results are summed up.
#lang racket
; Nested is one of:
; - Number
; - [List-of Nested]
; Nested -> Number
(define (count-if pred inp)
; Symbol -> Number
(define (score n) (if (pred n) 1 0))
; Nested -> Number
(define (count-if-h inp)
(if (symbol? inp)
(score inp)
(apply + (map count-if-h inp))))
(count-if-h inp))
(count-if (lambda (x) (eq? 'z x)) '((f x) z (((z x c v z) (y)))))
; => 3

Racket Tree Travesal

I have the following problem with Racket.
I'm trying to implement tree pre-order, post-order traversal for a generic tree.
The struct definition is:
(define-struct eempty [])
(define-struct branch [left value right])
I can't use the unless/when operator, just if and cond.
I can't really come up with a solution. I've looked at the wikipedia pseudocode but it's not really helping due to racket programming paradigm.
(define (inorder tree x)
(cond [(and (branch? tree) (branch? (branch-left tree))) (inorder (branch-left tree) x)]
[(and (branch? tree) (branch? (branch-right tree))) (inorder (branch-right tree) x)]
This is what I've done until now, but it has problems when matching an empty struct.
Update:
What I am trying to do is display / printing node value in-order or/and post-order.
I know I have to implement (somehow) 2 more conditions:
(and (branch? tree) (empty? (branch-left tree))) do-something x)
(and (branch? tree) (empty? (branch-right tree))) do-something x)
What do I have to do in do-something? I think I'm missing this point.
Any help?
We start with what we have:
#lang racket
(define-struct empty []) ; no fields
(define-struct branch [left value right]) ; three fields
We can try to make some trees:
(define t1 (empty))
(define t2 (branch t1 7 t1))
Now we can try playing with it a little:
> t2
#<branch>
> (branch-left t2)
#<empty>
> (branch-left t1)
branch-left: contract violation
expected: branch?
given: #<empty>
> (branch? t2)
#t
> (branch? t1)
#f
> (empty? t2)
#f
> (empty? t1)
#t
>
So that is our repertoire. Racket's struct macro defines various functions for us to use -- constructors, accessors, predicates, ... .
How to print a value? Say,
(define (display-value v)
(display #\ )
(display v))
So now we can
> (display-value (branch-value t2))
7
empty has no value field, only branch does:
(define (display-tree-inorder t)
(cond
((empty? t)
(display-empty) ) ; define it later
((branch? t)
(display-branch-inorder ; define it later
(branch-left t)
(branch-value t)
(branch-right t)))))
In defining this, we have followed the type: our trees are either empty, or a branch. This is how we defined them, with those two struct definitions.
All that's left is to complete the missing definitions for display-empty and display-branch-inorder.
But before we do this, we can also have
(define (display-tree-preorder t)
(cond
((empty? t)
(display-empty) )
((branch? t)
(display-branch-preorder
(branch-left t)
(branch-value t)
(branch-right t)))))
(define (display-tree-postorder t)
(cond
((empty? t)
(display-empty) )
((branch? t)
(display-branch-postorder
(branch-left t)
(branch-value t)
(branch-right t)))))
So what is display-empty doing? It does nothing:
(define (display-empty)
#f)
And what about display-branch-inorder?
(define (display-branch-inorder lt val rt)
according to Wikipedia I'm sure, it starts by displaying its left sub-tree,
(display-tree-inorder .... )
then it gets to display its value
(display-value .... )
and it finishes up by displaying the right sub-tree:
.... )
Same for the other two variants.
After you've done all this, you'll feel the urge to abstract, and to generalize, by following the principle of separation of concerns. Good. Our display-tree-inorder lumps together several things: it traverses a tree, according to this or that notion of order, and it does something with each node's value. All these can be abstracted over and made into arguments to a generalized procedure, say, traverse-tree.
So you see, it's quite simple: follow the types! and everything will fall in line for you.
It looks like you're missing a 'cond' branch for the 'empty' struct. You can refer to the How To Design Programs textbook for help on this, specifically the "template" step associated with mixed self-referential data.

Typed Racket convert Any to All (a)

I'm trying to call take on the output of flatten. The problem is that take requires a list of a but flatten returns a list of Any. Is there a way to convert between them? Or some other approach I'm supposed to take? I wasn't able to find any examples in the Racket Docs.
(: extend (All (a) (-> (Listof a) Integer (Listof a))))
(define (extend l n)
; extend a list to length 'n' by appending it to itself
;
; #l list of any
; #n int
; #return list of any
(take (flatten (make-list n l)) n))
From the interpreter, here are the exact types for each function for reference.
> take
- : (All (a) (-> (Listof a) Integer (Listof a)))
#<procedure:take>
> flatten
- : (-> Any (Listof Any))
#<procedure:flatten>
Here's the error message for reference too.
alg/waterfall.rkt:65:2: Type Checker: Polymorphic function `take' could not be applied to arguments:
Argument 1:
Expected: (Listof a)
Given: (Listof Any)
Argument 2:
Expected: Integer
Given: Integer
Result type: (Listof a)
Expected result: (Listof a)
#Alexis King is right. The flatten function has more complicated behavior that doesn't fit with the type you need. The append* function is simpler, and here it's actually what you need instead of flatten.
In the place where you use it:
; n : Integer
; l : (Listof a)
(take (flatten (make-list n l)) n)
; expected type: (Listof a)
The input to flatten is a (Listof (Listof a)), and for it to typecheck the output must be a (Listof a). This has to be true *even when a includes lists*.
The function you want is something with the type (Listof (Listof a)) -> (Listof a). Now, does flatten always have that type? No it can't, here's a counterexample:
a = (Listof Integer)
input : (Listof (Listof (Listof Integer)))
input = (list (list (list 1)))
expected output type: (Listof (Listof Integer))
actual output value: (list 1)
Therefore flatten cannot have the type (Listof (Listof a)) -> (Listof a). What you need is append*, which does have that type.
> append*
- : (All (a) (-> (Listof (Listof a)) (Listof a)))
#<procedure:append*>
In your example, you can use append* where you used flatten.
(: extend (All (a) (-> (Listof a) Integer (Listof a))))
(define (extend l n)
; extend a list to length 'n' by appending it to itself
;
; #l list of any
; #n int
; #return list of any
(take (append* (make-list n l)) n))

list to tree in typedracket

I am trying to convert a list of integers to a tree.
The following are my function definitions:
(define-struct (Some T)
([value : T]))
(define-type (Option T)
(U 'None (Some T)))
(define-type BST (U 'E Nd))
(define-struct Nd
([root : Integer]
[lsub : BST]
[rsub : BST]))
(: bst-from-list ((Listof Integer) -> BST))
;; build a BST from a list of integers: use foldl to do s
(define (bst-from-list x)
(cond
('() 'E)
((cons hd _) (Nd hd 'E 'E))
(else
(foldl
I am learning from home and have no idea what to do after foldl. Can someone please help me?>
You already have an (: insert : Integer BST -> BST) function.
To build a tree with the elements 1, 2, 3, using insert you could write
(insert 3 (insert 2 (insert 1 'E)))
This is a left fold over (1 2 3) with insert as the function and 'E as the initial value.
A left fold combines the first element with the initial value and then combines the result of that with the second element, and so on.
So all you need is
(: bst-from-list : ((Listof Integer) -> BST))
(define (bst-from-list ls)
(foldl insert 'E ls))

How to use 'let' and 'map' to simplify a recursive function in racket?

I'm stuck on a practice problem that requires me to simplify a recursive function by using 'let' and 'map'.
The original function (biggest-number) takes a list as input and outputs the biggest number in that list. (ex: (biggest-number (list 1 2 3)) -> 3
Here's the code for the original function.
(define (biggest-number list1)
(cond
[(empty? (rest list1)) (first list1)]
[(cons? (rest list1))
(if (> (first list1) (biggest-number (rest list1)))
(first list1)
(biggest-number (rest list1)))]))
I'm just having trouble finding a lambda function to use map with.
This is what I have so far, which is very wrong and worsened the original.
(define (simple-max list1)
(cond
[(empty? (rest list1)) (first list1)]
[(cons? (rest list1))
(let ((test (lambda (number) (if (> number (simple-max (rest list1)))
number
(simple-max (rest list1))))))
(map test list1))]))
I want to start by finding a lambda function that can replace the 'if' statement, and then use 'let' to assign a variable to the lambda equation. Can someone help me with the thinking process to get the lambda function?
I don't know how you would use map to simplify a catamorphic function (i.e. a function which folds a data structure into a value). In your case, you are folding a list into the biggest number of that list:
biggest-number :: [Int] -> Int
You can't use map because map is a structure preserving operation:
map :: (a -> b) -> [a] -> [b]
You need to fold the list into a value using an operation such as foldl:
foldl :: (b -> a -> b) -> b -> [a] -> b
This is how I would write it:
(define (max x y) (if (> x y) x y))
(define (biggest-number list) (foldl max (car list) (cdr list)))
Simple and succinct.

Resources