0

I have a requirement where I have to reverse an array without changing the index of '#' presents in an array, like below example:

  • Array [18,-4,'#',0,8,'#',5] should return [5, 8, "#", 0, -4, "#", 18], here numbers should be reversed, excluding '#' while keeping the same index.

I have tried to get the correct output, but it doesn't seem to be correct in all scenarios: var arr = [18,-4,'#',0,8,'#',5]; // giving result is correct var arr1 = [18,-4,0,'#',8,'#',5]; // result is not correct

var reverse = function(numbers, start, end){
	var temp = numbers[start];
  numbers[start] = numbers[end];
  numbers[end] = temp;
}
var flip = function(numbers) {
var start = 0;
var end = numbers.length-1;
	for(var i=0;i<parseInt(numbers.length/2);i++) {
  	if(numbers[i] === '#') {
    	start = i+1;
      end = numbers.length - i - i;
      reverse(numbers, start, end);
    } else if (numbers[numbers.length - i - 1] === '#') {
    	start = i;
      end = numbers.length - i - 2;
      reverse(numbers, start, end);
    } else {
    	reverse(numbers, start, end);
    }
  }
  return numbers;
}

var arr = [18,-4,'#',0,8,'#',5];
var arr1 = [18,-4,0,'#',8,'#',5];
console.log(flip(arr));
console.log(flip(arr1));

6 Answers 6

2

You could simplify the function and use only two indices, the start and end and check if the value at the indices should stay, then choose another index for swapping.

const
    swap = (array, a, b) => [array[a], array[b]] = [array[b], array[a]],
    flip = numbers => {
        var start = 0,
            end = numbers.length - 1;

        while (start < end) {
            if (numbers[start] === '#') {
                start++;
                continue;
            }
            if (numbers[end] === '#') {
                end--;
                continue;
            }
            swap(numbers, start++, end--);
        }
        return numbers;
    },
    array1 = [18, -4, '#', 0, 8, '#', 5],
    array2 = [18, -4, 0, '#', 8, '#', 5];

console.log(...flip(array1));
console.log(...flip(array2));

Sign up to request clarification or add additional context in comments.

Comments

2

The trivial approach would be to remove all '#''s, reverse the array using the built in [].reverse method, and then re-insert the '#''s:

let flip = numbers => {
  let removed = numbers.reduce((r, v, i) =>
          v === '#' ? r.concat(i) : r
      , []);

  let reversed = numbers.filter(v => v !== '#').reverse();

  removed.forEach(i => reversed.splice(i, 0, '#'));

  return reversed;
};

let arr = [18, -4, '#', 0, 8, '#', 5];
let arr1 = [18, -4, 0, '#', 8, '#', 5];
console.log(flip(arr));
console.log(flip(arr1));

2 Comments

Thanks, @junvar for the efforts, but I need it without predefined functions, I want to use basic logics of loop or something, can it be simplified ?
@SarveshMahajan: Unless this is homework, or you have some really serious performance constraints, I would suggest that using filter, concat, reduce, etc. makes for more easily readable code than custom loops.
1

You can try this:

var numbers = arr.filter(a => a !== '#')
var revArr = [];
arr.forEach((currentValue) => {
    if(currentValue !== "#") {
        revArr.push(numbers.pop());
    } else {
        revArr.push("#");
    }
});

1 Comment

Thanks, @sagar for your efforts, can it be simplified without filters?
1

You can base your algorithm on two basic array (array of reversed numbers and and an array with "#" saved positions)

const array = [5, 8, "#", 0, -4, "#", 18];

function flip(array) {

  const arrayNumbers = array.filter((el, index) => el !== "#").reverse();

  var counter = 0;

  return array.map(el => el === "#").map(el => {
    if (!el) {
      let num = arrayNumbers[counter];
      counter = counter + 1;
      return num;
    } else {
      return "#"
    }
  })
}

console.log(flip(array));

3 Comments

Note that the question asked for a reverse, not a sort
Thanks @G.aziz for your efforts, but I need to implement it without filters, can it be simplified ?
@SarveshMahajan: replacing the filter and map with custom loops would be the opposite of simplifying.
0
var arr = [18,-4,'#',0,8,'#',5]
var stack = []

for (i=0 ; i<arr.length; i++) {
    if (arr[i] == '#') continue;
    stack.push(arr[i]);
}

for (i=0 ; i<arr.length; i++) {
    if (arr[i] != '#') {
        arr[i] = stack.pop();
    }
}

console.log(arr)

The above code should solve your problem.
The implementation uses stack where we keep inserting elements into stack untill we see a '#' and skip it. While creating the output array we refer the original array for '#' index and stack for reverse index.

Comments

0

You can do it like this.

        int end = v.length - 1;
        int start = 0;
        for (int i = 0; i < v.length >> 1; i++) {
            if (v[start].equals("#")) {
                start++;
                continue;
            }
            if (v[end].equals("#")) {
                end--;
                continue;
            }
            Object temp = v[end];
            v[end] = v[start];
            v[start] = temp;
            end--;
            start++;

        }
        System.out.println(Arrays.toString(v));

1 Comment

Perhaps now, but not earlier. The OP changed the tag.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.