wu :: forums
« wu :: forums - rearrange the array. »

Welcome, Guest. Please Login or Register.
Apr 18th, 2024, 9:42pm

RIDDLES SITE WRITE MATH! Home Home Help Help Search Search Members Members Login Login Register Register
   wu :: forums
   riddles
   cs
(Moderators: Icarus, ThudnBlunder, Grimbal, Eigenray, william wu, SMQ, towr)
   rearrange the array.
« Previous topic | Next topic »
Pages: 1 2  Reply Reply Notify of replies Notify of replies Send Topic Send Topic Print Print
   Author  Topic: rearrange the array.  (Read 6460 times)
saujin
Newbie
*





   
Email

Posts: 9
rearrange the array.  
« on: Sep 3rd, 2004, 12:53pm »
Quote Quote Modify Modify

An array {A1,A2,A3,....,An,B1,B2,......,Bn} is given and we have to rearrange it as {A1,B1,A2,B2......} .give an algo with minimum time and space complexity.
IP Logged
towr
wu::riddles Moderator
Uberpuzzler
*****



Some people are average, some are just mean.

   


Gender: male
Posts: 13730
Re: rearrange the array.  
« Reply #1 on: Sep 4th, 2004, 8:12am »
Quote Quote Modify Modify

This is very similar to "Shuffle a deck of cards" (except we'd need to switch every two consecutive elements in the end)
« Last Edit: Sep 4th, 2004, 8:13am by towr » IP Logged

Wikipedia, Google, Mathworld, Integer sequence DB
Grimbal
wu::riddles Moderator
Uberpuzzler
*****






   


Gender: male
Posts: 7526
Re: rearrange the array.  
« Reply #2 on: Sep 4th, 2004, 10:57am »
Quote Quote Modify Modify

Simpler, it is like shuffling A2..An with B1..Bn-1, using the other method, leaving A1 and Bn in place.
IP Logged
Aryabhatta
Uberpuzzler
*****






   


Gender: male
Posts: 1321
Re: rearrange the array.  
« Reply #3 on: Sep 6th, 2004, 2:03pm »
Quote Quote Modify Modify

saujin, I am curious to know your solution. Could you please post it here?  
IP Logged
NoName
Guest

Email

Re: rearrange the array.  
« Reply #4 on: Sep 7th, 2004, 12:28pm »
Quote Quote Modify Modify Remove Remove

on Sep 3rd, 2004, 12:53pm, saujin wrote:
An array {A1,A2,A3,....,An,B1,B2,......,Bn} is given and we have to rearrange it as {A1,B1,A2,B2......} .give an algo with minimum time and space complexity.

 
Here's a simple code that does the job (perl).  Not sure this is the same you guys converged on in the shuffle problem, but I'll post it anyway.
Code:

#!/usr/bin/perl -w
use strict;
 
my $N= $ARGV[0];
 
my @A= ("");
 
my $i;
 
for ($i = 1; $i <= $N; ++$i) {
    $A[$i] = "A$i";
    $A[$i+$N] = "B$i";
}
 
print "Initial array:\n @A\n";
 
for (my $x = 2, my $swaps = 3, $i = 2;  
     $swaps < 2*$N;  
     ++$swaps) {
 
    my $k = ($i > $N) ? 2*($i - $N) : 2*$i - 1;
 
    swapA($x, $k);
     
    $i = $k;
    if ($i == $x) {
 $x += 2;
 $i = $x;
    }
}
 
print "Output array:\n @A\n";
 
exit(0);
     
sub swapA {
    (my $i, my $j) = @_;
    my $tm = $A[$i];
    $A[$i] = $A[$j];
    $A[$j] = $tm;
}
IP Logged
NoName
Guest

Email

Re: rearrange the array.  
« Reply #5 on: Sep 7th, 2004, 1:02pm »
Quote Quote Modify Modify Remove Remove

on Sep 7th, 2004, 12:28pm, NoName wrote:

...

Sorry, my bad.  This does not work for N>11.
IP Logged
saujin
Newbie
*





   
Email

Posts: 9
Re: rearrange the array.  
« Reply #6 on: Sep 13th, 2004, 12:00pm »
Quote Quote Modify Modify

Hi aryabhatta,
 
sorry for late replying. But i too donn know exact answer to this Qn. This question was asked to one of my frend at interview. I'll post other Qns from that interview here as well, and will appreciate if i can get some good answers to those Qns.
 
saurabh
IP Logged
NoName
Guest

Email

Re: rearrange the array.  
« Reply #7 on: Sep 14th, 2004, 1:28pm »
Quote Quote Modify Modify Remove Remove

on Sep 7th, 2004, 1:02pm, NoName wrote:

Sorry, my bad.  This does not work for N>11.

 
OK, here's another try.  It's not linear, but I thought it maybe interesting to those who thought about this problem.
 
Code:

int *A, N;
void re(int from, int many) {
    int i, k = (many+1)/2;
    int x = (k & 1);
     
    if (many < 2)
 return;
     
    re(from, k);
    if (x)
 re(from+k-1, k);
    else
 re(from+k, k-1);
     
    for (i = from+1; i < from+k; i += 2)
 swapA(i, i + k - 1 + x);
}
 
int main() {
    ...
    re(0, N);
    ....
}

 
BTW, I saw some discussion about the existence of the linear solution to this problem in the "deck of cards" topic, but I have not seen it posted.  
 
My impression is that the idea of shuffling a larger array with only one cycle is good, but wouldn't those "extra" elements that you introduce have to serve as additional storage, so that you can always find an element at the "right place"?  I suspect that they cannot just be ignored...  So, I see that it will be linear, but I'm not sure it will be O(1) in space.  And surely, if it turns out to use O(N) in space, there's a much simpler algorithm for that.
 
Please prove me wrong, post the code that we all could try and convince ourselves.
IP Logged
Aryabhatta
Uberpuzzler
*****






   


Gender: male
Posts: 1321
Re: rearrange the array.  
« Reply #8 on: Sep 14th, 2004, 3:07pm »
Quote Quote Modify Modify

on Sep 14th, 2004, 1:28pm, NoName wrote:

BTW, I saw some discussion about the existence of the linear solution to this problem in the "deck of cards" topic, but I have not seen it posted.  

 
An algorithm was posted in that thread but was hidden (you will need to highlight to view it). I will repeat it here for convenience.
 
Given Array A[1...2n].
 
Algo:
 
Step 1) Find an m such that 2m+1 = 3k <= 2n < 3k+1
Step 2) Right cyclic shift A[m+1 ... n+m] by m.
Step 3) Foreach i = 0 to k - 1, considering only the Array[1...2m] start at 3i and 'follow the cycle'.  
Step 4) Recurse  on A[2m+1...2n]
 
Basic idea is as follows:
If for each n, we can find an m (Step 1) for which we can easily do the 'following the cycle' algorithm, we can first shuffle some elements (Step 2), then do the algo for m (Step 3) and then recurse on the remaining elements (Step 4).
 
'following the cycle': element i1 goes to i2 which goes to i3 ... goes to finally back to i1. We can put the elements of this cycle in their right places by using just one extra location as follows:
Store element i1 in the extra location. Look at what goes into i1. say X1. Store element in X1 in i1. Follow the cycle. Finally store i1 in is right position.
« Last Edit: Sep 14th, 2004, 3:09pm by Aryabhatta » IP Logged
NoName
Guest

Email

Re: rearrange the array.  
« Reply #9 on: Sep 14th, 2004, 7:30pm »
Quote Quote Modify Modify Remove Remove

on Sep 14th, 2004, 3:07pm, Aryabhatta wrote:

Step 1) Find an m such that 2m+1 = 3k <= 2n < 3k+1
Step 2) Right cyclic shift A[m+1 ... n+m] by m.
Step 3) Foreach i = 0 to k - 1, considering only the Array[1...2m] start at 3i and 'follow the cycle'.  
Step 4) Recurse  on A[2m+1...2n]
...

 
Thanks.  I did misunderstand your algorithm.
 
Two questions, please:
1.  How do you keep track of misplaced elements A[2m+1 ...n+m] (misplaced after previous cyclic shift(s))?
 
2.  You wouldn't be willing, perhaps, to post actual working code perl or C or whatever for the implementation?
 
IP Logged
Aryabhatta
Uberpuzzler
*****






   


Gender: male
Posts: 1321
Re: rearrange the array.  
« Reply #10 on: Sep 14th, 2004, 9:53pm »
Quote Quote Modify Modify

Here is C code which seems to work on the few values that I have tried.
 
Sorry about the long post.
 
Code:

 
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
 
 
void Inshuffle(int *A, int N);
void follow_cycle(int *A, int N, int seed);
void cyclic_shift(int *A, int size, int distance);
void reverse(int *A, int size);
int Inverseof2(int M);
 
 
/***************************
Main Insuffle Algorithm.
Shuffle a1 a2 ..an b1 b2 ...bn
to
b1 a1 b2 a2 .... bn an
 
Parameters: A = the array
N = 2n, size of the array.
 
The permutation is given by
i -> 2i mod (N + 1)
 
We shuffle the array starting  
from A[1] for easier coding.
****************************/
 
void Inshuffle(int *initialA, int initialN)
{
 
      int m =1;
      int i;
      int power3 = 1;
      int seed = 1;
      int k = 1;
      int n = initialN/2; //N is assumed to be even.
      int *A = initialA;
      int N = initialN;
      
      while (N > 0){
 
            
            //Reset Values.
            m = 1;
            i = 0;
            power3 = 1;
            seed = 1;
            k = 1;
            n = N/2;
 
//Step 1: Find an m such that 2m+1 is the largest power of 3 <= N+1
            for (i = 0; i <= N+1; i ++){
                  if (3*power3 > N+1){
                        break;
                  }
                  power3 = 3*power3;
            }
            k = i;
 
            m = (power3 - 1)/2;
//Step 2: Cyclic Right Shift A[m+1, n+m] by m
            cyclic_shift(A+m+1,n,m);
 
// Step3: Do inshuffle of A[1....2m] by 'following cycle'.
      
            for (i = 0 ; i < k; i ++)
            {
                  follow_cycle(A,2*m,seed);
                  seed = 3*seed;
            }
// Step 4: Recurse on A[2m+1...,2n]
 
//Could have made a recursive call here:
//Inshuffle(A+2*m,2*(n-m));
// But to make it O(1) space, convert tail recursion to iteration and put in a while loop.
      
            A = A + 2*m;
            N = 2*(n-m);
            // Reset Values.
      } //End of while loop.
}
 
/****************************************
Follow the cycle starting at seed.
For example: insuffle of 1 2 3 4 5 6 7 8
1 -> 2 -> 4 -> 8 -> 7 -> 5 -> 1
We follow this cycle in reverse order.
We look at 1. Save A[1].
Then look at what goes to 1, i.e 5 = 1*x
where x is inverse of 2.
Now fill A[1] with A[5].
Now look at what goes into A[5]. 7 = 5*x  
(x is inverse of 2)
So fill A[5] with A[7].
And so on.
*****************************************/
 
void follow_cycle(int *A, int N, int seed)
{
      int cur;
      int inverse2 = Inverseof2(N+1);
      int tmp;
      int prev;
 
      cur = (seed*inverse2 % (N+1));
      
      tmp = A[seed];
      prev = seed;
      while (cur != seed){
            A[prev] = A[cur];
            prev = cur;
            cur = (cur*inverse2 % (N+1));
      }
      A[prev] = tmp;
}
/*******************************
cyclic right shift an array by a given amount.
********************************/
void cyclic_shift(int *A, int sz, int k)
{
      reverse(A,sz - k);  
      reverse(A+sz-k,k);
      reverse(A,sz);
}
 
/******************************
reverse an array
*******************************/
void reverse(int *A, int sz)
{
      int i;
      int tmp;
      for (i = 0; i < sz/2; i++)
      {
            tmp = A[i];
            A[i] = A[sz-i-1];
            A[sz-i-1] = tmp;
      }
}
 
/***************************
 
find x such that 2x = 1 (mod M)
M is assumed to be an odd integer.
x = (M+1)/2
***************************/
int Inverseof2(int M)
{
      return (M+1)/2;
}
 
 
int main()
{
      int n;
      int i;
      int *A;
      printf("Enter the value of n, (total size of array = 2n): ");
      scanf("%d",&n);
      A = (int *)malloc((2*n+1)*sizeof(int));
      for (i = 0; i <= 2*n; i++){
            A[i] = i;
      }
      
      Inshuffle(A,2*n);
      
      printf("\n[");
      for (i = 1; i <= 2*n; i ++){
            printf(" %d",A[i]);
      }
      printf(" ]\n");
      free(A);
      return 1;
}
 
« Last Edit: Sep 14th, 2004, 9:55pm by Aryabhatta » IP Logged
NoName
Guest

Email

Re: rearrange the array.  
« Reply #11 on: Sep 15th, 2004, 10:20am »
Quote Quote Modify Modify Remove Remove

on Sep 14th, 2004, 9:53pm, Aryabhatta wrote:
Here is C code which seems to work on the few values that I have tried.
...

 
Thanks!  Any idea why it wouldn't work for values of n >= 88573 = (3^11-1)/2 ?
IP Logged
Aryabhatta
Uberpuzzler
*****






   


Gender: male
Posts: 1321
Re: rearrange the array.  
« Reply #12 on: Sep 15th, 2004, 1:17pm »
Quote Quote Modify Modify

on Sep 15th, 2004, 10:20am, NoName wrote:

 
Thanks!  Any idea why it wouldn't work for values of n >= 88573 = (3^11-1)/2 ?

 
It is most likely an integer overflow in the follow_cycle method due to the cur*inverse2.
IP Logged
Aryabhatta
Uberpuzzler
*****






   


Gender: male
Posts: 1321
Re: rearrange the array.  
« Reply #13 on: Sep 15th, 2004, 4:48pm »
Quote Quote Modify Modify

on Sep 15th, 2004, 1:17pm, Aryabhatta wrote:

 
It is most likely an integer overflow in the follow_cycle method due to the cur*inverse2.

 
Maybe not. I changed everything to unsigned long int and 88573 was still the point where the performance went down drastically. My guess is this has to do with paging.
On my machine with 4K sized pages, the array A will require 129 pages of memory. I think the working set limit might be 128 pages.  88572 will require 129 pages too, but our algorithm ends up accessing a lot less pages, because the power of 3 involved is 310, so we require no more than 128 pages to remain in memory rather than the 129 which 88573 requires. Maybe the access pattern is fooling the page replacement algorithm of the OS.
 
Of course this might be all be nonsense.
 
btw, are you using Visual Studio by any chance?
 
« Last Edit: Sep 15th, 2004, 5:23pm by Aryabhatta » IP Logged
Aryabhatta
Uberpuzzler
*****






   


Gender: male
Posts: 1321
Re: rearrange the array.  
« Reply #14 on: Sep 15th, 2004, 8:07pm »
Quote Quote Modify Modify

Forget the blabber about paging.
 
It *is* an integer overflow. Because of that we have an infinite loop.
 
In the follow_cycle function:
 
for n = 88573 we have
inverse2 = 88574.
for seed = 1 (the first case)
the variable cur has to become 88573*2 sometime.
(this is because theoretically, cur must iterate through all the numbers relatively prime to 88573*2+1)
 
now 88574*88573*2 is > 2^32...
so there is an overflow.
 
It is also possible that cur never achieves 88573*2 because an overflow occured *earlier* causing an infinite loop and never reaching 88573*2.
 
I guess by we can get around this by using two 32 bit numbers to represent the intermediates of our computation, without changing the linear order of time...
IP Logged
towr
wu::riddles Moderator
Uberpuzzler
*****



Some people are average, some are just mean.

   


Gender: male
Posts: 13730
Re: rearrange the array.  
« Reply #15 on: Sep 16th, 2004, 7:51am »
Quote Quote Modify Modify

Currently on most computers int and long int are equal in size (i.e. 32 bits). You can try long long int (64) instead if you actually want something bigger.
Or use some a very large integer library Tongue
IP Logged

Wikipedia, Google, Mathworld, Integer sequence DB
Aryabhatta
Uberpuzzler
*****






   


Gender: male
Posts: 1321
Re: rearrange the array.  
« Reply #16 on: Sep 16th, 2004, 9:26am »
Quote Quote Modify Modify

on Sep 16th, 2004, 7:51am, towr wrote:
Currently on most computers int and long int are equal in size (i.e. 32 bits). You can try long long int (64) instead if you actually want something bigger.
Or use some a very large integer library Tongue

 
Isn't the distinction between int and long int compiler dependent and not the machine? I guess most compilers make a distinction between int and short int and keep int and long int the same...
 
Anyway for our purposes, we don't need a large integer library because we will be multiplying at most two u_ints which will fit nicely in 2 u_ints. If we use a large integer library, the running time of the algorithm might not be linear anymore, in fact space usage might not be constant too, but that is an interesting problem to think about.  
IP Logged
NoName
Guest

Email

Re: rearrange the array.  
« Reply #17 on: Sep 16th, 2004, 10:47am »
Quote Quote Modify Modify Remove Remove

Yeah, I forgot to tell you guys yesterday.  After I switched to using 64 bit integers, that problem went away.  The runtime went up, though, getting longer than for the O(N log(N)) algorithm I posted before.  Because I don't have native 64-bit arithmetics.  BTW, I'm using gcc-3.2.2 on i386-Linux.
 
I must say, I admire your solution, Aryabhatta, it's great.  I can't help wondering, though, if there's a simpler way...
IP Logged
towr
wu::riddles Moderator
Uberpuzzler
*****



Some people are average, some are just mean.

   


Gender: male
Posts: 13730
Re: rearrange the array.  
« Reply #18 on: Sep 16th, 2004, 11:21am »
Quote Quote Modify Modify

well, a (theoretical) O(N) algorithm may for all practical purposes always take longer than an O(N log(N)) algorithm.  
One big problem is reading/writing of very large arrays, because you can't keep the whole array in memory/cache. This means that if you try to swap an element in the front of the array with one somewhere near the back, you'll have to swap from disk to memory (or memory to cache), again and again (since this is essentially what happens when we swap elements cyclicly). So it will be much better to divide and conquer, dealing mostly with one consecutive part of the array at a time.
On an ideal computer that shouldn't be a problem, but unfortunately it doesn't exist.
« Last Edit: Sep 16th, 2004, 11:23am by towr » IP Logged

Wikipedia, Google, Mathworld, Integer sequence DB
Grimbal
wu::riddles Moderator
Uberpuzzler
*****






   


Gender: male
Posts: 7526
Re: rearrange the array.  
« Reply #19 on: Sep 16th, 2004, 12:31pm »
Quote Quote Modify Modify

That would call for a method like this:
 
def proc shuffle(a, n) // a is 2n elements, starts at 0
- k = n/s
- swap a[k]..a[n-1] with a[n]..a[n+k-1].  The sizes of the parts to exchange might not be equal, but if it is the case, it is a rotation that is actually easier to do.
- shuffle(a,k)
- shuffle(a+2k,n-k)
end proc
 
The good thing is that when you begin and swap big parts, you go through them sequentially, so you access only 2 pages at a time.  Later, when the interval becomes small, you swap small parts that fit in 1 or 2 pages.
 
It is O(n log n) if I am not mistaken.
IP Logged
Aryabhatta
Uberpuzzler
*****






   


Gender: male
Posts: 1321
Re: rearrange the array.  
« Reply #20 on: Sep 17th, 2004, 9:02am »
Quote Quote Modify Modify

Thanks NoName, I hope there is a simpler solution too.
Btw, why don't you register as a member? Registering gives you more features...
IP Logged
John_Gaughan
Uberpuzzler
*****



Behold, the power of cheese!

5187759 5187759   john23874   SnowmanJTG
WWW Email

Gender: male
Posts: 767
Re: rearrange the array.  
« Reply #21 on: Sep 21st, 2004, 8:40am »
Quote Quote Modify Modify

on Sep 16th, 2004, 10:47am, NoName wrote:
The runtime went up, though, getting longer than for the O(N log(N)) algorithm I posted before.  Because I don't have native 64-bit arithmetics.  BTW, I'm using gcc-3.2.2 on i386-Linux.

As long as your CPU supports MMX or SSE, you have 64 bit integer arithmetic. 32 bit CPUs perform 64 bit arithmetic by using MMX and SSE registers. While it is not as fast as a true 64 bit CPU, it is much faster than emulation. The version of GCC you use supports these extensions, although you may have to enable them with a compiler flag.
 
Also, keep in mind that any inefficiencies in the implementation are constants, so they will not affect your algorithmic asymptotic notation. It is still O(N lg(N)).
« Last Edit: Sep 21st, 2004, 8:42am by John_Gaughan » IP Logged

x = (0x2B | ~0x2B)
x == the_question
m_aakash
Junior Member
**





   


Posts: 96
Re: rearrange the array.  
« Reply #22 on: Apr 9th, 2008, 3:11am »
Quote Quote Modify Modify

a) If all the elements are positive then here is a simple O(n) and O(1) space algorithm.
i/p:  a1 a2 a3 a4 b1 b2 b3 b4
o/p: a1 b1 a2 b2 a3 b3 a4 b4
 
element at index  (i *n) % (2n-1) goes to index i. follow up this cycle. since elements are positive keep track of which elements are moved to correct positions by negating them.
Take the next index which is positive and again continue the above process till all elements moved to their correct locations.
 
b) for general array of size n, we need n bits to know which elements moved to correct positions.
 
edit: rewritten b to make it clear suggested by aryabatta
« Last Edit: Apr 9th, 2008, 10:40am by m_aakash » IP Logged
pscoe2
Junior Member
**





   


Gender: male
Posts: 77
Re: rearrange the array.  
« Reply #23 on: Apr 9th, 2008, 6:47am »
Quote Quote Modify Modify

@m_aakash
 
i dont think the algo will work as intended
because once u know the pos of say 2nd element will u swap it with the 3rd one.
If u swap the index or third one will be lost....
If u dont do so how will u save the indexes in O(1) space....
The only way i can think this algo can be implemented is by finding the index of the next one b4 swapping...
wht do u say
IP Logged
m_aakash
Junior Member
**





   


Posts: 96
Re: rearrange the array.  
« Reply #24 on: Apr 9th, 2008, 10:00am »
Quote Quote Modify Modify

on Apr 9th, 2008, 6:47am, pscoe2 wrote:
@m_aakash
 
i dont think the algo will work as intended
because once u know the pos of say 2nd element will u swap it with the 3rd one.
If u swap the index or third one will be lost....
If u dont do so how will u save the indexes in O(1) space....
The only way i can think this algo can be implemented is by finding the index of the next one b4 swapping...
wht do u say

 
Why do you want to save index at all....i am just traversing cycle by cycle..
Example: Assume the array starts from index 0
 
1<--- 4 <----- 2 <------ 1   this is one cycle
3<--- 5 <----- 6 <------ 3   this is second cycle
 
 
IP Logged
Pages: 1 2  Reply Reply Notify of replies Notify of replies Send Topic Send Topic Print Print

« Previous topic | Next topic »

Powered by YaBB 1 Gold - SP 1.4!
Forum software copyright © 2000-2004 Yet another Bulletin Board