Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calculating the Cartesian product of a list of numbers with F#

Tags:

f#

I am new to f#

I am try to calculate the Cartesian products of a list of numbers. I "borrowed" this.

let xs = [1..99]
let ys = [1..99]
seq {for x in xs do for y in ys do yield x * y}

Is there a better or more elegant way?

Gary

like image 331
Gary Avatar asked Jun 01 '09 18:06

Gary


People also ask

What is Cartesian product in c++?

The Cartesian product of two sets is. A x B = {a, d}, {a, e}, {a, f}, {b, d}, {b, e}, {b, f}, {c, d}, {c, e}, {c, f}} A has 3 elements and B also has 3 elements. The Cartesian Product has 3 x 3 = 9 elements.

How do you take the Cartesian product of two lists in Python?

Suppose we have two list of data l1 and l2. We have to find Cartesian product of these two lists. As we know if two lists are like (a, b) and (c, d) then the Cartesian product will be {(a, c), (a, d), (b, c), (b, d)}. To do this we shall use itertools library and use the product() function present in this library.

How do you create a Cartesian product in Python?

Get Cartesian Product in Python Using the itertools ModuleThe product(*iterables, repeat=1) method of the itertools module takes iterables as input and returns their cartesian product as output. The cartesian product order will be the order of each set/list in the provided argument iterables .


2 Answers

Another possibiltiy to tackle the problem based on functionality provided by the List module would be:

let xs = [1..99]
let ys = [1..99]
let zs = xs |> List.collect (fun x -> ys |> List.map (fun y -> x*y))

which avoids the extra calls to .concat and should also do the job.

But I'd stick with your solution. It should be the most readable which is a real matchwinner. (Just try to read the codes out loud. Yours is perfectly understandable and Noldorins or mine are not.)

like image 65
leen Avatar answered Nov 15 '22 12:11

leen


Disclaimer: I don't have a machine with the current F# installed, so I can't test my code. Basically, though, if you steal sequence from Haskell, you can write your program as

let cartesian = sequence >> List.map product

and run it as

cartesian [[1..99]; [1..99]]

Here's how to write sequence. It's a generalised version of the sequence expression you wrote. It just handles an unlimited number of lists: { for x in xs do for y in ys do for z in zs ... yield [x;y;z;...] }.

let rec sequence = function
  | [] -> Seq.singleton []
  | (l::ls) -> seq { for x in l do for xs in sequence ls do yield (x::xs) }
// also you'll need product to do the multiplication
let product = Seq.fold_left1 ( * )

Then you can write your program as

let cartesian xs ys = [xs; ys] |> sequence |> List.map product
// ... or one-argument, point-free style:
let cartesian' = sequence >> Seq.map product

You might have to change some Seqs to Lists.

However, the number of people who can guess the meaning of your non-general list comprehension is probably a lot more than will recognise the name sequence, so you're probably better off with the list comprehension. sequence comes in handy any time you want to run a whole list of computation expressions, though.

like image 31
Nathan Shively-Sanders Avatar answered Nov 15 '22 10:11

Nathan Shively-Sanders