It's not all that bad, seriously. I've been using an algorithm-based scheme across probably hundreds of sites for probably 10 years.
There are 3 'tricks':
1. First, use several different initial functions for different levels of security, each with different levels of complexity (i.e. f1(user,domain), f2(user,domain), etc).
2. Then, use a function for password requirement rules (i.e. g(f(user,domain),rules)).
3. Finally, use a final function for rotating passwords (i.e. h(g(f(user,domain),rules),rotation)).
So, all together, maybe 5 different algorithms, each of different levels of complexity.
You'd think that this would be very difficult to manage, but it hasn't been in practice. Very, very few times do I pick the wrong initial algorithm when trying to derive my password. And, in that case, I can quickly iterate to the correct password within 3-4 tries.
Most of the time I get it on the first try. Sometimes, I get it on the 2nd-3rd try. Very, very rarely (< 1%), I cannot derive it within 5 tries. And, at that point, I just do a password reset (and rotate the password using the h function).