Smart most recently used algorithm
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.