Given a list: [1; 2; 3], how can I generate all possible splits:
[
[ [1; 2; 3] ];
[ [1]; [2; 3] ];
[ [1]; [2]; [3] ];
[ [1; 2]; [3] ]
]
I have no real attempt yet, I don't know how to start
EDIT : attempt
I tried to do it step by step but it's kinda messy
and I couldn't do mergeFirst, without mergeFirst it gives : [[[1]; [2; 3]]; [[1]; [2]; [3]]]
Am I on the right path ? I don't think my code will work if the list contains more than 3 elements too ...
let split = function
| [] -> []
| x::y -> [[x::y]] # [[[x]] # [[List.hd y]]]
(* let mergeFirst a = function
... *)
let addtoseperatelist a list =
List.map (fun t -> [[a]] # t) (list)
let rec generateAllSplit = function
| [] -> []
| [x;y] -> split (x::y::[])
| x::y -> addtoseperatelist x (generateAllSplit y) # (mergeFirst x (generateAllSplit y))
let myList = [[1;2;3]]
let _ = generateAllSplit myList
Until you get farther with your analysis, this isn't actually an OCaml question. It's more a question about breaking down a problem recursively.
One good way to solve problems that feel recursive is to imagine that you already had the solution. If you had your split function already, it would return the following for the tail of your list ([2; 3]):
[ [[2; 3]]; [[2]; [3]] ]
Is there a way to process this smaller result into your desired final result? Yes. There are two things you can do with [1]: you can merge it with the first element of the returned lists, or you can add it as a separate list. That gives you the four values of the desired result. You should be able to prove to yourself that his always gives the right answer. (Or maybe it doesn't, you'll have to check.)
If your given list has fewer than 2 elements, the result is obvious. You can probably combine this with the above recursive processing to get the answer.
You are on the right track. The merge first is still missing, which you have to do with pattern matching because the empty list is a special case. In my code that is (function [] -> [[x]] | z::zs -> (x::z)::zs) ys
The one element list is also a special case for split because it only has one result. If you would solve that recursively you would get [[x]; []] and [[x] # []] == [[x]].
Instead of adding to the recursive results and merging to the recursive results and then appending the two resulting lists I decided to use a fold_left and construct the adding and merging of each sub list in parallel. Then you can :: the results instead of append:
let myList = [1;2;3]
let rec split = function
| [] -> [[[]]]
| [x] -> [[[x]]]
| (x : int)::xs ->
List.fold_left
(fun (acc : int list list list) (ys : int list list) ->
([x] :: ys) (* add to separate list *)
:: (function [] -> [[x]] | z::zs -> (x::z)::zs) ys (* merge first *)
:: acc
)
[]
(split xs)
let res = split myList;;
val myList : int list = [1; 2; 3]
val split : int list -> int list list list = <fun>
val res : int list list list =
[[[1]; [2; 3]]; [[1; 2; 3]]; [[1]; [2]; [3]]; [[1; 2]; [3]]]
Related
I tried to write my own solution for this exercise by iterating through a list with a empty complst list where all non duplicates are inserted into and then get returned.
I know it is a over complicated approach after looking up the solution but would still like to understand why the pattern matching does not work as intended:
let compress list =
let rec aux complst lst =
match lst with
| [] -> complst
| a :: (b :: c) -> if a = b then aux complst (b::c) else aux (a::complst) (b::c)
| x -> x
in aux [] list;;
val comp : 'a list -> 'a list = <fun>
Regardless of the input, the output is always a list with only the last element:
compress [1;1;2;2;3];;
- : int list = [3]
compress [1;2;3];;
- : int list = [3]
Pattern matching
Your pattern-matching matches against three patterns:
The empty list: []
The list with at least two elements: a :: (b :: c)
A catch-all, which must by process of elimination be a list with a single element.
Consider what happens when we evaluate your example:
compress [1; 1; 2; 2; 3]
aux [] [1; 1; 2; 2; 3]
aux [] [1; 2; 2; 3]
aux [1] [2; 2; 3]
aux [1] [2; 3]
aux [2; 1] [3]
[3]
Oops, as soon as it hit lst being [3] it just returned it.
Let's rewrite your function to handle that single element list by adding to complst.
let compress lst =
let rec aux complst lst =
match lst with
| [] -> complst
| [x] -> aux (x::complst) []
| a :: (b :: c) ->
if a = b then aux complst (b::c)
else aux (a::complst) (b::c)
in
aux [] list
Now:
compress [1; 1; 2; 2; 3]
aux [] [1; 1; 2; 2; 3]
aux [] [1; 2; 2; 3]
aux [1] [2; 2; 3]
aux [1] [2; 3]
aux [2; 1] [3]
aux [3; 2; 1] []
[3; 2; 1]
Clean up and reversing the resulting list
Of course, there are also ways to clean up your code a bit using a conditional guard and _ for values you don't need to bind names to. You probably also want to reverse your accumulator.
let compress lst =
let rec aux complst lst =
match lst with
| [] -> List.rev complst
| [x] -> aux (x::complst) []
| a :: (b :: _ as tl) when a = b -> aux complst tl
| a :: (_ :: _ as tl) -> aux (a::complst) tl
in
aux [] lst
Fold
When you see this pattern of iterating over a list one element at a time and accumulating a new value, you can usually map that pretty well to List.fold_left.
let compress lst =
List.(
fold_left
(fun i x ->
match i with
| (x'::_) when x = x' -> i
| _ -> x::i)
[] lst
|> rev
)
Because List.fold_left can only be aware of one element at a time on the list, the function we pass as its first argument can't be aware of the next element in the list. But it is aware of the accumulator or "init" value. In this case that's another list, and we can pattern match out that list.
If it's not empty and the first element is equal to the current element we're looking at, don't add it to the result list. Otherwise, do add it. This also handles the first element case where the accumulator is empty.
Kudos on creating a tail-recursive solution to this problem!
The problem with your code here is mainly the last part, which corresponds to when you have the last element in your list so here [3], and you return that list with this single element.
What you need to do instead is append it to complst like this :
let compress list =
let rec aux complst lst =
match lst with
| [] -> complst
| a :: (b :: c ) -> if a=b then aux complst (b::c) else aux (a::complst) (b::c)
| x::e -> x::complst
in aux [] list;;
val comp : 'a list -> 'a list = <fun>
Now you can check with the given example :
compress [1;1;2;2;3];;
- : int list = [3; 2; 1]
Hope it helps you understand your mistake better.
Note regarding comments:
you should keep the [] case, because although it can only happen in one scenario, it is still a valid input meaning it must be kept!.
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'm supposed to remove consecutive duplicates from an int list without using recursion and using only List.fold, map, filter, fold_left, fold_right.
I almost got it, but the problem with my code is that it checks if each element equals the 2nd element, and not the next element.
For example if let z = int list [3;1;4;5;5;1;1] my code will return [3;4;5] and not [3;1;4;5;1]. I'm not sure how to change it so filter uses a dynamically changing list parameter and not simply the original one (so it doesn't compare each element to the second element (1 in this case) each time):
let dupe (ls: int list) : int list =
List.filter (fun x -> if List.length ls = 0 then true else if x = List.hd (List.tl xs) then false else true) ls
The type of List.filter is this:
# List.filter;;
- : ('a -> bool) -> 'a list -> 'a list = <fun>
Notably, the filter function can see only one element of the list at a time. You need to see two consecutive elements to decide what to do, so I'd say List.filter won't do the job.
You're going to have to use map or one of the folds, I'd say. You can figure out which one(s) will work, with similar reasoning.
(I assume this is the sort of reasoning the assignment is supposed to illustrate. So I'm going to leave it there.)
Without rec
let remove = function
[] -> []
| x::tl ->
let (_,lxRes)=
List.fold_left (
fun (xPrec,lxRes) xCour ->
if xPrec=xCour then
(xCour,lxRes)
else
(xCour,lxRes#[xCour])
) (x+1,[]) (x::tl)
in
lxRes
Test:
# remove [3;1;4;5;5;1;1];;
- : int list = [3; 1; 4; 5; 1]
# remove [1;1];;
- : int list = [1]
# remove [1;1;1;1;2;2;3;4;5;5];;
- : int list = [1; 2; 3; 4; 5]
With rec (just for information)
let rec remove =
function
| [] -> []
| x::[] -> x::[]
| x::y::tl ->
if x=y then remove (y::tl)
else x::remove (y::tl)
Using just List.fold_left can be a little bit more concise than the previous answer. Of course, this will build up the list in reverse order, so we need to reverse the result.
let remove lst =
List.(
lst
|> fold_left
(fun acc x ->
match acc with
| [] -> [x]
| hd::_ when x = hd -> acc
| _ -> x::acc)
[]
|> rev
)
Of course, if you're not allowed to use List.rev we can reimplement it easily using List.fold_left, List.cons and Fun.flip.
let rev lst =
List.fold_left (Fun.flip List.cons) [] lst
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.
For [1;2;3;4;5], I want to return [[1;2;3;4;5];[2;3;4;5];[3;4;5;];[4;5];[5];[]]
I'm trying to use the List library but I'm unsure how to. So far, I know I have to use List.tl to get the list without the first element
let rec tailsoflist (l : 'a list) : 'a list list =
match l with
[] -> [[]]
| x::xs -> l::(tails xs)
I did this recursively but now I want to just use the list library without using recursion.
let tails (l : 'a list) : 'a list list
EDIT: Sorry guys, what I specified for the function to return is incorrect. Just updated it with the correct output.
As I said in the comment, these are not the tails of l but copies of the tails of l:
# let tails l = List.fold_right (fun e acc -> (e::(List.hd acc))::acc) l [[]] ;;
val tails : 'a list -> 'a list list = <fun>
# tails [1; 2; 3; 4] ;;- : int list list = [[1; 2; 3; 4]; [2; 3; 4]; [3; 4]; [4]; []]
There is no good way to write that function in terms of the built-in functions.
The answer you give in your question is fine but it would be more idiomatic to not annotate the types and use function:
let rec tails = function
| [] -> [[]]
| _::xs' as xs -> xs::tails xs'
Other languages, like F#, provide a List.unfold function that tails can be written in terms of.
Ah, the old trick to accumulate on the original list to cast tails as a catamorphism. This is done without explicit recursion using just functions on the List module:
let tails l = List.rev ( [] :: snd (List.fold_right
(fun _ (t,ts) -> List.tl t, t::ts) l (l, [])) )
It produces the tails as you expect:
# tails [1;2;3;4;5];;
- : int list list = [[1; 2; 3; 4; 5]; [2; 3; 4; 5]; [3; 4; 5]; [4; 5]; [5]; []]
and the tails are the actual structural tails of the input list, so that List.tl l == List.hd (List.tl (tails l)).
"Without using recursion"... why ? Recursion is a useful tool, even outside the List library.
let rec suffixes = function
| [] -> [[]]
| hd::tl as suff -> suff :: suffixes tl
Your function (which doesn't compile because you use tails instead of tailsoflist) returns the list of suffixes of a list. Due to the list structure, it's easier to compute than the prefixes.
You can express the prefixes from the suffixes :
let prefixes li = List.map List.rev (suffixes (List.rev li));;
You could do a direct version using an accumulator:
let prefixes li =
let rec pref acc = function
| [] -> List.rev acc :: []
| hd::tl -> List.rev acc :: pref (hd :: acc) tl
in pref [] li
and express it using List.fold_left if you want to avoid recursion, but this is convoluted so you should prefer the direct version in my opinion:
let prefixes li =
let acc, res =
List.fold_left
(fun (acc, res) e -> (e :: acc), (List.rev acc :: res))
([], []) li in
List.rev acc :: res
Finally, it is possible to destroy your brain with a version using continuations, but I don't remember the exact code. Roughly, the continuation is equivalent to the "accumulator" of the direct version.