F# Iterate over N dimensions [duplicate] - recursion

I was given a puzzle as a present. It consists of 4 cubes, arranged side by side. The faces of each cube are one of four colours.
To solve the puzzle, the cubes must be orientated so that all four cubes' tops are different, all their fronts are different, all their backs are different and all their bottom's are different. The left and right sides do not matter.
My pseudo-code solution was:
Create a representation of each
cube.
Get all the possible orientations of
each cube (there are 24 for each).
Get all the possible combinations of
orientations of each cube.
Find the combination of orientations
that satisfies the solution.
I solved the puzzle using an implementation of that pseudo-code in F#, but am not satisifed with the way I did step 3:
let problemSpace =
seq { for c1 in cube1Orientations do
for c2 in cube2Orientations do
for c3 in cube3Orientations do
for c4 in cube4Orientations do
yield [c1; c2; c3; c4] }
The above code is very concrete, and only works out the cartesian product of four sequences of orientations. I started thinking about a way to write it for n sequences of orientations.
I came up with (all the code from now on should execute fine in F# interactive):
// Used to just print the contents of a list.
let print =
Seq.fold (fun s i -> s + i.ToString()) "" >> printfn "%s"
// Computes the product of two sequences - kind of; the 2nd argument is weird.
let product (seq1:'a seq) (seq2:'a seq seq) =
seq { for item1 in seq1 do
for item2 in seq2 do
yield item1 |> Seq.singleton |> Seq.append item2 }
The product function could be used like so...
seq { yield Seq.empty }
|> product [ 'a'; 'b'; 'c' ]
|> product [ 'd'; 'e'; 'f' ]
|> product [ 'h'; 'i'; 'j' ]
|> Seq.iter print
... which lead to ...
let productn (s:seq<#seq<'a>>) =
s |> Seq.fold (fun r s -> r |> product s) (seq { yield Seq.empty })
[ [ 'a'; 'b'; 'c' ]
[ 'd'; 'e'; 'f' ]
[ 'h'; 'i'; 'j' ] ]
|> productn
|> Seq.iter print
This is exactly the usage I want. productn has exactly the signature I want and works.
However, using product involves the nasty line seq { yield Seq.empty }, and it unintuitively takes:
A sequence of values (seq<'a>)
A sequence of sequences of values (seq<seq<'a>>)
The second argument doesn't seem correct.
That strange interface is hidden nicely by productn, but is still nagging me regardless.
Are there any nicer, more intuitive ways to generically compute the cartesian product of n sequences? Are there any built in functions (or combination of) that do this?

Use recursion: the cartesian product of n lists {L1..LN} is the collection of lists you get when you add each element in L1 to each sublist in the cartesian product of lists {L2..LN}.
let rec cart1 LL =
match LL with
| [] -> Seq.singleton []
| L::Ls -> seq {for x in L do for xs in cart1 Ls -> x::xs}
Example:
> cart1 [[1;2];[3;4;5];[6;7]] |> Seq.toList;;
val it : int list list =
[[1; 3; 6]; [1; 3; 7]; [1; 4; 6]; [1; 4; 7]; [1; 5; 6]; [1; 5; 7]; [2; 3; 6];
[2; 3; 7]; [2; 4; 6]; [2; 4; 7]; [2; 5; 6]; [2; 5; 7]]
The cartesian product of [1;2] [3;4;5] and [6;7] is the union of {1 appended to each list in cart [[3;4;5];[6;7]]} and {2 appended to each list in cart [[3;4;5];[6;7]]}. This is the second clause in the match statement.

Here's a solution 'a list list -> Seq<'a list> to calculate the Cartesian product of n lists, with lazy evaluation. I wrote it to be an F# analogue of Python's itertools.product
let product lists =
let folder list state =
state |> Seq.allPairs list |> Seq.map List.Cons
Seq.singleton List.empty |> List.foldBack folder lists
It's based on List.allPairs which was introduced in F# 4.0.

Here's a first try at a list version. I think it could be cleaned up a bit.
let rec cart nll =
let f0 n nll =
match nll with
| [] -> [[n]]
| _ -> List.map (fun nl->n::nl) nll
match nll with
| [] -> []
| h::t -> List.collect (fun n->f0 n (cart t)) h

Related

How can I make a function that adds a number to each value in an array?

I am new to F# and I am trying to make a function called sumUp that adds 2 values like 1+2.
But I want it to work on an array, I tried the code you see in the snippit, but it doesnt seem to work, what am I doing wrong and why isn't this working?
let sumUp int1 int2 = int1 + int2
let numbers = [1;2;3]
numbers |> Seq.map (sumUp 4)
my expected result is [5,6,7] but i dont get any result at all.
This is my output:
- let sumUp int1 int2 = int1 + int2
-
- let numbers = [1;2;3]
-
- let result = numbers |> Seq.map (sumUp 4)
- ;;
val sumUp: int1: int -> int2: int -> int
val numbers: int list = [1; 2; 3]
val result: seq<int>
Your code is correct. The only problem is that Seq.map is a lazy function, so the value of result is just seq<int> until you do something to enumerate the sequence. You can do this using printfn, for example:
> let result = numbers |> Seq.map (sumUp 4);;
val result: seq<int>
> printfn "%A" result;;
seq [5; 6; 7]
Alternatively, you could use List.map instead of Seq.map to avoid lazy evaluation in the first place:
> let result = numbers |> List.map (sumUp 4);;
val result: int list = [5; 6; 7]
Note that your input ([1;2;3]) is a list, not an array. If you want to use arrays instead, try this:
> let numbers = [|1;2;3|];;
val numbers: int[] = [|1; 2; 3|]
> let result = numbers |> Array.map (sumUp 4);;
val result: int[] = [|5; 6; 7|]

F# - Recursion on list

Input: [x1; x2; ... ; xn]
Output ([x1; x3; ...; xn], [x2; x4; ...; xn], [x3; x5; ...; xn], ....)
What I have so far is:
let rec split = function
| x0 :: x1 :: xs -> (x0::xs) :: split(x1::xs)
| _ -> []
Which yields:
Input: [1;2;3;4;5;6]
Output: [[1; 3; 4; 5; 6]; [2; 4; 5; 6]; [3; 5; 6]; [4; 6]; [5]]
I don't quite see how I can build a tuple of lists recursively.
Any ideas?
I don't know why u want to do this, and if its some sort of exercise/homework I don't want to give you the answer BUT I will give you a hint, best start with something that does something sort of in the right direction.
This code takes a list and in a very unnecesary convoluted way, recursive returns a tuple of three of them.
let rec tripleList : List<'a> -> (List<'a> * List<'a> * List<'a>) =
function
| [] -> ([],[],[])
| (x :: xs) ->
let (tail1,tail2,tail3) = tripleList xs
(x :: tail1,x :: tail2,x :: tail3)
> tripleList [1..10];;
val it : List<int> * List<int> * List<int> =
([1; 2; 3; 4; 5; 6; 7; 8; 9; 10], [1; 2; 3; 4; 5; 6; 7; 8; 9; 10],
[1; 2; 3; 4; 5; 6; 7; 8; 9; 10])
you don't need to do the whole thing as a single function either, you could create 3 functions, 1 that builds each part of the tuple, and then a fourth function that calls the 3 functions to assemble the answer. That may be a simpler place to start.
So a similar sort of thing would be...
let rec tripleList1 : List<'a> -> List<'a> =
function
| [] -> []
| (x :: xs) ->
(x :: tripleList1 xs)
let rec tripleList2 : List<'a> -> List<'a> =
function
| [] -> []
| (x :: xs) ->
(2 * x :: tripleList2 xs)
let rec tripleList3 : List<'a> -> List<'a> =
function
| [] -> []
| (x :: xs) ->
(3 * x :: tripleList3 xs)
let tripleList : List<int> -> (List<int> * List<int> * List<int>) =
fun xs ->
(tripleList1 xs,tripleList2 xs,tripleList3 xs)
I prefer the first approach, but both are perfectively valid, and makes the distinction between the need for recursive functions to create the recusrive data structure List<'a>, whilst the tuple just requires a simple standalone function
so maybe try to write a function that takes.
[1,2,3,4,5,6,7] -> [1,3,5,7]
and then see if you can generalise that, and then assemble the pieces in another function
(note don't be misled by my example, they have the right structure but they fundamentally don't do what you need, you need to filter out values somehow in each part)

Average calculating of consecutive list elements in OCaml

I am trying to write a function in OCaml that will calculate the average of consecutive elements in a list. For example with [1; 2; 3; 4] it should output [1; 2; 3]. It should take (1 + 2) / 2 and give 1 then take (2 + 3) / 2 and give 2 and so on.
The code I wrote, however, only returns [1; 2]:
let rec average2 xs = match xs with
|[] -> []
|x :: [] -> [x]
|x :: x' :: xs -> if xs = [] then [(x + x') / 2] else [(x + x') / 2] # (average2 xs)
Can you please tell me how to fix this. Thank you.
When you're doing x :: y :: l in a match, you're effectively taking out the elements of the list permanently.
So if you want to do an operation on pairs of elements, you need to put one back in.
Example:
You have a list of [1;2;3;4]
You want to operate on 1 and 2, in your match it will interpret as:
1 :: 2 :: [3;4]
If you continue without adding an element in, the next statement would be:
3 :: 4 :: []
which is not what you want.
To correct this, in your recurice call you need to do (average2 (x'::xs) and not just (average2 xs) because xs is the rest of the list after taking the elements out.
OCaml allows to bind a pattern p to a variable v using p as v (alias patterns):
let rec average2 = function
| x :: (y :: _ as tail) -> (x + y) / 2 :: (average2 tail)
| _ -> []
Above, y :: _ as tail destructures a list named tail as a non-empty list headed by y and having an arbitrary tail _, the value of which we don't care about.
Note that I also simplified your function so that you don't check whether _ is empty or not: recursion handles this for you here.
Also, when you have zero or one element in the list, you should return an empty list.
# average2 [ 10; 20; 30; 40];;
- : int list = [15; 25; 35]

OCaml count the negatives

I'm really stuck on how to go about this I am asked to count the number of negatives within the list, I would have submitted the assignment with:
let nneg = [4; 9; -5; 0; -5; 1];;
List.filter nneg (fun -> (-))
List.filter nneg (fun x -> x < 0)
but it's not an int list -> int but instead an int list
so I started this but I can't figure it out for the life of me how to pattern match it:
let rec rev nneg =
match nneg with
| [] -> 0
| head::tail -> (filter tail < 0) head;;
You don't want to filter the list. You want to fold it to an int. Also the call has wrong arguments.
# List.filter;;
- : ('a -> bool) -> 'a list -> 'a list = <fun>
So filter is a function that takes a function that returns bool and a list. Filter returns filtered list. Example usage of filter:
# List.filter (fun x -> x > 0) [1;2;3;-3];;
- : int list = [1; 2; 3]
Since this is an assignment I'll just give you a hint. Have a look at fold function here. Obviously, you can solve it by filtering all elements greater or equal 0 and then counting them, but that requires two iterations.

OCaml non decreasing list without List.function

Update: I can't use any List.function stuff.
I'm new to OCaml and I'm learning this course in which I'm supposed to calculate a list of non decreasing values from a list of values.
So for e.g. I have a list [1; 2; 3; 1; 2; 7; 6]
So function mono that takes in a list returns the following:
# mono [1; 2; 3; 1; 2; 7; 6];;
- : int list = [1; 2; 3; 7]
I do the following:
let rec calculateCheck value lst = (
match lst with
[] -> true
| x :: xs -> (
if (value < x) then
false
else
calculateCheck value xs
)
);;
let rec reverse_list lst = (
match lst with
[] -> []
| x :: xs -> (
reverse_list xs # [x]
)
);;
let shouldReverse = ref 1;;
let cancelReverse somelist lst = (
shouldReverse := 0;
reverse_list lst
);;
let rec mono lst = (
let somelist = ref lst in
if (!shouldReverse = 1) then
somelist := cancelReverse somelist lst
else
somelist := lst;
match !somelist with
[] -> []
| x :: xs -> (
if (calculateCheck x xs) then
[x] # mono xs
else
[] # mono xs
);
);;
Problem?
This only works once because of shouldReverse.
I cannot reverse the value; mono list should return non decreasing list.
Question?
Any easy way to do this?
Specifically how to get a subset of the list. For e.g. for [1; 2; 3; 5; 6], I want [1; 2; 3] as an output for 5 so that I can solve this issue recursively. The other thing, is you can have a list as [1; 2; 3; 5; 6; 5]:: so for the second 5, the output should be [1; 2; 3; 5; 6].
Any ideas?
Thanks
A good way to approach this kind of problem is to force yourself to
formulate what you're looking for formally, in a mathematically
correct way. With some training, this will usually get you
a description that is close to the final program you will write.
We are trying to define a function incr li that contains the
a strictly increasing subsequence of li. As Jeffrey Scoffield asked,
you may be looking for the
longest
such subsequence: this is an interesting and non-trivial algorithmic
problem that is well-studied, but given that you're a beginner
I suppose your teacher is asking for something simpler. Here is my
suggestion of a simpler specification: you are looking for all the
elements that are greater than all the elements before them in the
list.
A good way to produce mathematical definitions that are easy to turn
into algorithms is reasoning by induction: define a property on
natural numbers P(n) in terms of the predecessor P(n-1), or define
a property on a given list in terms of this property on a list of one
less element. Consider you want to define incr [x1; x2; x3; x4]. You
may express it either in terms of incr [x1; x2; x3] and x4, or in
terms of x1 and incr [x2; x3; x4].
incr [x1;x2;x3;x4] is incr[x1;x2;x3], plus x4 if it is bigger
than all the elements before it in the list, or, equivalently, the
biggest element of incr[x1;x2;x3]
incr [x1;x2;x3;x4] is incr[x2;x3;x4] where all the elements
smaller than x1 have been removed (they're not bigger than all
elements before them), and x1 added
These two precise definitions can of course be generalized to lists of
any length, and they give two different ways to write incr.
(* `incr1` defines `incr [x1;x2;x3;x4]` from `incr [x1;x2;x3]`,
keeping as intermediate values `subli` that corresponds to
`incr [x1;x2;x3]` in reverse order, and `biggest` the biggest
value encountered so far. *)
let incr1 li =
let rec incr subli biggest = function
| [] -> List.rev subli
| h::t ->
if h > biggest
then incr (h::subli) h t
else incr subli biggest t
in
match li with
| [] -> []
| h::t -> incr [h] h t
(* `incr2` defines `incr [x1;x2;x3;x4]` from `incr [x2;x3;x4]`; it
needs no additional parameter as this is just a recursive call on
the tail of the input list. *)
let rec incr2 = function
| [] -> []
| h::t ->
(* to go from `incr [x2;x3;x4]` to `incr [x1;x2;x3;x4]`, one
must remove all the elements of `incr [x2;x3;x4]` that are
smaller than `x1`, then add `x1` to it *)
let rec remove = function
| [] -> []
| h'::t ->
if h >= h' then remove t
else h'::t
in h :: remove (incr2 t)

Resources