I am trying to create a function which interleaves a pair of triples such as ((6, 3, 2), ( 4, 5 ,1)) and create a 6-tuple out of this interleaving.
I made some research but could understand how interleaving is supposed to work so I tried something on my own end ended up with a code that is creating a 6-tuple but not in the right interleaved way. This is my code
let interleave ((a, b, c), (a', b', c')) =
let sort2 (a, b) = if a > b then (a, b) else (b, a) in
let sort3 (a, b, c) =
let (a, b) = sort2 (a, b) in
let (b, c) = sort2 (b, c) in
let (a, b) = sort2 (a, b) in
(a, b, c) in
let touch ((x), (y)) =
let (x) = sort3 (x) in
let (y) = sort3 (y) in
((x),(y)) in
let ((a, b, c), (a', b', c')) = touch ((a, b, c), (a', b', c')) in
(a, b', a', b, c, c');;
Can someone please explain to me how with what functions I can achieve a proper form of interleaving. I haven't learned about recursions and lists in case you would ask why I am trying to do it this way.
Thank you already.
The problem statement uses the word "max" without defining it. If you use the built-in compare function of OCaml as your definition, it uses lexicographic order. So you want the largest value (of the 6 values) in the first position in the 6-tuple, the second largest value next, and so on.
This should be pretty easy given your previously established skill with the sorting of tuples.
For what it's worth, there doesn't seem to be much value in preserving the identities of the two 3-tuples. Once inside the outermost function you can just work with the 6 values as a 6-tuple. Or so it would seem to me.
Update
From your example (should probably have given it at the beginning :-) it's pretty clear what you're being asked to do. You want to end up with a sequence in which the elements of the original tuples are in their original order, but they can be interleaved arbitrarily. This is often called a "shuffle" (or a merge). You have to find the shuffle that has the maximum value lexicographically.
If you reason this out, it amounts to taking whichever value is largest from the front of the two tuples and putting it next in the output.
This is much easier to do with lists.
Now that I understand what your end-goal is . . .
Since tuples of n elements are different types for different n's, you need to define helper functions for manipulating different sizes of tuples.
One approach, that basically mimics a recursive function over lists (but requires many extra functions because of tuples all having different types), is to have two sets of helper functions:
functions that prepend a value to an existing tuple: prepend_to_2, up through prepend_to_5. For example,
let prepend_to_3 (a, (b, c, d)) = (a, b, c, d)
functions that interleave two tuples of each possible size up to 3: interleave_1_1, interleave_1_2, interleave_1_3, interleave_2_2, interleave_2_3, and interleave_3_3. (Note that we don't need e.g. interleave_2_1, because we can just call interleave_1_2 with the arguments in the opposite order.) For example,
let interleave_2_2 ((a, b), (a', b')) =
if a > a'
then prepend_to_3 (a, interleave_1_2 (b, (a', b')))
else prepend_to_3 (a', interleave_1_2 (b', (a, b)))
(Do you see how that works?)
Then interleave is just interleave_3_3.
With lists and recursion this would be much simpler, since a single function can operate on lists of any length, so you don't need multiple different copies of the same logic.
Related
so I am new to OCaml and im having some trouble with lists.
What I have is a List of chars as follows:
let letters = [a;b;c;d]
I would like to know how can I iterate the list and apply a fuction that takes as arguments every possible combination of two chars on the list (do_someting char1 char2), for example: a and b (do_something a b), a and c .... d and b, d and c; never repeating the same element (a and a or c and c should not happen).
OCaml is a functional language, so we want to try to break down the procedure into as many functional pieces as we can.
Step 1 is "take a list of things and produce all combinations". We don't care what happens afterward; we just want to know all such combinations. If you want each combination to appear only once (i.e. (a, b) will appear but (b, a) will not, in your example), then a simple recursive definition will suffice.
let rec ordered_pairs xs =
match xs with
| [] -> []
| (x :: xs) -> List.append (List.map (fun y -> (x, y)) xs) (ordered_pairs xs)
If you want the reversed duplicates ((a, b) and (b, a)), then we can add them in at the end.
let swap (x, y) = (y, x)
let all_ordered_pairs xs =
let p = ordered_pairs xs in
List.append p (List.map swap p)
Now we have a list of all of the tuples. What happens next depends on what kind of result you want. In all likelihood, you're looking at something from the built-in List module. If you want to apply the function to each pair for the side effects, List.iter does the trick. If you want to accumulate the results into a new list, List.map will do it. If you want to apply some operation to combine the results (say, each function returns a number and you want the sum of the numbers), then List.map followed by List.fold_left (or the composite List.fold_left_map) will do.
Of course, if you're just starting out, it can be instructive to write these List functions yourself. Every one of them is a simple one- or two- line recursive definition and is very instructive to write on your own.
I'm have just started learning Haskell and am trying to create a function that performs several checks on a tuple containing 6 integers.
These checks include:
all digits are different;
alternate digits are even and odd, or odd and even;
alternate digits differ by more than two;
the first and middle pairs of digits form numbers that are both multiples of the last
The problem is that I can attempt this and have some working functions like
contains e [] = False
contains e (x:xs)
| x == e = True
| otherwise = contains e xs
unique :: [Int] -> Bool
unique [] = True
unique (x:xs)
| contains x xs = False
| otherwise = unique xs
for the first requirement, but as you can see this relies on using a list rather than a tuple.
I would appreciate it if someone could help me with how to create these functions for tuples instead, as well as any code efficiency suggestions.
You can convert a 6-tuple to a list, with:
tuple6ToList :: (a, a, a, a, a, a) -> [a]
tuple6ToList (a, b, c, d, e, f) = [a, b, c, d, e, f]
and then run the checks on the list for example. This is likely simpler, since one can then recurse on the list, whereas for a tuple it would mean that you "unwind" the checks into individual checks on the elements.
I would have thought that a list of tuples could easily be flattened:
scala> val p = "abcde".toList
p: List[Char] = List(a, b, c, d, e)
scala> val q = "pqrst".toList
q: List[Char] = List(p, q, r, s, t)
scala> val pq = p zip q
pq: List[(Char, Char)] = List((a,p), (b,q), (c,r), (d,s), (e,t))
scala> pq.flatten
But instead, this happens:
<console>:15: error: No implicit view available from (Char, Char) => scala.collection.GenTraversableOnce[B].
pq.flatten
^
I can get the job done with:
scala> (for (x <- pq) yield List(x._1, x._2)).flatten
res1: List[Char] = List(a, p, b, q, c, r, d, s, e, t)
But I'm not understanding the error message. And my alternative solution seems convoluted and inefficient.
What does that error message mean and why can't I simply flatten a List of tuples?
If the implicit conversion can't be found you can supply it explicitly.
pq.flatten {case (a,b) => List(a,b)}
If this is done multiple times throughout the code then you can save some boilerplate by making it implicit.
scala> import scala.language.implicitConversions
import scala.language.implicitConversions
scala> implicit def flatTup[T](t:(T,T)): List[T]= t match {case (a,b)=>List(a,b)}
flatTup: [T](t: (T, T))List[T]
scala> pq.flatten
res179: List[Char] = List(a, p, b, q, c, r, d, s, e, t)
jwvh's answer covers the "coding" solution to your problem perfectly well, so I am not going to go into any more detail about that. The only thing I wanted to add was clarifying why the solution that both you and jwvh found is needed.
As stated in the Scala library, Tuple2 (which (,) translates to) is:
A tuple of 2 elements; the canonical representation of a Product2.
And following up on that:
Product2 is a cartesian product of 2 components.
...which means that Tuple2[T1,T2] represents:
The set of all possible pairs of elements whose components are members of two sets (all elements in T1 and T2 respectively).
A List[T], on the other hand, represents an ordered collections of T elements.
What all this means practically is that there is no absolute way to translate any possible Tuple2[T1,T2] to a List[T], simply because T1 and T2 could be different. For example, take the following tuple:
val tuple = ("hi", 5)
How could such tuple be flattened? Should the 5 be made a String? Or maybe just flatten to a List[Any]? While both of these solutions could be used, they are working around the type system, so they are not encoded in the Tuple API by design.
All this comes down to the fact that there is no default implicit view for this case and you have to supply one yourself, as both jwvh and you already figured out.
We needed to do this recently. Allow me to explain the use case briefly before noting our solution.
Use case
Given a pool of items (which I'll call type T), we want to do an evaluation of each one against all others in the pool. The result of these comparisons is a Set of failed evaluations, which we represent as a tuple of the left item and the right item in said evaluation: (T, T).
Once these evaluations are complete, it becomes useful for us to flatten the Set[(T, T)] into another Set[T] that highlights all the items that have failed any comparisons.
Solution
Our solution for this was a fold:
val flattenedSet =
set.foldLeft(Set[T]())
{ case (acc, (x, y)) => acc + x + y }
This starts with an empty set (the initial parameter to foldLeft) as the accumulator.
Then, for each element in the consumed Set[(T, T)] (named set) here, the fold function is passed:
the last value of the accumulator (acc), and
the (T, T) tuple for that element, which the case deconstructs into x and y.
Our fold function then returns acc + x + y, which returns a set containing all the elements in the accumulator in addition to x and y. That result is passed to the next iteration as the accumulator—thus, it accumulates all the values inside each of the tuples.
Why not Lists?
I appreciated this solution in particular since it avoided creating intermediate Lists while doing the flattening—instead, it directly deconstructs each tuple while building the new Set[T].
We could also have changed our evaluation code to return List[T]s containing the left and right items in each failed evaluation—then flatten would Just Work™. But we thought the tuple more accurately represented what we were going for with the evaluation—specifically one item against another, rather than an open-ended type which could conceivably represent any number of items.
I have several places in my code which look like this:
let (a,b,c) = (f "a", f "b", f "c")
It would be nice if I can write something like:
let (a,b,c) = map f ("a", "b", "c")
If there is way to do something like this in OCaml?
You can easily write map for triples of one type of element:
let map_triple f (a, b, c) = (f a, f b, f c)
let a, b, c = map_triple String.length ("foo", "bar", "quux")
It will only work for one length of tuple, however.
It would be possible to write a GADTified tuple type and write a map over that type that is polymorphic in the length of the tuple, but that kind of trickery is best avoided unless the advantage is large, which does not seem to be the case here.
The best answer is that you can't do this, if you want it to work for tuples of different sizes. Each tuple size is a different type in OCaml. So there's no OCaml type representing the idea of "a tuple of any size whose elements are strings."
But in fact this sounds like a list more than a tuple. If you can use lists instead of tuples, you can use the plain old List.map function.
So let's say we are given the endpoints (A, B), (B, C), (C, D), then we can form the route A -> B -> C.
Note that the order the endpoints are given is random. So (A, B), (C, D), (B, C) would also have yielded the route A -> B -> C.
But in general, if we are given ordered pairs of endpoints, how to construct the route?
I'm not sure what data structure is most helpful here. I'm thinking of storing each coordinates (x,y) into a list as the inputs are read in.
So (A, B), (C, D) would be stored as {A, B, C, D}. Whether each element is x or y coordinates can be determined by the parity of its position in the list (so the 1st entry in the list is x, 2nd entry is y, 3rd is x, etc). Then as each ordered pair is read in, we look up the list to see if either the x or y coordinate is already in the list. If so, we connect.
To demonstrate, suppose we are reading in (A, B), (C, D), (B, C), our list would be {A, B, C, D} after (C, D) is just read. When (B, C) is read, we see that B is already in the list. So we know A -> B -> C. Also C is in the list, and we have A-> B -> C -> D, and then we add (B, C) to the list to form {A, B, C, D, B, C}.
My difficult is: how do we store A -> B -> C? What data structure should I use? How do we keep track of the partial route we have formed as we go?
Thank you!
Construct a graph of directed edges with adjacency list representation. Then use DFS on start point till end point and store previously visited nodes in buffer and as soon as you reach destination the values in the buffer is the path.