F# - generating a list of tuples from integer input - list

I'm supposed to return a list of tuples from an integer input.
For example:
output' 4 should return a list of tuples:
[(1, 1);
(2, 1); (2, 2);
(3, 1); (3, 2); (3, 3);
(4, 1); (4, 2); (4, 3); (4, 4)]
At the moment I'm getting
[(1, 1); (1, 2); (1, 3); (1, 4);
(2, 1); (2, 2); (2, 3); (2, 4);
(3, 1);(3, 2); (3, 3); (3, 4);
(4, 1); (4, 2); (4, 3); (4, 4)]
What I have so far:
let output' x =
let ls= [1..x]
ls |> List.collect (fun x ->[for i in ls -> x,i])
output' 4
I can't figure out how to get the needed output. Any help would be appreciated.

You can add a filter:
...
|> List.filter (fun (a, b) -> a >= b)`
or
let output x =
[ for i in 1..x do
for j in 1..i do yield (i,j)
]

In F# they mostly work with sequences, so here is a sequence-driven lazy solution:
let output' max =
let getTuples x =
seq { 1 .. x }
|> Seq.map (fun y -> (x, y))
seq { 1 .. max }
|> Seq.map getTuples
If you need lists, replace seq { 1 .. x } with [ 1 .. x ].
It will still be more functional-way than loops.

Related

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

Removing items from a list when I find a value

I have this list:
let myList = [(1,2,0);(1,3,0);(1,4,0);(2,6,0);(3,5,0);(4,6,0);(6,5,0);(6,7,0);(5,4,0)];;
I want to remove each element in list when the first position is equals with a number, for example if I remove the element starts with 1 the result must be this:
[(2,6,0);(3,5,0);(4,6,0);(6,5,0);(6,7,0);(5,4,0)];;
From OCaml's standard library:
val filter : ('a -> bool) -> 'a list -> 'a list
(** filter p l returns all the elements of the list l that satisfy
the predicate p. The order of the elements in the input list is
preserved. *)
The following function will compare a first element of a triple with a constant number n
let first_is n (m,_,_) = n = m
Then you can use this to filter your list:
List.filter (first_is 1) [1,2,3;4,5,6;7,8,9]
This will remove all elements that doesn't satisfy the predicate, i.e., in the given example it will return a list with only one triple: [1,2,3].
Since you want the opposite, then you can define predicate:
let first_isn't n (m,_,_) = n <> m
A full example in the interactive toplevel:
# let xs = [1,2,0;1,3,0;1,4,0;2,6,0;3,5,0;4,6,0;6,5,0;6,7,0;5,4,0];;
val xs : (int * int * int) list =
[(1, 2, 0); (1, 3, 0); (1, 4, 0); (2, 6, 0); (3, 5, 0); (4, 6, 0);
(6, 5, 0); (6, 7, 0); (5, 4, 0)]
# let first_isn't n (m,_,_) = n <> m;;
val first_isn't : 'a -> 'a * 'b * 'c -> bool = <fun>
# List.filter (first_isn't 1) xs;;
- : (int * int * int) list =
[(2, 6, 0); (3, 5, 0); (4, 6, 0); (6, 5, 0); (6, 7, 0); (5, 4, 0)]

convert a list of x and y coordinates into multistring

I have a set of x and y coordinates as follows:
x = (1,1,2,2,3,4)
y= (0,1,2,3,4,5)
What is the best way of going about transforming this list into a multiline string format, e.g:
x_y = [((1,0)(1,1)),((1,1)(2,2)),((2,2)(2,3)),((2,3)(3,4)),((3,4)(4,5))]
You can pair up the elements of x and y with zip():
>>> x = (1,1,2,2,3,4)
>>> y = (0,1,2,3,4,5)
>>> xy = zip(x, y)
>>> xy
[(1, 0), (1, 1), (2, 2), (2, 3), (3, 4), (4, 5)]
Then you can rearrange this into the kind of list in your example with a list comprehension:
>>> x_y = [(xy[i], xy[i+1]) for i in xrange(len(xy)-1)]
>>> x_y
[((1, 0), (1, 1)), ((1, 1), (2, 2)), ((2, 2), (2, 3)), ((2, 3), (3, 4)), ((3, 4), (4, 5))]
If you don't care about efficiency, the second part could also be written as:
>>> x_y = zip(xy, xy[1:])

merge (int * string) list ocaml

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)]

Composing a list of all pairs

I'm brand new to Scala, having had very limited experience with functional programming through Haskell.
I'd like to try composing a list of all possible pairs constructed from a single input list. Example:
val nums = List[Int](1, 2, 3, 4, 5) // Create an input list
val pairs = composePairs(nums) // Function I'd like to create
// pairs == List[Int, Int]((1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (2, 1) ... etc)
I tried using zip on each element with the whole list, hoping that it would duplicate the one item across the whole. It didn't work (only matched the first possible pair). I'm not sure how to repeat an element (Haskell does it with cycle and take I believe), and I've had trouble following the documentation on Scala.
This leaves me thinking that there's probably a more concise, functional way to get the results I want. Does anybody have a good solution?
How about this:
val pairs = for(x <- nums; y <- nums) yield (x, y)
For those of you who don't want duplicates:
val uniquePairs = for {
(x, idxX) <- nums.zipWithIndex
(y, idxY) <- nums.zipWithIndex
if idxX < idxY
} yield (x, y)
val nums = List(1,2,3,4,5)
uniquePairs: List[(Int, Int)] = List((1, 2), (1, 3), (1, 4), (1, 5), (2, 3), (2, 4), (2, 5), (3, 4), (3, 5), (4, 5))
Here's another version using map and flatten
val pairs = nums.flatMap(x => nums.map(y => (x,y)))
List[(Int, Int)] = List((1,1), (1,2), (1,3), (1,4), (1,5), (2,1), (2,2), (2,3), (2,4), (2,5), (3,1), (3,2), (3,3), (3,4), (3,5), (4,1), (4,2), (4,3), (4,4), (4,5), (5,1), (5,2) (5,3), (5,4), (5,5))
This can then be easily wrapped into a composePairs function if you like:
def composePairs(nums: Seq[Int]) =
nums.flatMap(x => nums.map(y => (x,y)))