Array question

Started by
10 comments, last by Lactose 10 years, 1 month ago

Hello everybody

I have a programming question.

My array looks like this:


array[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

And I want to erase from the array the elements like in a queue.


first modification:  |1|2|3|4|5|6|7|8|9|
second modification: |2|3|4|5|6|7|8|9|0|
tird modification:   |3|4|5|6|7|8|9|0|0|
fourth modification: |4|5|6|7|8|9|0|0|0|
...

Since now its easy:


array[i] = array[i+1];

But I have another boolean array that can lock in some numbers, for example:


bool lock[3] = {false, false, false};

I want that when lock[1] = true, the array[1] remains unchanged.


lock[1] = true;
first modification:       |1|2|3|4|5|6|7|8|9|
second modification:      |3|2|4|5|6|7|8|9|0|
tird modification:        |4|2|5|6|7|8|9|0|0|
and so on..

How can be implemented in a easy manner?

"Don't gain the world and lose your soul. Wisdom is better than silver or gold." - Bob Marley

Advertisement

EDIT: This won't work correctly after all. See further posts.

---

Since the arrays aren't the same size, you can't use:


if (!locked[i])
    array[i] = array[i + 1];

Either setting the array sizes to be the same and use above, or using something like this might work:


if (i < 3) //size of bool array
{
    if (!locked[i])
        array[i] = array[i + 1];
}
else
{
    array[i] = array[i + 1];
}

Note that I don't think this is actually safe for the last element, since you're trying to read outside the bounds of the array and using that value for something.

I would probably (at least before breakfast and waking up properly) do something like this:


for (int i = 0; i < 10; i++)
{
    int newValue = 0;
    if (i < 3) //Size of the bool array... AND a heart emoticon
    {
        if (!locked[i])
            newValue = array[i + 1];
        else
            newValue = array[i]; //Forgot this, as richardurich pointed out
    }
    else
    {
        if ((i + 1) < 10)
            newValue = array[i + 1];
    }
    array[i] = newValue;
}

Hello to all my stalkers.

Lactose, your solution needs to actually lock in the old value when locked is true instead of changing to zero.




for (int i = 0; i < 10; i++)
{
    int newValue = 0;
    if (i < 3) //Size of the bool array... AND a heart emoticon
    {
        if (!locked[i])
            newValue = array[i + 1];
        else //lock in old value
            newValue = array[i];
    }
    else
    {
        if ((i + 1) < 10)
            newValue = array[i + 1];
    }
    array[i] = newValue;
}

Different sizes is awkward. You should use a struct


struct Element
{
    int value;
    bool isLocked;
};
 
bool IsNotLocked(const Element& elt) { return !elt.isLocked; }
 
Element myArray[10] = { {0}, {1}, {2, true}, {3}, {4}, {5}, {6}, {7}, {8}, {9} };
 
Element* newEnd = std::remove_if(myArray, myArray + 10, IsNotLocked);
 
for(; newEnd != myArray + 10; ++newEnd)
{
     newEnd->value = 0;
     newEnd->isLocked = false;
}

It's still not very nice though ;) And I didn't test it. If you use a std::vector instead of an array you can use vector::erase(newEnd) instead of the loop at the end.

EDIT: Whoops, that erases everything that is not locked. I did say I didn't test it ;)

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley


Lactose, your solution needs to actually lock in the old value when locked is true instead of changing to zero.

Edited your fix into my post. Thanks for the correction :)

Hello to all my stalkers.

Actually, looking at it now, this wouldn't give the behavior wanted in the final parts of the post.

If lock[1] is true, array[0] should copy the value of array[2] instead of array[1] -- assuming lock[2] is false.

My suggestion solution will not work. Sorry sad.png

---

Starting to think nested loops.

Loop through to update values. In that loop, loop through the remaining until a non-locked entry is found (breaking the inner loop when found), and using that. If nothing found, use default value of 0.

Hello to all my stalkers.

Well my method doesn't work either ;)

It's going to be problematic anyway - what is supposed to happen if you want to keep say the 5th element locked and you delete everything else from the array?

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

EDIT: But this also shares the question from Paradigm Shifter...



for (int i = 0; i < 10; i++)
{
	int newValue = 0;
	if (locked[i])
		newValue = array[i];
	else
	{
		for (int j = (i + 1); j < 10; j++)
		{
			if (j < 3) //Size of the bool array
			{
				if (locked[j])
					continue;
			}
			newValue = array[j];
			break;
		}
	}
	array[i] = newValue;
}

Hello to all my stalkers.

This is tricky to get right. Here's my attempt (with same-length arrays, to keep sanity):
#include <algorithm> // Just for std::swap

unsigned find_first_unlocked(bool const *locked, unsigned n, unsigned i) {
  for (; i < n; ++i) {
    if (!locked[i])
      break;
  }
  
  return i;
}

void shift(int *v, bool const *locked, unsigned n) {
  unsigned i, j;
  for (i = find_first_unlocked(locked, n, 0), j = find_first_unlocked(locked, n, i + 1);
       j < n;
       std::swap(i, j), j = find_first_unlocked(locked, n, i + 1)) {
    v[i] = v[j];
  }
  
  if (i < n)
    v[i] = 0;
}

No love for recursion, huh? I'll provide a recursive solution:


int GetNextValue(int currIndex, int* array, int arraySize, bool* locked, int lockedSize){
  if (currIndex >= arraySize) return 0;
  if ((currIndex < lockedSize) && (locked[currIndex])) //locked, so skip this value
    return GetNextValue(currIndex+1, array, arraySize, locked, lockedSize);
  return array[currIndex];
}

void ShiftValues(int* array, int arraySize, bool* locked, int lockedSize){
  for (int i = 0; i < arraySize; i++){
    if ((i < lockedSize) && (locked[i])) //value is locked, so keep it the same
      continue;
    else //value is not locked, so set to the next value
      array[i] = GetNextValue(i+1, array, arraySize, locked, lockedSize);
  }
}

Edit: first post only had half the code for some reason?!?! And second post messed up the code block.

This topic is closed to new replies.

Advertisement