In OCaml, I want to write a function that returns the element at a given index of a list. For example [4;5;6] 0 -> 4, [4;5;6] 1 -> 5. I know how to do this recursively, but can anyone show how to do this problem using fold_left or fold_right? Thank you so much!
Let's look at how you can print the elements in a list using fold_left.
let print lst =
List.fold_left
(fun i x -> Format.printf "%d: %d\n" i x; i + 1)
0 lst;
The initial index of 0 is passed in as the initial value. Each time through we have the side effect of printing a line, and then update the initial value to i + 1.
Result:
utop # print [1;4;6;2;7];;
0: 1
1: 4
2: 6
3: 2
4: 7
- : int = 5
This shows us nicely how the fold updates its accumulator as it iterates through a list.
But if we're going to search for a value at an index, let's use a tuple of a current index and an option type for the return value, in case we don't find the index we're looking for.
let at idx lst =
List.fold_left
(fun i x ->
match i with
| (_, Some _). -> i
| (idx', _) when idx = idx' -> (idx', Some x)
| (idx', _) -> (idx' + 1, None))
(0, None)
lst
We start with 0 and None as our initial value. For each item in the list we check to see if the option type value in the accumulator is Some _. We don't care about the value, but if it's not None we've found what we're looking for and do not need to update the accumulator.
If the accumulator does contain None and the current index is the same as the one we're looking for, update the accumulator with Some of the current value. The index does not need to be updated.
If the index is not the one we're looking for, increment the index and continue.
utop # at 3 [1;2;3;4;5];;
- : int * int option = (3, Some 4)
But since we don't need the first element in the tuple, we can use a let binding to name the result we are looking for and return that.
let at idx lst =
let (_, result) = List.fold_left
(fun i x ->
match i with
| (_, Some _) -> i
| (idx', _) when idx = idx' -> (idx', Some x)
| (idx', _) -> (idx' + 1, None))
(0, None)
lst
in
result
Now:
utop # at 3 [1;2;3;4;5];;
- : int option = Some 4
Taking a look at how List.fold_left can be implemented may be instructive.
let rec fold_left f init lst =
match lst with
| [] -> init
| x::xs -> fold_left f (f init x) xs
In at the Some _ condition in the accumulator tuple causes that accumulator value to propagate to the end of the fold without update.
Alternately we could use a local exception to break out of the fold immediately on finding the index we're looking for.
let at idx lst =
let exception Early_exit of int in
try
let (_, result) = List.fold_left
(fun i x ->
match i with
| (_, Some _) -> i
| (idx', _) when idx = idx' -> raise (Early_exit x)
| (idx', _) -> (idx' + 1, None))
(0, None)
lst
in
result
with Early_exit x -> Some x
Or perhaps a little bit more cleanly:
let at idx lst =
let exception Early_exit of int in
match List.fold_left
(fun i x ->
match i with
| (_, Some _) -> i
| (idx', _) when idx = idx' -> raise (Early_exit x)
| (idx', _) -> (idx' + 1, None))
(0, None)
lst with
| (_, result) -> result
| exception Early_exit x -> Some x
Of course, we now know that if the exception Early_exit wasn't raised, the index wasn't found, so the result would always be None.
let at idx lst =
let exception Early_exit of int in
match List.fold_left
(fun i x ->
match i with
| (_, Some _) -> i
| (idx', _) when idx = idx' -> raise (Early_exit x)
| (idx', _) -> (idx' + 1, None))
(0, None)
lst with
| _ -> None
| exception Early_exit x -> Some x
And testing:
utop # at 3 [1;2;3;4;5];;
- : int option = Some 4
But if we're using exceptions this way, we really don't need List.fold_left at all. We can just use List.iteri.
let at idx lst =
let exception Found of int in
try
List.iteri (fun i x -> if i = idx then raise (Found x)) lst;
None
with Found x -> Some x
Both kinds of fold let you access the elements of a list in order while maintaining some state that you can choose freely. The difference is that fold_left starts at the beginning of the list and works toward the end and fold_right starts at the end of the list and works back toward the beginning.
Since your index starts at the beginning of the list I'd say it will be easier to work with fold_left.
So, your problem is to figure out some kind of state that you can maintain so that by the time you've looked at the whole list, you know what the nth element of the list was.
You can basically figure out the state from the problem: you need to know what element of the list you're looking at (so you know when you come to the nth one). You need to remember the nth element (if you've seen it already) so that it's available when you reach the end of the list. If you haven't seen the nth element yet you need something of the same type to use as a placeholder (or you could use an option type).
You need a function that takes state like this (along with one element of the list) and produces the state that goes with the next element of the list. This is really not so different from writing a loop, except that you need to pass the state explicitly as a parameter and return the new state as a result.
You need some exit mechanism when the index element is found.
exception Value of int
let get_index_value_using_fold_left l i =
let index_value = ref 0 in
try
List.fold_left
(
fun a e ->
if !index_value = i
then
raise (Value e)
else
(
index_value := !index_value + 1;
a
)
) None l
with
| Value ans -> Some ans
let ans = get_index_value_using_fold_left [11;2;13;4;15;6;17;8;19;20;] 2
let () =
Option.iter (fun x -> Printf.printf "%d\n" x) ans
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 =
...
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 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 am using OCaml to write a function that takes a list of ints and an int element and returns a list of pairs where the first element of every pair is the int element and the second element of the pair is a member from the list. For example, let say I have the number 1 and the list [10; 20; 30] as inputs. I like the function to return [(1, 10); (1, 20); (1, 30)]. I wrote the following function:
let rec f (lst : int list) (elm : int) : (int*int) list =
match lst with
| [] -> failwith "empty list"
| [x] -> [(x, elm)];;
I am getting the following error:
Characters 59-120:
Warning 8: this pattern-matching is not exhaustive.
Here is an example of a value that is not matched:
_::_::_ val f : int list -> int -> (int * int) list = <fun>
What am I missing?
Here is your code
let rec f (lst : int list) (elm : int) : (int*int) list =
match lst with
| [] -> failwith "empty list"
| [x] -> [(x, elm)]
In your match, you listed two cases: [] and [x].
Your first case is [], you mean empty, no problem.
Your second case is [x], what did you want to mean? In OCaml, it means a list with only one element.
How about the cases where there are more than one element?
For any if else or match with, you should include all cases.
When you fix this problem, you will soon find you really missed something more there.
Here is the correct code:
let rec f e l =
match l with
| [] -> []
| x::[] -> [(e,x)]
| x::tl -> (e,x)::(f e tl)
Note
above code is not tail-recursive and you normally should consider about it, I will leave that to you.
you don't need ;; if you write your code in file and compile the file
You don't need to declare types in most cases and that is one of the best thing ocaml has.
Your patterns match lists of length 0 ([]) and of length 1 ([x]). The compiler is telling you that there are other lengths that a list might have, so your pattern is probably wrong (which is true).
I might note that it's not an error to get an empty list as an argument. Thinking this way will make it much harder to answer the problem. If you get an empty list, the correct answer is an empty list of pairs.
let rec f e = function
| [] -> []
| x::tl -> (e,x)::f e tl
Or
let f e = List.map (fun x -> (e,x))
Test
# f 1 [];;
- : (int * 'a) list = []
# f 1 [10;20;30];;
- : (int * int) list = [(1, 10); (1, 20); (1, 30)]
What I'm hoping to make this function do is:
Generate a list of random integers of length specified by count
Generate another random number to replace first element of list
Sort the list
Split list in half, discarding second half
Discard first element of list
Repeat 2-5 unless list is empty
What I have so far (but not working) is below. What is the matter with it?
let go count =
let rec cut l =
if List.length l = 0 then l
printfn "%A" l
let list = System.Random().Next(100)::List.tail l
let cut list =
let firstHalf= list |> Seq.take (List.length list / 2) |> Seq.toList
firstHalf
let listSorted = List.sort list
cut (List.tail listSorted)
let r = System.Random()
let list1 = List.init count (fun numbers -> r.Next(100))
printfn "List = %A" list1
cut list1
A few tips:
Don't test if a list is empty by List.length L = 0. Each test will take as long as the amount of elements in the list. Test with pattern matching instead, that's (almost) instantanteous:
Don't instantiate a new instance of a random number generator each time your cut function is called: let list = System.Random().... Doing that means that you're likely to get the same numbers (each instantiaion seeds the generator with the current system time). Just move your declaration r = System.Random() up a bit, and use that generator throughout your code.
example:
let rec cut l =
match l with
| [] -> // the list is empty, end the recursion here
| head::tail -> // the list consists of the head element and the rest
// you can refer to head and tail in your code here
let newlist = r.next(100) :: tail
You're declaring a function called 'cut' inside your recursive 'cut' function, which means that the last call to 'cut' in your recursive function actually calls the non-recursive one you defined inside. Use different names there.
You've written 'if List.length l = 0 then l', which (apart from not using a pattern match) also presents a problem: an 'if' in F# is an expression, like the ? operator in C#. In C# that would mean something like
(l.Count == 0) ? l : //other case missing! error! danger!
Another tip: once your list is sorted, you don't need to sort again each time you add a new random element. You can write code that inserts a new element in a sorted list that would be more efficient than adding an element and sorting afterwards. I'll leave the insert-into-sorted-list as an excercise.
I hope these tips are useful.
Here it is as simple as making functions for each of your statements.
let rnd = new System.Random()
let genList n =
[for i = 0 to n-1 do yield rnd.Next()]
let replaceHead v lst = match lst with
| [] -> []
| (x::xs) -> (v::xs)
let splitInHalf lst =
let len = (lst |> List.length) / 2
let rec loop n lst =
match (n,lst) with
| 0,_ -> []
| _,[] -> []
| _,(x::xs) -> x :: (loop (n-1) xs)
loop len lst
let start n =
let lst = genList n
let rec loop l =
match l with
| [] -> []
| ls -> match ls |> replaceHead (rnd.Next())
|> List.sort
|> splitInHalf with
| [] -> []
| xs -> xs |> List.tail |> loop
loop lst
start 1
here is my try...
let go count =
System.Random() |> fun rnd -> // With ranomizer ... (we will need it)
let rec repeat = function // So we got recursion
| x::xs when xs.Length <> 1 -> // while we have head and tail
printfn "%A" xs
rnd .Next(100) :: (List.tail xs) // Add random value
|> Seq.sort // Sort
|> Seq.take( abs(xs.Length /2) ) // Make a half
|> Seq.skip 1 // Remove first (just skip)
|> List.ofSeq // Make the list
|> repeat // So and repeat
| x::xs -> printfn "%A" xs
| _ -> () // If we have no head and tail
repeat <| List.init count (fun _ -> rnd.Next(100)) // do it with our random list
It does look like homework :)
But here is my take on it:
#light
// Create random integer sequence
let random_integers_of_length l =
(l, new System.Random())
|> Seq.unfold (fun (c, rnd) -> if c = 0 then None else Some (rnd.Next(), (c-1, rnd)))
|> Seq.cache
let rec mutate numbers =
printfn "%A" (List.ofSeq numbers); // pretty print the list
match numbers with
| _ when (Seq.length numbers) <= 1 -> printfn "Done.." // if length is 1 or 0 we can stop.
| _ ->
numbers
|> Seq.skip 1 // discard first element
|> Seq.append (random_integers_of_length 1) // append random number at the start
|> Seq.sort // sort
|> Seq.take ((Seq.length numbers) / 2) // take the first half, ignore the rest
|> Seq.skip 1 // discard first element
|> mutate // do it again.