Change the entries in an array in Haskell - arrays

Suppose you have
let a = array ((1,1),(2,2)) [((2,1),3),((1,2),2),((1,1),2),((2,2),3)]
Now I want that to multiply the 3 in the last tuple with some number. How can I do that?

If you wanted to multiply that by 5 it would be:
accum (*) a [((2,2),5)]
-- ^ ^ ^ ^
-- function to combine values
-- array to read
-- one of the indices to manipulated
-- value to give to f for the associated index
The signature of this function reads
accum :: Ix i => (e -> a -> e) -> Array i e -> [(i, a)] -> Array i e
and its documentation says:
accum f takes an array and an association list and accumulates pairs
from the list into the array with the accumulating function f.
So calling accum f arrayValue listWithPairsOfIndicesAndValues will call f for every index given in listWithPairsOfIndicesAndValues providing the old value and the value from listWithPairsOfIndicesAndValues for this index and return a new array with all the positions mentioned in listWithPairsOfIndicesAndValues updated with the values returned by the respective calls to f.

There's two different ways to your goal:
Using the incremental update:
a // [((2,2),(3*7))]
>>> array ((1,1),(2,2)) [((1,1),2),((1,2),2),((2,1),3),((2,2),21)]
(Instead of 3*7, you could use your own n and refer to that same location (a!(2,2)))
Using the accumulation:
accum (*) a [((2,2), 7)]
>>> array ((1,1),(2,2)) [((1,1),2),((1,2),2),((2,1),3),((2,2),21)]

One could use a // [(2,2), n * (a ! (2,2))] to multiply the element with index (2,2) by n.
(There should also be some lens-y approach with a better syntax)

Related

Array manipulations in Ocaml

I am trying to do all combinations of an Array in Ocaml.
I am trying to do a recursive function that recives an array and its initial state need to be let a = [|0;0;0|] and i need to change it recursivly like in the first iteration needs to be a = [|1;0;0|] and the next one a = [|0;1;0|] and so on until it reaches a = [|1;1;1|] making all the possible combinations, so in this case needs to do 2^3 changes.
I know that im not been very explicit but its a bit hard to me to explain, but if someone could help me i would be grateful.
An array is a mutable data structure, so if you're going to mutate it in every recursive call, then the mutation will be taken in place. Basically, it means, that after 2^3 calls, the state of array will be the last combination. So, there is no point in doing this at all. A valid solution would be to create a function, that will take an initial array, and will return a list of all combinations. An even more efficient solution is to write a function, that will take another function, and applies it to all combinations (or fold over all combinations). This will allow you to save memory, as you don't need to store all the combinations.
The outline would be to implement the following interface:
type state
val zero : state
val next : state -> state option
val value : state -> int array
Where state will be a cursor, that will move through the space of combinations. It can be an integer or an integer array, or anything else. Once these functions are implemented you can easily implement your function as follows:
let fold_combinations f init =
let rec fold state x =
let x = f (value state) x in
match next state with
| None -> x
| Some state -> fold state x in
fold zero init
Finally, your example shows not all possible combinations or permutations, but all possible binary values of bit width equal to the length of the input array. If this is really a task that you're trying to solve, then you can just translate an integer into a binary representation. In that case, the good choice for the state would be int, and then next function is an increment, that will stop at 2^k-1, where k is the length of the initial state. And the value function will just translate an integer into the array of bits, where the n-th bit (element) can be determined as state land (1 lsl n). You can use Array.init to create a fresh new array every time, alternatively, you can just iterate over the existing array. This will be more efficient, but error-prone.
let combinaison f n =
let rec aux acc n =
if n=0 then List.iter f acc
else (
aux (List.map (fun l -> 0::l ) acc) (n-1);
aux (List.map (fun l -> 1::l ) acc) (n-1);
)
in
aux [[]] n
;;
Test
combinaison ( fun lx ->
let a=Array.of_list lx in
Array.iter ( fun x ->
Printf.printf "%d " x
) a ;
Printf.printf "\n"
) 3;;
0 0 0
1 0 0
0 1 0
1 1 0
0 0 1
1 0 1
0 1 1
1 1 1

Substitute a vector value with two values in MATLAB

I have to create a function that takes as input a vector v and three scalars a, b and c. The function replaces every element of v that is equal to a with a two element array [b,c].
For example, given v = [1,2,3,4] and a = 2, b = 5, c = 5, the output would be:
out = [1,5,5,3,4]
My first attempt was to try this:
v = [1,2,3,4];
v(2) = [5,5];
However, I get an error, so I do not understand how to put two values in the place of one in a vector, i.e. shift all the following values one position to the right so that the new two values fit in the vector and, therefore, the size of the vector will increase in one. In addition, if there are several values of a that exist in v, I'm not sure how to replace them all at once.
How can I do this in MATLAB?
Here's a solution using cell arrays:
% remember the indices where a occurs
ind = (v == a);
% split array such that each element of a cell array contains one element
v = mat2cell(v, 1, ones(1, numel(v)));
% replace appropriate cells with two-element array
v(ind) = {[b c]};
% concatenate
v = cell2mat(v);
Like rayryeng's solution, it can replace multiple occurrences of a.
The problem mentioned by siliconwafer, that the array changes size, is here solved by intermediately keeping the partial arrays in cells of a cell array. Converting back to an array concenates these parts.
Something I would do is to first find the values of v that are equal to a which we will call ind. Then, create a new output vector that has the output size equal to numel(v) + numel(ind), as we are replacing each value of a that is in v with an additional value, then use indexing to place our new values in.
Assuming that you have created a row vector v, do the following:
%// Find all locations that are equal to a
ind = find(v == a);
%// Allocate output vector
out = zeros(1, numel(v) + numel(ind));
%// Determine locations in output vector that we need to
%// modify to place the value b in
indx = ind + (0:numel(ind)-1);
%// Determine locations in output vector that we need to
%// modify to place the value c in
indy = indx + 1;
%// Place values of b and c into the output
out(indx) = b;
out(indy) = c;
%// Get the rest of the values in v that are not equal to a
%// and place them in their corresponding spots.
rest = true(1,numel(out));
rest([indx,indy]) = false;
out(rest) = v(v ~= a);
The indx and indy statements are rather tricky, but certainly not hard to understand. For each index in v that is equal to a, what happens is that we need to shift the vector over by 1 for each index / location of v that is equal to a. The first value requires that we shift the vector over to the right by 1, then the next value requires that we shift to the right by 1 with respect to the previous shift, which means that we actually need to take the second index and shift by the right by 2 as this is with respect to the original index.
The next value requires that we shift to the right by 1 with respect to the second shift, or shifting to the right by 3 with respect to the original index and so on. These shifts define where we're going to place b. To place c, we simply take the indices generated for placing b and move them over to the right by 1.
What's left is to populate the output vector with those values that are not equal to a. We simply define a logical mask where the indices used to populate the output array have their locations set to false while the rest are set to true. We use this to index into the output and find those locations that are not equal to a to complete the assignment.
Example:
v = [1,2,3,4,5,4,4,5];
a = 4;
b = 10;
c = 11;
Using the above code, we get:
out =
1 2 3 10 11 5 10 11 10 11 5
This successfully replaces every value that is 4 in v with the tuple of [10,11].
I think that strrep deserves a mention here.
Although it's called string replacement and warns for non-char input, it still works perfectly fine for other numbers as well (including integers, doubles and even complex numbers).
v = [1,2,3,4]
a = 2, b = 5, c = 5
out = strrep(v, a, [b c])
Warning: Inputs must be character arrays or cell arrays of strings.
out =
1 5 5 3 4
You are not attempting to overwrite an existing value in the vector. You're attempting to change the size of the vector (meaning the number of rows or columns in the vector) because you're adding an element. This will always result in the vector being reallocated in memory.
Create a new vector, using the first and last half of v.
Let's say your index is stored in the variable index.
index = 2;
newValues = [5, 5];
x = [ v(1:index), newValues, v(index+1:end) ]
x =
1 2 5 5 3 4

Assigning array elements based on elements in another array

First time post here, and I had a (likely very simple) question.
I wanted to assign the values of elements in one array (A) based on the corresponding values in another array(B), eg if A(1)=2 assign 4 to B(1).
I imagined this would be achieved using DO loops and some if statements. However the If staments I'm using seem to refering to the loop index rather than the specific element at that point.
Can anyone point me in the right direction ?
You could also try a construct with merge... merge constructs a new array from two existing arrays using a mask to choose the correct value:
program test
integer,parameter :: LENGTH=5
integer :: A(LENGTH)
integer :: B(LENGTH)
real :: R(LENGTH)
integer :: i
call random_number(R)
A = int( R*3 )
B = [ ( i,i=1,LENGTH) ]
print *,'A:',A
print *,'B:',B
B = merge( 4, B, A == 2 )
print *,'B:',B
end program
Output:
A: 2 1 2 2 1
B: 1 2 3 4 5
B: 4 2 4 4 5
Explanation:
B = merge( 4, B, A == 2 )
A == 2 constructs a temporary logical array which is .true. at i if A(i) == 2
4 in this case is a temporary array with the same length as B
So, merge choses the value from 4 if the temporary logical array is .true., and the correspond value from B, otherwise.
The resulting vector is written back to B (=)
You might be able to use masked array assignment. Given two arrays, A and B, of the same shape (ie same number of ranks, same size in each dimension), and if you wanted to set elements of B to 4 where the corresponding element of A equals 2 you could simply write
where(A==2) B = 4
where teams up with elsewhere, rather like if and else if, and there is an end where too. Consult your favourite documentation for further details.
If you can't express your operation with where you might (if you have an up to date compiler) be interested in the do concurrent construct. And, if all else fails, there are good old-fashioned do and if to fall back on.

Redefining a value at index of recursive lazy array

I'm having a <<loop>> error for trying to redefine a value on an already defined index.
Simplified example:
ghci > let axs = array (1,5) [(1,1),(2,2),(3,3),(4,4),(5,5),(1, 1 + axs!1)]
ghci > axs
array (1,5) [(1,^CInterrupted.
This will loop. I'm assuming that the lazy nature of Data.Array is what is causing that behaviour.
This, on the other hand, won't loop and will work as expected (redefines index 1).
ghci > array (1,5) [(1,1),(2,2),(3,3),(4,4),(5,5),(1,6)]
array (1,5) [(1,6),(2,2),(3,3),(4,4),(5,5)]
Is there any way to redefine an indexed value with recursion to self?
I'm assuming I need to force the evaluation of the wanted index to be able to "update" the value again using the previous one.
Is that possible or I shouldn't/can't use the array this way?
In a recursive definition, the meaning of the thing being defined on the right is its final value. So
x = x + 1
will be an infinite loop. In an array definition (in GHC), the value of an index is its last appearance, so
axs = array (1,5) [(1,1),(2,2),(3,3),(4,4),(5,5),(1, 1 + axs!1)]
is the same as
axs = array (1,5) [(2,2),(3,3),(4,4),(5,5),(1, 1 + axs!1)]
the important part of this is
axs' = array (1,1) [(1, 1 + axs!1)]
which is the same idea as
x = 1 + x
Note that "redefinition" in array definitions is not permitted by the Haskell standard at all, and should always loop or throw an exception. GHC allows it, but that is not strictly is agreement with the standard.
Even in GHC the "redefinition" is not imperative. You are not one by one setting the values in the array. Rather, an array definition is a declarative specification for the entire array.
If you want an imperative approach to constructing arrays, use the st monad
This is not tested:
arr = runSTArray $ do
retArr <- newArray (1,5) [(1,1),(2,2),(3,3),(4,4),(5,5)]
curVal <- readArray retArr 1
writeArray retArr 1 (curVal + 1)
retArr

Fortran 90 array subsets

I am trying to read some Fortran code but there is something I can't understand with array subsets operations like this one
Assume n = 3
And the arrays
INTEGER, PARAMETER :: dp = SELECTED_REAL_KIND(12)
REAL(KIND=dp) :: P(n+1),P0(n)
what does this line exactly do?
DO i=1,n-1
…..
P(3:i+2) = P(3:i+2) - i*P0(1:i) / (i+1)
….
END DO
Is it a nested loop? Like j from 3 to i+2 for P and k from 1 to i for P0?
Thanks in advance.
Take the line
P(3:i+2) = P(3:i+2) - i*P0(1:i) / (i+1)
and replace i with 1 (the first value it takes in the do loop)
P(3:3) = P(3:3) - 1*P0(1:1) / 2
On the lhs you have a slice (or section) of array P from element 3 to element 3, so in this case just one element -- but still an array slice not a scalar. This is updated by subtracting 1 times the (same sized) slice of array P0 and divided by 2.
It's a bit more interesting in the next iteration, with i==2 and
P(3:4) = P(3:4) - 2*P0(1:2) / 3
where the array slices are now 2 elements each. The operations on array slices are applied on corresponding elements from each array so this statement is approximately equivalent to the two statements
P(3) = P(3) - 2*P0(1) / 3
P(4) = P(4) - 2*P0(2) / 3
It's better to think of this in Fortran terms, as operations on array sections, than as some kind of syntactic sugar for nested loops.

Resources