So I have this datatype implemented
datatype 'a expression = Not of 'a expression
| Or of 'a expression list
| And of 'a expression list
| Equality of 'a expression list
| Impication of 'a expression * 'a expression
| Variable of 'a
| True | False;
What I am trying to do is remove whole elements that are the same in the list list. Because i want to follow this mathematical rule and simplify my equation
A||(A&&B)∼A
A && (A||B)∼A
So what I am looking to do is remove all matches. Meaning my function would remove elements that match like this if the and or statements are correct
[[x,y,a], a, [b,c,f],[a,[c,g]]] => [[x,y], a , [b,c,f] [c, g]]
And it would also detect and remove whole matching lists like this
[[x,y,a], [c, b, d, [x,y,a]] ] => [[x,y,a], [c,b,d]]
First it should remove whole matches than it should remove element matches. I kinda came as far as to implement one dimension removal but I am strugling now
fun remove[] = []
| remove(x::xs) = x::remove(List.filter (fn y => y <> x) xs)
Here is what I have and I know it is not even close to the solution
Related
Hi I'm new to f# and I got this exercise I can't figure out:
"Implement a Function :"
let compress (l : List<'a>) : List<'a> = ...
That removes consecutive occurences of the same element in l. for example compressing [a;a;a;a;b;b;c] to [a;b;c]
I'm not allowed to use the built-in functions of f# and need to do this with pattern matching.
My current code (it's not much) :
let rec compress (l: List<'a>) : List<'a> =
match l with
| [] -> l
thanks for the help!
For any recursive function you need to consider: 1. the terminal case and 2. the general case. In your scenario:
the empty list []
non-empty list x::xs (where x represents the head of the list and xs the rest aka tail)
The other important aspect to consider when you build such a functions is to assume it works for a previous value. For example in the case of factorial, we assume the function already works for a previous scenario e.g. factorial of n-1.
let fact n =
match n with
| 0 | 1 -> 1
| _ -> n * fact (n-1)
I need to implement a method to return common elements in two lists as part of an assignment problem:
My idea was to remove duplicates in both lists, concatenate them and return elements that are repeated in the resulting list. I want to define a Boolean function that check for each elements in the list if they appear more than once. My idea was to use List.fold_left with a specific element b in the list and use acc to keep track of the number of times it appears in the list. However, I have an error here:
I have another idea that involves sorting the lists first, But the list could be of any type, hence comparison has to be implemented for new types as well. Or can I just use < to compare any type of values?
Here are the codes that I have so far.
let rec remove (b : 'a) (l : 'a list)=
match l with
| [] -> []
| w::e -> if w=b then remove b e
else w::(remove b e)
let rec removeduplicates (l:'a list)=
match l with
| [] -> []
| w::e -> w::(removeduplicates(remove w e))
let removeduppair (l : 'a list * 'a list)=
let (l1,l2) = l in
(removeduplicates l1, removeduplicates l2)
This expression has a type error:
if x = b then acc + 1
The problem is that doesn't have an else part. In other words, it doesn't say what you want the value to be when x is not equal to b.
You can fix this just by adding an else part.
A little more detail: OCaml allows you to leave off the else part, but only if the then part has unit type. In such a case, the value when the test is false will be the same as when it is true, namely () (the only value of unit type).
I am currently working on a function, that computes the difference of the two lists in the following way.
The input lists are sorted by the value of the key of type 'a.
The result includes the pairs from the first list with the keys
that are not included in the second list.
Example:
diff [(1,2);(2,3);(4,5)];(5,6)] [(2,4);(4,6)] → [(1,2);(5,6)]
Now I am facing Error, I can't solve.
My code:
let rec diff list1 list2= match list1,list2 with
|x,[] -> [x]
| [],_->[]
| h1::t1,h2::t2 ->
let (k1,v1) = h1 in
let (k2,v2)=h2 in
if(k1=k2) then diff t1 t2
else if (k1>k2) then h1::(diff list1 t2)
else h2::(diff t1 list2)
ERROR message:
else if (k1>k2) then h1::(diff list1 t2) Error: This expression has
type 'a * 'b
but an expression was expected of type ('a * 'b) list#
Working code:
let rec diff list1 list2= match list1,list2 with
|_,[] -> list1
| [],_->[]
| h1::t1,h2::t2 ->
let (k1,v1) = h1 in
let (k2,v2)=h2 in
if(k1=k2) then diff t1 t2
else if (k1>k2) then h1::(diff list1 t2)
else h1::(diff t1 list2)
Thanks for the answers.
When list2 is empty, you return a list of lists containing list1 (a.k.a. x). This tells OCaml that the return type is a list of lists of what the input lists contain. So when you later try to return just plain lists of tuples, rather than lists of lists of tuples, OCaml thinks that's the mistake.
But in fact returning a list of tuples is what you want. The mistake is returning a list of lists in the x, [] case. You can fix that by changing that case to | x, [] -> x or | _, [] -> list1.
I have a few problems creating a tree size function with type 'a option tree -> int
type 'a tree = Leaf of 'a
| Fork of 'a * 'a tree * 'a tree
How would I create a t_opt_size function with type 'a option tree -> int?
I know I would have to use Some and the None operate.
I have this so far, but it's complicated to match with the option type.
let rec t_size (tr: 'a tree): int =
match tr with
| Leaf _ -> 1
| Fork (_, t1, t2) -> t_size t1 + t_size t2 + 1
I assume from your comments that you want a leaf that looks like (Leaf None) not to be counted in your tree size calculation.
Seems like the key is to split this:
| Leaf _ -> 1
Into two cases:
| Leaf None -> (* Left as exercise *)
| Leaf (Some _) -> (* Left as exercise *)
Since OCaml will take the first match, you can abbreviate this as follows if you like:
| Leaf None -> (* Left as exercise *)
| Leaf _ -> (* Left as exercise *)
You should make a similar change to the Fork case, though I have to say that Fork (None, l, r) doesn't really work for constructing a search tree.
If you want to generalize, you might need to write a generic tree walker which accepts a visitor function. I recommend you try to implement fold_tree, which accepts: (1) a fold function, taking some value, a tree and producing a new result ('a -> 'b t -> 'c), (2) an initial element of type 'a as well as (3) a tree. Then, fold_tree returns a value of type 'c.
Then, you should be able to call fold_tree with a function that skips over None leaves but otherwise increment the count like you did.
If you don't want to count all values in the tree as 1, but each depending on its contents, write a function that determines the count per value and use that:
let weight = function
| _ -> 1 (* or anything else *)
let rec t_opt_size (tr: 'a tree): int = match tr with
| Leaf v -> weight v
| Fork (v, t1, t2) -> t_size t1 + t_size t2 + weight v
You even might want to generalise and pass the weight function as a parameter to t_size instead of writing different size functions that all use their own weighting.
I am new to OCaml and I am trying to write a function to do this:
(4,a)(1,b)(2,c)(2,a)(1,d)(4,e) --> ((4 a) b (2 c) (2 a) d (4 e))
and this is what I wrote:
let rec transform l =
match l with
| (x,y)::t -> if x = 1 then y::transform(t) else [x; y]::transform(t)
| [] -> []
I put it in the ocaml interpreter but error generated like this:
Error: This expression has type int list
but an expression was expected of type int
Could anyone give some help?
Your example transformation doesn't make it clear what the types of the values are supposed to be.
If they're supposed to be lists, the result isn't a possible list in OCaml. OCaml lists are homogeneous, i.e., all the elements of the list have the same type. This is (in essence) what the compiler is complaining about.
Update
Looking at your code, the problem is here:
if x = 1
then y :: transform (t)
else [x; y] :: transform t
Let's say the type of y is 'a. The expression after then seems to have type 'a list, because y is the head of the list. The expression after else seems to have type 'a list list, because a list containing y is the head of the list. These aren't the same type.
The main problem is to decide how to represent something as either (4 a) or b. The usual OCaml way to represent something-or-something-else is variants, so let's define one of those:
type 'a element =
| Single of 'a
| Count of int * 'a
let rec transform = function
| [] -> []
| (x,y)::t ->
if x = 1 then Single y::transform t
else Count (x, y)::transform t
Note that this won't print in quite the way you want, unless you register a printer with the toplevel.
Or better:
let compact (x, y) =
if x = 1 then Single y else Count (x, y)
let transform list = List.map compact list