verifying size of binary trees? - sml

I have a datatype in this way
datatype 'a bin_tree =
Leaf of 'a
| Node of 'a bin_tree (* left tree *)
* int (* size of left tree *)
* int (* size of right tree *)
* 'a bin_tree (* right tree *)
so an example for correct tree would be:
val tree1 =
Node(Node(Node(Leaf 47, 1, 1, Leaf 38),
2,1,
Leaf 55),
3,2,
Node(Leaf 27, 1, 1, Leaf 96))
and an example for violating tree would be
val tree1false =
Node(Node(Node(Leaf 47, 1, 1, Leaf 38),
2,1,
Leaf 55),
4,2,
Node(Leaf 27, 1, 1, Leaf 96))
How can I write a predicate test such that
- test tree1;
val it = true : bool
- test tree1false;
val it = false : bool

This is a recursive problem. Before solving recursive problems on trees, it is a good idea to have a firm grasp on recursion on lists. You could say that trees are generalisations of lists, or that lists are special-cases of trees: lists have one tail, trees can have any number of tails depending on the type of tree. So here is how you could reconstruct and solve the problem using lists:
If, instead of the typical list definition, you have a list that also memoizes its own length:
(* datatype 'a list = [] | :: of 'a * 'a list *)
datatype 'a lenlist = Nil | Cons of int * 'a * 'a lenlist
Then you can test that the stored length is in accordance with the actual number of values.
I'll start by creating a function that counts to illustrate the part of the function that performs recursion:
(* For regular built-in lists *)
fun count0 [] = 0
| count0 (x::xs) = 1 + count0 xs
(* Counting the memoized list type disregarding the n *)
fun count1 Nil = 0
| count1 (Cons (n, x, xs)) = 1 + count1 xs
The next part is that I'd like, in each recursive step, to test that the stored number n is also in accordance with the actual counting. What is the return type of this function? Well, the test function that you want should be 'a lenlist -> bool and the count function that I made is 'a lenlist -> int.
I will suggest that you make a testcount that kinda does both. But you can do so in many ways, e.g. by giving it "extra arguments", or by giving it "extra return values". I will demonstrate both, just to show that sometimes one is better than the other and experience will tell you which.
Here is a val testcount1 : 'a lenlist -> bool * int function:
fun testcount1 Nil = (true, 0)
| testcount1 (Cons (n, x, xs)) =
let val (good_so_far, m) = testcount1 xs
val still_good = good_so_far andalso n = m + 1
in (still_good, m + 1)
end
val goodList = Cons (4, #"c", Cons (3, #"o", Cons (2, #"o", Cons (1, #"l", Nil))))
val badList = Cons (3, #"d", Cons (2, #"e", Cons (1, #"r", Cons (0, #"p", Nil))))
Testing this,
- testcount1 goodList;
> val it = (true, 4) : bool * int
- testcount1 badList;
> val it = (false, 4) : bool * int
This shows that testcount1 returns whether the numbers add up and the list's actual length, which was necessary during recursion to test that the numbers add up in each step, but in the end is no longer necessary. You could wrap this testcount function up in a simpler test function that only cares about the bool:
fun test xs = #1 (testcount1 xs)
Here is another way to go about: There is something not so satisfying with the way testcount1 recurses. It keeps calculating the m + 1s even though it is able to determine that a list (e.g. at Cons (0, #"p", Nil)) is broken.
Here is an alternate val testcount2 : 'a lenlist * int -> bool that stores a number in an extra argument instead:
fun testcount2 (Nil, 0) = true
| testcount2 (Nil, _) = false
| testcount2 (Cons (n, x, xs), m) =
n = m andalso testcount2 (xs, m - 1)
This seems a lot neater to me: The function is tail-recursive, and it stops immediately when it senses that something is fishy. So it doesn't need to traverse the entire list if it's broken at the head. The downside is that it needs to know the length, which we don't know yet. But we can compensate by assuming that whatever is advertised is correct until it's clearly the case, or not.
Testing this function, you need to not only give it a goodList or a badList but also an m:
- testcount2 (goodList, 4);
> val it = true : bool
- testcount2 (badList, 4);
> val it = false : bool
- testcount2 (badList, 3);
> val it = false : bool
It's important that this function doesn't just compare n = m, since in badList, that'd result in agreeing that badList is 3 elements long, since n = m is true for each iteration in all Cons cases. This is helped in the two Nil cases that require us to have reached 0 and not e.g. ~1 as is the case for badList.
This function can also be wrapped inside test to hide the fact that we feed it an extra argument derived from the 'a lenlist itself:
fun size Nil = 0
| size (Cons (n, _, _)) = n
fun test xs = testcount2 (xs, size xs)
Some morals so far:
Sometimes it is necessary to create helper functions to solve your initial problem.
Those helper functions are not restricted to have the same type signature as the function you deliver (whether this is for an exercise in school, or for an external API/library).
Sometimes it helps to extend the type that your function returns.
Sometimes it helps to extend the arguments of your functions.
Just because your task is "Write a function foo -> bar", this does not mean that you cannot create this by composing functions that return a great deal more or less than foo or bar.
Now, for some hints for solving this on binary trees:
Repeating the data type,
datatype 'a bin_tree =
Leaf of 'a
| Node of 'a bin_tree (* left tree *)
* int (* size of left tree *)
* int (* size of right tree *)
* 'a bin_tree (* right tree *)
You can start by constructing a skeleton for your function based on the ideas above:
fun testcount3 (Leaf x, ...) = ...
| testcount3 (Leaf x, ...) = ...
| testcount3 (Node (left, leftC, rightC, right), ...) = ...
I've embedded som hints here:
Your solution should probably contain pattern matches against Leaf x and Node (left, leftC, rightC, right). And given the "extra argument" type of solution (which at least proved nice for lists, but we'll see) needed two Leaf x cases. Why was that?
If, in the case of lists, the "extra argument" m represents the expected length of the list, then what would an "extra argument" represent in the case of trees? You can't say "it's the length of the list", since it's a tree. How do you capture the part where a tree branches?
If this is still too difficult, consider solving the problem for lists without copy-pasting. That is, you're allowed to look at the solutions in this answer (but try not to), but you're not allowed to copy-paste code. You have to type it if you want to copy it.
As a start, try to define the helper function size that was used to produce test from testcount2, but for trees. So maybe call it sizeTree to avoid the name overlap, but other than that, try and make it resemble. Here's a skeleton:
fun sizeTree (Leaf x) = ...
| sizeTree (Node (left, leftC, rightC, right)) = ...
Sticking testcount3 and sizeTree together, once written, should be easy as tau.

Related

How to compare and search for an element in a list with a tuple inside a list SML

I want to search in with searchingElements list inside each second element in tuple list and count if there are months in the list inside tuple lists as it shown in the test, I don't know if it should done by recursion, which I have no clue how to use here.
fun number_in_months(months : (int * int * int) list, months2 : (int * int * int) list,
months3 : (int * int * int) list, searchingElements : int list) =
if #2 (hd (tl months)) = (hd searchingElements)
then
1
else
0
val test3 = number_in_months ([(2012, 2, 28), (2013, 12, 1), (2011, 3, 31), (2011, 4, 28)], [2, 3, 4]) = 3
I get these 2 errors that I understood later I can't compare between list and tuple list
(fn {1=1,...} => 1) (hd number)
main.sml:30.2-30.30 Error: operator and operand do not agree [overload - bad instantiation]
stdIn:2.1-2.5 Error: unbound variable or constructor: fun3
It's really misleading if we read the function code and the test as they both are not type consistent in the very first place.
If I follow the test function which is
val test3 = number_in_months ([(2012,2,28),(2013,12,1),(2011,3,31),(2011,4,28)],[2,3,4]) = 3
then the type of number_in_months should be
val number_in_months = fn: ('a * ''b * 'c) list * ''b list -> int
which is a pair(2-tuple) and the function which is supposed to implement the logic
fun fun3 (months :(int*int*int) list, months2: (int*int*int) list, months3:
(int*int*int) list, searchingElements: int list)
is actually a function with a parameter which is a 4-tuple and a mismatch is evident. Also the parameters months2 and months3 are not used anywhere. Plus, each of the so called months parameters are of type list in themselves. Furthermore, except for the test3 line, there isn't anything which is quite meaningful to come-up with an answer or even a reply.
However, following the test3 line, I have attempted to write a function that at least gets the thing done and is as follows:
fun number_in_months (date_triples, months) =
let
fun is_second_of_any_triple ele = List.exists (fn (_, x, _) => x = ele)
in
List.foldl (fn (curr, acc) => if is_second_of_any_triple curr date_triples then acc + 1 else acc) 0 months
end
A version with explicit recursion:
Suppose we had a function that counted the occurrences of a single number in a list of tuples;
month_occurrences: ((int * int * int) list * int) -> int
Then we could recurse over the list of numbers, just adding as we go along:
fun number_in_months(dates, []) = 0
| number_in_months(dates, m::ms) = month_occurrences(dates, m) + number_in_months(dates, ms)
And month_occurrences with a straight recursion might look like
fun month_occurrences([], _) = 0
| month_occurrences((_, m, _)::ds, m') = (if m = m' then 1 else 0) + month_occurrences(ds, m')

Is there a way to multiply elements in list of pairs

Hello I'm trying to write a program in OCaml and was wondering if there is a way to get from list of pairs : [(1,2);(2,3);(3;5)] to a list where pairs are multiplied [2;6;15] this is what i have tried but it's giving me Exception: Failure "hd"
let rec mul l=
let x=(List.hd l) and y=(List.tl l) in
((fst x)*(snd x))::(mul y);;
mul [(3, 5); (3, 4); (3, 3);];;
What you want essentially is List.map (uncurry ( * )).
# let uncurry f (a, b) = f a b;;
val uncurry : ('a -> 'b -> 'c) -> 'a * 'b -> 'c = <fun>
# List.map (uncurry ( * )) [(3, 5); (3, 4); (3, 3);];;
- : int list = [15; 12; 9]
(uncurry is a basic FP function, but unfortunately it isn't defined in OCaml's fairly sparse standard library. But as you can see the definition is straightforward.)
To be honest, I think there must be simpler methods. Specifically, you have a list of n elements which are pairs (so a list of type (int * int) list) and you want to get a list of the same size, but which is the result of multiplying the two members of the pair. So, going from an (int * int) list to an int list.
As the objective is to preserve the size of the list, you can rephrase the statement by saying "I would like to apply a function on each element of my list". It is possible to do this manually, using, for example, pattern matching (which makes it possible to be explicit about the treatment of the empty list):
let rec mult my_list =
match my_list with
| [] -> (* case if my list is empty *)
[] (* The process is done! *)
| (a, b) :: tail -> (* if I have, at least, one element)
(a * b) :: (mult tail)
But generally, applying a function to each element of a list and preserving its size is called "mapping" (roughly), and fortunately there is a function in the standard OCaml library which allows this, and it is called, logically: List.map, here is its type: val map : ('a -> 'b) -> 'a list -> 'b list which could be translated as: give me a function which goes from 'a to 'b, a list of 'a and I can produce a list of 'b for you.
Here, we would like to be able to apply a function that goes from (int * int) -> int, for example: let prod (x, y) = x * y. So let's try to reimplement mult in terms of map:
let mult my_list =
let prod (x, y) = x * y in
List.map prod my_list
And voila, the pattern captured in the first purpose is exactly the idea behind List.map, for each element of a list, I apply a function and I keep the result of the function application.
Here is a working solution with the least amount of modification to your original code:
let rec mul l =
match l with
| [] -> [] (* <-- Deal with the base case *)
| _ -> (* Same as before --> *)
let x = (List.hd l) and y = (List.tl l) in
((fst x)*(snd x))::(mul y);;
Note that we just need to consider that happens when the list is empty, and we do that by matching on the list. The recursive case stays the same.

Lazy list of x, f x, f (f x),

Batteries.LazyList allows one to define lazy lists. I would like to define a lazy list consisting of x, f x, f (f x), f (f (f x)), etc.
Based on comments in the module documentation, it appears that from_loop is the function I want:
"from_loop data next creates a (possibly infinite) lazy list from the successive results of applying next to data, then to the result, etc."
This description suggests that if I wanted a lazy list of non-negative integers, for example, I could define it like this:
let nat_nums = from_loop 0 (fun n -> n + 1)
However, this fails because the signature of from_loop is
'b -> ('b -> 'a * 'b) -> 'a LazyList.t
so the next function has signature ('b -> 'a * 'b). In utop, the error message underlines n + 1 and says
Error: This expression has type int but an expression was expected of type 'a * int
I don't understand what 'a is supposed to be. Why is the next function supposed to return a pair? Why is the type of the list supposed to be a 'a LazyList.t? Shouldn't the type of the elements be the same as the type of the argument to the next function? The description of the function doesn't make the answers clear to me.
In case it's helpful, my conception of what I'm trying to do comes from Clojure's iterate. In Clojure I could create the above definition like this:
(def nat-nums (iterate (fn [n] (+ n 1)) 0))
The function passed to from_loop has to return a pair. The first element of the pair is the value you want to return. The second element of the pair is the state required to calculate the next element later on.
Your code:
(fun n -> n + 1)
Just calculates the next element of the lazy list, it doesn't return the state required for the next call. Something like this is what is wanted:
(fun n -> (n, n + 1))
(This will return a list starting with 0, which I think is what you want.)
This formulation is more flexible than your clojure example, because it allows you to maintain arbitrary state distinct from the values returned. The state is of type 'b in the type you give for from_loop.
I don't have Batteries right now, so I can't try this out. But I think it's correct based on the types.
It turns out that the function that I really wanted was LazyList.seq, not from_loop. While from_loop has its uses, seq is simpler and does what I wanted. The only trick is that you have to provide a third argument which is a termination test that returns false when the list should end. I wanted an infinite list. One can create that using use a termination function that always returns true:
let nat_nums = seq 0 (fun n -> n + 1) (fun _ -> true);;
LazyList.to_list (LazyList.take 8 nat_nums);;
- : int list = [0; 1; 2; 3; 4; 5; 6; 7]

I want to make function maptree with standard ML

I want to make function maptree with standard ML.
If function f(x) = x + 1;
then
maptree(f, NODE(NODE(LEAF 1,LEAF 2),LEAF 3));
should make result
NODE(NODE(LEAF 2,LEAF 3),LEAF 4))
I write the code like below.
datatype 'a tree = LEAF of 'a | NODE of 'a tree * 'a tree;
fun f(x) = x + 1;
fun maptree(f, NODE(X, Y)) = NODE(maptree(f, X), maptree(f, Y))
| maptree(f, LEAF(X)) = LEAF(f X);
but when I execute this code like this
maptree(f, (NODE(NODE(LEAF 1,LEAF 2),LEAF 3)));
result is not I want to
(NODE(NODE(LEAF 2,LEAF 3),LEAF 4)))
but
NODE(NODE(LEAF #,LEAF #),LEAF 4)).
Why this happened(not a number but #)?
# is used by the REPL when the data structure it prints is deeper than a pre-set value. If you increase that value, you'll get the result you excepted. I assume you're using SML/NJ, which calls that setting print.depth:
sml -Cprint.depth=20
- maptree(f, (NODE(NODE(LEAF 1,LEAF 2),LEAF 3)));
val it = NODE (NODE (LEAF 2,LEAF 3),LEAF 4) : int tree
You can find more options like these by executing sml -H. Look them up under the "compiler print settings" section:
compiler print settings:
print.depth (max print depth)
print.length (max print length)
print.string-depth (max string print depth)
print.intinf-depth (max IntInf.int print depth)
print.loop (print loop)
print.signatures (max signature expansion depth)
print.opens (print `open')
print.linewidth (line-width hint for pretty printer)
Some comments:
I would probably go with the definition
datatype 'a tree = Leaf | Node of 'a tree * 'a * 'a tree
so that trees with zero or two elements can also be expressed.
I would probably curry the tree map function
fun treemap f Leaf = Leaf
| treemap f (Node (l, x, r)) = Node (treemap f l, x, treemap f r)
since you can then partially apply it, e.g. like:
(* 'abstree t' returns t where all numbers are made positive *)
val abstree = treemap Int.abs
(* 'makeFullTree n' returns a full binary tree of size n *)
fun makeFullTree 0 = Leaf
| makeFullTree n =
let val subtree = makeFullTree (n-1)
in Node (subtree, n, subtree)
end
(* 'treetree t' makes an int tree into a tree of full trees! *)
val treetree = treemap makeFullTree
You may at some point want to fold a tree, too.

SML Lazy sort of int list using streams

The question
1 Streams and lazy evaluation (40 points)
We know that comparison sorting requires at least O(n log n) comparisons where were are sorting n elements. Let’s say we only need the first f(n) elements from the sorted list, for some function f. If we know f(n) is asymptotically less than log n then it would be wasteful to sort the entire list. We can implement a lazy sort that returns a stream representing the sorted list. Each time the stream is accessed to get the head of the sorted list, the smallest element is found in the list. This takes linear time. Removing the f(n) elements from the list will then take O(nf(n)). For this question we use the following datatype definitions. There are also some helper functions defined.
(* Suspended computation *)
datatype 'a stream' = Susp of unit -> 'a stream
(* Lazy stream construction *)
and 'a stream = Empty | Cons of 'a * 'a stream'
Note that these streams are not necessarily infinite, but they can be.
Q1.1 (20 points) Implement the function lazysort: int list -> int stream'.
It takes a list of integers and returns a int stream' representing the sorted list. This should be done in constant time. Each time the stream' is forced, it gives either Empty or a Cons(v, s'). In the case of the cons, v is the smallest element from the sorted list and s' is a stream' representing the remaining sorted list. The force should take linear time. For example:
- val s = lazysort( [9, 8, 7, 6, 5, 4] );
val s = Susp fn : int stream'
- val Cons(n1, s1) = force(s);
val n1 = 4 : int
val s1 = Susp fn : int stream'
- val Cons(n2, s2) = force(s1);
val n2 = 5 : int
val s2 = Susp fn : int stream'
- val Cons(n3, s3) = force(s2);
val n3 = 6 : int
val s3 = Susp fn : int stream'
Relevant definitions
Here is what is given as code:
(* Suspended computation *)
datatype 'a stream' = Susp of unit -> 'a stream
(* Lazy stream construction *)
and 'a stream = Empty | Cons of 'a * 'a stream'
(* Lazy stream construction and exposure *)
fun delay (d) = Susp (d)
fun force (Susp (d)) = d ()
(* Eager stream construction *)
val empty = Susp (fn () => Empty)
fun cons (x, s) = Susp (fn () => Cons (x, s))
(*
Inspect a stream up to n elements
take : int -> 'a stream' -> 'a list
take': int -> 'a stream -> 'a list
*)
fun take 0 s = []
| take n (s) = take' n (force s)
and take' 0 s = []
| take' n (Cons (x, xs)) = x::(take (n-1) xs)
My attempt at a solution
I tried to do the following which get the int list and transforms it to int stream':
(* lazysort: int list -> int stream' *)
fun lazysort ([]:int list) = empty
| lazysort (h::t) = cons (h, lazysort(t));
But when calling force it does not return the minimum element. I have to search for the minimum, but I do not know how... I thought of doing insertion sort like following:
fun insertsort [] = []
| insertsort (x::xs) =
let fun insert (x:real, []) = [x]
| insert (x:real, y::ys) =
if x<=y then x::y::ys
else y::insert(x, ys)
in insert(x, insertsort xs)
end;
But I have to search for the minimum and to not sort the list and then put it as a stream...
Any help would be appreciated.
Each time the stream is accessed to get the head of the sorted list, the smallest element is found in the list.
You are on the correct path with the placement function (sort of... I don't know why you have real types instead of int when there will only be int streams . Your pattern would not match if you have not realized by now).
fun insertsort ([]:int list) = empty
| insertsort (h::t) =
let
fun insert (x:real, []) = [x] (* 1 *)
| insert (x:real, y::ys) = (* 2 *)
if x<=y then x::y::ys (* 3 *)
else y::insert(x, ys) (* 4 *)
in insert(x, insertsort xs) (* 5 *)
This is your helping inner magic for getting the smallest item each time.
Some hints/tips to make the above work
You should have only one argument
I don't think it matters to have less than or equal to (just less than should work .... have not really thought about that). Also you have to reach the bottom of the list first to tell which is the smallest so this is tail first. so that (* 1 *) is the first then each inside call of (* 2 *) till the outermost one.
That should be cons(x, insertsort xs) in (* 5 *) since you are returning a int stream' with the function.
I'm in your class and I think you're going about this the totally wrong way. I've solved the question, but I think it's a bit unethical for me to fully share the code with you. That said, here's a pointer:
you don't need to transform the int list into an int stream'. Firstly, this violates the rule that the initial call to lazysort must be done in constant time. Note that transforming it to an int stream' is done in linear time. What you need to do is provide an embedded sort function within the closure of the suspended stream you're returning (using a let block.) The first element of the stream would be the result of the sort function (done with the suspended closure.) The second element of the stream (which is just an int stream') should be a call to your lazysort function, because it returns an int stream'. Notice how this lets you avoid having to transform it. The sort function itself is quite simple, because you only need to find the smallest element and return the rest of the list without the element you found to be the smallest.