Exit / stop Array2D.initBased early - arrays

How is it possible to exit early / break out of / stop an array creation in F# (in this case, of Array2D.initBased)?
Remark: dic is a Dictionary<,>() whose value is an object that has a method named someMethod that takes two int parameters.
let arr = Array2D.initBased 1 1 width height (fun x y ->
let distinctValues = dic |> Seq.map (fun (KeyValue(k,v)) -> v.someMethod x y) |> Set.ofSeq
match distinctValues.count with
| dic.Count ->
// do something
// exit array creation here, because I do not need arr any more if v.someMethod x y produced distinct values for each dic value
| _ ->
// do something else

This is a tricky question - I don't think there is any function that lets you do this easily. I think the best option is probably to define your own higher-order function (implemented using not very elegant recursion) that hides the behavior.
The idea would be to define tryInitBased that behaves as initBased but the user-provided function can return option (to indicate failure) and the function returns option (either successfully created array or None):
/// Attempts to initialize a 2D array using the specified base offsets and lengths.
/// The provided function can return 'None' to indicate a failure - if the initializer
/// fails for any of the location inside the array, the construction is stopped and
/// the function returns 'None'.
let tryInitBased base1 base2 length1 length2 f =
let arr = Array2D.createBased base1 base2 length1 length2 (Unchecked.defaultof<_>)
/// Recursive function that fills a specified 'x' line
/// (returns false as soon as any call to 'f' fails, or true)
let rec fillY x y =
if y < (base2+length2) then
match f x y with
| Some v ->
arr.[x, y] <- v
fillY x (y + 1)
| _ -> false
else true
/// Recursive function that iterates over all 'x' positions
/// and calls 'fillY' to fill individual lines
let rec fillX x =
if x < (base1+length1) then
if fillY x base2 then fillX (x + 1)
else false
else true
if fillX base1 then Some arr else None
Then you can keep your code pretty much the same, but replace initBased with tryInitBased and return None or Some(res) from the lambda function.
I also posted the function to F# snippets with a nicer formatting.

Related

Shifting arrays in F#

So I have a function which shifts some ternary values in an array by the desired amount, but when I shift any array, (b) value(s) (on the right if shifting left, and the left if shifting right) will always be replaced with null. Here's my code:
let ( <<| ) (a:FalseTrit[]) (b:int) =
array.Copy(a, b, a, 0, a.Length - 1)
array.Clear(a, a.Length - b, b)
let ( |>> ) (a:FalseTrit[]) (b:int) =
array.Copy(a, 0, a, b, a.Length - b)
array.Clear(a, 0, b)
I couldn't find any answers on the internet. Is there a better way to do this, or something I did wrong? Thanks in advance.
Array.Clear sets a range of elements in an array to the default value of each element type (see docs).
Since FalseTrit is a reference type and not a value type, it has default value null.
Expanding on the comment by Alexey Romanov why you should prefer standard library functions from Microsoft.FSharp.Collections.Array module over instance members of System.Array: Type inference makes them easier to use and curried arguments prettier.
While the documentation for Array.blit misses the assurance of System.Array.Copy in regard of arrays overlapping, I strongly suspect the same applies because of its underlying implementation:
If sourceArray and destinationArray overlap, this method behaves as if
the original values of sourceArray were preserved in a temporary
location before destinationArray is overwritten.
let (<<|) a b =
Array.blit a b a 0 (Array.length a - b)
Array.fill a (Array.length a - b) b Unchecked.defaultof<_>
// val ( <<| ) : a:'a [] -> b:int -> unit
let (|>>) a b =
Array.blit a 0 a b (Array.length a - b)
Array.fill a 0 b Unchecked.defaultof<_>
// val ( |>> ) : a:'a [] -> b:int -> unit
Here, the behavior of the original code is kept: Unchecked.defaultof will return null for reference types.
On a stylistic note, consider replacing the code by a generator expression returning a fresh array, because mutation is not seen as functional best practice, and neither are custom operators returning unit.
let (<<|) a b = [|
for i in b..Array.length a - 1 + b ->
if i < Array.length a then a.[i]
else Unchecked.defaultof<_> |]
// val ( <<| ) : a:'a [] -> b:int -> 'a []
let (|>>) a b = [|
for i in -b..Array.length a - 1 - b ->
if i < 0 then Unchecked.defaultof<_>
else a.[i] |]
// val ( |>> ) : a:'a [] -> b:int -> 'a []

If I convert a sequence to an array and treat it as a sequence, do I get O(1) on length?

I was wondering whether I would get special treatment when a sequence is converted to an array and then henceforth treated as a sequence again.
let sq = seq { for i in 0 .. 10 do yield i }
let arr = Seq.toArray sq
let len = Array.length arr // O(1)
let sq2 = arr |> Seq.ofArray
// from converted seq
let len2 = Seq.length sq2 // O(n)???
// or direct:
let len2 = Seq.length arr // O(n)???
On the same token, is F# smart enough with Seq.toArray arr to simply create a copy of the array, to leave it alone (not create a copy), or would it iterate over each item using the enumerator?
Put in another way, do sequence in F# remember somehow that their internal structure is an array?
I am asking this since on expensive sequences, you may need the length multiple times, and evaluating it once would be beneficial. I can either create a specific sequence type that remembers the length, or I could use the magic that's already there.
If the sequence is actually an array type then it will simply be cast back to an array to determine the array within Seq.length. You can see this in in the implementation of the length function here:
[<CompiledName("Length")>]
let length (source : seq<'T>) =
checkNonNull "source" source
match source with
| :? ('T[]) as a -> a.Length
| :? ('T list) as a -> a.Length
| :? ICollection<'T> as a -> a.Count
| _ ->
use e = source.GetEnumerator()
let mutable state = 0
while e.MoveNext() do
state <- state + 1;
state
You can see this behaviour if you put it in FSI:
let arr = [|1..40000000|];;
Using Array.length:
Array.length arr;;
Real: 00:00:00.000, CPU: 00:00:00.015, GC gen0: 0, gen1: 0, gen2: 0
val it : int = 40000000
Using Seq.length:
Seq.length arr;;
Real: 00:00:00.000, CPU: 00:00:00.000, GC gen0: 0, gen1: 0, gen2: 0
val it : int = 40000000
If you use Seq.ofArray you are specifically hiding the underlying type information, creating a new enumerator that steps through the array element by element.
This can be a useful behaviour because it prevents a consumer of your API from sneakily casting seq<'T> back to 'T[] and consequently allowing said consumer to mutate something that you, the API designer, expected to be exposing an immutable view of.
The downside of this information hiding is that you can't cast back to array so the enumeration becomes significantly slower:
Seq.length <| Seq.ofArray arr;;
Real: 00:00:00.148, CPU: 00:00:00.140, GC gen0: 0, gen1: 0, gen2: 0
val it : int = 40000000
Seq.ofArray uses the mkSeq function which just creates an anonymous IEnumerable from an ArrayEnumerator:
let mkSeq f =
{ new IEnumerable<'U> with
member x.GetEnumerator() = f()
interface IEnumerable with
member x.GetEnumerator() = (f() :> IEnumerator) }
Seq.ofArray returns an ArrayEnumerator which only implements IEnumerator<T> so calling Seq.length on it will require enumerating the entire sequence to get the length.
Calling Seq.length on an array directly will use the underlying Length property since it does a dynamic type check for array types, list and instances of ICollection<T>.

Taking two elements from an array and adding them, then adding them back into the array

Im trying to create a calculator in f# using two arrays, one which stores the numbers and the other to store the operator symbols. I need the symbols array to pattern match the symbol and depending on the operator take the first two elements from the array and do the operation and add the new number into the head of the 2nd array.
open System
[<EntryPoint>]
let main argv =
printfn "%A" argv
let Add x y = x + y
let Sub x y = x - y
let Div x y = x * y
let Mul x y = x / y
printfn "1 > Calculator \n2 > Load from txt file"
let chosenIn = Console.ReadLine();
//This is where I need to do the operation and after call the sum function
//again until there's only one element left in the number array
let rec sum num (numArray : int[]) sym (symArray : string[]) () =
let rec calc () =
printfn "Enter Sum"
let input = Console.ReadLine()
let intInput = input.Split()
let numArray = [|for num in intInput do
let v , vp = System.Int32.TryParse(num)
if v then yield vp|]
let symbolArray = [|for symbol in intInput do
match symbol with
| "+" -> yield symbol
| "-" -> yield symbol
| "/" -> yield symbol
| "*" -> yield symbol
| _ -> ignore 0|]
calc()
match chosenIn with
| "1" -> calc()
| "2" -> printfn "File"
| _ -> printfn "Invalid"
0 // return an integer exit code
In response to the answer #Liam Donnelly posted to his own question: I'll leave aside questions like "is that really the best way of solving the problem", just commenting on how to better write the code you currently have.
Array slicing and concatenating the way you are doing it here can be written as
let newNumArray = Array.append [| result |] numArray.[2..]
However, I would use F# lists rather than arrays for your task. With lists, you can do pattern matching to access the first 2 elements. Pattern matching, in my view, wins over direct indexing because you can directly encode corner cases, and get the F# compiler to remind you of corner cases. Do the same thing for the operators. You can do both operators and operands in the same go. It will then look something like this:
let rec sum2 (numArray : int list) (symArray : string list) =
let newNum, newSym =
match numArray with
| [] -> failwith "No numbers left to process"
| arg1 :: [] -> failwith "There's only one number left to process"
| arg1 :: arg2 :: args ->
match symArray with
| op1 :: ops ->
let result =
match op1 with
| "+" -> Add arg1 arg2
| "-" -> Sub arg1 arg2
| "*" -> Mul arg1 arg2
| _ -> failwithf "Operator not recognized: '%s'" op1
// Return the result, concatenate the non-processed
// numbers. Return the non-processed operators
result :: args, ops
| _ -> failwith "I've run out of operators?"
<snip>
Also, returning a "default result" if you don't recognize the operators is something that I consider very risky (even though the practice is rather widespread)
If you use lists (F# lists, that is), you can directly access the elements at indices 1.. via head: let newSymArray = symArray.Head or use List.head
Take a step back each time you see yourself writing a for loop in F#. They are cumbersome to write and error-prone. Most of the typical use-cases for loops are covered by F# library functions, so have a good read through those. Your printing loop can be written way shorter by doing:
newNumArray
|> Seq.iter (printfn "%i")
I've managed to make the function which performs the task I needed for it to do and I'm sure there's a much more code efficient way of taking the first elements of the arrays by using Array.copy with filters but I'm new to f# so I just it the way I was confident with
let rec sum (numArray : int[]) (symArray : string[]) =
let result = match symArray.[0] with
| "+" -> Add numArray.[0] numArray.[1]
| "-" -> Sub numArray.[0] numArray.[1]
| "*" -> Mul numArray.[0] numArray.[1]
| _ -> 0
let newNumArray = [|
for i = 0 to numArray.Length - 1 do
if i = 0 then yield result
if i > 1 then yield numArray.[i]|]
let newSymArray = [|
for i = 0 to symArray.Length - 1 do
if i > 0 then yield symArray.[i]|]
if newNumArray.Length > 1 then
sum newNumArray newSymArray
else
for i = 0 to newNumArray.Length - 1 do
printfn "%i" (newNumArray.[i])

F# memoization efficiency - near 1 million elements

I'm working on an f# solution to this problem where I need to find the generator element above 1,000,000 with the longest generated sequence
I use a tail-recursive function that memoizes the previous results to speed up the calculation. This is my current implementation.
let memoize f =
let cache = new Dictionary<_,_>(1000000)
(fun x ->
match cache.TryGetValue x with
| true, v ->
v
| _ -> let v = f x
cache.Add(x, v)
v)
let rec memSequence =
memoize (fun generator s ->
if generator = 1 then s + 1
else
let state = s+1
if even generator then memSequence(generator/2) state
else memSequence(3*generator + 1) state )
let problem14 =
Array.init 999999 (fun idx -> (idx+1, (memSequence (idx+1) 0))) |> Array.maxBy snd |> fst
It seems to work well until want to calculate the lengths of the sequences generated by the first 100,000 numbers but it slows down significantly over that. In fact, for 120,000 it doesn't seem to terminate. I had a feeling that it might be due to the Dictionary I use, but I read that this shouldn't be the case. Could you point out why this may be potentially inefficient?
You're on the right track, but there's one thing very wrong in how you implement your memoization.
Your memoize function takes a function of one argument and returns a memoized version of it. When you use it in memSequence however, you give it a curried, two argument function. What then happens is that the memoize takes the function and saves down the result of partially applying it for the first argument only, i.e. it stores the closure resulting from applying the function to generator, and than proceeds to call those closures on s.
This means that your memoization effectively doesn't do anything - add some print statements in your memoize function and you'll see that you're still doing full recursion.
I think the underlying question may have been How to combine a memoizing function with a potentially costly calculating function that takes more than one argument?.
In this case, that second argument isn't needed. There's nothing inherently wrong with memoizing 2168612 elements (the size of the dictionary after the calculation).
Beware of overflow, since at 113383 the sequence surpasses System.Int32.MaxValue. A solution might thus look like this:
let memoRec f =
let d = new System.Collections.Generic.Dictionary<_,_>()
let rec g x =
match d.TryGetValue x with
| true, res -> res
| _ -> let res = f g x in d.Add(x, res); res
g
let collatzLong =
memoRec (fun f n ->
if n <= 1L then 0
else 1 + f (if n % 2L = 0L then n / 2L else n * 3L + 1L) )
{0L .. 999999L}
|> Seq.map (fun i -> i, collatzLong i)
|> Seq.maxBy snd
|> fst

How to calculate the "sliding sliced" fold of an array of int arrays in F#?

I have a function called calcArr_ArrOfArr in F# with the signature int [] -> int [][] -> int, i.e. calcArr_ArrOfArr takes two arguments, an int array and an array of int arrays, and returns an int.
I want to create the function calcArrOfArr with the signature int [][] -> int, which does the following:
let calcArrOfArr (arrOfArr : int [][]) =
Array.fold (fun acc e -> acc + (calcArr_ArrOfArr e arrOfArr.[?..])) 0 arrOfArr
where ? would be the index of e + 1.
In other words, in calcArrOfArr I want to apply calcArr_ArrOfArr to every element e of arrOfArr plus the "remaining portion" of arrOfArr, i.e. the slice of arrOfArr starting from after element e. Of course, for the last element of arrOfArr, nothing would be added to the accumulator, nor would an exception be thrown.
Is there a way to create calcArrOfArr in a functional way? An Array.foldi function would come handy...
If you feel you need Array.foldi, write one! The following snippet will extend the built-in Array module with a foldi:
module Array =
let foldi f z a =
a |> Array.fold (fun (i,a) x -> i+1, f i a x) (0,z) |> snd
Slicing from past-the-end gives you the empty array (i.e., [|0;1|].[2..] = [||]), so now your original suggestion works:
let calcArrOfArr (arrOfArr : int [][]) =
Array.foldi (fun i acc e -> acc + (calcArr_ArrOfArr e arrOfArr.[i+1..])) 0 arrOfArr
However, the slice arrOfArr.[i+1..] copies the array slice; this might be unfortunate for efficiency.
Haven't tested it, but this seems about right:
let calcArrOfArr (arrOfArr : int [][]) =
arrOfArr
|> Seq.mapi (fun i x -> i, x)
|> Seq.fold (fun acc (i, e) -> acc + (calcArr_ArrOfArr e arrOfArr.[i+1..])) 0

Resources