/
maps/
package mapmaker;

public class Compressor {

  /** provides information to resize an array to a given size by 
   * inserting or removing elements in it; which elements are 
   * allowed to be removed is given in advance;
   * if number of non-removable elements is larger that targeted
   * size, resizes to an array containing only the non-removeables;
   * returns an array of size equal to the new array size, with each
   * element equal to -1 if none of the old elements got transfered
   * to this position, or equal to that element's previous index 
   * in the given array otherwise
   * @param compressable is of length of the old array, indicates for
   * each element wether it's allowed to be removed or not
   * @param size the size the new array should have if possible
   */
  public static int[] compress(boolean[] removable, int size) {
    int minSize = 0;
    for (int i = 0; i < removable.length; i++)
      if (!removable[i])
	minSize++;
    // three cases: no removal, max removal, or something in between
    // no removal:
    if (size >= removable.length) {
      int[] compressed = new int[size];
      for (int i = 0; i < compressed.length; i++) 
	if (i < removable.length)
	  compressed[i] = i;
	else
	  compressed[i] = -1;
      return compressed;
    }
    // max removal:
    if (size <= minSize) {
      int[] compressed = new int[minSize];
      int pos = 0;
      for (int i = 0; i < compressed.length; i++) {
	// find next non-removable element
	while (removable[pos])
	  pos++;
	compressed[i] = pos;
	pos++;
      }
      return compressed;
    }
    // something in between:
    // Strategy: remove elements from the outside first
    int[] compressed = new int[size];
    int maxRemovable = size - minSize; // nr of removable elements to copy
    // find last non-removable element
    int lastPos = size - 1;
    while (lastPos >= 0 && removable[lastPos])
      lastPos--;
    // find first non-removable element
    int firstPos = 0;
    while (firstPos < compressed.length && removable[firstPos])
      firstPos++;
    // calculate maximum ammout of beginning elements to skip
    int maxSkip = (lastPos + 1) - size;
    if (maxSkip < 0)
      maxSkip = 0;
    // pos = min(maxSkip, firstPos)
    int pos = maxSkip < firstPos ? maxSkip : firstPos;
    // start coppying positions at pos, copy removable positions
    // until maxRemovable reached
    int removed = 0;
    for (int i = 0; i < compressed.length; i++) {
      if (removed >= maxRemovable)
	while (removable[pos])
	  pos++;
      else
	if (removable[pos])
	  removed++;
      compressed[i] = pos++;
    }
    return compressed;
  } // compress
    
} // Compressor