Combining 2 lists in F# - f#

I have 2 lists with coordinates (one per axis) and I'm making squares out of them:
// create all combinations
let squares = List<int * int * int * int>()
seqX
|> Seq.pairwise
|> Seq.iter (fun (x1, x2) ->
seqY
|> Seq.pairwise
|> Seq.iter (fun (y1, y2) -> squares.Add(x1, y1, x2, y2))
)
Is there a way, using the collection functions to make this?
I can't use Seq.map because the output will not match the total number of iterations
|> Seq.map (fun (y1, y2) -> (x1, y1, x2, y2))
will not work

You could use Seq.collect to flat-map an inner sequence.
Collect (aka SelectMany in LINQ, and flatMap in JS) projects each item onto a new sequence, and flattens the results.
seqX
|> Seq.pairwise
|> Seq.collect(fun (x1, x2) -> seqY |> Seq.map(fun (y1, y2) -> (x1, x2, y1, y2))
Or you could make a sequence expression to do it for you, which de-sugars to the above:
seq {
for (x1, x2) in seqX |> Seq.pairwise do
for (y1, y2) in seqY |> Seq.pairwise do
yield (x1, x2, y1, y2)
}
Sequence expressions are very useful when there is depth involved.
It's much cleaner than writing nested closures for every level (seq |> Seq.collect (fun _ -> Seq.collect(fun...).
Here's an example which finds all right-angled triangles whose sides are less than 10, by going through every possible triangle and checking Pythagoras' theorem.
seq {
let sides = [1..10]
for a in sides do
for b in sides do
for c in sides do
if a * a + b * b = c * c then
yield (a, b, c)
}
This would be much uglier de-sugared.

Related

F# Matching results of recursive calls using higher order functions

Given a simple function, where we do pattern matching on the result of a recursive call, such as:
let rec sumProd = function
| [] -> (0,1)
| x::rest -> let (rSum,rProd) = sumProd rest
(x + rSum,x * rProd)
sumProd [2;5] //Expected (7, 10)
How would I go about changing it into something using higher order functions, e.g. foldBack?
let sumProdHigherOrder lst =
List.foldBack (fun x acc -> (acc + x, acc * x)) lst (0,0)
The above seemed almost like the way to do it, but calling it gives the error: The type 'int' does not match the type 'int * int'
sumProdHigherOrder [2;5] //Expected (7, 10)
What am I missing?
Your missing the tuple functions fst and snd:
List.foldBack (fun x acc -> (fst acc + x, snd acc * x)) [2;5] (0,1)
// val it : int * int = (7, 10)
Or even better, decomposing the tuple at the lambda. I see you just found it:
List.foldBack (fun x (s, m) -> (s + x, m * x)) [2;5] (0,1)
Also note that since the operations are commutative you can do a straight fold:
List.fold (fun (s, m) x -> (s + x, m * x)) (0,1) [2;5]
It will be more efficient.
Right! Of course it shouldn't be the same accumulator that gets passed through the list. After staring intensely at the code for some minutes, I figured it out:
let sumProdHigherOrder lst =
List.foldBack (fun x (acc,acc') -> (acc + x, acc' * x)) lst (0,1)

Does (Array/List/Seq).groupBy maintain sort order within groups?

Does groupBy guarantee that sort order is preserved in code like the following?
x
|> Seq.sortBy (fun (x, y) -> y)
|> Seq.groupBy (fun (x, y) -> x)
By preserving sort order, I mean can we guarantee that within each grouping by x, the result is still sorted by y.
This is true for simple examples,
[(1, 3);(2, 1);(1, 1);(2, 3)]
|> Seq.sortBy (fun (x, y) -> y)
|> Seq.groupBy (fun (x, y) -> x)
// seq [(2, seq [(2, 1); (2, 3)]); (1, seq [(1, 1); (1, 3)])]
I want to make sure there are no weird edge cases.
What do you mean by preserving sort order? Seq.groupBy changes the type of the sequence, so how can you even meaningfully compare before and after?
For a given xs of the type seq<'a * 'b>, the type of the expression xs |> Seq.sortBy snd is seq<'a * 'b>, whereas the type of the expression xs |> Seq.sortBy snd |> Seq.groupBy fst is seq<'a * seq<'a * 'b>>. Thus, whether or not the answer to the question is yes or no depends on what you mean by preserving the sort order.
As #Petr wrote in the comments, it's easy to test this. If you're worried about special cases, write a Property using FsCheck and see if it generalises:
open FsCheck.Xunit
open Swensen.Unquote
[<Property>]
let isSortOrderPreserved (xs : (int * int) list) =
let actual = xs |> Seq.sortBy snd |> Seq.groupBy fst
let expected = xs |> Seq.sortBy snd |> Seq.toList
expected =! (actual |> Seq.map snd |> Seq.concat |> Seq.toList)
In this property, I've interpreted the property of sort order preservation to mean that if you subsequently concatenate the grouped sequences, the sort order is preserved. Your definition may be different.
Given this particular definition, however, running the property clearly demonstrates that the property doesn't hold:
Falsifiable, after 6 tests (13 shrinks) (StdGen (1448745695,296088811)):
Original:
[(-3, -7); (4, -7); (4, 0); (-4, 0); (-4, 7); (3, 7); (3, -1); (-5, -1)]
Shrunk:
[(3, 1); (3, 0); (0, 0)]
---- Swensen.Unquote.AssertionFailedException : Test failed:
[(3, 0); (0, 0); (3, 1)] = [(3, 0); (3, 1); (0, 0)]
false
Here we see that if the input is [(3, 1); (3, 0); (0, 0)], the grouped sequence doesn't preserve the sort order (which isn't surprising to me).
Based on the updated question, here's a property that examines that question:
[<Property(MaxTest = 10000)>]
let isSortOrderPreservedWithEachGroup (xs : (int * int) list) =
let actual = xs |> Seq.sortBy snd |> Seq.groupBy fst
let expected =
actual
|> Seq.map (fun (k, vals) -> k, vals |> Seq.sort |> Seq.toList)
|> Seq.toList
expected =!
(actual |> Seq.map (fun (k, vals) -> k, Seq.toList vals) |> Seq.toList)
This property does, indeed, hold:
Ok, passed 10000 tests.
You should still consider carefully whether you want to rely on behaviour that isn't documented, since it could change in later incarnations of F#. Personally, I'd adopt a piece of advice from the Zen of Python:
Explicit is better than implicit.
BTW, the reason for all that conversion to F# lists is because lists have structural equality, while sequences don't.
The documentation doesn't say explicitly (except through the example), but the implementation does preserve the order of the original sequence. It would be quite surprising if it didn't: the equivalent functions in other languages that I am aware of do.
Who cares. Instead of sorting and then grouping, just group and then sort and the ordering is guaranteed even if the F# implementation of groupBy eventually changes:
x
|> Seq.groupBy (fun (x, y) -> x)
|> Seq.map (fun (k, v) -> k, v |> Seq.sortBy (fun (x, y) -> y))

get polynom representation for lagrangian interpolation

How can I represent an incomplete mathematical function?
I need to do something like (x - constant) then
(x - constant)*(x - another) => (x^2 - x * constant - x * another + constant * another)
and so on.
I'm trying to make a program to do Lagrangian interpolation (finding a function for some points)
so I need to make a function that I can see (print, or something), from a set of known values.
sorry if confusing.
In case you want to implement the Lagrange Interpolation as discussed here
getting a function that interpolates values:
then this is the direct translation into F#:
let LagrangeInterpol (points : (Double*Double)[]) x =
let indizes = [0..points.Length-1]
let p j =
indizes
|> List.map (fun k ->
if k <> j
then (x - fst points.[k])
/ (fst points.[j] - fst points.[k])
else 1.0)
|> List.fold (*) 1.0
indizes |> List.sumBy (fun j -> p j * snd points.[j])
examples
Here is a simple test-session:
> let points = [|0.0,0.0; 1.0,2.0; 2.0,3.0|];;
val points : (float * float) [] = [|(0.0, 0.0); (1.0, 2.0); (2.0, 3.0)|]
> let f = LagrangeInterpol points;;
val f : (Double -> float)
> f 0.0;;
val it : float = 0.0
> f 1.0;;
val it : float = 2.0
> f 2.0;;
val it : float = 3.0
So I hope I did not make any major mistake.
Please note that I made no efford to do any performance optimizations here - this should be sufficent to draw a graph or get a few values in between.
getting a representation of the polynom
This is a bit more trickier - you can either try to come up with the combinatorical formulas for the coefficients or (like me here) be mathematical lazy and just implement a Polynom-Type with just enough operators:
type Polynom =
Poly of float list with
override p.ToString () =
match p with
| Poly coefs ->
System.String.Join (" + ", coefs |> List.mapi (fun i c -> sprintf "%AX^%d" c i))
static member Const c = Poly [c]
static member Zero = Polynom.Const 0.0
static member One = Polynom.Const 1.0
static member X = Poly [0.0; 1.0]
static member (+) (Poly cs1, Poly cs2) =
let m = max (List.length cs1) (List.length cs2)
List.zip (ofLen m cs1) (ofLen m cs2)
|> List.map (fun (a,b) -> a+b)
|> Poly
static member (-) (Poly cs1, Poly cs2) =
let m = max (List.length cs1) (List.length cs2)
List.zip (ofLen m cs1) (ofLen m cs2)
|> List.map (fun (a,b) -> a-b)
|> Poly
static member (*) (f : float, Poly cs2) : Polynom =
cs2
|> List.map (fun c -> f * c)
|> Poly
static member private shift n (Poly cs) =
List.replicate n 0.0 # cs |> Poly
static member (*) (Poly cs1, p2 : Polynom) : Polynom =
cs1
|> List.mapi (fun i c -> Polynom.shift i (c * p2))
|> List.sum
static member (/) (Poly cs1, f : float) : Polynom =
cs1
|> List.map (fun c -> c / f)
|> Poly
Here I just use a list of floats to represent the coefficients of a polynom (so X^2 + 2X + 3 is Poly [3.0; 2.0; 1.0] note that the ith coefficient is the one at X^i.
Having this we can use almost the same function as before:
let getPolynom (points : (float * float)[]) =
let indizes = [0..points.Length-1]
let p j =
indizes
|> List.map (fun k ->
if k <> j
then (Polynom.X - Polynom.Const (fst points.[k]))
/ (fst points.[j] - fst points.[k])
else Polynom.One)
|> List.fold (*) Polynom.One
indizes |> List.sumBy (fun j -> Polynom.Const (snd points.[j]) * p j)
As you can see I used the same function and only replaces the argument x with Polynom.X and wrapped the constants approbiatley.
examples
and here are two examples (compare them to the Wiki-Page they should be right):
> LagrangeInterpolation.getPolynom
[|(1.0, 1.0); (2.0, 4.0); (3.0, 9.0)|] |> string;;
val it : string = "0.0X^0 + 0.0X^1 + 1.0X^2"
> LagrangeInterpolation.getPolynom
[| 1.0,1.0; 2.0,8.0; 3.0,27.0 |] |> string;;
val it : string = "6.0X^0 + -11.0X^1 + 6.0X^2"
complete code with helpers
the complete code for this inside a module is:
module LagrangeInterpolation =
let private ofLen n cs =
let l = List.length cs
if l < n
then cs # List.replicate (n-l) 0.0
else cs
type Polynom =
Poly of float list with
override p.ToString () =
match p with
| Poly coefs ->
System.String.Join (" + ", coefs |> List.mapi (fun i c -> sprintf "%AX^%d" c i))
static member Const c = Poly [c]
static member Zero = Polynom.Const 0.0
static member One = Polynom.Const 1.0
static member X = Poly [0.0; 1.0]
static member (+) (Poly cs1, Poly cs2) =
let m = max (List.length cs1) (List.length cs2)
List.zip (ofLen m cs1) (ofLen m cs2)
|> List.map (fun (a,b) -> a+b)
|> Poly
static member (-) (Poly cs1, Poly cs2) =
let m = max (List.length cs1) (List.length cs2)
List.zip (ofLen m cs1) (ofLen m cs2)
|> List.map (fun (a,b) -> a-b)
|> Poly
static member (*) (f : float, Poly cs2) : Polynom =
cs2
|> List.map (fun c -> f * c)
|> Poly
static member private shift n (Poly cs) =
List.replicate n 0.0 # cs |> Poly
static member (*) (Poly cs1, p2 : Polynom) : Polynom =
cs1
|> List.mapi (fun i c -> Polynom.shift i (c * p2))
|> List.sum
static member (/) (Poly cs1, f : float) : Polynom =
cs1
|> List.map (fun c -> c / f)
|> Poly
let getPolynom (points : (float * float)[]) =
let indizes = [0..points.Length-1]
let p j =
indizes
|> List.map (fun k ->
if k <> j
then (Polynom.X - Polynom.Const (fst points.[k]))
/ (fst points.[j] - fst points.[k])
else Polynom.One)
|> List.fold (*) Polynom.One
indizes |> List.sumBy (fun j -> Polynom.Const (snd points.[j]) * p j)
remarks
For better output you should probably add some simplifications (for example Poly [1.0;0.0] -> Poly [1.0]) and improve the ToString method but I'm sure you can handle ;)
If you mean a function that is partial, i.e. it is undefined on some of its inputs, then there are generally two ways to deal with this. One option is to use option<'T> type and wrap the correct result in Some or return None when the value is undefined. For example:
let safeDivide a b =
if b = 0 then None else Some(a / b)
The caller than has to pattern match on the result (or use something like the Maybe computation builder) which makes calling the function harder, but you have full control over how the error is handled.
The other option is to throw an exception. This happens automatically for integer division, but you could write something like this:
let safeDivide a b =
if b = 0 then invalidArg "b" "Division by zero!"
a / b
This is a bit easier to write, but you need to be aware of the behavior and handle the exceptions correctly.

How do you sum up and average a Sequence?

Say I have a coordinate (x, y) and its neighbors in a sequences of sequence (-1, 1)(0, 1)(1, 1)(-1, 0)(0, 0)(1, 0)(-1, -1)(0, -1)(1, -1)
let n = [1 .. -1 .. -1]
|> Seq.collect (fun j -> [-1 .. 1] |> Seq.map(fun i -> [i, j]))
n |> Seq.iter(printf "%A")
I'm trying to add x and y to each element in the sequence respectively
Then get Color p = GetPixel(x+i, y+j) for every element in sequence, sum up and average out their R, G, B for (x,y)
So we have 9 Red, 9 Green, 9 Blue to Ave(Red), Ave(Blue), Ave(Green)
let offsets = seq { for i in -1 .. 1 do for j in -1 .. 1 do yield (i, j) }
let neighbourhood (x, y) = Seq.map (fun (i, j) -> (x + i, y + j)) offsets
let avgColours (cs : System.Drawing.Color seq) =
let ((r, g, b), c) = cs |> Seq.fold (fun ((r, g, b), c) col -> ((r + int col.R, g + int col.G, b + int col.B), c + 1)) ((0, 0, 0), 0)
System.Drawing.Color.FromArgb(r / c, g / c, b / c)
let avgNeighbours p = p |> neighbourhood |> Seq.map (fun (x, y) -> GetPixel(x, y)) |> avgColours
Something like this?
let f x y =
let n = [1 .. -1 .. -1] |> Seq.collect (fun j -> [-1 .. 1] |> Seq.map(fun i -> (i, j)))
n |> Seq.map (fun (i,j) -> x+i,y+j)
|> Seq.map bitmapobject.GetPixel
|> Seq.map (fun c -> float c.R, float c.G, float c.B)
|> Seq.fold (fun (R,G,B) (r,g,b) -> (R+r, G+g, B+b)) (0.0, 0.0, 0.0)
|> (fun (r,g,b) -> (r/9.0, g/9.0, b/9.0))

Compute min and max of a tuple list in F#

In F#, given
game: (int*int) list
I'd like to compute minx, maxx, miny, maxy the min and max values for each tuple dimension.
This code works but seems a bit clumsy:
let minX (game: (int*int) list) = game |> List.map (fun (x,y) -> x) |> Seq.min
let maxX (game: (int*int) list) = game |> List.map (fun (x,y) -> x) |> Seq.max
let minY (game: (int*int) list) = game |> List.map (fun (x,y) -> y) |> Seq.min
let maxY (game: (int*int) list) = game |> List.map (fun (x,y) -> y) |> Seq.max
Any hint for improvement?
let minX game = List.minBy fst game |> fst
let maxX game = List.maxBy fst game |> fst
let minY game = List.minBy snd game |> snd
let maxY game = List.maxBy snd game |> snd
Like John's, but easier to read:
let game = [(1,4);(2,1)]
let minx, miny, maxx, maxy =
let folder (mx,my,Mx,My) (ax,ay) = min mx ax, min my ay, max Mx ax, max My ay
((Int32.MaxValue, Int32.MaxValue, Int32.MinValue, Int32.MinValue), game) ||> List.fold folder
There are a few small changes you can make to improve what you have:
use Seq.map instead of List.map to avoid creating new lists and therefore keep memory usage constant
use the built-in fst/snd functions instead of lambdas
since game is the only argument you can use function composition to make your code more concise
You end up with:
let minX = Seq.map fst >> Seq.min
let maxX = Seq.map fst >> Seq.max
let minY = Seq.map snd >> Seq.min
let maxY = Seq.map snd >> Seq.max
Interestingly, I found this to be quite a bit faster than pad's solution: 0.28 vs 1.75 sec for 10M elements.
The fold version of pad's answer (only 1 list traversal)
let minx,miny,maxx,maxy =game |> List.fold (fun (mx,my,Mx,My) (ax,ay) ->
let nmx,nMx = if ax<mx then ax,Mx else if ax > Mx then mx,ax else mx,Mx
let nmy,nMy = if ay<my then ay,My else if ay > My then my,ay else my,My
nmx,nmy,nMx,nMy) (Int32.MaxValue,Int32.MaxValue,Int32.MinValue,Int32.MinValue)

Resources