Access float in (int * float) list in OCaml - list

I have a list of type (int * float) list.
So, as far as I understand it (I'm new to OCaml/Functional Programming)
the list is structured like this: [(3, 1.0); (4, 2.0); (6, 0.1)].
Now I want to access the first element in each tuple in the list.
I'd be happy with an example solution and an explanation.

The suggestion from #glennsl in the comments about learning resources is spot on.
If you want an example of getting a list comprised of the first element in each tuple:
List.map (fun (i, _) -> i) [(3, 1.0); (4, 2.0); (6, 0.1)]
List.map applies a function to each element in a list and builds a list of the resulting values. It's a simple concept and easy enough to implement in a few lines.
let rec my_map f lst =
match lst with
| [] -> []
| first::rest -> f first :: my_map f rest
Or more tersely using function:
let rec my_map f =
function
| [] -> []
| first::rest -> f first :: my_map f rest
If we evaluated my_map (fun (i, _) -> i) [(3, 1.0); (4, 2.0); (6, 0.1)] it would work out something like:
my_map (fun (i, _) -> i) [(3, 1.0); (4, 2.0); (6, 0.1)]
3 :: my_map (fun (i, _) -> i) [(4, 2.0); (6, 0.1)]
3 :: 4 :: my_map (fun (i, _) -> i) [(6, 0.1)]
3 :: 4 :: 6 :: my_map (fun (i, _) -> i) []
3 :: 4 :: 6 :: []
[3; 4; 6]
The anonymous function fun (i, _) -> i is one which takes a tuple of two items and returns the first. The second is unimportant to us, so we use _ rather than giving it a name.

Related

OCaml: create a tuple list from a list using fold_left

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

How would you use map on a list of tuples that contains a list of tuples?

I have a list here that has the following structure:
list = [((1,1),[("A", 1), ("D", 4), ("E", 5)]), ((2,2),[("B", 2)]), ((3,3),[("C",3)])]
I want to output a list that has the following structure (aka summing the values of each of the second values of each sublist so for example (1+4+5) = 10
[((1,1),10), ((2,2),2), ((3,3),3))]
I am not sure how to get that structure by using map or even filter and the closest I have gotten is:
map snd (concat (map snd list))
which produces [1,4,5,2,3]
How would I achieve this structure?
First, write out the types:
have :: [((Int,Int), [(String,Int)])]
have = [ ((1,1),[("A", 1), ("D", 4), ("E", 5)]), ... ]
want :: [((Int,Int), Int)]
Evidently, the (Int,Int) isn't really relevant here, nor is the String. So our conversion function can be
give :: [(a, [(b, Int)])] -> [(a, Int)]
Furthermore, the a is just passed as-is, so the interesting bit is going to be [(b, Int)] -> Int. For this, you first need to throw away the bs
Prelude> map snd [("A", 1), ("D", 4), ("E", 5)]
[1,4,5]
and sum the result (composition!)
Prelude> sum . map snd $ [("A", 1), ("D", 4), ("E", 5)]
10
So sum . map snd is the function you'll need to apply to every RHS in the list of outer tuples.
How do you actually use it on only the RHS? Well, one way is to write a lambda
\(x,y) -> (x, f y)
...but actually there's a standard combinator for this, called second
second :: (b -> c) -> (d,b) -> (d,c)
(operating on the snd element of a tuple, applying a function† to it, putting it back in the tuple).
Prelude Control.Arrow> second (sum . map snd) (346, [("A", 1), ("D", 4), ("E", 5)])
(346,10)
All that's left to do is mapping that whole thing over the outer list:
Prelude Control.Arrow> map (second $ sum . map snd) [((1,1),[("A", 1), ("D", 4), ("E", 5)]), ((2,2),[("B", 2)]), ((3,3),[("C",3)])]
[((1,1),10),((2,2),2),((3,3),3)]
Or as a definition
give :: Num c => [(a, [(b, c)])] -> [(a, c)]
give = map . second $ sum . map snd
†If you look in the docs you'll find that second is actually more general than that: it can work not only with functions, but general arrows ~>, i.e. second :: Arrow (~>) => (b ~> c) -> ((d,b)~>(d,c)). If that's confusing to you, don't worry... in most applications, the arrow will just be the normal function one.
If you don't mind the map you could use list comprehension here:
list = [((1,1),[("A",1),("D",4),("E",5)]),((2,2),[("B",2)]),((3,3),[("C",3)])]
[(fst x, sum [snd y | y <- (snd x) ]) | x <- list]
returns
[((1,1),10),((2,2),2),((3,3),3)]

Printing a Function After Calling (ocaml)

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 = ()

How can i make inner recursive function reach original variable in OCaml?

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.

create a histogram OCaml

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 [];;