Trying to write a recursive function that will cut a list by n. Then return 2 lists. So if I pass
cut(2, [5;10;4;2;7]);;
val it : int list * int list = ([5; 10], [4; 2; 7])
I would like to get something like that.
let rec cut (n, xs) =
match n, xs with
| 0, xt -> (n, xs)
| n, x::xt -> cut(n, xt), xs;;
Please help.
I'll ad an explanation of #MisterMetaphors recursive function.
The cut function isn't recursive but aux is, it works by counting down from n and removing elements from the head of the list passed to cut.
Say you call cut like this cut 2 [ 3; 4; 5; 7; 8 ]. aux is a pattern matching function taking three arguments: n, partition 1, partition 2. Partition 1 starts out with being an empty list and partition 2 starts out with being the full list passed to cut.
First time aux will match the second clause, then it'll call itself with arguments (1, [3], [4; 5; 7; 8]). Next time it'll also match second clause, now it calls itself with (0, [4; 3], [5; 7; 8]). Third and final time it matches first clause (n=0) and it will return a tuple containing xs and ys.
Notice however that the elements of the xs is in reverse order since each element was prepended (using cons operator ::). The reason this is done is because it's an O(1) operation compared to the append operator # which is O(n) on the left side.
Since xs is in reverse order the last expression in the function is a reversal of xs.
An alternative and slightly short definition could be:
let cut n xs =
let rec aux = function
| 0, xs, ys -> List.rev xs, ys
| n, xs, y :: ys -> aux (n - 1, y :: xs, ys)
| _ -> failwith "invalid arguments"
aux (n, [], xs)
It's probably better to combine built-in functions on lists or sequences to achieve this:
let cut' (n, xs) =
Seq.take n xs, Seq.skip n xs
Recursively, your function can be defined like so:
let cut (n, xs) =
let rec aux = function
| 0, xs, ys -> xs, ys
| n, xs, y :: ys -> aux (n - 1, y :: xs, ys)
| _ -> failwith "invalid arguments"
let l, r = aux (n, [], xs)
(List.rev l, r)
Related
So consider getting a list of [1; 2; 3; 4; 5; 6; 7; 8; 9] and reshape it into [[1; 2; 3]; [4; 5; 6]; [7; 8; 9]]. How would you do that in OCaml? I want a simple function or something from the standard library.
Turns out, it can be easily done with 3 lines of code, considering that the length of the list is divisible by 3.
let rec re_shape = function
| x :: xs :: xz :: xt -> [x; xs; xz] :: re_shape xt
| _ -> []
How this works is that for each iteration it cons a list of 3 to the rest of the function, till it reaches the end. The last line is added for safety.
As you have shown an effort to solve this, for your consideration, see a strategy below for generalizing this to allow for any length.
The partition function will allow us to get the first n elements from the list and the remainder, raising Invalid_argument if there aren't n elements in the list.
The chunks function applies this recursively to the remainder to build a list of lists.
let partition n lst =
let rec partition' n (first, rest) =
match n, rest with
| 0, _ -> (List.rev first, rest)
| _, [] -> raise (Invalid_argument "List not long enough")
| _, x::xs -> partition' (n-1) (x :: first, xs)
in
partition' n ([], lst)
let rec chunks n lst =
match partition n lst with
| first, [] -> [first]
| first, rest -> first :: chunks n rest
| exception (Invalid_argument _) ->
raise (Invalid_argument (Format.sprintf "List length not evenly divisible by %d" n))
This second function is not tail-recursive, though that can readily be addressed in OCaml 4.14 and later with:
let[#tail_mod_cons] rec chunks n lst =
...
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 ([], [])
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.