Ocaml homework need some advices - algorithm

We have N sets of integers A1, A2, A3 ... An. Find an algorithm that returns a list containg one element from each of the sets, with the property that the difference between the largest and the smallest element in the list is minimal
Example:
IN: A1 = [0,4,9], A2 = [2,6,11], A3 = [3,8,13], A4 = [7,12]
OUT: [9,6,8,7]
I have an idea about this exercise, first we need sort all the elements on one list(every element need to be assigned to its set), so with that input we get this:
[[0,1],[2,2],[3,3],[4,1],[6,2],[7,4],[8,3],[9,1],[11,2],[12,4],[13,3]]
later on we create all possible list and find this one with the difference between smallest and largest element, and return correct out like this: [9,6,8,7]
I am newbie in ocaml so I have some questions about coding this stuff:
Can I create a function with N(infinite amount of) arguments?
Should I create a new type, like list of pair to realize assumptions?
Sorry for my bad english, hope you will understand what I wanted to express.

This answer is about the algorithmic part, not the OCaml code.
You might want to implement your proposed solution first, to have a working one and to compare its results with an improved solution, which I now write about.
Here is a hint about how to improve the algorithmic part. Consider sorting all sets, not only the first one. Now, the list of all minimum elements from all sets is a candidate to the output.
To consider other candidate output, how can you move from there?

I'm just going to answer your questions, rather than comment on your proposed solution. (But I think you'll have to work on it a little more before you're done.)
You can write a function that takes a list of lists. This is pretty much the same
as allowing an arbitrary number of arguments. But really it just has one argument
(like all functions in OCaml).
You can just use built-in types like lists and tuples, you don't need to create or
declare them explicitly.
Here's an example function that takes a list of lists and combines them into one big long list:
let rec concat lists =
match lists with
| [] -> []
| head :: tail -> head # concat tail

Here is the routine you described in the question to get you started. Note that
I did not pay any attention to efficiency. Also added the reverse apply (pipe)
operator for clarity.
let test_set = [[0;4;9];[2;6;11];[3;8;13]; [7;12]]
let (|>) g f = f g
let linearize sets =
let open List in sets
|> mapi (fun i e -> e |> map (fun x -> (x, i+1) ))
|> flatten |> sort (fun (e1,_) (e2, _) -> compare e1 e2)
let sorted = linearize test_set

Your approach does not sound very efficient, with an n number of sets, each with x_i elments, your sorted list will have (n * x_i) elements, and the number of sub-lists you can generate out of that would be: (n * x_i)! (factorial)
I'd like to propose a different approach, but you'll have to work out the details:
Tag (index) each element with it's set identifier (like you have done).
Sort each set individually.
Build the exact opposite to that of your desired result!
Optimize!
I hope you can figure out steps 3, 4 on your own... :)

Related

SML Syntax Breakdown

I am trying to study SML (for full transparency this is in preparation for an exam (exam has not started)) and one area that I have been struggling with is higher level functions such as map and foldl/r. I understand that they are used in situations where you would use a for loop in oop languages (I think). What I am struggling with though is what each part in a fold or map function is doing. Here are some examples that if someone could break them down I would be very appreciative
fun cubiclist L = map (fn x=> x*x*x) L;
fun min (x::xs) = foldr (fn (a,b) => if (a < b) then a else b) x xs;
So if I could break down the parts I see and high light the parts I'm struggling with I believe that would be helpful.
Obviously right off the bat you have the name of the functions and the parameters that are being passed in but one question I have on that part is why are we just passing in a variable to cubiclist but for min we pass in (x::xs)? Is it because the map function is automatically applying the function to each part in the map? Also along with that will the fold functions typically take the x::xs parameters while map will just take a variable?
Then we have the higher order function along with the anonymous functions with the logic/operations that we want to apply to each element in the list. But the parameters being passed in for the foldr anonymous function I'm not quite sure about. I understand we are trying to capture the lowest element in the list and the then a else b is returning either a or b to be compared with the other elements in the list. I'm pretty sure that they are rutnred and treated as a in future comparisons but where do we get the following b's from? Where do we say b is the next element in the list?
Then the part that I really don't understand and have no clue is the L; and x xs; at the end of the respective functions. Why are they there? What are they doing? what is their purpose? is it just syntax or is there actually a purpose for them being there, not saying that syntax isn't a purpose or a valid reason, but does they actually do something? Are those variables that can be changed out with something else that would provide a different answer?
Any help/explanation is much appreciated.
In addition to what #molbdnilo has already stated, it can be helpful to a newcomer to functional programming to think about what we're actually doing when we crate a loop: we're specifying a piece of code to run repeatedly. We need an initial state, a condition for the loop to terminate, and an update between each iteration.
Let's look at simple implementation of map.
fun map f [] = []
| map f (x :: xs) = f x :: map f xs
The initial state of the contents of the list.
The termination condition is the list is empty.
The update is that we tack f x onto the front of the result of mapping f to the rest of the list.
The usefulness of map is that we abstract away f. It can be anything, and we don't have to worry about writing the loop boilerplate.
Fold functions are both more complex and more instructive when comparing to loops in procedural languages.
A simple implementation of fold.
fun foldl f init [] = init
| foldl f init (x :: xs) = foldl f (f init x) xs
We explicitly provide an initial value, and a list to operate on.
The termination condition is the list being empty. If it is, we return the initial value provided.
The update is to call the function again. This time the initial value is updated, and the list is the tail of the original.
Consider summing a list of integers.
foldl op+ 0 [1,2,3,4]
foldl op+ 1 [2,3,4]
foldl op+ 3 [3,4]
foldl op+ 6 [4]
foldl op+ 10 []
10
Folds are important to understand because so many fundamental functions can be implemented in terms of foldl or foldr. Think of folding as a means of reducing (many programming languages refer to these functions as "reduce") a list to another value of some type.
map takes a function and a list and produces a new list.
In map (fn x=> x*x*x) L, the function is fn x=> x*x*x, and L is the list.
This list is the same list as cubiclist's parameter.
foldr takes a function, an initial value, and a list and produces some kind of value.
In foldr (fn (a,b) => if (a < b) then a else b) x xs, the function is fn (a,b) => if (a < b) then a else b, the initial value is x, and the list is xs.
x and xs are given to the function by pattern-matching; x is the argument's head and xs is its tail.
(It follows from this that min will fail if it is given an empty list.)

Is there a performance difference between head$filter and head$dropWhile with Haskell Strings?

I'm working on lists of "People" objects in Haskell, and I was wondering if there was any difference in performance between head$dropWhile and head$filter to find the first person with a given name. The two options and a snip of the datatype would be:
datatype Person = Person { name :: String
, otherStuff :: StuffTypesAboutPerson }
findPerson :: String -> [Person] -> Person
findPerson n = head $ dropWhile (\p -> name p /= n)
findPerson n = head $ filter (\p -> name p == n)
My thought was, filter would have to compare the full length of n to the full length of every name until it finds the first one. I would think dropWhile would only need to compare the strings until the first non-matching Char. However, I know there is a ton of magic in Haskell, especially GHC. I would prefer to use the filter version, because I think it's more straight-forward to read. However, I was wondering if there actually is any performance difference? Even if it's negligible, I'm also interested from a curiosity standpoint at this point.
Edit: I know I also need to protect from errors with Maybe, etc, but I left that out to simplify the code example.
There are several approaches to the problem
findPerson n = head $ dropWhile (\p -> name p /= n)
findPerson n = head $ filter (\p -> name p == n)
findPerson n = fromJust $ find (\p -> name p == n)
The question also points out two facts:
when x,y are equal strings, == needs to compare all the characters
when x,y are different strings, /= only needs to compare until the first different character
This is correct, but does not consider the other cases
when x,y are equal strings, /= needs to compare all the characters
when x,y are different strings, == only needs to compare until the first different character
So, between == and /= there is no performance winner. We can expect that, at most, one of them will perform an additional not w.r.t. the other one.
Also, all the three implementations of findPerson mentioned above, essentially perform the same steps. Given xs :: [Person], they will all scan xs until a matching name is found, and no more. On all the persons before the match, the name will be compared against n, and this comparison will stop at the first different character (no matter what comparison we use above). The matching person will have their name compared completely with n (again, in all cases).
Hence, the approaches are expected to run in the same time. There might be a very small difference between them, but it could be so small that it would be hard to detect. You can try to experiment with criterion and see what happens, if you wish.

SWI-Prolog split the list into ordered decreased lists

I would really appreciate it if someone has a solution that splits the list into ordered decreased lists. The order of elements must be the same as the input list.
I have made some tasks in Prolog, but that was much easier, now I don't even know where to start .
For example
[5,4,2,8,3,1,6,9,5] -> [5,4,2],[8,3,1],[6],[9,5].
Regarding CapelliC answer here you should be able to use nearly the same pattern matching for a descending order.
'ascending([A], [[A]]).
ascending([A,B|T], R) :-
( A < B -> R = [[A],P|Q] ; P = [M|N], R = [[A,M|N]|Q] ),
ascending([B|T], [P|Q]).'

Sort two-dimensional list on predicate in Haskell

I have a list of lists of tuples ([[(Int, Custom)]]) and I would like to sort the outer lists by comparing the integers with each other. It should behave just like a normal two-dimensional sort, i.e. it should sort the first by the first list items, then by the second items and so on - but compare the first parts instead of the whole tuples.
For a one-dimensional list I would've used sortBy (comparing fst), but I'm totally lost with having them wrapped in another list. I know it would work automatically if I'd make my Custom an instance of Ord as the sort worked automatically then, but it is not really orderable.
Please comment if you'd like to have an example and expected result. Thanks in advance!
Uh, right after asking the question it hit me like a stroke:
comparing needs a function that returns an orderable result, not an Ordering or the sorted partial list [(Int, Custom)] (which is unorderable):
comparing :: Ord a => (b -> a) -> b -> b -> Ordering
comparing = on compare
So what I had to return is a list of the orderable integers, i.e. just map fst. Altogether:
sortBy (compare `on` map fst)
:: Ord a => [[(a, b)]] -> [[(a, b)]]

FP homework. Is it possible to define a function using nested pattern matching instead of auxiliary function?

I am solving the Programming assinment for Harvard CS 51 programming course in ocaml.
The problem is to define a function that can compress a list of chars to list of pairs where each pair contains a number of consequent occurencies of the character in the list and the character itself, i.e. after applying this function to the list ['a';'a';'a';'a';'a';'b';'b';'b';'c';'d';'d';'d';'d'] we should get the list of [(5,'a');(3,'b');(1,'c');(4,'d')].
I came up with the function that uses auxiliary function go to solve this problem:
let to_run_length (lst : char list) : (int*char) list =
let rec go i s lst1 =
match lst1 with
| [] -> [(i,s)]
| (x::xs) when s <> x -> (i,s) :: go 0 x lst1
| (x::xs) -> go (i + 1) s xs
in match lst with
| x :: xs -> go 0 x lst
| [] -> []
My question is: Is it possible to define recursive function to_run_length with nested pattern matching without defining an auxiliary function go. How in this case we can store a state of counter of already passed elements?
The way you have implemented to_run_length is correct, readable and efficient. It is a good solution. (only nitpick: the indentation after in is wrong)
If you want to avoid the intermediary function, you must use the information present in the return from the recursive call instead. This can be described in a slightly more abstract way:
the run length encoding of the empty list is the empty list
the run length encoding of the list x::xs is,
if the run length encoding of xs start with x, then ...
if it doesn't, then (x,1) ::run length encoding of xs
(I intentionally do not provide source code to let you work the detail out, but unfortunately there is not much to hide with such relatively simple functions.)
Food for thought: You usually encounter this kind of techniques when considering tail-recursive and non-tail-recursive functions (what I've done resembles turning a tail-rec function in non-tail-rec form). In this particular case, your original function was not tail recursive. A function is tail-recursive when the flows of arguments/results only goes "down" the recursive calls (you return them, rather than reusing them to build a larger result). In my function, the flow of arguments/results only goes "up" the recursive calls (the calls have the least information possible, and all the code logic is done by inspecting the results). In your implementation, flows goes both "down" (the integer counter) and "up" (the encoded result).
Edit: upon request of the original poster, here is my solution:
let rec run_length = function
| [] -> []
| x::xs ->
match run_length xs with
| (n,y)::ys when x = y -> (n+1,x)::ys
| res -> (1,x)::res
I don't think it is a good idea to write this function. Current solution is OK.
But if you still want to do it you can use one of two approaches.
1) Without changing arguments of your function. You can define some toplevel mutable values which will contain accumulators which are used in your auxilary function now.
2) You can add argument to your function to store some data. You can find some examples when googling for continuation-passing style.
Happy hacking!
P.S. I still want to underline that your current solution is OK and you don't need to improve it!

Resources