Using List filter to impose a boolean condition on a list and returning a new filtered list - f#

Given a source and target grid point, write the function: dist: p1: pos -> p2: pos -> int
I have successfully created this function as shown below:
type pos = int*int
let p1 = (1, 1) // source grid point
let p2 = (3, 3) // target grid point
let dist (p1: pos) (p2: pos) : int =
(((pown ((fst p2)-(fst p1)) 2) + (pown ((snd p2)-(snd p1)) 2)))
dist p1 p2
printfn "%A" (dist p1 p2)
Given a source and a target and dist, write the function
candidates: src: pos -> tg: pos -> pos list
which returns the list of candidate next positions, which brings the robot closer to its
target. I.e., if src = (x, y), then the function must consider all the neighbouring positions,
{(x+1, y),(x−1, y),(x, y+1),(x, y−1)}, and return those whose distance is equal to or
smaller than dist(src,tg). This can be done with List.filter.
This is what I have so far:
let src = p1
let tg = p2
let candidates (src: pos) (tg: pos) : pos list =
let candi = [((fst p1)+1), (snd p1); ((fst p1)-1), (snd p1); (fst p1), ((snd p1)+1); (fst p1), ((snd p1)-1)]
let candilist = candi |> List.filter (fun x -> x <=dist p1 p2)
candilist
printfn "%A" (candidates p1 p2)
Since my dist function returns an int, I get an error message saying: This expression was expected to have type
'int * int'
but here has type
'int'
I hope someone can give a few tips.

This line:
let candilist = candi |> List.filter (fun x -> x <=dist p1 p2)
should probably read:
let candilist = candi |> List.filter (fun x -> dist x p2 <= dist p1 p2)
The filter function should return true for points which are closer to the target than the current point. At present you are comparing the candidate point itself (of type int * int) with the distance (of type int) from the target.

Related

How to create a function which can test the random Word cooccurrence of another function?

So my team and I have created a function, wordMarkovChain, which generates a random string with nWords words, whose word-pairs are distributed according to the cooccurrence histogram wCooc.
Now we wanted to create a function which will test the newly created wordMarkovChain, so I can confirm that it's working as it should.
The function, diffw2, which compares two cooccurrence histograms as the average sum of squared differences, needs to take in two parameters, c1 and c2, of type wordCooccurrences and return a double, where c1 and c2 are two cooccurrence histograms of M elements such that c1(i, j) is the number
of times word number i is found following word number j.
The math behind the function should look like this: 1/M^2 * Summation from i=0 to M-1 Summation from i=0 to M-1 (c1(i, j) - c2(i, j))^2.
Sorry, I can't post a picture:(
Our two types which we have created seems to be the problem. c1 and c2 can have a different length but the type wordHistogram inside the type wordCoocurence can also have a different length.
The question is, how can we create such a function?
We tried with for loops, but we think it needs to be a recursive function. We are quite new to the whole concept of programming and are looking for some guidance. Please bear in mind that we do not possess vast knowledge of F#, especially not their in build functions.
CODE
// Types
type wordHistogram = (string * int) list
type wordCooccurrences = (string * wordHistogram) list
let diffw2 (c1 : wordCooccurrences) (c2 : wordCooccurrences) : double =
let mutable res = 0
let z1, z2 = c1 |> List.unzip
let z3, z4 = c2 |> List.unzip
let m1 = c1 |> List.length
let m2 = c2 |> List.length
let m = m1 + m2
for i in 0 .. (m - 1) do
for j in 0 .. (m - 1) do
for k in 0 .. ((z2.[j] |> List.length) - 1) do
res <- res + (snd z2.[j].[k] - snd z4.[j].[k]) * (snd z2.[j].[k] - snd z4.[j].[k])
(1.0 / (float(m * m))) * float(res)
This might get you closer to what you need. This could instead be done using recursive functions, but I usually prefer to use built-in higher-order functions like fold or fold2 when they can do the job. See https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/list.fold2%5B't1%2C't2%2C'state%5D-function-%5Bfsharp%5D
Each call of List.fold2 receives an "accumulator" with an initial value (or "state") of 0.0. This accumulator is passed to the lambda function in the parameter named "acc". As the lambda is applied to each element of the two input lists, it adds the intermediate result to that acc value, which is then returned as the result of the List.fold2 call.
type wordHistogram = (string * int) list
type wordCooccurrences = (string * wordHistogram) list
let diffw2 (c1 : wordCooccurrences) (c2 : wordCooccurrences) =
let m1 = c1 |> List.length
let m2 = c2 |> List.length
let m = m1 + m2
let res =
(0.0, c1, c2) |||>
List.fold2 (fun acc (_str1, hist1) (_str2, hist2) ->
let intermedRes =
(0.0, hist1, hist2) |||>
List.fold2 (fun acc (_str1, freq1) (_str2, freq2) ->
let diff = float (freq1 - freq2)
acc + diff * diff
)
acc + intermedRes
)
(1.0 / float(m * m)) * res
I think you are trying to do the following
let diffw2_ (c1 : wordCooccurrences) (c2 : wordCooccurrences) =
List.zip c1 c2
|> List.sumBy (fun ((_, w1), (_, w2)) ->
List.zip w1 w2
|> List.sumBy (fun ((_,i1), (_,i2)) ->
(float (i1 - i2)) ** 2.0
)
) |> (fun totalSumOfSquares -> totalSumOfSquares / (c1 |> List.length |> float))
This just returns the average square differences between corresponding elements of c1 and c2. It assumes that c1 and c2 have the same structure.
With F# (and functional programming in general), you typically avoid using mutable variables and for loops, in favor of pure functions.

How to use match Map elements in F#?

I tried to create a function that takes two integers a,b as input and return 5 if a=1 b=2 and 6 otherwise, Here is what I did:
let examplef (a:int), (b:int)=
match a,b with
|1,2 -> 5
|_,_->6;;
It gives this error: "The pattern discriminator 'examplef' is not defined."
I ask this question because of the error in this code:
type Team = string
type Goals = Goals of int
type Points = Points of int
type Fixture = Team * Team
type Result = (Team * Goals) * (Team * Goals)
type Table = Map<Team,Points>
let league =["Chelsea"; "Spurs"; "Liverpool"; "ManCity"; "ManUnited"; "Arsenal"; "Everton"; "Leicester"]
let pointsMade (a: Result)=
match a with
|((b,Goals bg),(c,Goals cg))-> if b<c then ((b,Points 0),(c, Points 3))
elif b=c then ((b,Points 1),(c,Points 1))
else ((b, Points 3),(c, Points 0))
I get an error when trying to define the following function:
let updateTable (t:Table, r: Result)=
let pointmade = pointsMade r
match pointmade with
|((f,Points s),(f1,Points s1))-> match Map.tryFind f t Map.tryFind f1 t with
|None, None -> t
|Some Points x, Some Points y ->t .Add (f, Points s+x1) .Add(f1, Points s1+y1)
When I hover the mouse over the first "Map.tryFind f t" It says "This value is not a function and cannot be applied. Also, there is an error with t .Add (f, Points s+x1) .Add(f1, Points s1+y1) it says: "Successive arguments should be separated by space and tuples and arguments involving functions or method applications should be parenthesized".
Please help
It looks like you're confusing tuple and curried arguments.
Examples with a single tuple argument (parenthesis are requiered).
signature: int * int -> int
//let example1 (a: int, b:int) =
let example1 (a, b) =
match a, b with
| 1, 2 -> 5
| _ -> 6
//let example2 (t: int * int) =
let example2 t =
match t with
| 1, 2 -> 5
| _ -> 6
Example with two curried arguments:
signature: int-> int -> int
//let example3 (a: int) (b: int) =
let example3 a b =
match a, b with
| 1, 2 -> 5
| _ -> 6
Anyway, The code that work looks like this:
open System.Security.Cryptography
open System.Threading
type Team = string
type Goals = Goals of int
type Points = Points of int
type Fixture = Team * Team
type Result = (Team * Goals) * (Team * Goals)
type Table = Map<Team,Points>
let league =["Chelsea"; "Spurs"; "Liverpool"; "ManCity"; "ManUnited"; "Arsenal"; "Everton"; "Leicester"]
let pointsMade (a: Result)=
match a with
|((b,Goals bg),(c,Goals cg))-> if bg<cg then ((b,Points 0),(c, Points 3))
elif bg=cg then ((b,Points 1),(c,Points 1))
else ((b, Points 3),(c, Points 0))
let initEntry (name:Team)=(name, Points 0)
let initializeTable l = Map.ofList (List.map initEntry l)
let updateTable (t:Table, r: Result)=
let pointmade = pointsMade r
match pointmade with
|((f,Points s),(f1,Points s1))-> match Map.tryFind f t, Map.tryFind f1 t with
|None, None -> t
|Some x, Some y-> match x,y with
| Points x1 , Points y1 -> t |> Map.add f (Points(x1+s)) |> Map.add f1 (Points (y1+s1))
|None, Some y -> match y with
| Points y1 -> t.Add(f,Points s) .Add(f1, Points (s1+y1))
|Some x, None -> match x with
| Points x1 -> t.Add(f,Points (s+x1)) .Add(f1, Points s1)
let rec weekendUpdate (t:Table , rl:Result list)=
match rl with
|[]->t
|ai::at-> weekendUpdate(updateTable(t,ai),at)
let rec seasonUpdate (t:Table, sll: Result list list)=
match sll with
|[]->t
|ah::at-> seasonUpdate(weekendUpdate(t,ah),at)
let less((s1,n1):Team * Points, (s2,n2):Team * Points) =
match n1,n2 with
|Points m1,Points m2 ->if m1<m2 then true
else false
let rec myinsert item lst =
match lst with
| [] -> [item]
| x::xs -> if less(item,x) then x::(myinsert item xs) else item::lst
let rec isort lst =
match lst with
| [] -> []
| x::xs -> myinsert x (isort xs)
let showStandings (t:Table) = isort (Map.toList t)
In your "working code", in the pointsMade function you do not need to use pattern matching, you can simply use a let binding.
let pointsMade (r: Result) =
let (t1, Goals g1), (t2, Goals g2) = r
if g1 < g2 then (t1, Points 0), (t2, Points 3)
elif g1 = g2 then (t1, Points 1), (t2, Points 1)
else (t1, Points 3), (t2, Points 0)
The updateTable function also can be re-written in more concise way by using some addPoints function to avoid repeating the same thing for each team.
let addPoints (team: Team, Points points) (table: Table) =
match Map.tryFind team table with
| None -> table
| Some (Points p) -> Map.add team (Points (points + p)) table
let updateTable (table: Table, result: Result) =
let pts1, pts2 = pointsMade result
table |> addPoints pts1 |> addPoints pts2

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)

F# find largest element in list of structures

I'm new to F# and I want to find largest element form list of structures:
type Element = struct
val X: int
val Y: int
val RES: int
new (x, y, res) =
{X = x; Y = y; RES = res;}
override this.ToString() = sprintf "%i = %i * %i" this.RES this.X this.Y
end
X is larger than Y when X.RES > Y.RES. I wrote some code:
let max2 x y = if x.RES < y.RES then y else x //BAD LINE
let max_list list =
let rec loop hi list =
match list with
| h::t -> loop (max2 h hi) t
| [] -> hi
match list with
| h::t -> loop h t
| [] -> invalidArg "list" "Empty list"
and call:
let list = findPalindromes 1 1 List.empty //this call populates the "list"
printfn "%A" (max_list list)
This call generates 2 errors (pointing x.RES and y.RES) in line //BAD LINE:
error FS0072: Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this program point to constrain the type of the object. This may allow the lookup to be resolved.
I know that I should cast x and y to Element, I've tried to do it but every time I failed.
How can I fix this code or implement this functionality other way?
The F# standard library has this built-in – List.maxBy:
findPalindromes 1 1 List.empty
|> List.maxBy (fun e -> e.RES)
|> printfn "%A"
As to the error you're getting with max2, type annotations solve it:
let max2 (x:Element) (y:Element) = if x.RES < y.RES then y else x

F# Polynomial Derivator

I'm writing a program that takes a polynomial and returns its derivative. The polynomial is passed as predefined type "poly", which is a list of tuples in which the first element is a float representing a coefficient, and the second is an integer representing the degree of that term. So a poly p = [(2.0, 3);(1.5,2);(3.2;1)] would represent 2x^3 + 1.5x^2 + 3.2x^1. My code is as follows:
let rec diff (p:poly):poly =
match p with
| [] -> raise EmptyList
| [a]-> (fst a * snd a, snd a - 1)
| x::xs -> ((fst x * snd x), (snd x - 1)) :: diff xs
The error I'm getting tells me that the program expects the function to return a type poly, but here has the type 'a * 'b. I don't see why thats the case, when in my base case I return a tuple and in all other situations I'm appending onto an accumulating list. I've played around with the brackets, to no avail. Why is my code tossing this error?
All input is appreciated on the matter.
you said it yourself: in the base case you are returning a tuple not a list - so the inference thinks this is what you want
Just change it into:
let rec diff (p:poly):poly =
match p with
| [] -> raise EmptyList
| [a]-> [fst a * snd a, snd a - 1]
| x::xs -> ((fst x * snd x), (snd x - 1)) :: diff xs
and it should be fine (just replace the (..) with [..] ;) )
remember: :: will cons a new head onto a list
there are a few issues with float vs. int there so I would suggest this (using recursion):
type Poly = (float*int) list
let test : Poly = [(2.0, 3);(1.5,2);(3.2,1);(1.0,0)]
let rec diff (p:Poly):Poly =
match p with
| [] -> []
| x::xs -> (fst x * float (snd x), snd x - 1) :: diff xs
which is really just this:
let diff : Poly -> Poly =
List.map (fun x -> fst x * float (snd x), snd x - 1)
and can look a lot nicer without fst and snd:
let diff : Poly -> Poly =
List.map (fun (a,p) -> a * float p, p - 1)

Resources