Erlang - how to "unflatten" an array - arrays

I'm new to Erlang, so this question might be a little basic.
I got an array with N^2 elements (I know N) which I want to break down into an array (or tuple, doesn't matter) with N tuples, each with N elements.
i.e: I want to turn:
[14,20,26,20,29,38,26,38,50]
into:
[ {14,20,26} , {20,29,38} , {26,38,50} }
Is there a simple way or a function that does this?
Thanks.

Use pattern matching:
s([X, Y, Z | Next]) ->
[{X, Y, Z} | s(Next)];
s([]) -> [].
This will fail if you don't supply a multiple of 3 elements, but that is probably what you want.

this should do what you want.
s(L,N) -> s(L,N,[]).
s([],_,R) -> lists:reverse;
s(L,N,R) ->
{L1,L2} = lists:split(N,L),
s(L2,[list_to_tuple(L1)|R]).

You can use this function sublist(List1, Start, Len) -> List2,
Returns the sub-list of List1 starting at Start and with (max) Len
elements. It is not an error for Start+Len to exceed the length of the
list.
unflatten(L, N) ->
case N*N == length(L) of
true -> unflatten_help(L, 1, N, []);
false ->
{error, "wrong list length!"}
end.
unflatten_help(_L, Start, N, Res) when Start == (N*N + 1) ->
lists:reverse(Res);
unflatten_help(L, Start, N, Res) ->
Temp = lists:sublist(L, Start, N),
unflatten_help(L, Start + N, N, [Temp | Res]).
main() ->
L = [14,20,26,20,29,38,26,38,50],
unflatten(L, 3).
The output:
[[14,20,26],[20,29,38],[26,38,50]]

I think the following code is fine for you:
array_to_tuples([],_) -> [];
array_to_tuples(L,N) ->
{L1,L2} = lists:split(N,L),
[list_to_tuple(L1)|array_to_tuples(L2,N)].
This will split your array, considering N*2 elements, in N tuples.

Related

How to change for loop with an array module function?

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

F# why arrays are not scrambled in a different way when mapping a function to scramble each array in an array

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.

Find Maximun area on Array

I am doing exercises from the app Data Structures in Scala, I have coded the second problem on Arrays like this:
/**
* Given n non-negative integers a1, a2, ..., an, where each represents a
* point at coordinate (i, ai), n vertical lines are drawn such that
* the two endpoints of line i is at (i, ai) and (i, 0).
*
* Find two lines, which together with x-axis forms a container such
* that the container contains the most water.
*
* Efficiency: O(n)
*
* #param a Array of line heights
* #return Maximum area
*/
def maxArea(a: Array[Int]): Int = {
#tailrec
def go(l: Int, r: Int)(max: Int): Int = {
if (l >= r) max
else {
val currArea = math.min(a(l), a(r)) * (r - l)
val area = math.max(max, currArea)
log debug s"Current area for $l and $r is $currArea"
log debug s"Max area till now is $area"
if (a(l) < a(r)) go(l + 1, r)(area)
else go(l, r - 1)(area)
}
}
go(0, a.size - 1)(0)
}
I wonder if there is a better alternative to write recursive functions as a way of looping through the Array, as someone once told me calls recursion the GOTO of functional programming.
You can check the complete source code at GitHub
Thank you in advance.
Here's a way to implement your algorithm without recursion (not that I actually think there's anything inherently wrong with recursion).
def maxArea2(a: Array[Int]): Int = {
Stream.iterate(0 -> a){ case (_, arr) =>
if (arr.length < 2) -1 -> arr
else {
val (lft, rght) = (arr.head, arr.last)
val area = (lft min rght) * (arr.length - 1)
if (lft <= rght) area -> arr.dropWhile(_ <= lft)
else area -> arr.reverse.dropWhile(_ <= rght)
}
}.takeWhile(_._1 >= 0).maxBy(_._1)._1
}
The idea is to iterate lazily and the take (i.e. realize) only those you need.
You'll note that this iterates, and calculates areas, fewer times because it drops values that can't beat the current area calculation.

Run-length encoding of a Repa array

I have a one-dimensional Repa array that consists of 0's and 1's and I want to calculate its run-length encoding.
E.g.: Turn [0,0,1,1,1,0,0,0,1,0,1,1] into [2,3,3,1,1,2] or something similar. (I'm using a list representation because of readability)
Ideally, I would like the run-length of the 1's and ignore the 0's.
So [0,0,1,1,1,0,0,0,1,0,1,1] becomes [3,1,2].
I would like the result to be a (Repa) array as well.
How can I do this using Repa? I can't use map or traverse since they only give me one element at a time. I could try to fold with some special kind of accumulator but that doesn't seem to be ideal and I don't know it it's even possible (due to monad laws).
I'm currently just iterating over the array and returning a list without using any Repa function. I'm working on Booleans instead of 1's and 0's but the algorithm is the same. I'm converting this list to a Repa Array afterwards.
runLength :: Array U DIM1 Bool -> [Length]
runLength arr = go ([], 0, False) 0 arr
where
Z :. n = extent arr
go :: Accumulator -> Int -> Array U DIM1 Bool -> [Length]
go !acc#(xs, c, b) !i !arr | i == n = if c > 0 then c:xs else xs
| otherwise =
if unsafeIndex arr (Z :. i)
then if b
then go (xs, c+1, b) (i+1) arr
else go (xs, 1, True) (i+1) arr
else if b
then go (c:xs, 0, False) (i+1) arr
else go (xs, 0, False) (i+1) arr

Algorithm to apply permutation in constant memory space

I saw this question is a programming interview book, here I'm simplifying the question.
Assume you have an array A of length n, and you have a permutation array P of length n as well. Your method will return an array where elements of A will appear in the order with indices specified in P.
Quick example: Your method takes A = [a, b, c, d, e] and P = [4, 3, 2, 0, 1]. then it will return [e, d, c, a, b]. You are allowed to use only constant space (i.e. you can't allocate another array, which takes O(n) space).
Ideas?
There is a trivial O(n^2) algorithm, but you can do this in O(n). E.g.:
A = [a, b, c, d, e]
P = [4, 3, 2, 0, 1]
We can swap each element in A with the right element required by P, after each swap, there will be one more element in the right position, and do this in a circular fashion for each of the positions (swap elements pointed with ^s):
[a, b, c, d, e] <- P[0] = 4 != 0 (where a initially was), swap 0 (where a is) with 4
^ ^
[e, b, c, d, a] <- P[4] = 1 != 0 (where a initially was), swap 4 (where a is) with 1
^ ^
[e, a, c, d, b] <- P[1] = 3 != 0 (where a initially was), swap 1 (where a is) with 3
^ ^
[e, d, c, a, b] <- P[3] = 0 == 0 (where a initially was), finish step
After one circle, we find the next element in the array that does not stay in the right position, and do this again. So in the end you will get the result you want, and since each position is touched a constant time (for each position, at most one operation (swap) is performed), it is O(n) time.
You can stored the information of which one is in its right place by:
set the corresponding entry in P to -1, which is unrecoverable: after the operations above, P will become [-1, -1, 2, -1, -1], which denotes that only the second one might be not in the right position, and a further step will make sure it is in the right position and terminates the algorithm;
set the corresponding entry in P to -n - 1: P becomes [-5, -4, 2, -1, -2], which can be recovered in O(n) trivially.
Yet another unnecessary answer! This one preserves the permutation array P explicitly, which was necessary for my situation, but sacrifices in cost. Also this does not require tracking the correctly placed elements. I understand that a previous answer provides the O(N) solution, so I guess this one is just for amusement!
We get best case complexity O(N), worst case O(N^2), and average case O(NlogN). For large arrays (N~10000 or greater), the average case is essentially O(N).
Here is the core algorithm in Java (I mean pseudo-code *cough cough*)
int ind=0;
float temp=0;
for(int i=0; i<(n-1); i++){
// get next index
ind = P[i];
while(ind<i)
ind = P[ind];
// swap elements in array
temp = A[i];
A[i] = A[ind];
A[ind] = temp;
}
Here is an example of the algorithm running (similar to previous answers):
let A = [a, b, c, d, e]
and P = [2, 4, 3, 0, 1]
then expected = [c, e, d, a, b]
i=0: [a, b, c, d, e] // (ind=P[0]=2)>=0 no while loop, swap A[0]<->A[2]
^ ^
i=1: [c, b, a, d, e] // (ind=P[1]=4)>=1 no while loop, swap A[1]<->A[4]
^ ^
i=2: [c, e, a, d, b] // (ind=P[2]=3)>=2 no while loop, swap A[2]<->A[3]
^ ^
i=3a: [c, e, d, a, b] // (ind=P[3]=0)<3 uh-oh! enter while loop...
^
i=3b: [c, e, d, a, b] // loop iteration: ind<-P[0]. now have (ind=2)<3
? ^
i=3c: [c, e, d, a, b] // loop iteration: ind<-P[2]. now have (ind=3)>=3
? ^
i=3d: [c, e, d, a, b] // good index found. Swap A[3]<->A[3]
^
done.
This algorithm can bounce around in that while loop for any indices j<i, up to at most i times during the ith iteration. In the worst case (I think!) each iteration of the outer for loop would result in i extra assignments from the while loop, so we'd have an arithmetic series thing going on, which would add an N^2 factor to the complexity! Running this for a range of N and averaging the number of 'extra' assignments needed by the while loop (averaged over many permutations for each N, that is), though, strongly suggests to me that the average case is O(NlogN).
Thanks!
The simplest case is when there is only a single swap for an element to the destination index. for ex:
array=abcd
perm =1032. you just need two direct swaps: ab swap, cd swap
for other cases, we need to keep swapping until an element reaches its final destination. for ex: abcd, 3021 starting with first element, we swap a and d. we check if a's destination is 0 at perm[perm[0]]. its not, so we swap a with elem at array[perm[perm[0]]] which is b. again we check if a's has reached its destination at perm[perm[perm[0]]] and yes it is. so we stop.
we repeat this for each array index.
Every item is moved in-place only once, so it's O(N) with O(1) storage.
def permute(array, perm):
for i in range(len(array)):
elem, p = array[i], perm[i]
while( p != i ):
elem, array[p] = array[p], elem
elem = array[p]
p = perm[p]
return array
#RinRisson has given the only completely correct answer so far! Every other answer has been something that required extra storage — O(n) stack space, or assuming that the permutation P was conveniently stored adjacent to O(n) unused-but-mutable sign bits, or whatever.
Here's RinRisson's correct answer written out in C++. This passes every test I have thrown at it, including an exhaustive test of every possible permutation of length 0 through 11.
Notice that you don't even need the permutation to be materialized; we can treat it as a completely black-box function OldIndex -> NewIndex:
template<class RandomIt, class F>
void permute(RandomIt first, RandomIt last, const F& p)
{
using IndexType = std::decay_t<decltype(p(0))>;
IndexType n = last - first;
for (IndexType i = 0; i + 1 < n; ++i) {
IndexType ind = p(i);
while (ind < i) {
ind = p(ind);
}
using std::swap;
swap(*(first + i), *(first + ind));
}
}
Or slap a more STL-ish interface on top:
template<class RandomIt, class ForwardIt>
void permute(RandomIt first, RandomIt last, ForwardIt pfirst, ForwardIt plast)
{
assert(std::distance(first, last) == std::distance(pfirst, plast));
permute(first, last, [&](auto i) { return *std::next(pfirst, i); });
}
You can consequently put the desired element to the front of the array, while working with the remaining array of the size (n-1) in the the next iteration step.
The permutation array needs to be accordingly adjusted to reflect the decreasing size of the array. Namely, if the element you placed in the front was found at position "X" you need to decrease by one all the indexes greater or equal to X in the permutation table.
In the case of your example:
array permutation -> adjusted permutation
A = {[a b c d e]} [4 3 2 0 1]
A1 = { e [a b c d]} [3 2 0 1] -> [3 2 0 1] (decrease all indexes >= 4)
A2 = { e d [a b c]} [2 0 1] -> [2 0 1] (decrease all indexes >= 3)
A3 = { e d c [a b]} [0 1] -> [0 1] (decrease all indexes >= 2)
A4 = { e d c a [b]} [1] -> [0] (decrease all indexes >= 0)
Another example:
A0 = {[a b c d e]} [0 2 4 3 1]
A1 = { a [b c d e]} [2 4 3 1] -> [1 3 2 0] (decrease all indexes >= 0)
A2 = { a c [b d e]} [3 2 0] -> [2 1 0] (decrease all indexes >= 2)
A3 = { a c e [b d]} [1 0] -> [1 0] (decrease all indexes >= 2)
A4 = { a c e d [b]} [0] -> [0] (decrease all indexes >= 1)
The algorithm, though not the fastest, avoids the extra memory allocation while still keeping the track of the initial order of elements.
Here a clearer version which takes a swapElements function that accepts indices, e.g., std::swap(Item[cycle], Item[P[cycle]])$
Essentially it runs through all elements and follows the cycles if they haven't been visited yet. Instead of the second check !visited[P[cycle]], we could also compare with the first element in the cycle which has been done somewhere else above.
bool visited[n] = {0};
for (int i = 0; i < n; i++) {
int cycle = i;
while(! visited[cycle] && ! visited[P[cycle]]) {
swapElements(cycle,P[cycle]);
visited[cycle]=true;
cycle = P[cycle];
}
}
Just a simple example C/C++ code addition to the Ziyao Wei's answer. Code is not allowed in comments, so as an answer, sorry:
for (int i = 0; i < count; ++i)
{
// Skip to the next non-processed item
if (destinations[i] < 0)
continue;
int currentPosition = i;
// destinations[X] = Y means "an item on position Y should be at position X"
// So we should move an item that is now at position X somewhere
// else - swap it with item on position Y. Then we have a right
// item on position X, but the original X-item now on position Y,
// maybe should be occupied by someone else (an item Z). So we
// check destinations[Y] = Z and move the X-item further until we got
// destinations[?] = X which mean that on position ? should be an item
// from position X - which is exactly the X-item we've been kicking
// around all this time. Loop closed.
//
// Each permutation has one or more such loops, they obvisouly
// don't intersect, so we may mark each processed position as such
// and once the loop is over go further down by an array from
// position X searching for a non-marked item to start a new loop.
while (destinations[currentPosition] != i)
{
const int target = destinations[currentPosition];
std::swap(items[currentPosition], items[target]);
destinations[currentPosition] = -1 - target;
currentPosition = target;
}
// Mark last current position as swapped before moving on
destinations[currentPosition] = -1 - destinations[currentPosition];
}
for (int i = 0; i < count; ++i)
destinations[i] = -1 - destinations[i];
(for C - replace std::swap with something else)
Traceback what we have swapped by checking index.
Java, O(N) swaps, O(1) space:
static void swap(char[] arr, int x, int y) {
char tmp = arr[x];
arr[x] = arr[y];
arr[y] = tmp;
}
public static void main(String[] args) {
int[] intArray = new int[]{4,2,3,0,1};
char[] charArray = new char[]{'A','B','C','D','E'};
for(int i=0; i<intArray.length; i++) {
int index_to_swap = intArray[i];
// Check index if it has already been swapped before
while (index_to_swap < i) {
// trace back the index
index_to_swap = intArray[index_to_swap];
}
swap(charArray, index_to_swap, i);
}
}
I agree with many solutions here, but below is a very short code snippet that permute throughout a permutation cycle:
def _swap(a, i, j):
a[i], a[j] = a[j], a[i]
def apply_permutation(a, p):
idx = 0
while p[idx] != 0:
_swap(a, idx, p[idx])
idx = p[idx]
So the code snippet below
a = list(range(4))
p = [1, 3, 2, 0]
apply_permutation(a, p)
print(a)
Outputs [2, 4, 3, 1]

Resources