I have a function that takes in a list and then puts elements into two different lists based on a condition. However, when I check the returned lists they are always empty. Why is this happening?
fun divide_list(l1: type list): (type list, type list) =
let
val count = ref 0
and list1 = nil
and list2 = nil
in
while !count <> 8 do (
if !count % 2 = 0 then
list1 # [List.nth(l1, !count)]
else
list2 # [List.nth(l1, !count)];
count := !count + 1
);
(list1, list2)
end
The output I get after running this is as follows:
val it = ([],[]) : type list * type list
You're not modifying the lists, you're creating new lists that are discarded. In order to achieve what you want, you'd need to also wrap the lists in references: and list1 = ref [] and list2 = ref []. Then, at each instance where you intend to modify them, you use := (as you have for modifying the count). Note that you'd rewrite the tuple you're returning to fetch the value held by each reference as well: (!list1, !list2).
As a sidenote, it is regrettable that Standard ML does not inform you of this. In OCaml, for example, the typing rule for sequencing expressions e ; e' ensures e evaluates to () : unit due to the way it's desugared (let () = e in e'). So, the OCaml analogue to your code wouldn't even typecheck.
I would dispense with the ref based solution entirely and do something using a fold, carrying the index:
fun divide xs =
let
fun choose (x, ((l, r), i)) =
(if i mod 2 = 0 then (x :: l, r) else (l, x :: r), i + 1)
val (l, r) =
#1 (List.foldl choose (([], []), 0) xs)
in
(List.rev l, List.rev r)
end
I build up the list partitions backwards and then reverse at the end to avoid quadratic blowup of appending to the end for every element. If you wish to have the length of 8 constraint, then you can combine the usage of the above function with List.take from the basis library.
#contificate has offered a good explanation.
If you're implementing a list partitioning function.
There's no reason not to factor out the function that will decide how to partition the list. This function only needs to take in a value and return a boolean value.
This is easily implemented in terms of a fold. There is no need, from what I can see, to keep track of the index.
fun partition f lst =
let
val (a, b) = List.foldl (fn (x, (a, b)) => if f x then (x::a, b) else (a, x::b)) ([], []) lst
in
(List.rev a, List.rev b)
end;
partition (fn x => x mod 2 = 0) [1, 2, 3, 4, 5];
Yields:
([2, 4], [1, 3, 5])
If you simply want to split based on index
If we're aiming to split a list into two lists based on the index:
[4, 7, 1, 9, 8]
Becomes:
([4, 1, 8], [7, 9])
That can be done entirely functionally as well with simple pattern matching and recursion.
let rec split lst (acc1, acc2) =
match lst with
| [] -> (acc1, acc2)
...
Here we're passing in the list to split, and an accumulator with the two lists. Obviously, if the list is empty, the result is just the accumulator. What if there's one element in the list?
let rec split lst (acc1, acc2) =
match lst with
| [] -> (acc1, acc2)
| [x] -> (x::acc1, acc2)
...
Well, that goes in the first list. What if there are more elements than one?
let rec split lst (acc1, acc2) =
match lst with
| [] -> (acc1, acc2)
| [x] -> (x::acc1, acc2)
| x::y::tail -> split tail (x::acc1, y::acc2)
Well, then we match the first two elements and the tail. We update the accumulator to place the first two elements in their respective lists, and call split again with the tail and that updated accumulator.
utop # split [4; 7; 1; 9; 8] ([], []);;
- : int list * int list = ([8; 1; 4], [9; 7])
Oops. They're backwards because of how we constructed the accumulators. We can use List.rev to fix this, but because we don't want to do it twice, when there's one element we'll call split on an empty list.
let rec split lst (acc1, acc2) =
match lst with
| [] -> (List.rev acc1, List.rev acc2)
| [x] -> split [] (x::acc1, acc2)
| x::y::tail -> split tail (x::acc1, y::acc2)
utop # split [4; 7; 1; 9; 8] ([], []);;
- : int list * int list = ([4; 1; 8], [7; 9])
And finally you can shadow split to remove the need to explicitly pass the tuple of empty lists.
let rec split lst (acc1, acc2) =
match lst with
| [] -> (List.rev acc1, List.rev acc2)
| [x] -> split [] (x::acc1, acc2)
| x::y::tail -> split tail (x::acc1, y::acc2)
let split lst = split lst ([], [])
Related
I don't understand the error message I'm getting or what's wrong with what I'm trying to do
I just want to use List.fold_left to apply my add1 function to this list [1,2,3]
My add1 function should just add 1 to each element, so I would get [2, 3, 4]
My main goal in doing this exercise is just to experiment with List.fold_left. I don't actually care about adding 1, I just choose that function because it seemed easy to write (I'm an ocaml beginner).
My ultimate goal is actually to populate the keys of a empty StringMap using List.fold_left and a function already written elsewhere, so if anyone has insight on that it would also be appreciated
Here's the 1st try (which I tried twice)
let rec add1 = function
| [] -> []
| h::t -> (h+1)::(add1 t) in List.fold_left add1 [1, 2, 3];;
Here's the 2nd try
let a(b) =
let rec add1 = function
| [] -> []
| h::t -> (h+1)::(add1 t)
in
let c = List.fold_left add1 b
in a [1,2,3];;
I think you should start with:
let add x = x + 1
And then build a function that applies a function to a list via List.fold_left:
let apply_f_to_list_elements fn lst = (*use List.fold_left here*)
Are you sure you want List.fold_left and not List.map?
It may help you to see how fold_left can be implemented.
let rec fold_left f init lst =
match lst with
| [] -> init
| x::xs -> fold_left f (f init x) xs
So consider what's happening when something like a sum function works, when implemented in term of fold_left.
let sum lst =
fold_left (+) 0 lst
If we evaluate sum [1; 2; 3; 4]:
sum [1; 2; 3; 4]
fold_left (+) 0 [1; 2; 3; 4]
fold_left (+) (0 + 1) [2; 3; 4]
fold_left (+) (1 + 2) [3; 4]
fold_left (+) (3 + 3) [4]
fold_left (+) (6 + 4) []
10
We can defined map in terms of fold_left:
let map f lst =
let f' init x = f x :: init in
fold_left f' [] lst
Let's evaluate map (fun x -> x + 1) [5; 2; 6]:
map (fun x -> x + 1) [5; 2; 6]
fold_left f' [] [5; 2; 6]
fold_left f' (5 + 1 :: []) [2; 6]
fold_left f' (2 + 1 :: [6]) [6]
fold_left f' (6 + 1 :: [3; 6]) []
[7; 3; 6]
Now, because of the way we destructure and create lists, the result is backwards. we can overcome this with fold_left by reversing the resulting list.
let map f lst =
let f' init x = f x :: init in
let lst' = fold_left f' [] lst in
List.rev lst'
Or with the |> operator:
let map f lst =
let f' init x = f x :: init in
fold_left f' [] lst |> List.rev
Taking this to the next level
At each iteration, fold_left transforms the first element in a list and an accumulator, into the accumulator for the next iteration. If you want to apply this concept to your StringMap module, consider StringMap.empty which generates an empty StringMap.t, and StringMap.add which take a key, an associated value, and an existing map, and returns a new map with that added mapping.
You can readily use fold_left to take an initially empty map and build it into a complete map step by step. The only question remaining will be what value you choose to associate with each string in your list.
As you seems to confuse map and fold_left I think this quote could help you to understand the difference:
Imagine you have a big dinner with numerous people. You are serving the dish: you go through all the people and replace their empty plates with plates containing food. This is a map operation: the number of plate on the table didn't change, but for each plate, you have done the same action (changing the content of the plate).
Once everything is done, you collect all the dirty plates: This is a fold operation, at the end, there are no more plates on the table, but you have done something for each plates (stacking them) and return the file result (a stack of dirty plates).
In both case, an action is applied systmatically. The difference is that Map preserves the current "structure" (the plates on the table) while Fold removes the structure, and build something else."
I am new to F# & tuples and I am trying to split a list into three lists of tuples using recursion and matching.
For example, a list of [1; 2; 3] would return:
l1 = [1]
l2 = [2]
l3 = [3]
or
[1;2;3;4;5;6;7]:
l1 = [1;2;3]
l2 = [4; 5]
l3 = [6; 7]
So far my code starts out as
let rec split x =
match x with
| _ -> [], [], []
I'm not sure where to start when inserting elements into each list.
The most basic approach would be to walk over the list, process the rest of it recursively and then append the current element to one of the three returned lists. You will need to add an extra parameters i to the function to keep track of how far in the list you are (and then use this to determine where should the current elemnt go). The general structure in the most basic form is:
let split l =
let length = List.length l
let rec loop i l =
match l with
| [] ->
// Empty list just becomes a triple of empty lists
[], [], []
| x::xs ->
// Process the rest of the list recursively. This
// gives us three lists containing the values from 'xs'
let l1, l2, l3 = loop (i + 1) xs
// Now comes the tricky bit. Here you need to figure out
// whether 'x' should go into 'l1', 'l2' or 'l3'.
// Then you can append it to one of them using something like:
l1, x::l2, l3
// Walk over the list, starting with index 'i=0'
loop 0 l
What to do about the tricky bit? I do not have a solution that works exactly as you wanted, but the following is close - it simply looks whether i is greater than 1/3 of the length or 2/3 of the length:
let split l =
let length = List.length l
let rec loop i l =
match l with
| [] -> [], [], []
| x::xs ->
let l1, l2, l3 = loop (i + 1) xs
if i >= length / 3 * 2 then l1, l2, x::l3
elif i >= length / 3 then l1, x::l2, l3
else x::l1, l2, l3
loop 0 l
This will always create groups of length / 3 and put remaining elements in the last list:
split [1..3] // [1], [2], [3]
split [1..4] // [1], [2], [3; 4]
split [1..5] // [1], [2], [3; 4; 5]
split [1..6] // [1; 2], [3; 4], [5; 6]
You should be able to adapt this to the behaviour you need - there is some fiddly calculation that you need to do to figure out exactly where the cut-off points are, but that's a matter of getting the +/-1s right!
There is a function for that in the List module.
You can test it easily in F# interactive (fsi).
let input = [1;2;3];;
let output = List.splitInto 3 input;;
output;;
val it : int list list = [[1]; [2]; [3]]
So it returns a list of lists.
If you want to do it by hand, you can still use other list functions (which might be good exercise in itself):
let manualSplitInto count list =
let l = List.length list
let n = l / count
let r = l % count
List.append
[(List.take (n+r) list)]
(List.unfold (fun rest ->
match rest with
| [] -> None
| _ -> let taken = min n (List.length rest)
Some (List.take taken rest, List.skip taken rest))
(List.skip (n+r) list))
Here, List.unfold does the iteration (recursing) part for you.
So, if you really want to train working with recursive functions, you will end up writing your own List.unfold replacement or something more tailored to your concrete use case.
let pedestrianSplitInto count list =
let l = List.length list
let n = l / count
let r = l % count
let rec step rest acc =
match rest with
| [] -> acc
| _ ->
let taken = min n (List.length rest)
step (List.skip taken rest) ((List.take taken rest) :: acc)
List.rev (step (List.skip (n+r) list) [List.take (n+r) list])
Please observe how similar the implementation of function step is to the lambda given to List.unfold in manualSplitInto.
If you also do not want to use functions like List.take or List.skip, you will have to go even lower level and do element wise operations, such as:
let rec splitAtIndex index front rear =
match index with
| 0 -> (List.rev front, rear)
| _ -> splitAtIndex (index - 1) ((List.head rear) :: front) (List.tail rear)
let stillLivingOnTreesSplitInto count list =
let l = List.length list
let n = l / count
let r = l % count
let rec collect result (front,rear) =
match rear with
| [] -> (front :: result)
| _ -> collect (front :: result) (splitAtIndex n [] rear)
let x = splitAtIndex (n+r) [] list
collect [] x |> List.rev
If you know it will always be triplets then this should work.
let xs = [1..7]
let n = List.length xs
let y = List.mapi (fun i x -> (x, 3 * i / n)) xs
List.foldBack (fun (x, i) (a,b,c) -> match i with 0 -> (x::a,b,c) | 1 -> (a,x::b,c) | 2 -> (a,b,x::c)) y (([],[],[]))
fun p(L) =
[L] # p( tl(L) # [hd(L)] );
If L is [1,2,3] then I want to have a [ [1,2,3], [2,3,1], [3,1,2] ].
Since every time I append the first num to the end, then if L = [] then [] doesn't work here.
How to stop the function once it has the three lists?
You can have a parameter x in the function to keep track of how many levels deep in the recursion you are.
fun p(L, x) =
if x < length(L) then [L] # p(tl(L) # [hd(L)], x+1)
else [];
Then call the function with x=0.
p([1, 2, 3], 0)
And if you don't like the extra parameter, then as you probably know you can define another function and make it equal to the p function with the parameter forced to 0.
fun p0(L) = p(L, 0);
p0([1, 2, 3]); (* same result as p([1, 2, 3], 0); *)
Let me show some more implementation variants.
First of all, let's define an auxiliary function, which rotates a list 1 position to the left:
(* operates on non-empty lists only *)
fun rot1_left (h :: tl) = tl # [h]
Then the p function could be defined as follows:
fun p xs =
let
(* returns reversed result *)
fun loop [] _ _ = []
| loop xs n res =
if n = 0
then res
else loop (rot1_left xs) (n-1) (xs :: res)
in
List.rev (loop xs (length xs) [])
end
It's usually better (performance-wise) to add new elements at the beginning of the list and then reverse the resulting list once, than to append to the end many times. Note: this version does one spurious rotate at the end and I could have optimized it out, but didn't, to make code more clear.
We have calculated the length of the given list to make its rotated "copies", but we don't have to traverse xs beforehand, we can do it as we rotate it. So, we can use xs as a kind of counter, recursively calling the loop helper function on the tail of the xs list.
fun p xs =
let
(* returns reversed result *)
fun loop [] _ _ = []
| loop xs [] res = res
| loop xs (_::tl) res =
loop (rot1_left xs) tl (xs :: res)
in
List.rev (loop xs xs [])
end
Having done that, we are now closer to implementing p as a foldl function:
fun p xs =
(List.rev o #1)
(List.foldl
(fn (_, (res, rot)) => (rot::res, rot1_left rot))
([], xs)
xs)
The second argument to the List.foldl function is our "accumulator", which is represented here as a pair of the current (partial) result as in the previous implementations and the current rotated list. That explains (List.rev o #1) part: we need to take the first component of the accumulator and reverse it. And as for the ([], xs) part -- the current result is empty at the beginning (hence []) and we start rotating the initial xs list. Also, the _ in (_, (res, rot)) means the current element of the given xs, which we don't care about, since it just serves as a counter (see the prev. variant).
Note: o stands for function composition in Standard ML.
I would like to implement a function that takes as input a size n and a list. This function will cut the list into two lists, one of size n and the rest in another list. I am new to this language and have a hard time learning the syntax.
The main problem I have is that is finding a way to express a size of the list without using any loops or mutable variables.
Can anyone give a me some pointers?
Let's start with the function's type signature. Since it gets n and a list as arguments and returns a pair of lists, you have a function split:
val split : int -> 'a list -> 'a list * 'a list
Here is one approach to implement this function:
let split n xs =
let rec splitUtil n xs acc =
match xs with
| [] -> List.rev acc, []
| _ when n = 0 -> List.rev acc, xs
| x::xs' -> splitUtil (n-1) xs' (x::acc)
splitUtil n xs []
The idea is using an accumulator acc to hold elements you have traversed and decreasing n a long the way. Because elements are prepended to acc, in the end you have to reverse it to get the correct order.
The function has two base cases to terminate:
There's no element left to traverse (xs = [] at that point).
You have gone through the first n elements of the list (n decreases to 0 at that time).
Here is a short illustration of how split computes the result:
split 2 [1; 2; 3] // call the auxiliary function splitUtil
~> splitUtil 2 [1; 2; 3] [] // match the 3rd case of x::xs'
~> splitUtil 1 [2; 3] [1] // match the 3rd case of x::xs'
~> splitUtil 0 [3] [2; 1] // match the 2nd case of n = 0 (base case)
~> List.rev [2; 1], [3] // call List.rev on acc
~> [1; 2], [3]
let split n list =
let rec not_a_loop xs = function
| (0, ys) | (_, ([] as ys)) -> (List.rev xs), ys
| (n, x::ys) -> not_a_loop (x::xs) (n-1, ys)
not_a_loop [] (n, list)
New solution - splitAt is now built into List and Array. See commit around 2014 on github. I noticed this today while using F# in VS.2015
Now you can simply do this...
let splitList n list =
List.splitAt n list
And as you might expect the signature is...
n: int -> list: 'a list -> 'a list * 'a list
Example usage:
let (firstThree, remainder) = [1;2;3;4;5] |> (splitList 3)
printfn "firstThree %A" firstThree
printfn "remainder %A" remainder
Output:
firstThree [1; 2; 3]
remainder [4; 5]
Github for those interested: https://github.com/dsyme/visualfsharp/commit/1fc647986f79d20f58978b3980e2da5a1e9b8a7d
One more way, using fold:
let biApply f (a, b) = (f a, f b)
let splitAt n list =
let splitter ((xs, ys), n') c =
if n' < n then
((c :: xs, ys), n' + 1)
else
((xs, c :: ys), n' + 1)
List.fold splitter (([], []), 0) list
|> fst
|> biApply List.rev
Here is a great series on folds than you can follow to learn more on the topic.
One more question about most elegant and simple implementation of element combinations in F#.
It should return all combinations of input elements (either List or Sequence).
First argument is number of elements in a combination.
For example:
comb 2 [1;2;2;3];;
[[1;2]; [1;2]; [1;3]; [2;2]; [2;3]; [2;3]]
One less concise and more faster solution than ssp:
let rec comb n l =
match n, l with
| 0, _ -> [[]]
| _, [] -> []
| k, (x::xs) -> List.map ((#) [x]) (comb (k-1) xs) # comb k xs
let rec comb n l =
match (n,l) with
| (0,_) -> [[]]
| (_,[]) -> []
| (n,x::xs) ->
let useX = List.map (fun l -> x::l) (comb (n-1) xs)
let noX = comb n xs
useX # noX
There is more consise version of KVB's answer:
let rec comb n l =
match (n,l) with
| (0,_) -> [[]]
| (_,[]) -> []
| (n,x::xs) ->
List.flatten [(List.map (fun l -> x::l) (comb (n-1) xs)); (comb n xs)]
The accepted answer is gorgeous and quickly understandable if you are familiar with tree recursion. Since elegance was sought, opening this long dormant thread seems somewhat unnecessary.
However, a simpler solution was asked for. Iterative algorithms sometimes seem simpler to me. Furthermore, performance was mentioned as an indicator of quality, and iterative processes are sometimes faster than recursive ones.
The following code is tail recursive and generates an iterative process. It requires a third of the amount of time to compute combinations of size 12 from a list of 24 elements.
let combinations size aList =
let rec pairHeadAndTail acc bList =
match bList with
| [] -> acc
| x::xs -> pairHeadAndTail (List.Cons ((x,xs),acc)) xs
let remainderAfter = aList |> pairHeadAndTail [] |> Map.ofList
let rec comboIter n acc =
match n with
| 0 -> acc
| _ ->
acc
|> List.fold (fun acc alreadyChosenElems ->
match alreadyChosenElems with
| [] -> aList //Nothing chosen yet, therefore everything remains.
| lastChoice::_ -> remainderAfter.[lastChoice]
|> List.fold (fun acc elem ->
List.Cons (List.Cons (elem,alreadyChosenElems),acc)
) acc
) []
|> comboIter (n-1)
comboIter size [[]]
The idea that permits an iterative process is to pre-compute a map of the last chosen element to a list of the remaining available elements. This map is stored in remainderAfter.
The code is not concise, nor does it conform to lyrical meter and rhyme.
A naive implementation using sequence expression. Personally I often feel sequence expressions are easier to follow than other more dense functions.
let combinations (k : int) (xs : 'a list) : ('a list) seq =
let rec loop (k : int) (xs : 'a list) : ('a list) seq = seq {
match xs with
| [] -> ()
| xs when k = 1 -> for x in xs do yield [x]
| x::xs ->
let k' = k - 1
for ys in loop k' xs do
yield x :: ys
yield! loop k xs }
loop k xs
|> Seq.filter (List.length >> (=)k)
Method taken from Discrete Mathematics and Its Applications.
The result returns an ordered list of combinations stored in arrays.
And the index is 1-based.
let permutationA (currentSeq: int []) (n:int) (r:int): Unit =
let mutable i = r
while currentSeq.[i - 1] = n - r + i do
i <- (i - 1)
currentSeq.[i - 1] <- currentSeq.[i - 1] + 1
for j = i + 1 to r do
currentSeq.[j - 1] <- currentSeq.[i - 1] + j - i
()
let permutationNum (n:int) (r:int): int [] list =
if n >= r then
let endSeq = [|(n-r+1) .. n|]
let currentSeq: int [] = [|1 .. r|]
let mutable resultSet: int [] list = [Array.copy currentSeq];
while currentSeq <> endSeq do
permutationA currentSeq n r
resultSet <- (Array.copy currentSeq) :: resultSet
resultSet
else
[]
This solution is simple and helper function costs constant memory.
My solution is less concise, less effective (altho, no direct recursion used) but it trully returns all combinations (currently only pairs, need to extend filterOut so it can return a tuple of two lists, will do little later).
let comb lst =
let combHelper el lst =
lst |> List.map (fun lstEl -> el::[lstEl])
let filterOut el lst =
lst |> List.filter (fun lstEl -> lstEl <> el)
lst |> List.map (fun lstEl -> combHelper lstEl (filterOut lstEl lst)) |> List.concat
comb [1;2;3;4] will return:
[[1; 2]; [1; 3]; [1; 4]; [2; 1]; [2; 3]; [2; 4]; [3; 1]; [3; 2]; [3; 4]; [4; 1]; [4; 2]; [4; 3]]
Ok, just tail combinations little different approach (without using of library function)
let rec comb n lst =
let rec findChoices = function
| h::t -> (h,t) :: [ for (x,l) in findChoices t -> (x,l) ]
| [] -> []
[ if n=0 then yield [] else
for (e,r) in findChoices lst do
for o in comb (n-1) r do yield e::o ]