Trying to insert a number in all positions of the list, result being a list of lists.
something like:
insert 4 [1; 2; 3] = [[4; 1; 2; 3]; [1; 4; 2; 3]; [1; 2; 4; 3]; [1; 2; 3; 4]]
My idea is to apply Map on the list with a function that returns a list.
resulting in list of lists. like [f 1; f 2 ; f3] (I know will only have 3 lists, but just want to get this working first)
let insert (x : 'a) (ls : 'a list): 'a list list =
let aux p =
List.fold_left
(fun f2 acc q ->
if p = q then List.append acc x::[q]
else List.append acc q::[])
[] ls
in
List.map aux ls
Hope is, function aux will return a list with x inserted in the right place.
The problem is, List.map f1 ls line is assuming ls is 'a list list even though it is defined as 'a list
Any ideas please?
To actually answer your question, instead of providing you with different methods to reach your goal (you wanted to know what is actually wrong with your code, not how one could solve the problem.):
signature of fold_left is ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a = <fun>. Instead of ('a -> 'b -> 'a) your provide it with fun f2 acc q -> ... = ('a -> 'b -> 'c -> 'a). Just remove the f2 and you're fine.
put brackets around stuff like x::[q], or use ##.
Your code:
let insert (x : 'a) (ls : 'a list): 'a list list =
let aux p =
List.fold_left
(fun f2 acc q ->
if p = q then List.append acc x::[q]
else List.append acc q::[])
[] ls
in
List.map aux ls
Working code:
let insert (x : 'a) (ls : 'a list): 'a list list =
let aux p =
List.fold_left
(fun acc q ->
if p = q then List.append acc (x::[q])
else List.append acc (q::[]))
[] ls
in
List.map aux ls
For input insert 4 [1;2;3]this returns int list list = [[4; 1; 2; 3]; [1; 4; 2; 3]; [1; 2; 4; 3]]. This is almost what you wanted. The rest can be fixed by you :).
Note:
The Error that the Compiler throws is: Error: This expression has type 'a list but an expression was expected of type 'b list -> 'b list list. For the next time, just think about what happened. You provide fold_left with ('a -> 'b -> 'c -> 'a); which is not "wrong", but not what you want. You could write it as ('a -> ('b -> 'c) -> 'a). This means the acc-value is some 'a and the value of the fold is a function 'b -> 'c. This explains the error-message :).
Try breaking this problem down.
First hurdle: can you insert an element at a given index in a list? The start might look like:
let rec insert lst pos v =
(* ... *)
Well, we know if the position is 0, it should go at the front.
let rec insert lst pos v =
match pos with
| 0 -> v :: lst
| _ -> (* ... *)
If it's not 0 then you'd need to append the first element in lst to the result of inserting into the tail of the list at pos - 1.
Of course, the devil is in the details. What happens if you try insert [1; 2; 3; 4] 7 5? You need to find a way to check for situations like this.
If you can get this function to work, you then just need to iterate from 0 to the length of the list, inserting the new value into the list.
List.init would work nicely.
List.(
let lst = [1; 2; 3; 4] in
let len = length lst + 1 in
init len (fun i -> insert lst i 5)
)
And as a result, if you wrote insert correctly, you should get:
[[5; 1; 2; 3; 4]; [1; 5; 2; 3; 4]; [1; 2; 5; 3; 4];
[1; 2; 3; 5; 4]; [1; 2; 3; 4; 5]]
This should do the trick:
let rec insert v l =
match l with
| [] -> [[v]]
| x::xs -> (v::l) :: (List.map (List.cons x) (insert v xs))
Adding an explanation, had to think about this a while too:
For an empty list there is only one way to insert v and [[v]] is the result.
For a list x::xs first insert v at all positions in xs: insert v xs, which gives a list of lists. Then for each list add x back to the front: List.map (List.cons x) .... This gives all the results where v is inserted after x. So last construct the list where v is added before x: v::l. Adding that to the front of the list of lists gives the final result.
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!.
How to create a tuple list from one single list, like so:
[1; 2; 4; 6] -> [(1, 2); (4, 6)]
I want to do it using function List.fold_left since I'm trying to learn that currently but don't know how... Is there a way? Or should I leave it like that?
This is a working code that doesn't use List.fold_left:
let rec create_tuple acc l = match l with
| [] -> acc
| x :: y :: l' -> create_tuple (acc # [(x, y)]) l'
| _ -> acc
List.fold_left reads elements one by one. There is no direct way to make it read elements two by two.
It really is pointless complication (great for teaching, though), but if you absolutely want to use List.fold_left here, your accumulator needs to somehow record the state of the traversal:
either you have read an even number of elements so far,
or you have read an odd number and then you have to record what was the last element you read, so that, upon reading the following one, you can pair them.
Here is a way to do it. I use an algebraic datatype to represent the state.
(* This is the type that we’ll use for the accumulator;
the option component is the state of the traversal.
(None, acc) means that we have read an even number of elements so far;
(Some x, acc) means that we have read an odd number of elements so far,
the last of which being x. *)
type 'a accumulator = 'a option * ('a * 'a) list
let folder (state, acc) x =
match state with
| None -> (Some x, acc)
| Some y -> (None, (y,x)::acc)
let create_pairs l =
let (_, acc) = List.fold_left folder (None, []) l in
List.rev acc
Also notice how I avoid the complexity bug that I outlined in a comment: I add elements in reverse order (i.e. at the head of the accumulating list), and at the very end I reverse that list.
#Maëlan's answer is beautiful, but what if we want to get triples rather than pairs? Is there a way we can use List.fold_left to handle this more generically?
let chunks n lst =
let (_, _, acc) = List.fold_left
(fun (counter, chunk, lst') x ->
if counter = n - 1 then
(0, [], List.rev (x :: chunk) :: lst')
else
(counter + 1, x :: chunk, lst'))
(0, [], [])
lst
in
List.rev acc
Using this, chunks 2 [1; 2; 4; 6] returns [[1; 2]; [4; 6]]. We can map this to the result you're looking for with a very simple function that takes a list with two elements and creates a tuple with two elements.
chunks 2 [1; 2; 4; 6] |> List.map (fun [x; y] -> (x, y))
And we get:
[(1, 2), (4, 6)]
This could be used to implement a triples function.
let create_triples lst =
chunks 3 lst |> List.map (fun [x; y; z] -> (x, y, z));;
And now create_triples [1; 2; 3; 4; 5; 6; 7; 8; 9] returns [(1, 2, 3); (4, 5, 6); (7, 8, 9)].
I tried this question(using List.fold_left) and this is the best I could come up with:
type 'a node = First of 'a | Second of ('a * 'a)
let ans =
List.fold_left
(
fun a e ->
match a with
| [] -> (First e)::a
| (First f)::tl -> Second(f, e)::tl
| (Second n)::tl -> (First e)::(Second n)::tl
)
[]
[1; 2; 3; 4; 5; 6; ]
let () =
List.iter
(
fun e ->
match e with
| First f ->
print_endline(string_of_int f)
| Second (f, s) ->
Printf.printf "(%d, %d)" f s
)
(List.rev ans)
Just to make my answer all there...
type 'a node = One of 'a | Two of ('a * 'a)
let ans =
(List.map
(
fun e ->
match e with
| One _ -> failwith "Should only be Two's"
| Two (f, s) -> (f, s)
)
(List.filter
(
fun e ->
match e with
| One _ -> false
| Two _ -> true
)
(List.rev
(List.fold_left
(
fun a e ->
match a with
| [] -> (One e)::[]
| (One o)::tl -> (Two (o, e))::tl
| (Two t)::tl -> (One e)::(Two t)::tl
)
[]
(List.init 10 (fun x -> x + 1))
)
)
)
)
let () =
List.iter
(fun (f, s) -> Printf.printf "(%d, %d) " f s)
ans
I’m trying to create a function that takes an int list as an argument and returns the sum of the product between an int and its position in the list. To put in an example this : multSum [5; 11; 15] should return (5 * 1 + 11 * 2 + 15 * 3) = 72.
It should be written recursively and I’m trying while avoiding List.map or List.filter or any other prefabricated functions.
By dividing and reigning the query above, I have so far started by trying the following :
let rec tir f acc l =
match l with
|[] -> acc
|h::t -> tir f (f acc h) t ;;
val tir : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a = <fun>
then I moved to this :
let rec carto f a b =
match (a,b) with
|([],[])->([])
|(h1::t1,h2::t2)->(f h1 h2):: (carto f t1 t2)
|_->invalid_arg "carto";;
val carto : ('a -> 'b -> 'c) -> 'a list -> 'b list -> 'c list = <fun>
with the final idea to be able to do that :
let prod arg1 arg2 =
tir (+) 1 (carto ( * ) arg1 arg2);;
val prod : int list -> int list -> int = <fun>
But I am stuck now and I’m not sure of my orientation from here forward. I thought of trying to search for the index in a "l" and replace each index int in the acc, in order to make it work but I'm afraid I'm rather complicating things... Any help please ?
Edit 1 :
let rec multSum l =
let rec indices n xs = match xs with
| [] -> []
| h::t -> n::(indices (n+1) t)in
let rec tir f acc l =
match l with
|[] -> acc
|h::t -> tir f (f acc h) t in
let rec carto f a b =
match (a,b) with
|([],[])->([])
|(h1::t1,h2::t2)->(f h1 h2):: (carto f t1 t2)
|_->invalid_arg "carto" in
let prod arg1 arg2 =
tir (+) 0 (carto ( * ) arg1 arg2) in
prod l (indices 1 l);;
val multSum : int list -> int = <fun>
Building on your replies, surely these are 'fold' and 'map' rewritten. At least, I'm sure now that I was on the right track. I have come to put together the whole code as signaled above in Edit 1.
It seems to be working well... I know that I want a recursive function and here it is. But, do you think it could be done even shorter recursively of course?
#coredump is quite right about this looking like an ideal scenario for a fold, but the extra functions aren't really that necessary. We can just use a tuple to pass the index and sum information around, then when we're done, discard the index information from the tuple.
let sum_list_prod lst =
let (_, result) = List.fold_left
(fun (i, sum) x -> (i + 1, sum + i * x))
(1, 0)
lst
in
result
Edit: A simple implementation of a left fold to demonstrate the recursion going on here.
let rec foldl f init lst =
match lst with
| [] -> init
| first :: rest -> foldl f (f init first) rest
So working through a simple example with sum_list_prod:
sum_list_prod [2; 3; 4]
Calls the fold like so:
List.fold_left (fun (i, sum) x -> (i + 1, sum + i * x)) (1, 0) [2; 3; 4]
And as that evaluates:
List.fold_left (fun (i, sum) x -> (i + 1, sum + i * x)) (1, 0) [2; 3; 4]
List.fold_left (fun (i, sum) x -> (i + 1, sum + i * x)) (2, 2) [3; 4]
List.fold_left (fun (i, sum) x -> (i + 1, sum + i * x)) (3, 8) [4]
List.fold_left (fun (i, sum) x -> (i + 1, sum + i * x)) (4, 20) []
(4, 20)
And then we throw away the 4 because we don't need it anymore and are just left with 20.
Your tir functions looks like a fold; in fact has the exact same type as List.fold_left:
# List.fold_left;;
- : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a = <fun>
In the following snippets the prod function looks like a map2
# List.map2;;
- : ('a -> 'b -> 'c) -> 'a list -> 'b list -> 'c list = <fun>
You can use a fold and a map to compute the function you want, but you also need first to build a list of indices from the list of values. You could do this as follows:
let rec indices n xs = match xs with
| [] -> []
| h::t -> n::(indices (n+1) t);;
For example:
# indices 1 [5;1;3];;
- : int list = [1; 2; 3]
This is not recursive terminal, if you first computed the length of the list, how would you build the list in a recursive terminal way?
Then you should be able to call prod on a list xs and on a secondary list indices 1 xs. It is a bit wasteful because you need to build an auxiliary list, but it looks quite simple to me to understand, higher-order functions like map or fold do work on whole lists so there are fewer corner cases to consider.
But, it might be better to first write a direct recursive function for your particular problem before going the more abstract route.
The direct recursive function also requires no additional memory allocation. If you write a recursive terminal function you'll carry additional accumulator values:
the current position in the list, initially 1
the current sum of products, initially 0
Then, your function has the following skeleton:
let rec f xs index product = match xs with
| [] -> ...
| h::t -> ...
You can wrap it in a main function g:
let g xs = f xs 1 0;;
I have a function that returns every "sublists" from a given list:
let rec sublists = function
[] -> [[]]
| h::t -> let st = sublists t in
List.map (function l -> h::l) st # st;;
For example, if you try
sublists [1;4;9;12]
it will return:
[[1; 4; 9; 12]; [1; 4; 9]; [1; 4; 12]; [1; 4]; [1; 9; 12]; [1; 9]; [1; 12];
[1]; [4; 9; 12]; [4; 9]; [4; 12]; [4]; [9; 12]; [9]; [12]; []]
That are every possible combinations of elements in the list (order doesn't matter)
I have to do a function that returns a different sublists pair that fulfill a given property.
Function must have this type: ('a list -> 'a list -> bool) -> 'a list -> 'a list * 'a list
For example, if we have the previous list and we try
search (<4) [1;4;9;12]
It will return:
([9;12], [9]) because these lists satisfaces the given condition (<4). Order does not matter, it could return ([9], [12]) instead, or another possible combination.
I'm stucked at this, I have done a function that check if a given list is a sublist of another list:
let is_sublist_of l1 l2 =
let sub = sublists l1 in
List.mem l2 sub;;
But I think that is useless here. Coul anyone help me?
Can't you just filter the list first and then apply the two first runs of sublist to it ?
let filter_sublist f l =
let l = List.filter f l in
let rec sublists = function
| [] -> [], []
| h :: t ->
let st1, st2 = sublists t in
h :: st1, st2
in sublists l
The problem here is that f is of type 'a -> bool because I don't understand your type ('a list -> 'a list -> bool). What is it supposed to represent ?
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.