Appending lists in SML - list

I'm trying to add an int list list with another int list list using the append function, but I can't get it to work the way I want.
Say that I want to append [[1,2,3,4,5]] with [6,7] so that I get [[1,2,3,4,5,6,7]].
Here's my attempt: [1,2,3,4,5]::[]#[6,7]::[], but it just gives me the list I want to append as a list of its own instead of the two lists combined into one, like this: [[1,2,3,4,5],[6,7]].
How can I re-write the operation to make it return [[1,2,3,4,5,6,7]]?

Your question is too unspecific. You are dealing with nested lists. Do you want to append the second list to every inner list of the nested list, or only the first one? Your example doesn't tell.
For the former:
fun appendAll xss ys = List.map (fn xs => xs # ys) xss
For the latter:
fun appendHd [] ys = raise Empty
| appendHd (xs::xss) ys = (xs # ys)::xss
However, both of these should rarely be needed, and I somehow feel that you are trying to solve the wrong problem if you end up there.

Related

Problem with a list in the form of [(key, [..]) ; ...]

I'm trying to learn OCaml since I'm new to the language and I stumbled across this problem where I can't seem to find a way to see, in a function where I need to merge 2 kinds of these lists, if there is already an element with a key, and if so how to join the elements that come after. Would appreciate any guidance.
For example if I have:
l1: [(k, [e]); (ka, [])]
l2: [(k, [f; g])]
How can I end up with:
fl: [(k, [e; f; g]); (ka, [])]
Basically, how can I filter the key k from both lists while making their elements combine.
There are functions in the standard OCaml library for dealing with lists of pairs where the first element of each pair is a key. You will find them described here: https://ocaml.org/releases/4.12/api/List.html under Association lists.
I will repeat what #ivg says. This is not how you want to solve your problem if you have more than just a few pairs to work with.
First of all, using lists as mappings is a bad idea. It is much better to use dedicated data structures such as maps and hash tables.
Answering your question directly, you can concatenate two lists using the (#) operator, e.g.,
# [1;2;3] # [4;5;6];;
- : int list = [1; 2; 3; 4; 5; 6]
If you don't want repetitive elements when you merge then, and I feel like I repeat myself, it is bad to use lists for sets, it is better to use dedicated data structures such as sets and hash sets. But if you want to continue, then you can merge two lists without repetitions by checking if an element is already in the list before prepending to it. Easy to implement but hard to run, in a sense that it takes quadratic time to merge two lists this way.
If you still want to stick with the list of pairs, then you will find that the List.assoc function is useful, as it finds a value by key. The overall algorithm would be, given two lists, xs and ys, fold over elements of ys using xs as the initial value acc, and for each (ky,y) in ys if ky is already in acc, find the associated with ky value x and remove (List.remove_assoc) it, then merge x and y and prepend the merged value with the acc list, otherwise (if it is not in acc) just prepend (ky,y) to acc`. Note that this algorithm doesn't preserve order, so if it matters you need something more complex. Also, if your keys are sorted you can make it a little bit more efficient and easier to implement.
I guess you're doing this to practice with list.
What I would do is store the already found keys in an accumulator
let mergePairs yourList =
let rec aux accKeys = function
| [] -> []
| x :: xs -> let k,v = x in if (* k in accKeys *) then aux accKeys xs (*we suppress already
existing keys*)
else (k, v # (* get all the list of the other pairs with key = k in xs*))
:: aux (k::accKeys) xs
in aux [] yourList;;

How to solve "unresolved flex record" in else if statement in SML?

I want to find a list of nodes that currently given nodes directly or indirectly connect to.
For example, I have a list of nodes:
[1,2]
and a list of tuples, and each of the tuples represents a direct edge:
[(1,5),(2,4),(4,6)]
So, the nodes I am looking for are
[1,2,5,4,6]
Because, 1 connects to 5, 2 connects to 4. Then, 4 is connected to 6.
To achieve this, I need two a queues, and a list. Each time a new node is discovered, we append the new node to the queue and the list. Then, we remove the first node of the queue, and go to next node. If a new node is connected to the current node of the queue. Then, we add new node to both the queue and the list.
We keep doing this until the queue is empty and we return the list.
So now, I have an append function which appends a list to another list:
fun append(xs, ys) =
case ys of
[] => xs
| (y::ys') => append(xs # [y], ys')
Then, I have a function called getIndirectNodes, which intends to return the lists of nodes that the given nodes indirectly connected to, but throws "unresolved flex record". List1 and List2 have the same items supposedly. But, List1 serves the queue, and list2 servers as the list to be returned.
fun getIndirectNode(listRoleTuples, list1, list2) =
if list1 = []
then list2
else if hd(list1) = #1(hd(listRoleTuples))
then (
append(list1,#2(hd(listRoleTuples)) :: []);
append(list2,#2(hd(listRoleTuples)) :: []);
getIndirectNode(listRoleTuples,tl(list1),list2)
)
else
getIndirectNode(listRoleTuples,tl(list1),list2)
If I remove the else if statement, it works perfectly fine. But, it's not what I intended to do. The problem is in the else if statement. What can I do to fix it?
SML needs to know exactly what shape a tuple has in order to deconstruct it.
You could specify the type of the parameter - listRoleTuples : (''a * ''a) list - but using pattern matching is a better idea.
(There are many other problems with that code, but that's the answer to your question.)
It seems that one of your classmates had this exact tuple problem in a very related task.
Make sure you browse the StackOverflow Q&A's before you ask the same question again.
As for getting the indirect nodes, this can be solved by fixed-point iteration.
First you get all the direct nodes, and then you get the direct nodes of the direct nodes.
And you do this recursively until no more new nodes occur this way.
fun getDirectNodes (startNode, edges) =
List.map #2 (List.filter (fn (node, _) => node = startNode) edges)
fun toSet xs =
... sort and remove duplicates ...
fun getReachableNodes (startNodes, edges) =
let
fun f startNode = getDirectNodes (startNode, edges)
val startNodes = toSet startNodes
val endNodes = toSet (List.concat (List.map f startNodes))
in
if startNodes = endNodes
then endNodes
else getReachableNodes (startNodes # endNodes, edges)
end
This doesn't exactly find indirect end-nodes; it finds all nodes directly or indirectly reachable by startNodes, and it includes startNodes themselves even if they're not directly or indirectly reachable by themselves.
I've tried to make this exercise easier by using sets as a datatype; it would be even neater with an actual, efficient implementation of a set type, e.g. using a balanced binary search tree. It is easier to see if there are no new nodes by adding elements to a set, since if a set already contains an element, it will be equivalent to itself before and after the addition of the element.
And I've tried to use higher-order functions when this makes sense. For example, given a list of things where I want to do the same thing on each element, List.map produces a list of results. But since that thing I want to do, getDirectNodes (startNode, edges) produces a list, then List.map f produces a list of lists. So List.concat collapses that into a single list.
List.concat (List.map f xs)
is a pretty common thing to do.

Generate all combinations of a 6 element list and apply a function to each combination

I want to generate all possible combinations of a 6 element list [x1,x2,x3,x4,x5,x6] with each xi being a number between 0 and 20.
I want to generate all possible combinations of such list, apply a function (takes the list as input and outputs a magical Int) to each list, then output the results to a list of tuples. So the list of tuples looks like
[([x11,x21,x31,x41,x51,x61],Int1), ([x12,x22,x32,x42,x52,x62],Int2), ...]
I tried to this by hand by quickly realised that there are too many combinations and it is practically impossible to do by hand.
The combinations are like [0,0,0,0,0,0], [1,7,0,10,11,6], [7,7,7,7,6,6], [20,20,20,20,20,20] and so on.
I know how to generate all combinations of a list and put them in a list of lists (because I asked this before)
foo [] = [[]]
foo (x:xs) = foo xs ++ map (x:) (foo xs)
What I want to achieve this time is different because I am not trying to generate the different combinations within a particular list, I am trying to generate all 6 element lists.
As far as I can tell, you want a cartesian product (denoted by × here) of 6 lists [0..20].
So essentially, something like this:
[0..20]×[0..20]×[0..20]×[0..20]×[0..20]×[0..20]
That's a lot of elements (85,766,121 to be exact). But, it could be done.
Perhaps an easier to understand version is as follows.
Let us define a function, cart, that would do something like a cartesian product over a list and a list of lists:
let cart xs ls = [x:l | x <- xs, l <- ls]
This function will take all elements from xs, and all elements from ls and build a list of lists with all possible concatenations.
Now, we need a base case. Suppose you wanted a list of lists of a single element instead of six. How would you apply our cart function? Well, since it adds each element from first argument to every element in second argument, we can pass a list of a single empty list as a second argument, and [0..20] as first argument:
cart [0..20] [[]]
We get
[[0],[1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13],[14],[15],[16],[17],[18],[19],[20]]
Great. Now we just apply it 6 times to its own result, starting with [[]]:
foldr ($) [[]] $ replicate 6 (cart [0..20])
($) is function application.
replicateM from Control.Monad (defined as sequence of n monadic actions: replicateM n x = sequence (replicate n x)) basically does the same when applied to lists (see e.g. Why does application of `sequence` on List of Lists lead to computation of its Cartesian Product? for why exactly that is) So shorter answer would be like this:
replicateM 6 [0..20]
You can map over those after this, e.g.
map (\x -> (x, magicFunction x)) $ replicateM 6 [0..20]
foo f xs = map (\ys -> (ys,f ys)) (replicateM (length xs) xs)
Here replicateM (length xs) xs will generate all combinations of the elements in xs. Then you just map over it.
Results in GHCI:
>import Control.Monad
>let foo f xs = map (\ys -> (ys,f ys)) (replicateM (length xs) xs)
>foo sum [1,2]
[([1,1],2),([1,2],3),([2,1],3),([2,2],4)]

Tranpose a list list in OCaml

let rec transpose list = match list with
| [] -> []
| [] :: xss -> transpose xss
| (x::xs) :: xss ->
(x :: List.map List.hd xss) :: transpose (xs :: List.map List.tl xss)
I found this code on this website and it transposes a list list or in my case a matrix from n × m to m × n.The only problem is I have no idea how it works. Can anyone please explain it step by step, line by line.
You should provide the link to the code as well, for context, or look on that question for an explanation.
Either way, I suspect other new OCaml programmers will come to this question looking for an answer.
-- After a quick Google search I believe this was the question you found the code from.
let rec transpose list = match list with
Create a function called transpose, make it recursive (rec) as we will make the function call itself. It will take an input parameter called list, where the type is determined by OCaml's type-system later.
Match the input parameter list with the following cases. That is, when the function finds a pattern matching those cases, it will execute that particular line of code. If code written does not cover all cases, OCaml will notify that not all cases are exhaustive and will cause a match_failure if it encounters cases that it doesn't cover.
First case:
| [] -> []
If we hit an empty list, return an empty list. This will end the recursion as the empty list is appended to the final result and returned. The empty list is a base case, where we meet a list with nothing inside, or it has recursed till there is nothing left. (the transpose of an empty list is ... and empty list)
| [] :: xss -> transpose xss
This is the case where there are still items in the list. Since it is a list of list, each element in the list we pass in is another list. i.e, [[1;2];[3;4]], so this function handles the case where we have [[];[1;2];[5;6]], it will skip the empty inner list, and then call transpose on the other [[1;2];[5;6]], since we don't need to transpose an empty list. Note that xss is the rest of the list (hence list of list), not just the next element only (which is just a list).
| (x::xs) :: xss ->
(x :: List.map List.hd xss) :: transpose (xs :: List.map List.tl xss)
This is the first case that will be matched when we pass in any regular list of list of length > 1, OCaml is able to match and also "unwrap" each element by breaking it down to fit the pattern, so we can immediately compute those elements without using nested match statements. In this case, we split the list of list into the (x::xs) list (first element) and the remaining list of list, xss. We could have also done it as x::xss but x will be a list that we need to break down into individual elements again.
For example, in [[1;2];[3;4]], (x::xs) will be [1;2] and xss will be [[3;4]]
(x :: List.map List.hd xss) will take the first element in the first list, in the given example, x will be 1. And apply that value to the List.hd of every item in xss list, (List.Map applies a function to every value in the list).
This is where it seems a little complicated. How you can look at it is: When you call List.hd [1;2;3] it will return 1 since it's the head. So when we do 3 :: List.map List.hd [[1;2]] it will return int list = [3; 1]. and it we did 3 :: List.map List.hd [[1;2];[4;5]] we get [3;1;4] as we are getting the head of every list inside the larger list, and appending 3 at the front of the resulting list.
If you did List.map List.tl [[1;2];[4;5]] instead your return type would be [2;5] since List.map applies the List.tl function to every list. You can use List.map to apply say a multiplication function (or anything complicated) to each item in the list in a quick and easy way.
The remaining transpose (xs :: List.map List.tl xss) just calls transpose to the remaining items in the list, which is the tail values of xss (all lists), appended with elements in xs. Try this out on paper if you feel you need a more concrete grasp on it.

Value of the last element of a list

how to get the value of the last element of a List? I've noted that List.hd (or .Head) return an item, while List.tl (or .Tail) returns a List.
Is rev the List and get the hd the only way around? Thanks.
Try this function. It uses recursion, though it gets optimised to iteration anyway since it's tail recursion. In any case, it is most likely quicker than reversing the entire list (using List.rev).
let rec last = function
| hd :: [] -> hd
| hd :: tl -> last tl
| _ -> failwith "Empty list."
The answer of Pavel Minaev is definitely worth taking into account, however. Nonetheless, the algorithm you have requested may be useful in some rare cases, and is the most efficient way to go about the task.
In general, if you need to do this, you're doing something wrong. Since F# lists are single-linked, accessing the last element is costly - O(N), where N is size of list. Try to rewrite your algorithm so that you always access the first element, not the last (which is O(1)). If you cannot do so, chances are good that your choice of list for a data structure wasn't correct in the first place.
A quick & dirty way of doing it is by using List.reduce. Assuming the list is called ls,
let lastElement ls = List.reduce (fun _ i -> i) ls
As for efficiency, I agree with Pavel.
A more concise version based on Mitch's answer:
let lastItem = myList |> List.rev |> List.head
The myList list is sent to List.rev function. The result is then processed by List.head
Agreed, not so efficient to get the last element of list, or any other "enumerable" sequence. That said, this function already exists in the Seq module, Seq.last.
As a novice F# developer, I don't see what the harm is in doing the following
let mylist = [1;2;3;4;5]
let lastValue = mylist.[mylist.Length - 1]
Imperative in nature? Yes but no need for recursion.
The regular way to work with lists in F# is to use recursion. The first item in a list is the head (obviously) and the rest of the list is the tail (as oppose to the last item). So when a function recieves a list it processes the head and then recursively processes the rest of the list (the tail).
let reversedList = List.rev originalList
let tailItem = List.hd reversedList
I think you can just write
list.[0..list.Length-1]
You can call List.Head to get the first element of a list, such that the below expression evaluates to true:
let lst = [1;2;3;4;5]
List.head lst = 1
However, calling List.Tail will return every element in the list after the first element, such that the below expression is true:
let lst = [1;2;3;4;5]
List.tail lst = [2;3;4;5]
Like some other people have mentioned, there isn't an efficient way in F# to get the tail end of a list, basic lists just aren't built with that functionality in mind. If you really want to get the last element you're going to have to reverse your list first, and then take the new head (which was the previous tail).
let lst = [1;2;3;4;5]
(List.head (List.rev lst) ) = 5
Below code worked fine with me, I've an array of integers, want to start from the 5th item, then take it minus the item number
Sum of [Array(xi) - Array(xi-5)] where i start at 5
The code used is:
series |> Array.windowed 5
|> Array.fold (fun s x ->
(x |> Array.rev |> Array.head) - (x |> Array.head) + s) 0
|> float
It's a very old question, but just in case someone comes here:
with FSharp 5, you can do x.[^index] where index will start at the end of the array / list.
let a = [1;2;3;4;5;6;7;8;9]
a.[^0] is 9
a.[^1] is 8
etc