Smart most recently used algorithm Background
I need such an algorithm inside an android app (home launcher) to show the recently used apps. I want to avoid simple LRU / MRU logic by combining those logics (or use an alternative if anyone has a suggestion). I don't want an app that was started 100x before 10 weeks to stay on top until another app was started 100x and I don't want to only show the LRU apps on top. I want something that matches what a human would expect to see in the most recently used section.
Solution
I can of course save every app launch in a database (including its timestamp) and then give each launch a weight based on its age and then sum them up and calc an avarage value. That's a valid solution and would fit my needs. BUT it will grow the database indefinitely.
Question
Does anyone has an idea or does there exist an algorithm for such a problem already that does not depend on a full list of historical data (app launches in my case)? But instead does update values that belong to each app?
I suggested looking at the Reddit ranking system in a comment, however,
that system is made in such a way that the time of creation is what
matters, and that's not really relevant in your scenario.
I therefore suggest a physics-based approach.
Model each app as a balloon (circular, in vacuum).  Every time you open
an app, it corresponds to hitting the balloon straight upwards (like a
volleyball set hit), and when you're not hitting the balloon, it falls
towards the earth.  Once it hits the ground it can remain idle (or bump
up a bit if you want to remind the user of apps they forgot about).
In order for an app to remain &quot;hot&quot; you need to keep it above ground.
So how to implement this?
We have a list of timestamps that maps days since epoch to the number of
times it was opened that day.  In the below sketch, I use a linear decay
(gravity would of course be quadratic).
You need to experiment with the constants and try different functions
(logarithms and polynomials) to get it to work to your likings.
Sketch
USAGE = {  # map day to number of opens for that day
    &quot;A&quot;: {0: 2, 1: 2, 2: 2, 3: 2, 4: 2},
    &quot;B&quot;: {0: 10, 1: 0, 2: 0, 4: 0},
    &quot;C&quot;: {0: 0, 1: 3, 2: 3, 4: 3},
    &quot;D&quot;: {0: 0, 1: 0, 2: 0, 3: 5},
    &quot;X&quot;: {0: 3, 1: 3, 2: 3, 3: 3, 4: 0},
    &quot;Y&quot;: {0: 0, 1: 0, 2: 0, 3: 0, 4: 3},
    &quot;Z&quot;: {0: 0, 1: 0, 2: 0, 3: 0, 4: 2},
}
IMPACT = 1.1
DECAY  = 1.1

def rank_app(timemap, t):
    &quot;&quot;&quot;Return the &quot;height&quot; of the balloon on day t given the timemap&quot;&quot;&quot;
    height = 0
    for day in range(t + 1):
        height += timemap.get(day, 0) ** IMPACT  # impact of opening
        since = abs((t - day - 1))
        height = max(0, height - since ** DECAY)  # decay
    return round(height, 1)

def rank(usage, day):
    &quot;&quot;&quot;Return (heigh, app) for each app on given day t.&quot;&quot;&quot;
    return sorted(
        [(rank_app(usage[app], day), app) for app in usage],
        reverse=True,
    )

print(&quot;\n&quot;.join([f&quot;{e[0]} {e[1]}&quot; for e in rank(USAGE, day=5)]))

... which gives
3.9 D
2.6 X
2.6 C
2.3 Y
2.3 A
1.1 Z
0.5 B

Notice that D is on top because it was visited 5 times yesterday.  On
the other hand, B was visited 10 times on Day 0, but hasn't been
visited since, so it is on the bottom.
If you are worried about the space it takes to store all the timestamps,
you can truncate the list at any point and replace with its height at a
given day.