I can do it easily if I use a mutable counter and 2 for loops but I want to do it inside the Array.init function.
This is it so far, I just need to change the zeroes in array2D.[0, 0].
let array2D = Array2D.init 10 10 (fun i j -> 0)
let array = Array.init 100 (fun i -> array2D.[0, 0])
You are quite correct that you can use the combination of / and % to do this, such as:
// assume a 2d array array2d
let m = Array2D.length1 array2d
let n = Array2D.length2 array2d
let array1d = Array.init (m * n) (fun i -> array2d.[i / n, i % n]
That would be 'purely functional'. Heavy use of division, and especially modulus, however, is not likely to be especially performant. If performance is a concern, you would indeed be much better off doing something like:
// assume a 2d array array2d
let m = Array2D.length1 array2d
let n = Array2D.length2 array2d
let array1d = Array.zeroCreate (m * n)
for i = 0 to (m - 1) do
for j = 0 to (n - 1) do
array1d.[(i * n) + j)] <- array2d.[i,j]
F# is functional-first, not zealously-functional-only. It's fine to use an imperative style when performance is a major concern. That's why it's an option. Probably best to turn the above into a referentially-transparent function, such as make1darrayfrom2darray:
let make1darrayfrom2darray array2d =
let m = Array2D.length1 array2d
let n = Array2D.length2 array2d
let array1d = Array.zeroCreate (m * n)
for i = 0 to (m - 1) do
for j = 0 to (n - 1) do
array1d.[(i * n) + j] <- array2d.[i,j]
array1d
If you are doing this a heck of a lot but your arrays are not long-lived (and especially if you need large arrays), consider using the ArrayPool system. This will help your program avoid a lot of potentially expensive but unnecessary memory allocations.
I thought about it some more, and got it right. Sorry for the quick post, should have just spent a bit more time on it.
array2D.[i / 10, i % 10]
Related
This is a school assignment. I'm trying to make a function which takes an array A and makes a new array B, which is telling how many repeated numbers there are in an array. For example A is this:
A = [|2;9;9;2;2;4|]
The B would be:
B = [|3;2;2;3;3;1|]
Ny code is right now like this and working perfectly:
let A = [|2;9;9;2;2;4|]
let n = A.Length - 1
let B = Array.create A.Length 0
for i = 0 to n do
Array.iter (fun j -> if i <> j && A.[i]=j then B.[i] <- (B.[i] + 1)) A
printfn "%A" B
My question is, how much would asymptotic time be? I know the first for loop is O(n), but what about Array.iter? And is there any way to switch the first for loop with an array function?
Array.iter is linear in the array length, so your for loop is essentially O(n²) in time complexity. Replacing the loop with another Array.iter is possible but would not change the time complexity.
If you can solve the problem whichever way you want, I suggest using a Map to aggregate the numbers and their frequencies, then mapping the original array into one showing these frequencies. Since this is a school assignment, you should probably wait until after your submission deadline before you look at the following code:
let numFrequency (a : _ []) =
let m =
(Map.empty, a)
||> Array.fold (fun m n ->
Map.tryFind n m
|> Option.defaultValue 0
|> fun x -> Map.add n (x + 1) m)
Array.map (fun n -> Map.find n m) a
let A = [|2; 9; 9; 2; 2; 4|]
let B = numFrequency A
printf "%A\n%A\n" A B
I was checking Microsoft f# guide on for...in loops and was wondering how could the for in loop be randomized.
For example:
let list1 = [ 1; 5; 100; 450; 788 ]
for i in list1 do
printfn "%d" i
output:
1
5
100
450
788
If I want to have the elements to be printed in a random order using for in loop, what could I do?
We have established that, essentially, there's only the Fisher–Yates shuffle for randomizing a given collection. Easy to get wrong; here's a C# discussion of Dos and Don'ts.
The freedoms we have left in implementation: we can count upwards or downwards when performing the random swaps, and we may decide to either mutate the array in place, or create a copy of the input data.
// Mutate in place, count downwards
let shuffle arr =
let rnd = System.Random()
for i in Array.length arr - 1 .. -1 .. 1 do
let tmp, j = arr.[i], rnd.Next(0, i)
arr.[i] <- arr.[j]; arr.[j] <- tmp
let a = [|1; 5; 100; 450; 788|]
shuffle a
// Create a copy, count upwards
let copyShuffle source =
let arr = Seq.toArray source
let rnd, len = System.Random(), arr.Length
for i in 0 .. len - 2 do
let tmp, j = arr.[i], rnd.Next(i, len)
arr.[i] <- arr.[j]; arr.[j] <- tmp
arr
copyShuffle [1; 5; 100; 450; 788]
|> Array.iter (printfn "%i")
Here is an easy way to do it using the random function
let random= new Random()
let randomizeList lst =
lst
|> List.sortBy (fun (_) -> random.Next(lst.Length * 1000))
let list1 = [ 1; 5; 100; 450; 788 ]
|> randomizeList
for i in list1 do
printfn "%d" i
Please see notes on the Random number generator with regards to randomness - there are better algorithms for producing a more pure random distribution, Dotnet Core Docs -
The chosen numbers are not completely random because a mathematical algorithm is used to select them, but they are sufficiently random for practical purposes.
I wrote a function to scramble an array and map an array of arrays to scramble each one different but they are scrambled the same way
let rand = System.Random()
let shuffle (rand : System.Random)(array :int[] ) = let rng = new Random()
let mutable n = array.Length
while (n > 1) do
let k = rng.Next(n)
n <- n - 1
let temp = array.[n]
array.[n] <- array.[k]
array.[k] <- temp
array
let playsarray = shuffle rand
let scrambledarray = Array.map (fun x -> playsarray x )
let playsarra = fun (array : int[]) -> array |> playsarray
let smallarray = [1..10].ToArray()
let megaarray = Array.create 10 smallarray
let megarrayscrambled = megaarray |> scrambledarray
megarrayscrambled |> Seq.iter (fun y -> printfn "Ar: %A" y)
after running the code all the 10 arrays have the same order in the data ej
Ar: [|5; 1; 7; 2; 8; 10; 6; 3; 9; 4|]
Ar: [|5; 1; 7; 2; 8; 10; 6; 3; 9; 4|] and so on ...
There are two problems with your code.
First, your shuffle function takes a rand parameter but isn't actually using it: inside the function you create a new System.Random instance and use it instead of using the one passed in. The docs for the System.Random constructor mention (in the examples) that the default constructor uses the current time as a seed, so if two Random objects are created in quick succession, they would have the same seed and thus produce the same values. To fix this problem, you just need to stop creating a new Random instance in your shuffle function and instead use the one passed in (I renamed it from rand to rng so that the rest of your code wouldn't need changing). Here's your shuffle function with that change made (and with much easier-to-read indentation: you don't have to start the first line of the function on the same line as the = sign; you can put it on the next line and just indent one indentation level, four spaces):
let shuffle (rng : System.Random) (array : int[]) =
let mutable n = array.Length // The number of items left to shuffle (loop invariant).
while (n > 1) do
let k = rng.Next(n) // 0 <= k < n.
n <- n - 1 // n is now the last pertinent index;
let temp = array.[n] // swap array[n] with array[k] (does nothing if k == n).
array.[n] <- array.[k]
array.[k] <- temp
array
BUT that won't solve your issues just yet, because you've also misunderstood how Array.create works. It creates an array of a given size, where each item in the array contains the value you passed in. I.e., every entry in your megarrayscrambled array contains a reference to the same smallarray. If you did megarrayscrambled.[0].[0] <- 999 you'd see that this changed every one of the ten entries in megarrayscrambled, because they're the same array.
What you actually wanted was to use Array.init, not Array.create. Array.init takes a function and runs that function once per item it's creating in the array you're building. This means that if that function returns [1..10].ToArray(), then each time it's called it will return a different array, and you'll therefore get the results you expect. (By the way, you can create an array more simply by doing [|1..10|], and that's what I'll use in the sample code below).
So just change your let megaarray line to:
let megaarray = Array.init 10 (fun _ -> [|1..10|])
and then you should see the results you were expecting.
BTW, one more little detail: in one line you have Array.map (fun x -> playsarray x), but that is just equivalent to Array.map playsarray, which is a little simpler to read.
Coming of a C# background and trying to learn F#.
I'm trying to iterate over an array of size 256, so the total sum of it be the product of the element position and the element, like this:
float sum = 0.0;
for (int i = 0; i < 256; i++) {
sum += i * arr[i];
}
I made this but I don't know if this is the best way to do it in F#, probably not.
let mutable sum = 0
for i in 0 .. 255 do
sum <- sum + i * arr.[i]
done
I don't know if it's possible to use Array.fold or Array.iteri to solve this in a better way.
You can use mapi and sum:
let f s = s |> Seq.mapi (fun i j -> i * j) |> Seq.sum
One way of doing this with only one iteration through the array:
let f s = snd (Array.fold (fun (i, sum) x -> (i + 1, sum + x * float i)) (0, 0.0) s)
Although I prefer Lee's solution as being much easier to follow.
An alternative would be to write your own Array.foldi function and use that.
I have Scala code like this
var i = 1
for(e <- array) {
acc += e * i
i += 1
}
I need to multiply the first element in the array by 1, the next by 2, the next by 3 and so on adding it all into an accumulator. I feel that there is a better way of doing this in Scala, maybe even with folding?
"Better" depends on what your goals are. Short and clear? Probably
{ for (i <- array.indices; e = array(i)) yield (i+1)*e }.sum
or
array.indices.map(i => (i+1)*array(i)).sum
(or slightly faster, since you create the intermediates as you go:
array.indices.iterator.map(i => (i+1)*array(i)).sum
).
You should usually be short and clear.
Fast? Then you'll need to go old-school:
var i = 0
var acc = 0
while (i < array.length) {
acc += (i+1)*array(i)
i += 1
}
or use recursion
def sum(a: Array[Int], i: Int = 0, acc: Int = 0): Int =
if (i >= a.length) acc else sum(a, i+1, (i+1)*a(i) + acc)
sum(array)
I prefer zipWithIndex which is simpler to read:
array.zipWithIndex.map { case (e, i) => e * (i + 1) }.sum
val x = List(1,1,1,1,1,1)
(((0,1) /: x){case ((acc, mult), l) => (acc + (l * mult), mult + 1) })._1
In other words, starting with an accumulator of 0 and a multiplier of 1, fold each element of the list in, changing the accumulator to acc + (l * mult) and incrementing the multiplier by 1. We get the final multiplier out at the end as well, so we call ._1 to just get the accumulator.
Edit: As #RexKerr points in his answer below (and the comment), if performance is a major concern then you're better off using an explicit recursive method.
I am not sure if what I suggest is a better way to do it or not, as it is more functional (== it will perform slower):
(0 /: (array zipWithIndex)) {(a, i) => (i._1 * (i._2 + 1)) + a}
This does perform foldLeft on an array which is produced by zipWithIndex method in http://www.scala-lang.org/api/current/index.html#scala.Array
zipWithIndex simply zips the elements of a collection with their indices.