I have this function:
let encode list =
let rec aux count acc = function
| [] -> [] (* Caso a lista esteja vazia*)
| [x] -> (count+1, x) :: acc
| a :: (b :: _ as t) ->
if a = b then aux (count + 1) acc t
else aux 0 ((count+1,a) :: acc) t in
List.rev (aux 0 [] list)
;;
and with this input:
let test = encode ["a";"a";"a";"a";"b";"f";"f";"c";"c";"a";"a";"d";"e";"e";"e";"e"];;
And i have this Output:
val test : (int * string) list =
[(4, "a"); (1, "b"); (2, "f"); (2, "c"); (2, "a"); (1, "d"); (4, "e")]
but the "a" is a repeated and "f" need to be at final!
I need a output like:
val test : (int * string) list =
[(6, "a"); (1, "b"); (2, "c"); (1, "d"); (4, "e"); (2, "f")]
Can anybody help, please?! Thanks!
You are counting repeated adjacent values, so-called run-length encoding. It appears you want to count occurrences across the whole input. You can either sort the input beforehand, or you can use a more complicated data structure (such as a Map) to keep track of your counts.
Something like this:
let encode xs =
let f acc x =
let n = try M.find x acc with Not_found -> 0 in
M.add x (n+1) acc in
let ans = (List.fold_left f M.empty) xs in
M.bindings ans ;;
# encode ["a";"a";"a";"a";"b";"f";"f";"c";"c";"a";"a";"d";"e";"e";"e";"e"];;
- : (M.key * int) list =
[("a", 6); ("b", 1); ("c", 2); ("d", 1); ("e", 4); ("f", 2)]
Related
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 am very new to ocaml! I am using the code found here: https://rosettacode.org/wiki/Cartesian_product_of_two_or_more_lists#OCaml
I have been trying to figure out how to print the result after running the product function, Thank you very much!
open Printf
let rec product l1 l2 = (* Create a recursive function (rec) named product that has 2 parameters *)
(*ignore (Printf.printf "Debug: %s\n" 1);*)
match l1, l2 with
| [], _ | _, [] -> []
| h1::t1, h2::t2 -> (h1,h2)::(product [h1] t2)#(product t1 l2)
;;
let test =
product [1;2] [3;4];;
ignore (Printf.printf "test: %d*" 1);
(*- : (int * int) list = [(1, 3); (1, 4); (2, 3); (2, 4)]*)
product [3;4] [1;2];;
(*- : (int * int) list = [(3, 1); (3, 2); (4, 1); (4, 2)]*)
product [1;2] [];;
(*- : (int * 'a) list = []*)
product [] [1;2];;
(*- : ('a * int) list = []*)
Your fuction product has this type:
'a list -> 'b list -> ('a * 'b) list
There is no built-in way to print out the results of this function, because the results don't have a particular type. The type of the results depends on the types of the two input lists. Since OCaml is a strongly typed language, there's no way in general to examine a type at runtime and print it differently depending on the type.
If you run your code in the toplevel (OCaml's REPL), it will write out the results for you. It uses code that's not really available to an ordinary OCaml program:
# product [1;2] [3;4];;
- : (int * int) list = [(1, 3); (1, 4); (2, 3); (2, 4)]
# product [1.; 2.] ['a'; 'b'];;
- : (float * char) list = [(1., 'a'); (1., 'b'); (2., 'a'); (2., 'b')]
If you're willing to restrict yourself to lists of ints you can use this function to print a list of type (int * int) list:
let print_ints pair_list =
let pair_str (i, j) = Printf.sprintf "(%d, %d)" i j in
print_string
("[" ^ String.concat "; " (List.map pair_str pair_list) ^ "]\n")
If you run it in the toplevel it looks like this:
# print_ints (product [2;3] [4;5]);;
[(2, 4); (2, 5); (3, 4); (3, 5)]
- : unit = ()
I am learning OCaml and now stuck with a code.
This is a code that makes a list of the accessible nodes from a graph.
type graph = (vertex * vertex) list
and vertex = int
let rec sort lst =
match lst with
[] -> []
| h::t -> insert h (sort t)
and insert n lst =
match lst with
[] -> [n]
| h::t -> if n <= h then n :: lst else h :: insert n t;;
let rec remove lst =
match lst with
| [] -> []
| x::[] -> x::[]
| x::y::tl ->
if x=y then remove (y::tl)
else x::remove (y::tl);;
let rec reach : graph * vertex -> vertex list
= fun (g, v) ->
match g with
|[] -> []
|h::t ->let x = [] in
match h with
|a,b -> if a = v then remove(sort(v::x) # (reach (g, b)))
else
remove(sort(v::reach (t, v)));;
reach([(1,2);(2,3);(3,4);(4,2);(2,5)],4);;
I think my code is meaninglessly complicated due to my lack of coding ability.
Besides, the main problem that I confront now is that I cannot make the recursive function 'reach' to access with original list 'g' as it goes recursive in else condition as it access with list 't'.
trace says
reach <-- ([(1, 2); (2, 3); (3, 4); (4, 2); (2, 5)], 4)
reach <-- ([(2, 3); (3, 4); (4, 2); (2, 5)], 4)
reach <-- ([(3, 4); (4, 2); (2, 5)], 4)
reach <-- ([(4, 2); (2, 5)], 4)
reach <-- ([(4, 2); (2, 5)], 2)
reach <-- ([(2, 5)], 2)
reach <-- ([(2, 5)], 5)
reach <-- ([], 5)
reach --> []
reach --> [5]
reach --> [2; 5]
reach --> [2; 5]
reach --> [4; 2; 5]
reach --> [2; 4; 5]
reach --> [2; 4; 5]
reach --> [2; 4; 5]
- : vertex list = [2; 4; 5]
First, I claimed a new variable with let y = g and change code
|a,b -> if a = v then remove(sort(v::x) # (reach (y, b)))
else
remove(sort(v::reach (t, v)));;
as I believed that the duplicates will be removed by fun 'remove' and inner function will access with list y, not t which lost its head. However, things did
not go as I planned. It still gives me a same result.
To make function access with original list 'g' in else condition what should I do...?
reach <-- ([(1, 2); (2, 3); (3, 4); (4, 2); (2, 5)], 4)
reach <-- ([(2, 3); (3, 4); (4, 2); (2, 5)], 4)
reach <-- ([(3, 4); (4, 2); (2, 5)], 4)
reach <-- ([(4, 2); (2, 5)], 4)
reach <-- ([(1, 2); (2, 3); (3, 4); (4, 2); (2, 5)], 2)
(*I want function goes back to original list as the variable changes like above*)
You can define an auxiliary function:
let reach g v =
let rec aux g' v' = ... (* here you can use g as the auxiliary function defines g' instead *)
in aux g v
Note that I also define the function with two arguments instead of one tuple, it's more idiomatic :)
Also if v' is always the same value the auxiliary function need not redefine it
let reach g v =
let rec aux g' = ...
in aux g v
One more remark. You can du deeper pattern matching, e.g.:
match g with
|[] -> []
|(a,b)::t -> let x = [] in
if a = v
then remove(sort(v::x) # (reach (g, b)))
else remove(sort(v::reach (t, v)));;
No need for a second match.
Finally, you might be aware of the function keyword that creates a function of one argument creating pattern matching:
let f x = match x with
(* same as *)
let f = function
Therefore:
let reach (g:graph) (v:vertex) =
let aux v' = function (*we don't create a g' variable here, we match it straight *)
| [] -> []
| (a,b)::t as g' -> (* you can still define the variable in the matching if you need it *)
let x = [] in
if a = v
then remove(sort(v::x) # (aux b g')) (* or g if that's what you need *)
else remove(sort(v::aux v t))
in aux v g
would do the same as your code
Edit: correctected recusrive calls to reach by recursive calls to aux as it wouldn't work.
Answering directly to your question, here is how to access the original value in a recursive function
let to_matrix outer =
let rec loop = function
| [] -> []
| x :: xs -> [x::outer] # loop xs in
loop outer
This function will iterate over each element of a list and create a list of list, where each element is a list made of the original element prepended to the whole original list, e.g.,
# to_matrix [1;2;3];;
- : int list list =
[[1; 1; 2; 3]; [2; 1; 2; 3]; [3; 1; 2; 3]]
The example might be silly, but I hope it clarifies the technique. Here the idea is that we create an inner function, named loop in our case, which has its own parameter, and we recurse only on this parameter while leaving the original outer list intact.
While it is an idiomatic approach, in general it is not required to create an inner function or an auxiliary function. What is really needed, is an extra parameter, so that at the end of the day we will have two parameters - one which decreases with each iteration and the other which stays invariant, e.g.,
let rec to_matrix outer inner = match inner with
| [] -> []
| x :: xs -> [x::outer] # to_matrix outer xs
the only caveat of this approach is that now we have to pass the list twice, e.g.,
to_matrix [1;2;3] [1;2;3];;
That's why it is idiomatic to hide this function by a nicer interface.
My task is to create a histogram that output the number of times that an element it is in a list.
Input:[2;2;2;3;4;4;1]
Output[(2, 3); (2, 2); (2, 1); (3, 1); (4, 2); (4, 1); (1, 1)]
Expected output : [(2, 3); (3, 1); (4, 2); (1, 1)]
My code:
let rec count a ls = match ls with
|[] -> 0
|x::xs when x=a -> 1 + count a xs
|_::xs -> count a xs
let rec count a = function
|[] -> 0
|x::xs when x=a -> 1 + count a xs
|_::xs -> count a xs
let rec histo l = match l with
|[] -> []
|x :: xs -> [(x, count x l)] # histo xs ;;
What have i done wrong?
The issue is that xs contains potentially elements that are equal to x. This is what you see in your ouput : (2,3) means that there is 3 times 2 in the list; xs is then equals to [2;2;3;4;4;1]... and so on.
Also (not impacting the conclusion): you have 2 definitions of count, but they are identical.
To implement an histogram, use Hashtbl :
let h = Hashtbl.create 1000;;
List.iter (fun x -> let c = try Hashtbl.find h x with Not_found -> 0 in Hashtbl.replace h x (c+1)) your_list;;
Hashtbl.fold (fun x y acc -> (x,y)::acc) h [];;
I have seen this question for Python, But I have the same question for SML (PolyMl).
I want to create a function to extract from a list of tuples (int, string) the string value of the tuple with minimum int.
For example, if I have this list:
l = [('a', 5), ('b', 3), ('c', 1), ('d', 6)]
The output should be 'c', because the minimum integer is in the tuple ('c', 1). Thank You!
val l = [(#"a", 5), (#"b", 3), (#"c", 1), (#"d", 6)]
fun min [] = NONE
| min [x] = SOME x
| min ((c1,n1) :: (c2,n2) :: xs) = if n1 < n2 then
min ((c1,n1) :: xs)
else
min ((c2,n2) :: xs)
val SOME (c,_) = min l
val lst = [(#"a", 5), (#"b", 3), (#"c", 1), (#"d", 6)];
(* The first item of a tuple is fetched with #1. *)
#1(List.foldl
(fn ((new as (_,n)), (old as (_,n0))) =>
if n < n0 then new else old)
(hd lst)
(tl lst));
(* val it = #"c" : char *)