-3

We have an array of some length(say 3) and some counting sequence: 0,1,2,3,4,... to infinity. Out of that input sequence we need to produce sequence that will traverse through array back and forth, like that: 0,1,2,1,0,1,2,1,0,... and so on for a length=3.

I think this task is a very common one in a many programming books, but i was not able to find standard solution, so i created my own solution. Are there any other more efficient and elegant solution, because i dont like my solution???

#define LENGTH 5
int main()
{
   char arr[LENGTH] = {'a','b','c','d','e'};
   int i;
   int base=0;
   for(i=0;i<100;i++){ 
        if(i%(LENGTH-1)==0){ 
            if(base==0) base=LENGTH-1;
            else base =0;
        }
    int j = abs(base-i%(LENGTH-1)); 
    printf("%c ",arr[j]); 
   }
}

Java code (for your convenience):

public static void traverse(){
        char arr[] = {'a','b','c','d','e'};
        int base=0;
        for(int i=0;i<100;i++){ 
            if(i%(arr.length-1)==0){ 
            if(base==0) base=arr.length-1;
            else base =0;
            }
        int j = Math.abs(base-i%(arr.length-1)); 
        System.out.println(arr[j]+" ");
        }
    }

2 Answers2

1

Maybe something like this:

#define LENGTH 5
int main()
{
    char arr[LENGTH] = { 'a','b','c','d','e' };
    int current = 0;
    int direction = 1;
    for (int i = 0; i < 100; i++) 
    {       
        printf("%c ", arr[current]);
        if (current == 0)
            direction = 1;
        else if (current == LENGTH - 1)
            direction = -1;
        current += direction;
    }
}
Nico Schertler
  • 32,049
  • 4
  • 39
  • 70
  • Brilliant! Thank you. Much cleaner solution. I think no better exists! :) – oleg_phorostyna Oct 30 '18 at 12:15
  • Cant use this solution. Some times counting sequence going like that: 0, 1, 2, 3, 3, 3, 4, 4. Independent incrementing of arr-index inside loop will produce results that is not corresponded to input (current += direction). Basically in you solution i-var sets duration of a loop but not its input data. – oleg_phorostyna Oct 30 '18 at 12:33
  • @oleg_phorostyna If I understand correctly, your `i` may repeat values and should then produce repeated output? In that case you either need to calculate the index from `i` (as per my answer), or detect repeated values of `i` and not advance `current` in that case. – Arkku Oct 30 '18 at 12:38
  • @oleg I am not sure if I understand the problem. If you don't want to repeat the repeated elements in the output sequence, then pre-process the input sequence (such that it does not contain repeated elements). You could try to handle this on the fly while generating the output. But why would you do something several times when you only need to do it once? – Nico Schertler Oct 30 '18 at 14:29
  • @Nico Schertler Pre-processing is a trick that will work. Input - is a result of a complicated sequence of actions that is not predictable (for loop is an abstraction) – oleg_phorostyna Oct 31 '18 at 10:13
1

This solution calculates the index of arr only from i, thus avoiding the need to keep any state (such as current direction). As a result it is a bit more convoluted, but would also work for non-consecutive values of i.

char arr[] = { '0', '1', '2', '3', '4' };
const int LENGTH = sizeof arr / sizeof(*arr); // not necessary for char
assert(LENGTH > 1); // doesn't work for fewer than 2 elements

const int CYCLE = LENGTH - 1;
for (int i = 0; i < 100; ++i) { 
    printf("%c ", arr[ (i / CYCLE) & 1 ? CYCLE - i % CYCLE : i % CYCLE ]);
}
printf("\n");

Explanation: i / CYCLE is the number of the cycle through the array, and & 1 checks the least significant bit of that number to determine the direction (odd cycles where the bit is 1 go backwards, even cycles – starting from 0 – go forwards). i % CYCLE is the forwards cycle, but since CYCLE = LENGTH - 1, it doesn't reach the last index of the array. CYCLE - i % CYCLE is the backwards cycle, starting from CYCLE - 0, which is the last index that wasn't reached when going forwards, and ending at 1, thus avoiding repetition of index 0 when going forwards again.

In other words, both the forwards and the backwards cycles omit one index to avoid repetition when changing direction, hence CYCLE = LENGTH - 1, which also means that LENGTH must be at least 2 to avoid division by zero.

Arkku
  • 41,011
  • 10
  • 62
  • 84
  • This is also workable solution, but not so clear to grasp.)) – oleg_phorostyna Oct 31 '18 at 10:16
  • @oleg_phorostyna I added a brief description to the answer. – Arkku Oct 31 '18 at 17:33
  • Looks approximately as my solution, but still better and laconic.(i / CYCLE) & 1 - this is awesome condition!! I will stick to this pattern. I just curious about- is this is the best way to go through array back and forth? And I have an idea of a site with some common algorithms described in a language independent style with a vast explanation of each step. Is there any of such in a web? – oleg_phorostyna Nov 01 '18 at 12:57
  • @oleg_phorostyna Well, Wikipedia has explanations for the common algorithms, and of course there are numerous textbooks with pseudocode implementations (e.g., Introduction to Algorithms by Cormen et al). – Arkku Nov 01 '18 at 15:07
  • @oleg_phorostyna As for `x & 1`, the more common way is `x % 2`, which is the same thing for non-negative numbers, I just happened to use the bitwise version. Many people may consider the `% 2` more readable, especially if you add the `!= 0` which is implicit here (in C). – Arkku Nov 01 '18 at 15:09