Can I directly use a tuple as an Array2D index in F#? - f#

Lets say I have an the following Array2D
> let arr = Array2D.init 2 3 (fun i j -> (i+1) * (j+2));;
> printfn "%A" arr
[[2; 3; 4]
[4; 6; 8]]
I know I can access an array element like so
> arr[1, 2];;
8
But what if I have the coordinates saved in a tuple. Why can't I do the following or something similar:
> let coord = (1, 2);;
> arr[coord]
Error: input.fsx (2,1)-(2,11) typecheck error This expression was expected to have type
''a[]'
but here has type
'int[,]'
It feels kinda stupid to unpack the tuple each time before using it. Or is this the only way?
> let x, y = coord;;
> arr[x, y];;
8

You could always use ||> to unpack the tuple rather than using let expressions, along with Array2D.get. The downside is that its a lil more verbose for sure.
- let arr = Array2D.init 2 3 (fun i j -> (i+1) * (j+2))
- let coord = (1,2)
- coord ||> Array2D.get arr;;
val it : int = 8

I don't think there's any direct way to index a 2D array using a tuple. One similar alternative is to use a Map instead:
let map =
seq {
for i = 0 to 1 do
for j = 0 to 2 do
yield (i, j), (i+1) * (j+2)
} |> Map
let coord = (1, 2)
map[coord] // 8

F# treats tupled arguments in a special way. If method is defined not in F#, then it's arguments should be tupled:
System.String.Join(", ", [|1; 2; 3|])
System.String.Join ", " [|1; 2; 3|] // not valid
It's done to help overload resolution.
What you can do is to extend multidimensional array type:
type ``[,]``<'a> with
member inline ar.Item with get ((x, y): (int*int)) : 'a =
ar.[x, y]
And then use it:
let coord = (1, 2)
arr.Item coord |> printfn "%d"
Unfortunately arr.[coord] is not available and looks like a bug in compiler

All problems are solved through functions!
let xss = Array2D.init 2 3 (fun i j -> (i+1) * (j+2));;
let get arr (x,y) = Array2D.get arr x y
get xss (1,2) (* Returns 8 *)

Related

Is it possible to repeat an array?

I need to add 1 to each element in an array, and if it goes out of range, I need to start over.
let arr = [| 1; 2; 3 |]
for i = 0 to Array.length arr - 1 do
arr.[i] <- arr.[i] + 1
printfn "i %A" (arr.[i])
I want to add 5 points to the array, so that it iterates over the array and gives one point in each element, so the array would partially be [| 2; 3; 4 |] and iterate through the array again and end up being arr = [| 3; 4; 4 |]
Actually you can calculate exactly how much you should add to each element of array. So you can solve the problem by going through the array in only one time.
let addPoints arr points =
let len = arr |> Array.length
let added = points / len
let extraCount = points % len
arr
|> Array.mapi (fun i x ->
if i < extraCount then x + added + 1
else x + added)
addPoints [| 1; 2; 3 |] 5
|> printfn "%A" // [|3; 4; 4|]
Mutating the array or not, it's up to you.
Rather than mutating the array, a more idiomatic F# approach is to create a new array with the newly calculated results. You can use the built-in Array.map function to do apply the same transformation to each element of the array. To increment all by one, you can write:
let arr = [| 1; 2; 3 |]
arr |> Array.map (fun v -> v + 1)
If you want to restrict the maximal value to 4, you'll need to do that in the body of the function, i.e. v + 1. To make it easier to do this repeatedly, it's helpful to define a function.
let step arr =
arr |> Array.map (fun v -> min 4 (v + 1))
Here, step is a function you can call to do one step of the transformation. min 4 (v + 1) ensures that when v + 1 is more than 4, you get just 4 as the result. Now you can run step repeatedly using |>:
let arr1 = arr |> step
let arr2 = arr |> step |> step
I agree with #TomasPetricek in that the way to go should be to create new arrays using map. However, if you must mutate the array, the following loop-based approach should work just fine:
let incArrayElements n (a : _ []) =
let rec loop k i =
if k > 0 then
a.[i] <- a.[i] + 1
let ii = i + 1
if ii >= a.Length then 0 else ii
|> loop (k - 1)
if n > 0 then loop n 0
If required, this can also be easily modified to include a parameter for the starting index.

F# Loop through a list of functions, applying each function in turn to a number

I've recently started learning F#. I'm attempting to loop through a list of functions, applying each function to a value. For example, I have:
let identity x = fun x -> x
let square x = fun x -> x * x
let cube x = fun x -> x * x * x
let functions = [identity; square; cube]
I would now like to do something like the following:
let resultList = List.map(fun elem -> elem 3) functions
where the result value would be the list [3;9;27]. However, this is not what happens. Instead, I get:
val resultList : (int -> int) list = [<fun:Invoke#3000>; <fun:Invoke#3000>; <fun:Invoke#3000>]
I guess I'm not entirely convinced that using map is the right way forward any longer, so my questions are:
Why do I not get a list of numbers?
How would return a list of numbers?
What does <fun:Invoke> mean?
Thanks very much for your help.
Daniel
Your functions aren't quite correctly defined, they're taking an extra (unused) argument and are therefore just partially applied and not evaluated as you're expecting. Besides that, your thinking is correct;
let identity2 = fun x -> x
let square2 = fun x -> x * x
let cube2 = fun x -> x * x * x
let functions = [identity2; square2; cube2]
let resultList = List.map(fun elem -> elem 3) functions;;
> val resultList : int list = [3; 9; 27]
Although I'm not an F# expert, the <fun:Invoke> would in this case seem to indicate that the value is a (partially applied) function.
Because I like to simplify where I can, you can reduce a bit on Joachim's answer by removing the fun from your functions:
let identity x = x
let square x = x * x
let cube x = x * x * x
let functions = [identity; square; cube]
printfn "%A" (List.map(fun elem -> elem 3) functions)
Gives the output [3; 9; 27]
For me this is more natural. I didn't understand why the functions themselves needed to wrap funcs, rather than simply be the function.

F# Parallel.ForEach invalid method overload

Creating a Parallel.ForEach expression of this form:
let low = max 1 (k-m)
let high = min (k-1) n
let rangesize = (high+1-low)/(PROCS*3)
Parallel.ForEach(Partitioner.Create(low, high+1, rangesize), (fun j ->
let i = k - j
if x.[i-1] = y.[j-1] then
a.[i] <- b.[i-1] + 1
else
a.[i] <- max c.[i] c.[i-1]
)) |> ignore
Causes me to receive the error: No overloads match for method 'ForEach'. However I am using the Parallel.ForEach<TSource> Method (Partitioner<TSource>, Action<TSource>) and it seems right to me. Am I missing something?
Edited: I am trying to obtain the same results as the code below (that does not use a Partitioner):
let low = max 1 (k-m)
let high = min (k-1) n
let rangesize = (high+1-low)/(PROCS*3)
let A = [| low .. high |]
Parallel.ForEach(A, fun (j:int) ->
let i = k - j
if x.[i-1] = y.[j-1] then
a.[i] <- b.[i-1] + 1
else
a.[i] <- max c.[i] c.[i-1]
) |> ignore
Are you sure that you have opened all necessary namespaces, all the values you are using (low, high and PROCS) are defined and that your code does not accidentally redefine some of the names that you're using (like Partitioner)?
I created a very simple F# script with this code and it seems to be working fine (I refactored the code to create a partitioner called p, but that does not affect the behavior):
open System.Threading.Tasks
open System.Collections.Concurrent
let PROCS = 10
let low, high = 0, 100
let p = Partitioner.Create(low, high+1, high+1-low/(PROCS*3))
Parallel.ForEach(p, (fun j ->
printfn "%A" j // Print the desired range (using %A as it is a tuple)
)) |> ignore
It is important that the value j is actually a pair of type int * int, so if the body uses it in a wrong way (e.g. as an int), you will get the error. In that case, you can add a type annotation to j and you would get a more useful error elsewhere:
Parallel.ForEach(p, (fun (j:int * int) ->
printfn "%d" j // Error here, because `j` is used as an int, but it is a pair!
)) |> ignore
This means that if you want to perform something for all j values in the original range, you need to write something like this:
Parallel.ForEach(p, (fun (loJ, hiJ) ->
for j in loJ .. hiJ - 1 do // Iterate over all js in this partition
printfn "%d" j // process the current j
)) |> ignore
Aside, I guess that the last argument to Partitioner.Create should actually be (high+1-low)/(PROCS*3) - you probably want to divide the total number of steps, not just the low value.

F# solution for Store Credit

I want to solve this excercise: http://code.google.com/codejam/contest/351101/dashboard#s=p0 using F#.
I am new to functional programming and F# but I like the concept and the language a lot. And I love the codejam excercise too it looks so easy but real life. Could somebody point me out a solution?
At the moment I have written this code which is just plain imperative and looks ugly from the functional perspective:
(*
C - Credit
L - Items
I - List of Integer, wher P is single integer
How does the data look like inside file
N
[...
* Money
* Items in store
...]
*)
let lines = System.IO.File.ReadAllLines("../../../../data/A-small-practice.in")
let CBounds c = c >= 5 && c <= 1000
let PBounds p = p >= 1 && p <= 1000
let entries = int(lines.[0]) - 1
let mutable index = 1 (* First index is how many entries*)
let mutable case = 1
for i = 0 to entries do
let index = (i*3) + 1
let C = int(lines.[index])
let L = int(lines.[index+1])
let I = lines.[index+2]
let items = I.Split([|' '|]) |> Array.map int
// C must be the sum of some items
// Ugly imperative way which contains duplicates
let mutable nIndex = 0
for n in items do
nIndex <- nIndex + 1
let mutable mIndex = nIndex
for m in items.[nIndex..] do
mIndex <- mIndex + 1
if n + m = C then do
printfn "Case #%A: %A %A" case nIndex mIndex
case <- case + 1
I would like to find out items which add up to C value but not in a usual imperative way - I want functional approach.
You don't specify how you would solve the problem, so it's hard to give advices.
Regarding reading inputs, you can express it as a series of transformation on Seq. High-order functions from Seq module are very handy:
let data =
"../../../../data/A-small-practice.in"
|> System.IO.File.ReadLines
|> Seq.skip 1
|> Seq.windowed 3
|> Seq.map (fun lines -> let C = int(lines.[0])
let L = int(lines.[1])
let items = lines.[2].Split([|' '|]) |> Array.map int
(C, L, items))
UPDATE:
For the rest of your example, you could use sequence expression. It is functional enough and easy to express nested computations:
let results =
seq {
for (C, _, items) in data do
for j in 1..items.Length-1 do
for i in 0..j-1 do
if items.[j] + items.[i] = C then yield (i, j)
}
Seq.iteri (fun case (i, j) -> printfn "Case #%A: %A %A" case i j) results

How to generate an array of exponential weights?

I am trying to do an "unfold" - (I think), by starting with an initial value, applying some function to it repeatedly, and then getting a sequence as a result.
In this example, I'm trying to start with 1.0, multiply it by .80, and do it 4 times, such that I end up with an array = [| 1.0; 0.80; 0.64; 0.512 |]
VS 2010 says I'm using "i" in an invalid way, and that mutable values cannot be captured by closures - so this function does not compile. Can anyone possibly suggest a clean approach that actually works? Thank you.
let expSeries seed fade n =
//take see and repeatedly multiply it by the fade factor n times...
let mutable i = 0;
let mutable weight = seed;
[| while(i < n) do
yield weight;
weight <- weight * fade |]
let testWeights = expSeries 1.0 0.80 4
let exp_series seed fade n =
Array.init (n) (fun i -> seed * fade ** (float i))
I think this recursive version should work.
let expSeries seed fade n =
let rec buildSeq i weight = seq {
if i < n then
yield weight;
yield! buildSeq (i + 1) (weight * fade)
}
buildSeq 0 seed
|> Seq.toArray
Based on the anwer to this question, you can create an unfold, and take a number of values of it:
let weighed startvalue factor =
startvalue |> Seq.unfold (fun x -> Some (x, factor * x))
let fivevalues = weighed 1.0 .8 |> Seq.take 5
If you want to explicitly use an unfold, here's how:
let expSeries seed fade n =
Seq.unfold
(fun (weight,k) ->
if k > n then None
else Some(weight,(weight*fade, k+1)))
(seed,1)
|> Array.ofSeq
let arr = expSeries 1.0 0.80 4
Note that the reason your original code won't work is that mutable bindings can't be captured by closures, and sequence, list, and array expressions implicitly use closures.

Resources