Array.create and jagged array - arrays

Can't understand the reason of such behavior:
let example count =
let arr = Array.create 2 (Array.zeroCreate count)
for i in [0..count - 1] do
arr.[0].[i] <- 1
arr.[1].[i] <- 2
arr
example 2 |> Array.iter(printfn "%A")
Print:
[|2; 2|]
[|2; 2|]
https://dotnetfiddle.net/borMmO
If I replace:
let arr = Array.create 2 (Array.zeroCreate count)
to:
let arr = Array.init 2 (fun _ -> Array.zeroCreate count)
Everything will work as expected:
let example count =
let arr = Array.init 2 (fun _ -> Array.zeroCreate count)
for i in [0..count - 1] do
arr.[0].[i] <- 1
arr.[1].[i] <- 2
arr
example 2 |> Array.iter(printfn "%A")
Print:
[|1; 1|]
[|2; 2|]
https://dotnetfiddle.net/uXmlbn
I think the reason is the fact that the array - a reference type. But I want to understand why this is happening. Since I didn't expect such results.

When you write:
let arr = Array.create 2 (Array.zeroCreate count)
You are creating an array where each element is a reference to the same array. This means that mutating a value using arr.[0] also mutates the value in arr.[1] - because the two array elements are pointing to the same mutable array. You end up with:
[| x ; x |]
\ /
[| 0; 0 |]
When you write:
let arr = Array.init 2 (fun _ -> Array.zeroCreate count)
The provided function is called for each position in the arr array and so you'll end up with different array for each element (and so arr.[0] <> arr.[1]). You end up with:
[| x ; y |]
/ \
[| 0; 0 |] [| 0; 0 |]

Related

Creating an array with a function using index and array?

I am wanting to create an array of the Fibonacci numbers using haskell, but using a this more efficient algorithm
F(2K) = F(K)[2F(K-1)-F(K)]
F(2K+1) = F(K+1)^2 + F(K)^2
I know the function works and I can pass through the index or the array but not both and I can't figure out why
fastFibo :: Array Int Int -> Int -> Int
fastFibo a 0 = 0
fastFibo a 1 = 1
fastFibo a 2 = 1
fastFibo a x = do
if ((mod x 2) == 0)
then do
let y = div x 2
(a!y) * (2 * (a!(y+1)) - (a!y))
else do
let y = div (x-1) 2
(a!y)^2 + (a!(y+1))^2
fibos n = a where a = array (0,n) ([(0, 0), (1, 1), (2,1)] ++ [(i, fastFibo(a i)) | i <- [2..n]])
The error I get is
• Couldn't match expected type ‘i1 -> Array Int Int’
with actual type ‘Array i1 (Int -> Int)’
• Possible cause: ‘array’ is applied to too many arguments
In the expression:
array
(0, n)
([(0, 0), (1, 1), (2, 1)] ++ [(i, fastFibo (a i)) | i <- [2 .. n]])
In an equation for ‘a’:
a = array
(0, n)
([(0, 0), (1, 1), (2, 1)] ++ [(i, fastFibo (a i)) | i <- [2 .. n]])
In an equation for ‘fibos’:
fibos n
= a
where
a = array
(0, n) ([(0, 0), ....] ++ [(i, fastFibo (a i)) | i <- [2 .. n]])
• Relevant bindings include
a :: i1 -> Array Int Int
(bound at /mnt/data/Documents/Programming/Haskell/Arrays/Arrays.hs:20:19)
|
20 | fibos n = a where a = array (0,n) ([(0, 0), (1, 1), (2,1)] ++ [(i, fastFibo(a i)) | i <- [2..n]])
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Using a less fast algorithm that still operates on an array, you could do:
import Data.Array
fib :: Int -> Int
fib n = arr ! n
where
arr :: Array Int Int
arr = listArray (1, n) $
0 : 1 : [ (arr ! (i-1)) + (arr ! (i-2)) | i <- [3..n] ]
If you were to transform this to use your faster algorithm, it'd be something like:
import Data.Array
fib :: Int -> Int
fib n = arr ! n
where
arr :: Array Int Int
arr = listArray (1, n) $
0 : 1 : 1 : map fib' [4..n]
fib' :: Int -> Int
fib' k
| even k = ...
| otherwise = ...
I figured listArray was sufficient here. It's pretty close to array which you use.
See the documentation on array construction for the difference.

How divide the mutable array into mutable subarrays

I need to divide the mutablearray into 3 mutablesubarrays with mutable elements.
#[derive(Debug)]
struct Server {
time: i64
}
impl Server {
fn new(x: i64) -> Server {
return Server {
time: x
}
}
}
fn main() {
let mut arr = Vec::<Server>::new();
arr.push(Server::new(10));
arr.push(Server::new(20));
arr.push(Server::new(30));
arr.push(Server::new(40));
arr.push(Server::new(50));
let mut arr1 = arr.iter_mut().filter(|x| x.time > 20).collect::<Vec<&mut Server>>();
let mut arr2 = arr.iter_mut().filter(|x| x.time < 20).collect::<Vec<&mut Server>>();
let mut arr3 = arr.iter_mut().filter(|x| x.time == 20).collect::<Vec<&mut Server>>();
}
Next, over each subarray to carry out different manipulations that do not affect the main array. (For example, each subarray is first sorted without affecting the order of the main array. The next step is to manipulate its elements over each subarray. And these changes should be reflected in the elements of the main array).
At the moment, when dividing the array Rust when compiling, it gives the following error:
error[E0499]: cannot borrow `arr` as mutable more than once at a time
--> src/main.rs:26:18
|
25 | let mut arr1 = arr.iter_mut().filter(|x| x.time > 20).collect::<Vec<&mut Server>>();
| --- first mutable borrow occurs here
26 | let mut arr2 = arr.iter_mut().filter(|x| x.time < 20).collect::<Vec<&mut Server>>();
| ^^^ second mutable borrow occurs here
...
29 | }
| - first borrow ends here
error[E0499]: cannot borrow `arr` as mutable more than once at a time
--> src/main.rs:27:18
|
25 | let mut arr1 = arr.iter_mut().filter(|x| x.time > 20).collect::<Vec<&mut Server>>();
| --- first mutable borrow occurs here
26 | let mut arr2 = arr.iter_mut().filter(|x| x.time < 20).collect::<Vec<&mut Server>>();
27 | let mut arr3 = arr.iter_mut().filter(|x| x.time == 20).collect::<Vec<&mut Server>>();
| ^^^ second mutable borrow occurs here
28 |
29 | }
| - first borrow ends here
You can use Iterator::partition to split up your vec into two distinct vecs without cloning the inner elements.
Because you want three different splits, you have to use partition twice (the order doesn't matter).
const THRESHOLD: i64 = 20;
let mut arr = Vec::<Server>::new();
arr.push(Server::new(10));
arr.push(Server::new(20));
arr.push(Server::new(30));
arr.push(Server::new(40));
arr.push(Server::new(50));
let (greater, rest): (Vec<_>, Vec<_>) = arr.into_iter().partition(|s| s.time > THRESHOLD);
let (equal, less): (Vec<_>, Vec<_>) = rest.into_iter().partition(|s| s.time == THRESHOLD);
(playground)
Because the Vectors greater, equal and less own the corresponding elements, you have mutable access to them.

Game of Life Ocaml with Matrix

I have generated a matrix for my Game of Life, and I'm trying to make it so that it loops through and continuously prints out the next generation, I am using a code I found online, and it doesn't seem to work. Here is my code
let generation = ref 1
let get g x y =
try g.(x).(y)
with _ -> 0
;;
let neighbourhood g x y =
(get g (x-1) (y-1)) +
(get g (x-1) (y )) +
(get g (x-1) (y+1)) +
(get g (x ) (y-1)) +
(get g (x ) (y+1)) +
(get g (x+1) (y-1)) +
(get g (x+1) (y )) +
(get g (x+1) (y+1))
let next_cell g x y =
let n = neighbourhood g x y in
match g.(x).(y), n with
| 1, 0 | 1, 1 -> 0 (* lonely *)
| 1, 4 | 1, 5 | 1, 6 | 1, 7 | 1, 8 -> 0 (* overcrowded *)
| 1, 2 | 1, 3 -> 1 (* lives *)
| 0, 3 -> 1 (* get birth *)
| _ -> 0
let copy g = Array.map Array.copy g
let rec next g =
let width = Array.length g
and height = Array.length g.(0)
and new_g = copy g in
for x = 0 to pred width do
for y = 0 to pred height do
new_g.(x).(y) <- (next_cell g x y)
done
done;
next new_g
let print g =
let width = Array.length g
and height = Array.length g.(0) in
for x = 0 to pred width do
for y = 0 to pred height do
if g.(x).(y) = 0
then print_char '.'
else print_char 'o'
done;
print_newline()
done
;;
print_string "Width ";
let num = read_int () in
print_string "Height";
let num2 = read_int () in
while !generation < 100 do
let myArray = Array.init num (fun _ -> Array.init num2 (fun _ -> Random.int 2)) in
print_string "Generation: "; print_int !generation; print_string "\n";
print (next myArray);
generation := !generation +1;
print_newline();
done;;
It only prints out the initial one and the generation after that rather than a new one. Since the parameters is the original array, however, when I put print (next new_g) it gives me an unbound value, is there a way I can continuously print out the subsequent generations?Shouldn't it overwrite the existing new_g when I do that?
Looking just at the main while loop, it allocates and initializes a random array each time around the loop. It doesn't seem like this could be right.
I also don't see how the function next could work, as it never returns. Its last action is to call itself again, unconditionally.
Update
If you change the last line of next to this:
new_g
it returns the next generation each time you call it.
Here's a way to drive the code in a functional (rather than imperative) style:
let rec generation n array =
if n < 100 then
begin
(* Print the array *);
generation (n + 1) (next array)
end
The outermost code might look like this:
let myArray =
Array.init num
(fun _ -> Array.init num2 (fun _ -> Random.int 2))
in
generation 0 myArray

Returning arrays of different dimensions from one function; is it possible in F#?

I am trying to convert some Python to F#, specifically numpy.random.randn.
The function takes a variable number of int arguments and returns arrays of different dimensions based on the number of arguments.
I believe that this is not possible because one cannot have a function that returns different types (int[], int[][], int[][][], etc.) unless they are part of a discriminated union, but want to be sure before committing to a workaround.
The sanity check:
member self.differntarrays ([<ParamArray>] dimensions: Object[]) =
match dimensions with
| [| dim1 |] ->
[|
1
|]
| [| dim1; dim2 |] ->
[|
[| 2 |],
[| 3 |]
|]
| _ -> failwith "error"
causes error:
This expression was expected to have type
int
but here has type
'a * 'b
with the expression being : [| 2 |], [| 3 |]
and the int referring to the 1 in [| 1 |]
i.e. the type of 1 is not the same as the type of [| 2 |], [| 3 |]
TLDR;
numpy.random.randn
numpy.random.randn(d0, d1, ..., dn)
Return a sample (or samples) from the “standard normal” distribution.
If positive, int_like or int-convertible arguments are provided, randn
generates an array of shape (d0, d1, ..., dn), filled with random
floats sampled from a univariate “normal” (Gaussian) distribution of
mean 0 and variance 1 (if any of the d_i are floats, they are first
converted to integers by truncation). A single float randomly sampled
from the distribution is returned if no argument is provided.
Examples from interactive python session:
np.random.randn(1) - array([-0.28613356])
np.random.randn(2) - array([-1.7390449 , 1.03585894])
np.random.randn(1,1)- array([[ 0.04090027]])
np.random.randn(2,3)- array([[-0.16891324, 1.05519898, 0.91673992],
[ 0.86297031, 0.68029926, -1.0323683 ]])
The code is for Neural Networks and Deep Learning and since the values need to mutable for performance reasons, using immutable list is not an option.
You are correct - an array of floats float[] is a different type than array of arrays of floats
float[][] or 2D array of floats float[,] and so you cannot write a function that returns one or the other depending on the input argument.
If you wanted to do something like the Python's rand, you could write an overloaded method:
type Random() =
static let rnd = System.Random()
static member Rand(n) = [| for i in 1 .. n -> rnd.NextDouble() |]
static member Rand(n1, n2) = [| for i in 1 .. n1 -> Random.Rand(n2) |]
static member Rand(n1, n2, n3) = [| for i in 1 .. n1 -> Random.Rand(n2, n3) |]
Although Tomas' suggestion to use overloading is probably best, .NET arrays do share a common sub-type: System.Array. So what you want is possible.
member self.differntarrays ([<ParamArray>] dimensions: Object[]) : Array =
match dimensions with
| [| dim1 |] ->
[|
1
|] :> _
| [| dim1; dim2 |] ->
[|
[| 2 |],
[| 3 |]
|] :> _
| _ -> failwith "error"

F# Manhatten distances between 2 Array2D

so I have 2 boards for example
let startingBoard = [|[|1; 4; 7|];
[|6; 3; 5|];
[|0; 8; 2|]|]
let goal = [|[|1; 2; 3|];
[|4; 5; 6|];
[|7; 8; 0|]|]
and want to find the sum of all the Manhattan distances of like elements between the 2 arrays ( for example the Manhattan distance for the 4 tile would be 2 one move down, one move left) all I have so far is the code below which finds the Manhattan distance for indexes its given.
let totalManhattenDistance board goal =
let manhattenDistance (x1, y1) (x2, y2) =
abs(x1 - x2) + abs(y1 - y2)
// solution here
the problem is I cant imagine doing this without for loops, but that seems unidiomatic.
Here's one version
let totalManhattanDistance board goal =
let manhattanDistance ((x1, y1), (x2, y2)) = abs(x1 - x2) + abs(y1 - y2)
let indexed xs = xs |> Seq.mapi (fun i -> Seq.mapi (fun j x -> (i, j), x))
|> Seq.concat
|> Seq.sortBy snd
|> Seq.map fst
Seq.zip (indexed board) (indexed goal)
|> Seq.map manhattanDistance
|> Seq.sum
The three Seq operations in the end could be done with just one Array.fold2 but I don't know if this makes the code any clearer
let totalManhattanDistance board goal =
let manhattanDistance (x1, y1) (x2, y2) = abs(x1 - x2) + abs(y1 - y2)
let indexed xs = xs |> Array.mapi (fun i -> Array.mapi (fun j x -> (i, j), x))
|> Array.concat
|> Array.sortBy snd
|> Array.map fst
let folder = fun acc n m -> acc + manhattanDistance n m
Array.fold2 folder 0 (indexed board) (indexed goal)
Using 2D Arrays the problems seams to be more natural:
let startingBoard = array2D [|[|1; 4; 7|];
[|6; 3; 5|];
[|0; 8; 2|]|]
let goal = array2D [|[|1; 2; 3|];
[|4; 5; 6|];
[|7; 8; 0|]|]
Unfortunately there is no findIndex2D function (like Array.findIndex). You have to define it yourself:
let findIndex2D (p:'A -> bool) (a:'A [,]) =
a |> Array2D.mapi (fun x y v -> x,y,v)
|> Seq.cast<int*int*'A>
|> Seq.pick (fun (x,y,v) -> if p v then Some (x,y) else None)
Straightforward definition of manhatten distance:
let manhattanDistance (x1, y1) (x2, y2) = abs(x1 - x2) + abs (y1 - y2)
And the sum of all manhatten distances:
let totalManhattanDistance board goal =
board |> Array2D.mapi (fun x y v -> manhattanDistance (x, y)
<| findIndex2D ((=) v) goal)
|> Seq.cast<int> // flatten
|> Seq.reduce (+)
Another version:
let newpos (start : int[][]) (finish:int[][]) (i, j) =
let rw =
finish |> Array.fold (fun (found, y, x) row ->
if found then (found, y, x)
else
match row |> Array.tryFindIndex ((=) start.[i].[j]) with
| Some nX -> (true, y, nX)
| None -> (false, y+1, x)
) (false, 0, 0)
match rw with
| (true, x, y) -> (x, y)
| _ -> failwith "Not found"
let totalManhattenDistance board goal =
let manhattenDistance (x1, y1) (x2, y2) = abs(x1 - x2) + abs(y1 - y2)
board |> Array.mapi (fun i arr ->
arr |> Array.mapi (fun j v ->
let (i1, j1) = newpos board goal (i, j)
manhattenDistance (i, j) (i1, j1)
)
)
totalManhattenDistance startingBoard goal
Answer is
val it : int [] [] =
[|[|0; 2; 4|];
[|2; 2; 1|];
[|2; 0; 3|]|]
Here's a F# idiomatic (I hope) version, not too dissimilar to mikkoma's:
let flatten a2D =
a2D |> Array.mapi (fun i1 a1D -> a1D
|> Array.mapi (fun i2 el -> (el, (i1, i2)) ))
|> Array.concat |> Array.sortBy fst
let manhattan b1 b2 =
flatten b1
|> Array.zip (flatten b2)
|> Array.sumBy (fun ((_, (i1, j1)), (_, (i2, j2))) -> abs(i2-i1) + abs(j2-j1))
flatten transforms the 2D array into a 1D array where each element is put next to its coordinates on the board.
manhattan then simply zips the 2 1D arrays together and sums up the coordinate offset.

Resources