help-octave
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: circshift C


From: Graham Toal
Subject: RE: circshift C
Date: Thu, 14 Mar 2013 21:19:08 +0000

There's another shuffling algorithm that's trickier to get right and can be 
faster if the left and right sections of the rotation are closer in size.  This 
is a function where measuring performance is worth the effort, if it is a 
significant overhead in your code.  (If not, the reversal code is almost 
idiot-proof to get right)  You should instrument it to count the swaps as well 
as timing it...

Anyway, I had 15 minutes spare at the end of the day and I wanted to see if I 
could still hack these CS101 style problems, so here's my version of array 
reversing, with the two best algorithms :-)

It's not this complicated if you can afford the space for a duplicate array to 
hold the results, which I think is how circshift is spec'd?  But if you can 
rewrite your code to use your own functions and avoid the memory overhead, then 
one or both of these (or a hybrid) are the ticket...

(btw I modified the recursive algorithm to use explicit tail recursion which 
converts it to an iterative solution.)

G

#include <stdio.h>
#include <stdlib.h>

// Rotate a subset of a array

//           0 1 2 3 4 5 6 7 8 9
// eg rotate A B C D E F G H I J, 2, 3, 8
//               \_/ \_______/

// =>        A B E F G H I C D J
//               \_______/ \_/


void reverse(int *A, int low, int high)
{
  while (low < high) {
    register int temp = A[low];
    A[low++] = A[high];
    A[high--] = temp;
  }
}

void rotate_by_reversals(int *A, int first_index, int rot_index, int last_index)
{
  //               f r         l
  //           0 1 2 3 4 5 6 7 8 9
  // eg rotate A B C D E F G H I J, 2, 3, 8
  //               \_/ \_______/
  // =>        A B E F G H I C D J, 2, 3, 8
  //               \_______/ \_/



  if (first_index == rot_index || rot_index+1 == last_index) return;
  reverse(A, first_index, rot_index);
  //               f r         l
  //           A B C D E F G H I J
  //               \_/
  // =>        A B D C E F G H I J

  reverse(A, rot_index+1, last_index);
  //               f r         l
  //           A B D C E F G H I J
  //                   \_______/
  // =>        A B D C I H G F E J

  reverse(A, first_index, last_index);
  //               f r         l
  //           0 1 2 3 4 5 6 7 8 9
  //           A B D C I H G F E J
  //               \___________/

  // =>        A B E F G H I C D J
  //               \___________/

}

void swap_blocks(int *A, int left, int right, int len)
{
  // preserve order
  while (len-- > 0) {
    register int temp = A[left];
    A[left++] = A[right];
    A[right++] = temp;
  }
}

void rotate_by_blocks(int *A, int first_index, int rot_index, int last_index)
{
  int len;
  while (first_index != last_index) {
  if (rot_index-first_index+1 < last_index-rot_index) {

    len = rot_index-first_index+1;

    //               f r         l
    //           0 1 2 3 4 5 6 7 8 9
    // eg rotate A B C D E F G H I J, 2, 3, 8
    //               \_/ \_______/

    // =>        A B E F G H I C D J
    //               \_______/ \_/


    swap_blocks(A, first_index, rot_index+1, len);
    //               f r         l
    //           0 1 2 3 4 5 6 7 8 9
    //           A B C D E F G H I J
    //               \_/ \_/
    // =>        A B E F C D G H I J
    //               \_/ \_/

    // rotate_by_blocks(A, rot_index+1, rot_index+len, last_index);
                           first_index = rot_index+1;
                                        rot_index += len;
    //               f r         l
    //           A B E F C D G H I J
    //                   \_/ \___/
    // =>        A B E F G H I C D J
    //                   \___/ \_/

  } else {
    len = last_index-rot_index;
    //               f       r   l
    //           0 1 2 3 4 5 6 7 8 9
    // eg rotate A B C D E F G H I J, 2, 6, 8
    //               \_______/ \_/
    // =>        A B H I C D E F G J
    //               \_/ \_______/


    swap_blocks(A, rot_index-len+1, last_index-len+1, len); // or rot_index, 
last_index, -len ???
    //               f       r   l
    //           0 1 2 3 4 5 6 7 8 9
    //           A B C D E F G H I J
    //                     \_/ \_/
    // =>        A B C D E H I F G J

    // rotate_by_blocks(A, first_index, rot_index-len, rot_index);
                                                       last_index = rot_index;
                                        rot_index -= len;
    //               f       r   l
    //           A B C D E H I F G J
    //               \___/ \_/
    // =>        A B H I C D E F G J
    //               \_/ \___/
  }
  }
}

int main(int argc, char **argv) {
  int fred[10], i;

  for (i = 0; i < 10; i++) fred[i] = i+'A';
  fprintf(stdout, "rotate_by_reversals(ABCDEFGHIJ, 2, 3, 8) => ");
  rotate_by_reversals(fred, 2, 3, 8);
  for (i = 0; i < 10; i++) putchar(fred[i]); putchar('\n');

  for (i = 0; i < 10; i++) fred[i] = i+'A';
  fprintf(stdout, "rotate_by_blocks(ABCDEFGHIJ, 2, 3, 8) => ");
  rotate_by_blocks(fred, 2, 3, 8);
  for (i = 0; i < 10; i++) putchar(fred[i]); putchar('\n');

  exit(0);
  return(1);
}

-----Original Message-----
From: address@hidden [mailto:address@hidden On Behalf Of Graham Toal
Sent: Thursday, March 14, 2013 9:32 AM
To: address@hidden
Subject: RE: circshift C

> hi all,

> can anyone provide C version of circshift function?

> regards,
> abhishek

You need the old reversing trick.

http://leetcode.com/2010/04/rotating-array-in-place.html

modify appropriately for your data type...

_______________________________________________
Help-octave mailing list
address@hidden
https://mailman.cae.wisc.edu/listinfo/help-octave


reply via email to

[Prev in Thread] Current Thread [Next in Thread]