2

I'm pretty new to Processing (coming from R) and have been having trouble with a certain weighted probability function.

I have an array of 100 numbers.

The sum of all these numbers is then used to create an array with the length of the sum of the numbers.

Each number in the new array is initialised to zero.

What I trying to do:

  1. Go through each number in the first array (example, starting with the first number of the first array which, for example, will be 6).

  2. Set the first 6 (since that is the current number) items in the second array with the length sum to the index number of the 6. So, the first six items in the second array will be {0,0,0,0,0,0}.

  3. Repeat for all the numbers. Example, an array {6, 3, 1} should create the array {0,0,0,0,0,0,1,1,1,2}

Does anyone have any ideas how to accomplish this? I've tried a ton of solutions, but have never had to do weighted probabilities like this before.

Peter O.
  • 32,158
  • 14
  • 82
  • 96
  • 2
    If your goal is ultimately to choose one of the 100 items with probability proportional to its weight, one idea to try is _rejection sampling_, or one of the other methods I suggest in an [answer to another question](https://stackoverflow.com/questions/5027757/what-are-efficient-data-structures-and-algorithms-for-simulating-loaded-dice/63166311#63166311). In contrast, your approach is feasible only if the sum of all 100 items is relatively small, say no more than a few thousand. – Peter O. Apr 12 '21 at 17:29

1 Answers1

4

One option is to make use of IntList() to dynamically append values to:


void setup(){
  int[] src = {6, 3, 1}; 
  IntList dst = new IntList();
  
  for(int i = 0; i < src.length; i++){
    // from 0 to the current index value in the array
    for(int j = 0; j < src[i]; j++){
      // add the index to the list
      dst.append(i);
    } 
  }
  
  println(sum(src));
  println(dst.size());
  println(dst);
  println(sum(dst));
}

int sum(int[] array){
  int total = 0;
  for(int i : array){
    total += i;
  }
  return total;
}

int sum(IntList list){
  int total = 0;
  for(int i : list){
    total += i;
  }
  return total;
}

Alternatively you can use ArrayList<Integer> or can probably do it all with int[] as well, since the sum is the number of elements in the second array:


void setup(){
  int[] src = {6, 3, 1}; 
  int[] dst = new int[sum(src)];
  int dstIndex = 0;
  for(int i = 0; i < src.length; i++){
    // from 0 to the current index value in the array
    for(int j = 0; j < src[i]; j++){
      // add the index to the list
      dst[dstIndex++] = i;
    } 
  }
  
  println(sum(src));
  println(dst);
}

int sum(int[] array){
  int total = 0;
  for(int i : array){
    total += i;
  }
  return total;
}

Bare in mind Processing comes in other flavours such as Python or JavaScript

In Python you could do something like:


import itertools
a = [6, 3, 1]
b = list(itertools.chain(*[ [index] * value for index, value in enumerate(a)]))
print(b) # prints [0, 0, 0, 0, 0, 0, 1, 1, 1, 2]

The above is creating a nested list via list comprehension then flattening the list via itertools

In JS you could do the same:

a = [6, 3, 1];
b = a.map((value, index) => new Array(value).fill(index)).flat();
console.log(b); //prints [0, 0, 0, 0, 0, 0, 1, 1, 1, 2] 

With these I'd also double check edge cases (what if you have values like 0, or -1 that can mess with indexing, etc.), otherwise if this needs to work on integers from 1 onwards simply wrap the instructions in a functions that checks the input first and rejects invalid input.

e.g.


void setup(){
  int[] src = {6, 3, 1}; 
  
  try{
    println(weightedProbabilities(src));
  }catch(Exception e){
    println(e.getMessage());
  }
  
}

int[] weightedProbabilities(int[] src) throws Exception{
  // validate input data
  for(int i = 0; i < src.length; i++){
    if(src[i] <= 0){
      throw new Exception(String.format("invalid element %d at index %d",src[i],i));
    }
  }
  // process data
  int[] dst = new int[sum(src)];
  int dstIndex = 0;
  for(int i = 0; i < src.length; i++){
    // from 0 to the current index value in the array
    for(int j = 0; j < src[i]; j++){
      // add the index to the list
      dst[dstIndex++] = i;
    } 
  }
  // return result
  return dst;
}

int sum(int[] array){
  int total = 0;
  for(int i : array){
    total += i;
  }
  return total;
}

George Profenza
  • 50,687
  • 19
  • 144
  • 218