1

I'd like to select an element of a list where each element is weight by how long since it was last selected.

I could make an LRU (least recently used) list with the weighting a function based on the position in the queue, which would be elegant except for the fact that initially all elements should be weighted equally.

Just subtracting or dividing the weight by a certain amount after it has been selected doesn't seem intuitively right. Is there a better way perhaps using a mathematical concept such as logarithms or inverses? (not my strong point)

hippietrail
  • 15,848
  • 18
  • 99
  • 158

1 Answers1

0

How about something like this:

Let n = number of elements, list = array of elements, watermark := 0.

r := random()
i := floor(r * n)

if i >= watermark :
    index := i
    watermark := watermark + 1  // weighted part grows
else :
    index := floor(weight(r * n / watermark) * watermark)
endif

move list[index] to list[0]     // shifting elements list[0..index-1] up one place
result := list[0]

Here we divide the list into two parts, weighted and uniform, with boundary tracked by watermark. Initially the weighted part is empty, but gradually it grows, in the end consuming the entire list.

random() is a function that returns a random number in [0.0, 1.0).

weight(x) is a function from [0.0, 1.0) into [0.0, 1.0) that defines required weighting behaviour.

The "r * n / watermark" as argument of weight() serves to normalize the argument range. Maybe this normalization is not needed for some choices of the weighting function.

atzz
  • 17,507
  • 3
  • 35
  • 35
  • atzz I'm going to try your algorithm and see how it behaves thanks! – hippietrail Dec 15 '10 at 15:50
  • @hippietrail - You're welcome! please let me know how does it do, I'm interested too :) – atzz Dec 15 '10 at 15:56
  • one thing I'm worried about is that if the list gets enormous I may use a lot of CPU recalculating the "break points" after each selection, whereas with a strict LRU and weight as a function of position in the queue these break points would never change. – hippietrail Dec 15 '10 at 16:14
  • @hippietrail - i think the most complex operation here is the list modification, which is O(n). But it is needed to maintain simple LRU as well, isn't it? "Watermark" is just one simple integer, it shouldn't affect anything. – atzz Dec 15 '10 at 21:02